piglop-prawn 0.10.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. data/COPYING +340 -0
  2. data/HACKING +49 -0
  3. data/LICENSE +56 -0
  4. data/README +140 -0
  5. data/Rakefile +52 -0
  6. data/data/encodings/win_ansi.txt +29 -0
  7. data/data/fonts/Action Man.dfont +0 -0
  8. data/data/fonts/Activa.ttf +0 -0
  9. data/data/fonts/Chalkboard.ttf +0 -0
  10. data/data/fonts/Courier-Bold.afm +342 -0
  11. data/data/fonts/Courier-BoldOblique.afm +342 -0
  12. data/data/fonts/Courier-Oblique.afm +342 -0
  13. data/data/fonts/Courier.afm +342 -0
  14. data/data/fonts/DejaVuSans.ttf +0 -0
  15. data/data/fonts/Dustismo_Roman.ttf +0 -0
  16. data/data/fonts/Helvetica-Bold.afm +2827 -0
  17. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  18. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  19. data/data/fonts/Helvetica.afm +3051 -0
  20. data/data/fonts/MustRead.html +19 -0
  21. data/data/fonts/Symbol.afm +213 -0
  22. data/data/fonts/Times-Bold.afm +2588 -0
  23. data/data/fonts/Times-BoldItalic.afm +2384 -0
  24. data/data/fonts/Times-Italic.afm +2667 -0
  25. data/data/fonts/Times-Roman.afm +2419 -0
  26. data/data/fonts/ZapfDingbats.afm +225 -0
  27. data/data/fonts/comicsans.ttf +0 -0
  28. data/data/fonts/gkai00mp.ttf +0 -0
  29. data/data/images/16bit.alpha +0 -0
  30. data/data/images/16bit.dat +0 -0
  31. data/data/images/16bit.png +0 -0
  32. data/data/images/arrow.png +0 -0
  33. data/data/images/arrow2.png +0 -0
  34. data/data/images/barcode_issue.png +0 -0
  35. data/data/images/dice.alpha +0 -0
  36. data/data/images/dice.dat +0 -0
  37. data/data/images/dice.png +0 -0
  38. data/data/images/dice_interlaced.png +0 -0
  39. data/data/images/fractal.jpg +0 -0
  40. data/data/images/letterhead.jpg +0 -0
  41. data/data/images/page_white_text.alpha +0 -0
  42. data/data/images/page_white_text.dat +0 -0
  43. data/data/images/page_white_text.png +0 -0
  44. data/data/images/pigs.jpg +0 -0
  45. data/data/images/rails.dat +0 -0
  46. data/data/images/rails.png +0 -0
  47. data/data/images/ruport.png +0 -0
  48. data/data/images/ruport_data.dat +0 -0
  49. data/data/images/ruport_transparent.png +0 -0
  50. data/data/images/ruport_type0.png +0 -0
  51. data/data/images/stef.jpg +0 -0
  52. data/data/images/tru256.bmp +0 -0
  53. data/data/images/web-links.dat +1 -0
  54. data/data/images/web-links.png +0 -0
  55. data/data/pdfs/complex_template.pdf +0 -0
  56. data/data/pdfs/contains_ttf_font.pdf +0 -0
  57. data/data/pdfs/encrypted.pdf +0 -0
  58. data/data/pdfs/hexagon.pdf +61 -0
  59. data/data/pdfs/indirect_reference.pdf +86 -0
  60. data/data/pdfs/nested_pages.pdf +118 -0
  61. data/data/pdfs/resources_as_indirect_object.pdf +83 -0
  62. data/data/pdfs/two_hexagons.pdf +90 -0
  63. data/data/pdfs/version_1_6.pdf +61 -0
  64. data/data/shift_jis_text.txt +1 -0
  65. data/examples/bounding_box/bounding_boxes.rb +43 -0
  66. data/examples/bounding_box/indentation.rb +34 -0
  67. data/examples/bounding_box/russian_boxes.rb +36 -0
  68. data/examples/bounding_box/stretched_nesting.rb +67 -0
  69. data/examples/example_helper.rb +4 -0
  70. data/examples/general/background.rb +23 -0
  71. data/examples/general/canvas.rb +15 -0
  72. data/examples/general/context_sensitive_headers.rb +37 -0
  73. data/examples/general/float.rb +11 -0
  74. data/examples/general/margin.rb +36 -0
  75. data/examples/general/measurement_units.rb +51 -0
  76. data/examples/general/metadata-info.rb +16 -0
  77. data/examples/general/multi_page_layout.rb +18 -0
  78. data/examples/general/outlines.rb +50 -0
  79. data/examples/general/page_geometry.rb +31 -0
  80. data/examples/general/page_numbering.rb +15 -0
  81. data/examples/general/repeaters.rb +47 -0
  82. data/examples/general/stamp.rb +41 -0
  83. data/examples/general/templates.rb +13 -0
  84. data/examples/graphics/basic_images.rb +23 -0
  85. data/examples/graphics/cmyk.rb +12 -0
  86. data/examples/graphics/curves.rb +11 -0
  87. data/examples/graphics/hexagon.rb +13 -0
  88. data/examples/graphics/image_fit.rb +15 -0
  89. data/examples/graphics/image_flow.rb +37 -0
  90. data/examples/graphics/image_position.rb +17 -0
  91. data/examples/graphics/line.rb +32 -0
  92. data/examples/graphics/png_types.rb +22 -0
  93. data/examples/graphics/polygons.rb +16 -0
  94. data/examples/graphics/remote_images.rb +12 -0
  95. data/examples/graphics/rounded_polygons.rb +19 -0
  96. data/examples/graphics/rounded_rectangle.rb +20 -0
  97. data/examples/graphics/ruport_style_helpers.rb +19 -0
  98. data/examples/graphics/stroke_bounds.rb +20 -0
  99. data/examples/graphics/stroke_cap_and_join.rb +45 -0
  100. data/examples/graphics/stroke_dash.rb +42 -0
  101. data/examples/graphics/transformations.rb +52 -0
  102. data/examples/graphics/transparency.rb +26 -0
  103. data/examples/m17n/chinese_text_wrapping.rb +17 -0
  104. data/examples/m17n/euro.rb +15 -0
  105. data/examples/m17n/sjis.rb +28 -0
  106. data/examples/m17n/utf8.rb +13 -0
  107. data/examples/m17n/win_ansi_charset.rb +54 -0
  108. data/examples/security/hello_foo.rb +8 -0
  109. data/examples/table/bill.rb +53 -0
  110. data/examples/table/cell.rb +12 -0
  111. data/examples/table/checkerboard.rb +22 -0
  112. data/examples/table/header.rb +14 -0
  113. data/examples/table/inline_format_table.rb +12 -0
  114. data/examples/table/multi_page_table.rb +9 -0
  115. data/examples/table/simple_table.rb +24 -0
  116. data/examples/table/subtable.rb +12 -0
  117. data/examples/table/widths.rb +20 -0
  118. data/examples/text/alignment.rb +18 -0
  119. data/examples/text/dfont.rb +48 -0
  120. data/examples/text/family_based_styling.rb +24 -0
  121. data/examples/text/font_calculations.rb +91 -0
  122. data/examples/text/font_size.rb +33 -0
  123. data/examples/text/hyphenation.rb +45 -0
  124. data/examples/text/indent_paragraphs.rb +18 -0
  125. data/examples/text/inline_format.rb +72 -0
  126. data/examples/text/kerning.rb +30 -0
  127. data/examples/text/rotated.rb +98 -0
  128. data/examples/text/shaped_text_box.rb +31 -0
  129. data/examples/text/simple_text.rb +17 -0
  130. data/examples/text/simple_text_ttf.rb +17 -0
  131. data/examples/text/text_box.rb +88 -0
  132. data/examples/text/text_box_returning_excess.rb +51 -0
  133. data/examples/text/text_flow.rb +67 -0
  134. data/lib/prawn/compatibility.rb +51 -0
  135. data/lib/prawn/core/annotations.rb +61 -0
  136. data/lib/prawn/core/byte_string.rb +9 -0
  137. data/lib/prawn/core/destinations.rb +90 -0
  138. data/lib/prawn/core/document_state.rb +84 -0
  139. data/lib/prawn/core/literal_string.rb +16 -0
  140. data/lib/prawn/core/name_tree.rb +165 -0
  141. data/lib/prawn/core/object_store.rb +219 -0
  142. data/lib/prawn/core/page.rb +179 -0
  143. data/lib/prawn/core/pdf_object.rb +83 -0
  144. data/lib/prawn/core/reference.rb +112 -0
  145. data/lib/prawn/core/text/formatted/arranger.rb +260 -0
  146. data/lib/prawn/core/text/formatted/line_wrap.rb +127 -0
  147. data/lib/prawn/core/text/formatted/wrap.rb +113 -0
  148. data/lib/prawn/core/text/line_wrap.rb +198 -0
  149. data/lib/prawn/core/text/wrap.rb +80 -0
  150. data/lib/prawn/core/text.rb +115 -0
  151. data/lib/prawn/core.rb +89 -0
  152. data/lib/prawn/document/bounding_box.rb +425 -0
  153. data/lib/prawn/document/graphics_state.rb +48 -0
  154. data/lib/prawn/document/internals.rb +176 -0
  155. data/lib/prawn/document/page_geometry.rb +136 -0
  156. data/lib/prawn/document/snapshot.rb +87 -0
  157. data/lib/prawn/document.rb +573 -0
  158. data/lib/prawn/encoding.rb +121 -0
  159. data/lib/prawn/errors.rb +94 -0
  160. data/lib/prawn/font/afm.rb +225 -0
  161. data/lib/prawn/font/dfont.rb +42 -0
  162. data/lib/prawn/font/ttf.rb +350 -0
  163. data/lib/prawn/font.rb +342 -0
  164. data/lib/prawn/graphics/cap_style.rb +38 -0
  165. data/lib/prawn/graphics/color.rb +205 -0
  166. data/lib/prawn/graphics/dash.rb +71 -0
  167. data/lib/prawn/graphics/join_style.rb +38 -0
  168. data/lib/prawn/graphics/transformation.rb +156 -0
  169. data/lib/prawn/graphics/transparency.rb +99 -0
  170. data/lib/prawn/graphics.rb +321 -0
  171. data/lib/prawn/images/jpg.rb +46 -0
  172. data/lib/prawn/images/png.rb +226 -0
  173. data/lib/prawn/images.rb +348 -0
  174. data/lib/prawn/measurement_extensions.rb +46 -0
  175. data/lib/prawn/measurements.rb +71 -0
  176. data/lib/prawn/outline.rb +278 -0
  177. data/lib/prawn/repeater.rb +129 -0
  178. data/lib/prawn/security/arcfour.rb +51 -0
  179. data/lib/prawn/security.rb +262 -0
  180. data/lib/prawn/stamp.rb +126 -0
  181. data/lib/prawn/table/accessors.rb +180 -0
  182. data/lib/prawn/table/cell/in_table.rb +27 -0
  183. data/lib/prawn/table/cell/subtable.rb +65 -0
  184. data/lib/prawn/table/cell/text.rb +128 -0
  185. data/lib/prawn/table/cell.rb +330 -0
  186. data/lib/prawn/table.rb +421 -0
  187. data/lib/prawn/text/box.rb +380 -0
  188. data/lib/prawn/text/formatted/box.rb +215 -0
  189. data/lib/prawn/text/formatted/fragment.rb +127 -0
  190. data/lib/prawn/text/formatted/parser.rb +202 -0
  191. data/lib/prawn/text/formatted.rb +4 -0
  192. data/lib/prawn/text.rb +442 -0
  193. data/lib/prawn.rb +25 -0
  194. data/spec/annotations_spec.rb +90 -0
  195. data/spec/bounding_box_spec.rb +190 -0
  196. data/spec/cell_spec.rb +337 -0
  197. data/spec/destinations_spec.rb +15 -0
  198. data/spec/document_spec.rb +461 -0
  199. data/spec/font_spec.rb +314 -0
  200. data/spec/formatted_text_arranger_spec.rb +400 -0
  201. data/spec/formatted_text_box_spec.rb +659 -0
  202. data/spec/formatted_text_fragment_spec.rb +211 -0
  203. data/spec/graphics_spec.rb +446 -0
  204. data/spec/images_spec.rb +96 -0
  205. data/spec/inline_formatted_text_parser_spec.rb +446 -0
  206. data/spec/jpg_spec.rb +25 -0
  207. data/spec/line_wrap_spec.rb +341 -0
  208. data/spec/measurement_units_spec.rb +23 -0
  209. data/spec/name_tree_spec.rb +112 -0
  210. data/spec/object_store_spec.rb +160 -0
  211. data/spec/outline_spec.rb +229 -0
  212. data/spec/pdf_object_spec.rb +127 -0
  213. data/spec/png_spec.rb +237 -0
  214. data/spec/reference_spec.rb +82 -0
  215. data/spec/repeater_spec.rb +96 -0
  216. data/spec/security_spec.rb +120 -0
  217. data/spec/snapshot_spec.rb +138 -0
  218. data/spec/spec_helper.rb +26 -0
  219. data/spec/stamp_spec.rb +108 -0
  220. data/spec/stroke_styles_spec.rb +163 -0
  221. data/spec/table_spec.rb +583 -0
  222. data/spec/template_spec.rb +158 -0
  223. data/spec/text_at_spec.rb +119 -0
  224. data/spec/text_box_spec.rb +675 -0
  225. data/spec/text_spacing_spec.rb +57 -0
  226. data/spec/text_spec.rb +328 -0
  227. data/spec/text_with_inline_formatting_spec.rb +193 -0
  228. data/spec/transparency_spec.rb +75 -0
  229. data/vendor/pdf-inspector/README +18 -0
  230. data/vendor/pdf-inspector/lib/pdf/inspector/extgstate.rb +18 -0
  231. data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +131 -0
  232. data/vendor/pdf-inspector/lib/pdf/inspector/page.rb +25 -0
  233. data/vendor/pdf-inspector/lib/pdf/inspector/text.rb +46 -0
  234. data/vendor/pdf-inspector/lib/pdf/inspector/xobject.rb +19 -0
  235. data/vendor/pdf-inspector/lib/pdf/inspector.rb +26 -0
  236. data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
  237. data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
  238. data/vendor/ttfunk/example.rb +45 -0
  239. data/vendor/ttfunk/lib/ttfunk/directory.rb +17 -0
  240. data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +88 -0
  241. data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +69 -0
  242. data/vendor/ttfunk/lib/ttfunk/reader.rb +44 -0
  243. data/vendor/ttfunk/lib/ttfunk/resource_file.rb +78 -0
  244. data/vendor/ttfunk/lib/ttfunk/subset/base.rb +141 -0
  245. data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +50 -0
  246. data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +48 -0
  247. data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +63 -0
  248. data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +55 -0
  249. data/vendor/ttfunk/lib/ttfunk/subset.rb +18 -0
  250. data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +72 -0
  251. data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +54 -0
  252. data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +126 -0
  253. data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +79 -0
  254. data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +34 -0
  255. data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +81 -0
  256. data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +37 -0
  257. data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +64 -0
  258. data/vendor/ttfunk/lib/ttfunk/table/head.rb +44 -0
  259. data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +41 -0
  260. data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +47 -0
  261. data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +62 -0
  262. data/vendor/ttfunk/lib/ttfunk/table/kern.rb +79 -0
  263. data/vendor/ttfunk/lib/ttfunk/table/loca.rb +43 -0
  264. data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +40 -0
  265. data/vendor/ttfunk/lib/ttfunk/table/name.rb +125 -0
  266. data/vendor/ttfunk/lib/ttfunk/table/os2.rb +78 -0
  267. data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +43 -0
  268. data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +35 -0
  269. data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +23 -0
  270. data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +17 -0
  271. data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +17 -0
  272. data/vendor/ttfunk/lib/ttfunk/table/post.rb +91 -0
  273. data/vendor/ttfunk/lib/ttfunk/table/simple.rb +14 -0
  274. data/vendor/ttfunk/lib/ttfunk/table.rb +46 -0
  275. data/vendor/ttfunk/lib/ttfunk.rb +102 -0
  276. metadata +364 -0
@@ -0,0 +1,131 @@
1
+ module PDF
2
+ class Inspector
3
+ module Graphics
4
+ class Line < Inspector
5
+ attr_accessor :points, :widths
6
+
7
+ def initialize
8
+ @points = []
9
+ @widths = []
10
+ end
11
+
12
+ def append_line(*params)
13
+ @points << params
14
+ end
15
+
16
+ def begin_new_subpath(*params)
17
+ @points << params
18
+ end
19
+
20
+ def set_line_width(params)
21
+ @widths << params
22
+ end
23
+
24
+ end
25
+
26
+ class Rectangle < Inspector
27
+ attr_reader :rectangles
28
+
29
+ def initialize
30
+ @rectangles = []
31
+ end
32
+
33
+ def append_rectangle(*params)
34
+ @rectangles << { :point => params[0..1],
35
+ :width => params[2],
36
+ :height => params[3] }
37
+ end
38
+ end
39
+
40
+ class Curve < Inspector
41
+
42
+ attr_reader :coords
43
+
44
+ def initialize
45
+ @coords = []
46
+ end
47
+
48
+ def begin_new_subpath(*params)
49
+ @coords += params
50
+ end
51
+
52
+ def append_curved_segment(*params)
53
+ @coords += params
54
+ end
55
+
56
+ end
57
+
58
+ class Color < Inspector
59
+ attr_reader :stroke_color, :fill_color, :stroke_color_count,
60
+ :fill_color_count
61
+
62
+ def initialize
63
+ @stroke_color_count = 0
64
+ @fill_color_count = 0
65
+ end
66
+
67
+ def set_color_for_stroking_and_special(*params)
68
+ @stroke_color_count += 1
69
+ @stroke_color = params
70
+ end
71
+
72
+ def set_color_for_nonstroking_and_special(*params)
73
+ @fill_color_count += 1
74
+ @fill_color = params
75
+ end
76
+ end
77
+
78
+ class Dash < Inspector
79
+ attr_reader :stroke_dash, :stroke_dash_count
80
+
81
+ def initialize
82
+ @stroke_dash_count = 0
83
+ end
84
+
85
+ def set_line_dash(*params)
86
+ @stroke_dash_count += 1
87
+ @stroke_dash = params
88
+ end
89
+ end
90
+
91
+ class CapStyle < Inspector
92
+ attr_reader :cap_style, :cap_style_count
93
+
94
+ def initialize
95
+ @cap_style_count = 0
96
+ end
97
+
98
+ def set_line_cap_style(*params)
99
+ @cap_style_count += 1
100
+ @cap_style = params[0]
101
+ end
102
+ end
103
+
104
+ class JoinStyle < Inspector
105
+ attr_reader :join_style, :join_style_count
106
+
107
+ def initialize
108
+ @join_style_count = 0
109
+ end
110
+
111
+ def set_line_join_style(*params)
112
+ @join_style_count += 1
113
+ @join_style = params[0]
114
+ end
115
+ end
116
+
117
+ class Matrix < Inspector
118
+ attr_reader :matrices
119
+
120
+ def initialize
121
+ @matrices = []
122
+ end
123
+
124
+ def concatenate_matrix(*values)
125
+ @matrices << values
126
+ end
127
+ end
128
+
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,25 @@
1
+ module PDF
2
+ class Inspector
3
+ class Page < Inspector
4
+ attr_reader :pages
5
+
6
+ def initialize
7
+ @pages = []
8
+ end
9
+
10
+ def begin_page(params)
11
+ @pages << {:size => params[:MediaBox][-2..-1], :strings => []}
12
+ end
13
+
14
+ def show_text(*params)
15
+ @pages.last[:strings] << params[0]
16
+ end
17
+
18
+ def show_text_with_positioning(*params)
19
+ # ignore kerning information
20
+ @pages.last[:strings] << params[0].reject { |e| Numeric === e }.join
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,46 @@
1
+ module PDF
2
+ class Inspector
3
+ class Text < Inspector
4
+ attr_accessor :font_settings, :size, :strings
5
+ attr_accessor :character_spacing, :word_spacing
6
+ attr_accessor :kerned
7
+
8
+ def initialize
9
+ @font_settings = []
10
+ @fonts = {}
11
+ @strings = []
12
+ @character_spacing = []
13
+ @word_spacing = []
14
+ @kerned = []
15
+ end
16
+
17
+ def resource_font(*params)
18
+ @fonts[params[0]] = params[1].basefont
19
+ end
20
+
21
+ def set_text_font_and_size(*params)
22
+ @font_settings << { :name => @fonts[params[0]], :size => params[1] }
23
+ end
24
+
25
+ def show_text(*params)
26
+ @kerned << false
27
+ @strings << params[0]
28
+ end
29
+
30
+ def show_text_with_positioning(*params)
31
+ @kerned << true
32
+ # ignore kerning information
33
+ @strings << params[0].reject { |e| Numeric === e }.join
34
+ end
35
+
36
+ def set_character_spacing(*params)
37
+ @character_spacing << params[0]
38
+ end
39
+
40
+ def set_word_spacing(*params)
41
+ @word_spacing << params[0]
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,19 @@
1
+ module PDF
2
+ class Inspector
3
+ class XObject < Inspector
4
+ attr_accessor :page_xobjects
5
+
6
+ def initialize
7
+ @page_xobjects = []
8
+ end
9
+
10
+ def resource_xobject(*params)
11
+ @page_xobjects.last << params.first
12
+ end
13
+
14
+ def begin_page(*params)
15
+ @page_xobjects << []
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ require "rubygems"
2
+ require "pdf/reader"
3
+ require "pdf/inspector/text"
4
+ require "pdf/inspector/xobject"
5
+ require "pdf/inspector/extgstate"
6
+ require "pdf/inspector/graphics"
7
+ require "pdf/inspector/page"
8
+
9
+ module PDF
10
+ class Inspector
11
+ def self.analyze(output,*args,&block)
12
+ obs = self.new(*args, &block)
13
+ PDF::Reader.string(output,obs)
14
+ obs
15
+ end
16
+
17
+ def self.analyze_file(filename,*args,&block)
18
+ analyze(File.open(filename, "rb") { |f| f.read },*args,&block)
19
+ end
20
+
21
+ def self.parse(obj)
22
+ PDF::Reader::Parser.new(
23
+ PDF::Reader::Buffer.new(StringIO.new(obj)), nil).parse_token
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,45 @@
1
+ $LOAD_PATH << "#{File.dirname(__FILE__)}/lib"
2
+ require "ttfunk"
3
+
4
+ def character_lookup(file, character)
5
+ puts "character : #{character}"
6
+
7
+ character_code = character.unpack("U*").first
8
+ puts "character code: #{character_code}"
9
+
10
+ glyph_id = file.cmap.unicode.first[character_code]
11
+ puts "glyph id : #{glyph_id}"
12
+
13
+ glyph = file.glyph_outlines.for(glyph_id)
14
+ puts "glyph type : %s" % glyph.class.name.split(/::/).last.downcase
15
+ puts "glyph size : %db" % glyph.raw.length
16
+ puts "glyph bbox : (%d,%d)-(%d,%d)" % [glyph.x_min, glyph.y_min, glyph.x_max, glyph.y_max]
17
+
18
+ if glyph.compound?
19
+ puts "components : %d %s" % [glyph.glyph_ids.length, glyph.glyph_ids.inspect]
20
+ end
21
+ end
22
+
23
+ file = TTFunk::File.open(ARGV.first || "data/fonts/DejaVuSans.ttf")
24
+
25
+ puts "-- FONT ------------------------------------"
26
+
27
+ puts "revision : %08x" % file.header.font_revision
28
+ puts "name : #{file.name.font_name.join(', ')}"
29
+ puts "family : #{file.name.font_family.join(', ')}"
30
+ puts "subfamily : #{file.name.font_subfamily.join(', ')}"
31
+ puts "postscript: #{file.name.postscript_name}"
32
+
33
+ puts "-- FONT METRICS ----------------------------"
34
+
35
+ puts "units/em : #{file.header.units_per_em}"
36
+ puts "ascent : #{file.ascent}"
37
+ puts "descent : #{file.descent}"
38
+ puts "line gap : #{file.line_gap}"
39
+ puts "bbox : (%d,%d)-(%d,%d)" % file.bbox
40
+
41
+ puts "-- SIMPLE CHARACTER -> GLYPH LOOKUP --------"
42
+ character_lookup(file, "\xE2\x98\x9C")
43
+
44
+ puts "-- COMPOUND CHARACTER -> GLYPH LOOKUP ------"
45
+ character_lookup(file, "ë")
@@ -0,0 +1,17 @@
1
+ module TTFunk
2
+ class Directory
3
+ attr_reader :tables
4
+ attr_reader :scaler_type
5
+
6
+ def initialize(io)
7
+ @scaler_type, table_count, search_range,
8
+ entry_selector, range_shift = io.read(12).unpack("Nn*")
9
+
10
+ @tables = {}
11
+ table_count.times do
12
+ tag, checksum, offset, length = io.read(16).unpack("a4N*")
13
+ @tables[tag] = { :tag => tag, :checksum => checksum, :offset => offset, :length => length }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,88 @@
1
+ module TTFunk
2
+ module Encoding
3
+ class MacRoman
4
+ TO_UNICODE = Hash[*(0..255).zip(0..255).flatten]
5
+ TO_UNICODE.update(
6
+ 0x81 => 0x00C5, 0x82 => 0x00C7, 0x83 => 0x00C9, 0x84 => 0x00D1, 0x85 => 0x00D6,
7
+ 0x86 => 0x00DC, 0x87 => 0x00E1, 0x88 => 0x00E0, 0x89 => 0x00E2, 0x8A => 0x00E4,
8
+ 0x8B => 0x00E3, 0x8C => 0x00E5, 0x8D => 0x00E7, 0x8E => 0x00E9, 0x8F => 0x00E8,
9
+ 0x90 => 0x00EA, 0x91 => 0x00EB, 0x92 => 0x00ED, 0x93 => 0x00EC, 0x94 => 0x00EE,
10
+ 0x95 => 0x00EF, 0x96 => 0x00F1, 0x97 => 0x00F3, 0x98 => 0x00F2, 0x99 => 0x00F4,
11
+ 0x9A => 0x00F6, 0x9B => 0x00F5, 0x9C => 0x00FA, 0x9D => 0x00F9, 0x9E => 0x00FB,
12
+ 0x9F => 0x00FC, 0xA0 => 0x2020, 0xA1 => 0x00B0, 0xA4 => 0x00A7, 0xA5 => 0x2022,
13
+ 0xA6 => 0x00B6, 0xA7 => 0x00DF, 0xA8 => 0x00AE, 0xAA => 0x2122, 0xAB => 0x00B4,
14
+ 0xAC => 0x00A8, 0xAD => 0x2260, 0xAE => 0x00C6, 0xAF => 0x00D8, 0xB0 => 0x221E,
15
+ 0xB2 => 0x2264, 0xB3 => 0x2265, 0xB4 => 0x00A5, 0xB6 => 0x2202, 0xB7 => 0x2211,
16
+ 0xB8 => 0x220F, 0xB9 => 0x03C0, 0xBA => 0x222B, 0xBB => 0x00AA, 0xBC => 0x00BA,
17
+ 0xBD => 0x03A9, 0xBE => 0x00E6, 0xBF => 0x00F8, 0xC0 => 0x00BF, 0xC1 => 0x00A1,
18
+ 0xC2 => 0x00AC, 0xC3 => 0x221A, 0xC4 => 0x0192, 0xC5 => 0x2248, 0xC6 => 0x2206,
19
+ 0xC7 => 0x00AB, 0xC8 => 0x00BB, 0xC9 => 0x2026, 0xCA => 0x00A0, 0xCB => 0x00C0,
20
+ 0xCC => 0x00C3, 0xCD => 0x00D5, 0xCE => 0x0152, 0xCF => 0x0153, 0xD0 => 0x2013,
21
+ 0xD1 => 0x2014, 0xD2 => 0x201C, 0xD3 => 0x201D, 0xD4 => 0x2018, 0xD5 => 0x2019,
22
+ 0xD6 => 0x00F7, 0xD7 => 0x25CA, 0xD8 => 0x00FF, 0xD9 => 0x0178, 0xDA => 0x2044,
23
+ 0xDB => 0x20AC, 0xDC => 0x2039, 0xDD => 0x203A, 0xDE => 0xFB01, 0xDF => 0xFB02,
24
+ 0xE0 => 0x2021, 0xE1 => 0x00B7, 0xE2 => 0x201A, 0xE3 => 0x201E, 0xE4 => 0x2030,
25
+ 0xE5 => 0x00C2, 0xE6 => 0x00CA, 0xE7 => 0x00C1, 0xE8 => 0x00CB, 0xE9 => 0x00C8,
26
+ 0xEA => 0x00CD, 0xEB => 0x00CE, 0xEC => 0x00CF, 0xED => 0x00CC, 0xEE => 0x00D3,
27
+ 0xEF => 0x00D4, 0xF0 => 0xF8FF, 0xF1 => 0x00D2, 0xF2 => 0x00DA, 0xF3 => 0x00DB,
28
+ 0xF4 => 0x00D9, 0xF5 => 0x0131, 0xF6 => 0x02C6, 0xF7 => 0x02DC, 0xF8 => 0x00AF,
29
+ 0xF9 => 0x02D8, 0xFA => 0x02D9, 0xFB => 0x02DA, 0xFC => 0x00B8, 0xFD => 0x02DD,
30
+ 0xFE => 0x02DB, 0xFF => 0x02C7
31
+ )
32
+
33
+ FROM_UNICODE = {}
34
+ (0..255).each { |key| FROM_UNICODE[TO_UNICODE[key]] = key }
35
+
36
+ # Maps MacRoman codes to their corresponding index in the Postscript glyph
37
+ # table (see TTFunk::Table::Post::Format10). If any entry in this array is a string,
38
+ # it is a postscript glyph that is not in the standard list, and which should be
39
+ # emitted specially in the TTF postscript table ('post', see format 2).
40
+ POSTSCRIPT_GLYPH_MAPPING = [
41
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0x0F
42
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 0x1F
43
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, # 0x2F
44
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, # 0x3F
45
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, # 0x4F
46
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, # 0x5F
47
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, # 0x6F
48
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 0, # 0x7F
49
+ 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, # 0x8F
50
+ 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, # 0x9F
51
+ 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, # 0xAF
52
+ 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, # 0xBF
53
+ 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, # 0xCF
54
+ 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, "Euro", 190, 191, 192, 193, # 0xDF
55
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, # 0xEF
56
+ 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225 # 0xFF
57
+ ]
58
+
59
+ def self.covers?(character)
60
+ !FROM_UNICODE[character].nil?
61
+ end
62
+
63
+ def self.to_utf8(string)
64
+ to_unicode_codepoints(string.unpack("C*")).pack("U*")
65
+ end
66
+
67
+ def self.to_unicode(string)
68
+ to_unicode_codepoints(string.unpack("C*")).pack("n*")
69
+ end
70
+
71
+ def self.from_utf8(string)
72
+ from_unicode_codepoints(string.unpack("U*")).pack("C*")
73
+ end
74
+
75
+ def self.from_unicode(string)
76
+ from_unicode_codepoints(string.unpack("n*")).pack("C*")
77
+ end
78
+
79
+ def self.to_unicode_codepoints(array)
80
+ array.map { |code| TO_UNICODE[code] }
81
+ end
82
+
83
+ def self.from_unicode_codepoints(array)
84
+ array.map { |code| FROM_UNICODE[code] || 0 }
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,69 @@
1
+ module TTFunk
2
+ module Encoding
3
+ class Windows1252
4
+ TO_UNICODE = Hash[*(0..255).zip(0..255).flatten]
5
+ TO_UNICODE.update(
6
+ 0x80 => 0x20AC, 0x82 => 0x201A, 0x83 => 0x0192, 0x84 => 0x201E, 0x85 => 0x2026,
7
+ 0x86 => 0x2020, 0x87 => 0x2021, 0x88 => 0x02C6, 0x89 => 0x2030, 0x8A => 0x0160,
8
+ 0x8B => 0x2039, 0x8C => 0x0152, 0x8E => 0x017D, 0x91 => 0x2018, 0x92 => 0x2019,
9
+ 0x93 => 0x201C, 0x94 => 0x201D, 0x95 => 0x2022, 0x96 => 0x2013, 0x97 => 0x2014,
10
+ 0x98 => 0x02DC, 0x99 => 0x2122, 0x9A => 0x0161, 0x9B => 0x203A, 0x9C => 0x0152,
11
+ 0x9E => 0x017E, 0x9F => 0x0178
12
+ )
13
+
14
+ FROM_UNICODE = {}
15
+ (0..255).each { |key| FROM_UNICODE[TO_UNICODE[key]] = key }
16
+
17
+ # Maps Windows-1252 codes to their corresponding index in the Postscript glyph
18
+ # table (see TTFunk::Table::Post::Format10). If any entry in this array is a string,
19
+ # it is a postscript glyph that is not in the standard list, and which should be
20
+ # emitted specially in the TTF postscript table ('post', see format 2).
21
+ POSTSCRIPT_GLYPH_MAPPING = [
22
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
25
+ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
26
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
27
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
28
+ 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
29
+ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 0,
30
+ "Euro", 0, 196, 166, 197, 171, 130, 194, 216, 198, 228, 190, 176, 0, 230, 0,
31
+ 0, 182, 183, 180, 181, 135, 178, 179, 217, 140, 229, 191, 177, 0, 231, 186,
32
+ 3, 163, 132, 133, 189, 150, 232, 134, 142, 139, 157, 169, 164, 16, 138, 218,
33
+ 131, 147, 242, 243, 141, 151, 136, 195, 222, 241, 158, 170, 245, 244, 246, 162,
34
+ 173, 201, 199, 174, 98, 99, 144, 100, 203, 101, 200, 202, 207, 204, 205, 206,
35
+ 233, 102, 211, 208, 209, 175, 103, 240, 145, 214, 212, 213, 104, 235, 237, 137,
36
+ 106, 105, 107, 109, 108, 110, 160, 111, 113, 112, 114, 115, 117, 116, 118, 119,
37
+ 234, 120, 122, 121, 123, 125, 124, 184, 161, 127, 126, 128, 129, 236, 238, 186
38
+ ]
39
+
40
+ def self.covers?(character)
41
+ !FROM_UNICODE[character].nil?
42
+ end
43
+
44
+ def self.to_utf8(string)
45
+ to_unicode_codepoints(string.unpack("C*")).pack("U*")
46
+ end
47
+
48
+ def self.to_unicode(string)
49
+ to_unicode_codepoints(string.unpack("C*")).pack("n*")
50
+ end
51
+
52
+ def self.from_utf8(string)
53
+ from_unicode_codepoints(string.unpack("U*")).pack("C*")
54
+ end
55
+
56
+ def self.from_unicode(string)
57
+ from_unicode_codepoints(string.unpack("n*")).pack("C*")
58
+ end
59
+
60
+ def self.to_unicode_codepoints(array)
61
+ array.map { |code| TO_UNICODE[code] }
62
+ end
63
+
64
+ def self.from_unicode_codepoints(array)
65
+ array.map { |code| FROM_UNICODE[code] || 0 }
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,44 @@
1
+ module TTFunk
2
+ module Reader
3
+ private
4
+
5
+ def io
6
+ @file.contents
7
+ end
8
+
9
+ def read(bytes, format)
10
+ io.read(bytes).unpack(format)
11
+ end
12
+
13
+ def read_signed(count)
14
+ read(count*2, "n*").map { |i| to_signed(i) }
15
+ end
16
+
17
+ def to_signed(n)
18
+ (n>=0x8000) ? -((n ^ 0xFFFF) + 1) : n
19
+ end
20
+
21
+ def parse_from(position)
22
+ saved, io.pos = io.pos, position
23
+ result = yield position
24
+ io.pos = saved
25
+ return result
26
+ end
27
+
28
+ # For debugging purposes
29
+ def hexdump(string)
30
+ bytes = string.unpack("C*")
31
+ bytes.each_with_index do |c, i|
32
+ print "%02X" % c
33
+ if (i+1) % 16 == 0
34
+ puts
35
+ elsif (i+1) % 8 == 0
36
+ print " "
37
+ else
38
+ print " "
39
+ end
40
+ end
41
+ puts unless bytes.length % 16 == 0
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,78 @@
1
+ module TTFunk
2
+ class ResourceFile
3
+ attr_reader :map
4
+
5
+ def self.open(path)
6
+ ::File.open(path, "rb") do |io|
7
+ file = new(io)
8
+ yield file
9
+ end
10
+ end
11
+
12
+ def initialize(io)
13
+ @io = io
14
+
15
+ data_offset, map_offset, data_length, map_length = @io.read(16).unpack("N*")
16
+
17
+ @map = {}
18
+ @io.pos = map_offset + 24 # skip header copy, next map handle, file reference, and attrs
19
+ type_list_offset, name_list_offset = @io.read(4).unpack("n*")
20
+
21
+ type_list_offset += map_offset
22
+ name_list_offset += map_offset
23
+
24
+ @io.pos = type_list_offset
25
+ max_index = @io.read(2).unpack("n").first
26
+ 0.upto(max_index) do
27
+ type, max_type_index, ref_list_offset = @io.read(8).unpack("A4nn")
28
+ @map[type] = { :list => [], :named => {} }
29
+
30
+ parse_from(type_list_offset + ref_list_offset) do
31
+ 0.upto(max_type_index) do
32
+ id, name_ofs, attr = @io.read(5).unpack("nnC")
33
+ data_ofs = @io.read(3)
34
+ data_ofs = data_offset + [0, data_ofs].pack("CA*").unpack("N").first
35
+ handle = @io.read(4).unpack("N").first
36
+
37
+ entry = { :id => id, :attributes => attr, :offset => data_ofs, :handle => handle }
38
+
39
+ if name_list_offset + name_ofs < map_offset + map_length
40
+ parse_from(name_ofs + name_list_offset) do
41
+ len = @io.read(1).unpack("C").first
42
+ entry[:name] = @io.read(len)
43
+ end
44
+ end
45
+
46
+ @map[type][:list] << entry
47
+ @map[type][:named][entry[:name]] = entry if entry[:name]
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def [](type, index=0)
54
+ if @map[type]
55
+ collection = index.is_a?(Fixnum) ? :list : :named
56
+ if @map[type][collection][index]
57
+ parse_from(@map[type][collection][index][:offset]) do
58
+ length = @io.read(4).unpack("N").first
59
+ return @io.read(length)
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def resources_for(type)
66
+ (@map[type] && @map[type][:named] || {}).keys
67
+ end
68
+
69
+ private
70
+
71
+ def parse_from(offset)
72
+ saved, @io.pos = @io.pos, offset
73
+ yield
74
+ ensure
75
+ @io.pos = saved
76
+ end
77
+ end
78
+ end