prawn 0.11.1 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (353) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +10 -0
  3. data/COPYING +2 -2
  4. data/GPLv2 +340 -0
  5. data/GPLv3 +674 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE +1 -1
  8. data/Rakefile +29 -38
  9. data/data/images/16bit.alpha +0 -0
  10. data/data/images/16bit.color +0 -0
  11. data/data/images/dice.alpha +0 -0
  12. data/data/images/dice.color +0 -0
  13. data/data/images/indexed_color.dat +0 -0
  14. data/data/images/indexed_color.png +0 -0
  15. data/data/images/page_white_text.alpha +0 -0
  16. data/data/images/page_white_text.color +0 -0
  17. data/data/pdfs/nested_pages.pdf +13 -13
  18. data/lib/prawn/document/bounding_box.rb +87 -12
  19. data/lib/prawn/document/column_box.rb +57 -28
  20. data/lib/prawn/document/graphics_state.rb +11 -74
  21. data/lib/prawn/document/internals.rb +25 -23
  22. data/lib/prawn/document/snapshot.rb +11 -8
  23. data/lib/prawn/document/span.rb +12 -10
  24. data/lib/prawn/document.rb +250 -194
  25. data/lib/prawn/encoding.rb +9 -10
  26. data/lib/prawn/errors.rb +18 -29
  27. data/lib/prawn/font/afm.rb +52 -41
  28. data/lib/prawn/font/dfont.rb +4 -3
  29. data/lib/prawn/font/ttf.rb +44 -48
  30. data/lib/prawn/font.rb +138 -88
  31. data/lib/prawn/font_metric_cache.rb +47 -0
  32. data/lib/prawn/graphics/cap_style.rb +4 -3
  33. data/lib/prawn/graphics/color.rb +13 -5
  34. data/lib/prawn/graphics/dash.rb +53 -31
  35. data/lib/prawn/graphics/join_style.rb +9 -7
  36. data/lib/prawn/graphics/patterns.rb +138 -0
  37. data/lib/prawn/graphics/transformation.rb +10 -9
  38. data/lib/prawn/graphics/transparency.rb +3 -1
  39. data/lib/prawn/graphics.rb +316 -61
  40. data/lib/prawn/image_handler.rb +36 -0
  41. data/lib/prawn/images/image.rb +49 -0
  42. data/lib/prawn/images/jpg.rb +21 -15
  43. data/lib/prawn/images/png.rb +62 -119
  44. data/lib/prawn/images.rb +89 -108
  45. data/lib/prawn/layout/grid.rb +66 -54
  46. data/lib/prawn/layout.rb +10 -15
  47. data/lib/prawn/measurement_extensions.rb +10 -6
  48. data/lib/prawn/measurements.rb +27 -21
  49. data/lib/prawn/outline.rb +6 -308
  50. data/lib/prawn/repeater.rb +11 -9
  51. data/lib/prawn/security/arcfour.rb +1 -0
  52. data/lib/prawn/security.rb +55 -33
  53. data/lib/prawn/soft_mask.rb +96 -0
  54. data/lib/prawn/stamp.rb +5 -3
  55. data/lib/prawn/table/cell/image.rb +69 -0
  56. data/lib/prawn/table/cell/in_table.rb +4 -2
  57. data/lib/prawn/table/cell/span_dummy.rb +93 -0
  58. data/lib/prawn/table/cell/subtable.rb +2 -2
  59. data/lib/prawn/table/cell/text.rb +44 -26
  60. data/lib/prawn/table/cell.rb +302 -50
  61. data/lib/prawn/table/cells.rb +147 -49
  62. data/lib/prawn/table/column_width_calculator.rb +61 -0
  63. data/lib/prawn/table.rb +297 -118
  64. data/lib/prawn/text/box.rb +21 -5
  65. data/lib/prawn/text/formatted/arranger.rb +290 -0
  66. data/lib/prawn/text/formatted/box.rb +103 -59
  67. data/lib/prawn/text/formatted/fragment.rb +34 -23
  68. data/lib/prawn/text/formatted/line_wrap.rb +266 -0
  69. data/lib/prawn/text/formatted/parser.rb +15 -5
  70. data/lib/prawn/text/formatted/wrap.rb +150 -0
  71. data/lib/prawn/text/formatted.rb +5 -4
  72. data/lib/prawn/text.rb +38 -24
  73. data/lib/prawn/utilities.rb +46 -0
  74. data/lib/prawn.rb +85 -20
  75. data/manual/basic_concepts/adding_pages.rb +27 -0
  76. data/manual/basic_concepts/basic_concepts.rb +34 -0
  77. data/manual/basic_concepts/creation.rb +39 -0
  78. data/manual/basic_concepts/cursor.rb +33 -0
  79. data/manual/basic_concepts/measurement.rb +25 -0
  80. data/manual/basic_concepts/origin.rb +38 -0
  81. data/manual/basic_concepts/other_cursor_helpers.rb +40 -0
  82. data/manual/bounding_box/bounding_box.rb +39 -0
  83. data/manual/bounding_box/bounds.rb +49 -0
  84. data/manual/bounding_box/canvas.rb +24 -0
  85. data/manual/bounding_box/creation.rb +23 -0
  86. data/manual/bounding_box/indentation.rb +46 -0
  87. data/manual/bounding_box/nesting.rb +45 -0
  88. data/manual/bounding_box/russian_boxes.rb +40 -0
  89. data/manual/bounding_box/stretchy.rb +31 -0
  90. data/manual/document_and_page_options/background.rb +27 -0
  91. data/manual/document_and_page_options/document_and_page_options.rb +32 -0
  92. data/manual/document_and_page_options/metadata.rb +23 -0
  93. data/manual/document_and_page_options/page_margins.rb +38 -0
  94. data/manual/document_and_page_options/page_size.rb +34 -0
  95. data/manual/document_and_page_options/print_scaling.rb +20 -0
  96. data/manual/example_file.rb +111 -0
  97. data/manual/example_helper.rb +411 -0
  98. data/manual/example_package.rb +53 -0
  99. data/manual/example_section.rb +46 -0
  100. data/manual/graphics/circle_and_ellipse.rb +22 -0
  101. data/manual/graphics/color.rb +24 -0
  102. data/manual/graphics/common_lines.rb +30 -0
  103. data/manual/graphics/fill_and_stroke.rb +42 -0
  104. data/manual/graphics/fill_rules.rb +37 -0
  105. data/manual/graphics/gradients.rb +37 -0
  106. data/manual/graphics/graphics.rb +58 -0
  107. data/manual/graphics/helper.rb +24 -0
  108. data/manual/graphics/line_width.rb +35 -0
  109. data/manual/graphics/lines_and_curves.rb +41 -0
  110. data/manual/graphics/polygon.rb +29 -0
  111. data/manual/graphics/rectangle.rb +21 -0
  112. data/manual/graphics/rotate.rb +28 -0
  113. data/manual/graphics/scale.rb +41 -0
  114. data/manual/graphics/soft_masks.rb +46 -0
  115. data/manual/graphics/stroke_cap.rb +31 -0
  116. data/manual/graphics/stroke_dash.rb +48 -0
  117. data/manual/graphics/stroke_join.rb +30 -0
  118. data/manual/graphics/translate.rb +29 -0
  119. data/manual/graphics/transparency.rb +35 -0
  120. data/manual/images/absolute_position.rb +23 -0
  121. data/manual/images/fit.rb +21 -0
  122. data/manual/images/horizontal.rb +25 -0
  123. data/manual/images/images.rb +40 -0
  124. data/manual/images/plain_image.rb +18 -0
  125. data/manual/images/scale.rb +22 -0
  126. data/manual/images/vertical.rb +28 -0
  127. data/manual/images/width_and_height.rb +25 -0
  128. data/manual/layout/boxes.rb +27 -0
  129. data/manual/layout/content.rb +25 -0
  130. data/manual/layout/layout.rb +28 -0
  131. data/manual/layout/simple_grid.rb +23 -0
  132. data/manual/manual/cover.rb +36 -0
  133. data/manual/manual/foreword.rb +85 -0
  134. data/manual/manual/how_to_read_this_manual.rb +41 -0
  135. data/manual/manual/manual.rb +34 -0
  136. data/manual/outline/add_subsection_to.rb +61 -0
  137. data/manual/outline/insert_section_after.rb +47 -0
  138. data/manual/outline/outline.rb +32 -0
  139. data/manual/outline/sections_and_pages.rb +67 -0
  140. data/manual/repeatable_content/page_numbering.rb +54 -0
  141. data/manual/repeatable_content/repeatable_content.rb +31 -0
  142. data/manual/repeatable_content/repeater.rb +55 -0
  143. data/manual/repeatable_content/stamp.rb +41 -0
  144. data/manual/security/encryption.rb +31 -0
  145. data/manual/security/permissions.rb +38 -0
  146. data/manual/security/security.rb +28 -0
  147. data/manual/syntax_highlight.rb +52 -0
  148. data/manual/table/basic_block.rb +53 -0
  149. data/manual/table/before_rendering_page.rb +26 -0
  150. data/manual/table/cell_border_lines.rb +24 -0
  151. data/manual/table/cell_borders_and_bg.rb +31 -0
  152. data/manual/table/cell_dimensions.rb +30 -0
  153. data/manual/table/cell_text.rb +38 -0
  154. data/manual/table/column_widths.rb +30 -0
  155. data/manual/table/content_and_subtables.rb +39 -0
  156. data/manual/table/creation.rb +27 -0
  157. data/manual/table/filtering.rb +36 -0
  158. data/manual/table/flow_and_header.rb +17 -0
  159. data/manual/table/image_cells.rb +33 -0
  160. data/manual/table/position.rb +29 -0
  161. data/manual/table/row_colors.rb +20 -0
  162. data/manual/table/span.rb +30 -0
  163. data/manual/table/style.rb +22 -0
  164. data/manual/table/table.rb +52 -0
  165. data/manual/table/width.rb +27 -0
  166. data/manual/text/alignment.rb +44 -0
  167. data/manual/text/color.rb +24 -0
  168. data/manual/text/column_box.rb +32 -0
  169. data/manual/text/fallback_fonts.rb +37 -0
  170. data/manual/text/font.rb +41 -0
  171. data/manual/text/font_size.rb +45 -0
  172. data/manual/text/font_style.rb +23 -0
  173. data/manual/text/formatted_callbacks.rb +60 -0
  174. data/manual/text/formatted_text.rb +54 -0
  175. data/manual/text/free_flowing_text.rb +51 -0
  176. data/manual/text/group.rb +31 -0
  177. data/manual/text/inline.rb +43 -0
  178. data/manual/text/kerning_and_character_spacing.rb +39 -0
  179. data/manual/text/leading.rb +25 -0
  180. data/manual/text/line_wrapping.rb +41 -0
  181. data/manual/text/paragraph_indentation.rb +26 -0
  182. data/manual/text/positioned_text.rb +38 -0
  183. data/manual/text/registering_families.rb +48 -0
  184. data/manual/text/rendering_and_color.rb +37 -0
  185. data/manual/text/right_to_left_text.rb +43 -0
  186. data/manual/text/rotation.rb +43 -0
  187. data/manual/text/single_usage.rb +37 -0
  188. data/manual/text/text.rb +75 -0
  189. data/manual/text/text_box_excess.rb +32 -0
  190. data/manual/text/text_box_extensions.rb +45 -0
  191. data/manual/text/text_box_overflow.rb +44 -0
  192. data/manual/text/utf8.rb +28 -0
  193. data/{examples/m17n → manual/text}/win_ansi_charset.rb +14 -10
  194. data/prawn.gemspec +27 -17
  195. data/spec/acceptance/png.rb +23 -0
  196. data/spec/annotations_spec.rb +16 -32
  197. data/spec/bounding_box_spec.rb +284 -2
  198. data/spec/cell_spec.rb +169 -38
  199. data/spec/column_box_spec.rb +65 -0
  200. data/spec/data/curves.pdf +66 -0
  201. data/spec/destinations_spec.rb +5 -5
  202. data/spec/document_spec.rb +212 -113
  203. data/spec/extensions/encoding_helpers.rb +9 -0
  204. data/spec/extensions/mocha.rb +2 -3
  205. data/spec/font_metric_cache_spec.rb +52 -0
  206. data/spec/font_spec.rb +205 -95
  207. data/spec/formatted_text_arranger_spec.rb +43 -43
  208. data/spec/formatted_text_box_spec.rb +63 -24
  209. data/spec/formatted_text_fragment_spec.rb +8 -8
  210. data/spec/graphics_spec.rb +175 -68
  211. data/spec/grid_spec.rb +26 -15
  212. data/spec/image_handler_spec.rb +54 -0
  213. data/spec/images_spec.rb +58 -30
  214. data/spec/inline_formatted_text_parser_spec.rb +73 -19
  215. data/spec/jpg_spec.rb +4 -4
  216. data/spec/line_wrap_spec.rb +28 -28
  217. data/spec/measurement_units_spec.rb +6 -6
  218. data/spec/object_store_spec.rb +17 -106
  219. data/spec/outline_spec.rb +103 -63
  220. data/spec/png_spec.rb +25 -25
  221. data/spec/reference_spec.rb +8 -65
  222. data/spec/repeater_spec.rb +25 -11
  223. data/spec/security_spec.rb +44 -12
  224. data/spec/snapshot_spec.rb +38 -6
  225. data/spec/soft_mask_spec.rb +117 -0
  226. data/spec/span_spec.rb +10 -15
  227. data/spec/spec_helper.rb +32 -8
  228. data/spec/stamp_spec.rb +29 -30
  229. data/spec/stroke_styles_spec.rb +36 -18
  230. data/spec/table/span_dummy_spec.rb +17 -0
  231. data/spec/table_spec.rb +850 -104
  232. data/spec/text_at_spec.rb +19 -33
  233. data/spec/text_box_spec.rb +117 -64
  234. data/spec/text_rendering_mode_spec.rb +5 -5
  235. data/spec/text_spacing_spec.rb +20 -2
  236. data/spec/text_spec.rb +111 -59
  237. data/spec/transparency_spec.rb +5 -5
  238. metadata +477 -328
  239. data/HACKING +0 -50
  240. data/README +0 -141
  241. data/data/fonts/Action Man.dfont +0 -0
  242. data/data/fonts/Activa.ttf +0 -0
  243. data/data/fonts/Chalkboard.ttf +0 -0
  244. data/data/fonts/DejaVuSans.ttf +0 -0
  245. data/data/fonts/Dustismo_Roman.ttf +0 -0
  246. data/data/fonts/comicsans.ttf +0 -0
  247. data/data/fonts/gkai00mp.ttf +0 -0
  248. data/data/images/16bit.dat +0 -0
  249. data/data/images/dice.dat +0 -0
  250. data/data/images/page_white_text.dat +0 -0
  251. data/data/images/rails.dat +0 -0
  252. data/data/images/rails.png +0 -0
  253. data/examples/bounding_box/bounding_boxes.rb +0 -44
  254. data/examples/bounding_box/indentation.rb +0 -35
  255. data/examples/bounding_box/russian_boxes.rb +0 -37
  256. data/examples/bounding_box/stretched_nesting.rb +0 -68
  257. data/examples/example_helper.rb +0 -8
  258. data/examples/general/background.rb +0 -24
  259. data/examples/general/canvas.rb +0 -16
  260. data/examples/general/context_sensitive_headers.rb +0 -38
  261. data/examples/general/float.rb +0 -12
  262. data/examples/general/margin.rb +0 -37
  263. data/examples/general/measurement_units.rb +0 -52
  264. data/examples/general/metadata-info.rb +0 -17
  265. data/examples/general/multi_page_layout.rb +0 -19
  266. data/examples/general/outlines.rb +0 -67
  267. data/examples/general/page_geometry.rb +0 -32
  268. data/examples/general/page_numbering.rb +0 -40
  269. data/examples/general/page_templates.rb +0 -20
  270. data/examples/general/repeaters.rb +0 -48
  271. data/examples/general/stamp.rb +0 -42
  272. data/examples/general/templates.rb +0 -14
  273. data/examples/graphics/basic_images.rb +0 -24
  274. data/examples/graphics/cmyk.rb +0 -13
  275. data/examples/graphics/curves.rb +0 -12
  276. data/examples/graphics/gradient.rb +0 -23
  277. data/examples/graphics/hexagon.rb +0 -14
  278. data/examples/graphics/image_fit.rb +0 -16
  279. data/examples/graphics/image_flow.rb +0 -38
  280. data/examples/graphics/image_position.rb +0 -18
  281. data/examples/graphics/line.rb +0 -33
  282. data/examples/graphics/png_types.rb +0 -23
  283. data/examples/graphics/polygons.rb +0 -17
  284. data/examples/graphics/remote_images.rb +0 -13
  285. data/examples/graphics/rounded_polygons.rb +0 -20
  286. data/examples/graphics/rounded_rectangle.rb +0 -21
  287. data/examples/graphics/ruport_style_helpers.rb +0 -20
  288. data/examples/graphics/stroke_bounds.rb +0 -21
  289. data/examples/graphics/stroke_cap_and_join.rb +0 -46
  290. data/examples/graphics/stroke_dash.rb +0 -43
  291. data/examples/graphics/transformations.rb +0 -53
  292. data/examples/graphics/transparency.rb +0 -27
  293. data/examples/grid/bounding_boxes.rb +0 -22
  294. data/examples/grid/column_gutter_grid.rb +0 -21
  295. data/examples/grid/multi_boxes.rb +0 -52
  296. data/examples/grid/show_grid.rb +0 -14
  297. data/examples/grid/simple_grid.rb +0 -21
  298. data/examples/m17n/chinese_text_wrapping.rb +0 -18
  299. data/examples/m17n/euro.rb +0 -16
  300. data/examples/m17n/full_win_ansi_character_list.rb +0 -20
  301. data/examples/m17n/sjis.rb +0 -29
  302. data/examples/m17n/utf8.rb +0 -14
  303. data/examples/security/hello_foo.rb +0 -9
  304. data/examples/table/bill.rb +0 -54
  305. data/examples/table/borders.rb +0 -25
  306. data/examples/table/cell.rb +0 -13
  307. data/examples/table/checkerboard.rb +0 -23
  308. data/examples/table/header.rb +0 -15
  309. data/examples/table/inline_format_table.rb +0 -13
  310. data/examples/table/multi_page_table.rb +0 -10
  311. data/examples/table/simple_table.rb +0 -25
  312. data/examples/table/subtable.rb +0 -13
  313. data/examples/table/widths.rb +0 -21
  314. data/examples/text/alignment.rb +0 -19
  315. data/examples/text/character_spacing.rb +0 -13
  316. data/examples/text/dfont.rb +0 -49
  317. data/examples/text/family_based_styling.rb +0 -25
  318. data/examples/text/font_calculations.rb +0 -92
  319. data/examples/text/font_size.rb +0 -34
  320. data/examples/text/hyphenation.rb +0 -45
  321. data/examples/text/indent_paragraphs.rb +0 -24
  322. data/examples/text/inline_format.rb +0 -104
  323. data/examples/text/kerning.rb +0 -31
  324. data/examples/text/rendering_mode.rb +0 -21
  325. data/examples/text/rotated.rb +0 -99
  326. data/examples/text/shaped_text_box.rb +0 -32
  327. data/examples/text/simple_text.rb +0 -18
  328. data/examples/text/simple_text_ttf.rb +0 -18
  329. data/examples/text/span.rb +0 -30
  330. data/examples/text/text_box.rb +0 -90
  331. data/examples/text/text_box_returning_excess.rb +0 -52
  332. data/examples/text/text_flow.rb +0 -68
  333. data/lib/prawn/compatibility.rb +0 -51
  334. data/lib/prawn/core/annotations.rb +0 -61
  335. data/lib/prawn/core/byte_string.rb +0 -9
  336. data/lib/prawn/core/destinations.rb +0 -90
  337. data/lib/prawn/core/document_state.rb +0 -78
  338. data/lib/prawn/core/literal_string.rb +0 -16
  339. data/lib/prawn/core/name_tree.rb +0 -165
  340. data/lib/prawn/core/object_store.rb +0 -264
  341. data/lib/prawn/core/page.rb +0 -213
  342. data/lib/prawn/core/pdf_object.rb +0 -108
  343. data/lib/prawn/core/reference.rb +0 -112
  344. data/lib/prawn/core/text/formatted/arranger.rb +0 -293
  345. data/lib/prawn/core/text/formatted/line_wrap.rb +0 -272
  346. data/lib/prawn/core/text/formatted/wrap.rb +0 -149
  347. data/lib/prawn/core/text.rb +0 -268
  348. data/lib/prawn/core.rb +0 -85
  349. data/lib/prawn/document/page_geometry.rb +0 -136
  350. data/lib/prawn/graphics/gradient.rb +0 -84
  351. data/spec/name_tree_spec.rb +0 -112
  352. data/spec/pdf_object_spec.rb +0 -170
  353. data/spec/template_spec.rb +0 -291
data/lib/prawn/errors.rb CHANGED
@@ -8,25 +8,18 @@
8
8
  #
9
9
  module Prawn
10
10
  module Errors
11
-
12
- # This error is raised when Prawn::PdfObject() encounters a Ruby object it
13
- # cannot convert to PDF
11
+ # Raised when a table is spanned in an impossible way.
14
12
  #
15
- FailedObjectConversion = Class.new(StandardError)
16
-
17
- # This error is raised when Document#page_layout is set to anything
18
- # other than :portrait or :landscape
19
- #
20
- InvalidPageLayout = Class.new(StandardError)
21
-
22
- # This error is raised when a method requiring a current page is called
13
+ InvalidTableSpan = Class.new(StandardError)
14
+
15
+ # This error is raised when a method requiring a current page is called
23
16
  # without being on a page.
24
17
  #
25
18
  NotOnPage = Class.new(StandardError)
26
-
27
- # This error is raised when Prawn cannot find a specified font
19
+
20
+ # This error is raised when Prawn cannot find a specified font
28
21
  #
29
- UnknownFont = Class.new(StandardError)
22
+ UnknownFont = Class.new(StandardError)
30
23
 
31
24
  # Raised when Prawn is asked to draw something into a too-small box
32
25
  #
@@ -35,18 +28,18 @@ module Prawn
35
28
  # Raised if group() is called with a block that is too big to be
36
29
  # rendered in the current context.
37
30
  #
38
- CannotGroup = Class.new(StandardError)
31
+ CannotGroup = Class.new(StandardError)
39
32
 
40
33
  # This error is raised when Prawn is being used on a M17N aware VM,
41
34
  # and the user attempts to add text that isn't compatible with UTF-8
42
35
  # to their document
43
36
  #
44
37
  IncompatibleStringEncoding = Class.new(StandardError)
45
-
38
+
46
39
  # This error is raised when Prawn encounters an unknown key in functions
47
40
  # that accept an options hash. This usually means there is a typo in your
48
41
  # code or that the option you are trying to use has a different name than
49
- # what you have specified.
42
+ # what you have specified.
50
43
  #
51
44
  UnknownOption = Class.new(StandardError)
52
45
 
@@ -66,26 +59,22 @@ module Prawn
66
59
  # This error is raised when an object is attempted to be
67
60
  # referenced by name, but no such name is associated with an object
68
61
  UndefinedObjectName = Class.new(StandardError)
69
-
62
+
70
63
  # This error is raised when a required option has not been set
71
64
  RequiredOption = Class.new(StandardError)
72
-
65
+
73
66
  # This error is raised when a requested outline item with a given title does not exist
74
67
  UnknownOutlineTitle = Class.new(StandardError)
75
68
 
76
69
  # This error is raised when a block is required, but not provided
77
70
  BlockRequired = Class.new(StandardError)
78
-
71
+
79
72
  # This error is rased when a graphics method is called with improper arguments
80
73
  InvalidGraphicsPath = Class.new(StandardError)
81
-
82
- # This error is raised when Prawn fails to load a template file
83
- #
84
- TemplateError = Class.new(StandardError)
85
-
86
- # This error is raise when trying to restore a graphic state that
74
+
75
+ # Raised when unrecognized content is provided for a table cell.
87
76
  #
88
- EmptyGraphicStateStack = Class.new(StandardError)
89
-
77
+ UnrecognizedTableContent = Class.new(StandardError)
78
+
90
79
  end
91
- end
80
+ end
@@ -6,10 +6,13 @@
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
- require 'prawn/encoding'
9
+ require_relative '../../prawn/encoding'
10
10
 
11
11
  module Prawn
12
12
  class Font
13
+
14
+ # @private
15
+
13
16
  class AFM < Font
14
17
  BUILT_INS = %w[ Courier Helvetica Times-Roman Symbol ZapfDingbats
15
18
  Courier-Bold Courier-Oblique Courier-BoldOblique
@@ -27,8 +30,8 @@ module Prawn
27
30
  @metrics_path ||= [
28
31
  ".", "/usr/lib/afm",
29
32
  "/usr/local/lib/afm",
30
- "/usr/openwin/lib/fonts/afm/",
31
- Prawn::BASEDIR+'/data/fonts/']
33
+ "/usr/openwin/lib/fonts/afm",
34
+ Prawn::DATADIR+'/fonts']
32
35
  end
33
36
  end
34
37
 
@@ -41,16 +44,20 @@ module Prawn
41
44
 
42
45
  super
43
46
 
44
- @attributes = {}
45
- @glyph_widths = {}
46
- @bounding_boxes = {}
47
- @kern_pairs = {}
47
+ @@winansi ||= Prawn::Encoding::WinAnsi.new # parse data/encodings/win_ansi.txt once only
48
+ @@font_data ||= SynchronizedCache.new # parse each ATM font file once only
48
49
 
49
50
  file_name = @name.dup
50
51
  file_name << ".afm" unless file_name =~ /\.afm$/
51
52
  file_name = file_name[0] == ?/ ? file_name : find_font(file_name)
52
53
 
53
- parse_afm(file_name)
54
+ font_data = @@font_data[file_name] ||= parse_afm(file_name)
55
+ @glyph_widths = font_data[:glyph_widths]
56
+ @glyph_table = font_data[:glyph_table]
57
+ @bounding_boxes = font_data[:bounding_boxes]
58
+ @kern_pairs = font_data[:kern_pairs]
59
+ @kern_pair_table = font_data[:kern_pair_table]
60
+ @attributes = font_data[:attributes]
54
61
 
55
62
  @ascender = @attributes["ascender"].to_i
56
63
  @descender = @attributes["descender"].to_i
@@ -87,13 +94,19 @@ module Prawn
87
94
  # is replaced with a string in WinAnsi encoding.
88
95
  #
89
96
  def normalize_encoding(text)
90
- enc = Prawn::Encoding::WinAnsi.new
97
+ enc = @@winansi
91
98
  text.unpack("U*").collect { |i| enc[i] }.pack("C*")
92
99
  rescue ArgumentError
93
100
  raise Prawn::Errors::IncompatibleStringEncoding,
94
101
  "Arguments to text methods must be UTF-8 encoded"
95
102
  end
96
103
 
104
+ # Returns the number of characters in +str+ (a WinAnsi-encoded string).
105
+ #
106
+ def character_count(str)
107
+ str.length
108
+ end
109
+
97
110
  # Perform any changes to the string that need to happen
98
111
  # before it is rendered to the canvas. Returns an array of
99
112
  # subset "chunks", where each chunk is an array of two elements.
@@ -144,6 +157,7 @@ module Prawn
144
157
  end
145
158
 
146
159
  def parse_afm(file_name)
160
+ data = {:glyph_widths => {}, :bounding_boxes => {}, :kern_pairs => {}, :attributes => {}}
147
161
  section = []
148
162
 
149
163
  File.foreach(file_name) do |line|
@@ -160,27 +174,41 @@ module Prawn
160
174
  when ["FontMetrics", "CharMetrics"]
161
175
  next unless line =~ /^CH?\s/
162
176
 
163
- name = line[/\bN\s+(\.?\w+)\s*;/, 1]
164
- @glyph_widths[name] = line[/\bWX\s+(\d+)\s*;/, 1].to_i
165
- @bounding_boxes[name] = line[/\bB\s+([^;]+);/, 1].to_s.rstrip
177
+ name = line[/\bN\s+(\.?\w+)\s*;/, 1]
178
+ data[:glyph_widths][name] = line[/\bWX\s+(\d+)\s*;/, 1].to_i
179
+ data[:bounding_boxes][name] = line[/\bB\s+([^;]+);/, 1].to_s.rstrip
166
180
  when ["FontMetrics", "KernData", "KernPairs"]
167
181
  next unless line =~ /^KPX\s+(\.?\w+)\s+(\.?\w+)\s+(-?\d+)/
168
- @kern_pairs[[$1, $2]] = $3.to_i
182
+ data[:kern_pairs][[$1, $2]] = $3.to_i
169
183
  when ["FontMetrics", "KernData", "TrackKern"],
170
184
  ["FontMetrics", "Composites"]
171
185
  next
172
186
  else
173
- parse_generic_afm_attribute(line)
187
+ parse_generic_afm_attribute(line, data)
174
188
  end
175
189
  end
190
+
191
+ # process data parsed from AFM file to build tables which
192
+ # will be used when measuring and kerning text
193
+ data[:glyph_table] = (0..255).map do |i|
194
+ data[:glyph_widths][Encoding::WinAnsi::CHARACTERS[i]].to_i
195
+ end
196
+
197
+ character_hash = Hash[Encoding::WinAnsi::CHARACTERS.zip((0..Encoding::WinAnsi::CHARACTERS.size).to_a)]
198
+ data[:kern_pair_table] = data[:kern_pairs].inject({}) do |h,p|
199
+ h[p[0].map { |n| character_hash[n] }] = p[1]
200
+ h
201
+ end
202
+
203
+ data.each_value { |hash| hash.freeze }
204
+ data.freeze
176
205
  end
177
206
 
178
- def parse_generic_afm_attribute(line)
207
+ def parse_generic_afm_attribute(line, hash)
179
208
  line =~ /(^\w+)\s+(.*)/
180
209
  key, value = $1.to_s.downcase, $2
181
210
 
182
- @attributes[key] = @attributes[key] ?
183
- Array(@attributes[key]) << value : value
211
+ hash[:attributes][key] = hash[:attributes][key] ? Array(hash[:attributes][key]) << value : value
184
212
  end
185
213
 
186
214
  # converts a string into an array with spacing offsets
@@ -192,43 +220,26 @@ module Prawn
192
220
  kerned = [[]]
193
221
  last_byte = nil
194
222
 
195
- kern_pairs = latin_kern_pairs_table
196
-
197
- string.unpack("C*").each do |byte|
198
- if k = last_byte && kern_pairs[[last_byte, byte]]
223
+ string.each_byte do |byte|
224
+ if k = last_byte && @kern_pair_table[[last_byte, byte]]
199
225
  kerned << -k << [byte]
200
226
  else
201
227
  kerned.last << byte
202
- end
228
+ end
203
229
  last_byte = byte
204
230
  end
205
231
 
206
- kerned.map { |e|
232
+ kerned.map { |e|
207
233
  e = (Array === e ? e.pack("C*") : e)
208
- e.respond_to?(:force_encoding) ? e.force_encoding("Windows-1252") : e
234
+ e.respond_to?(:force_encoding) ? e.force_encoding(::Encoding::Windows_1252) : e
209
235
  }
210
236
  end
211
-
212
- def latin_kern_pairs_table
213
- @kern_pairs_table ||= @kern_pairs.inject({}) do |h,p|
214
- h[p[0].map { |n| Encoding::WinAnsi::CHARACTERS.index(n) }] = p[1]
215
- h
216
- end
217
- end
218
-
219
- def latin_glyphs_table
220
- @glyphs_table ||= (0..255).map do |i|
221
- @glyph_widths[Encoding::WinAnsi::CHARACTERS[i]].to_i
222
- end
223
- end
224
237
 
225
238
  private
226
239
 
227
240
  def unscaled_width_of(string)
228
- glyph_table = latin_glyphs_table
229
-
230
- string.unpack("C*").inject(0) do |s,r|
231
- s + glyph_table[r]
241
+ string.bytes.inject(0) do |s,r|
242
+ s + @glyph_table[r]
232
243
  end
233
244
  end
234
245
  end
@@ -6,12 +6,13 @@
6
6
  #
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
  #
9
- require 'prawn/font/ttf'
9
+ require_relative 'ttf'
10
10
 
11
11
  module Prawn
12
12
  class Font
13
+ # @private
13
14
  class DFont < TTF
14
-
15
+
15
16
  # Returns a list of the names of all named fonts in the given dfont file.
16
17
  # Note that fonts are not required to be named in a dfont file, so the
17
18
  # list may be empty even if the file does contain fonts. Also, note that
@@ -32,7 +33,7 @@ module Prawn
32
33
  end
33
34
  end
34
35
 
35
- private
36
+ private
36
37
 
37
38
  def read_ttf_file
38
39
  TTFunk::File.from_dfont(@name, @options[:font] || 0)
@@ -2,7 +2,7 @@
2
2
 
3
3
  # prawn/font/ttf.rb : Implements AFM font support for Prawn
4
4
  #
5
- # Copyright May 2008, Gregory Brown / James Healy / Jamis Buck
5
+ # Copyright May 2008, Gregory Brown / James Healy / Jamis Buck
6
6
  # All Rights Reserved.
7
7
  #
8
8
  # This is free software. Please see the LICENSE and COPYING files for details.
@@ -12,13 +12,15 @@ require 'ttfunk/subset_collection'
12
12
 
13
13
  module Prawn
14
14
  class Font
15
+
16
+ # @private
15
17
  class TTF < Font
16
18
  attr_reader :ttf, :subsets
17
19
 
18
20
  def unicode?
19
21
  true
20
22
  end
21
-
23
+
22
24
  def initialize(document, name, options={})
23
25
  super
24
26
 
@@ -26,8 +28,8 @@ module Prawn
26
28
  @subsets = TTFunk::SubsetCollection.new(@ttf)
27
29
 
28
30
  @attributes = {}
29
- @bounding_boxes = {}
30
- @char_widths = {}
31
+ @bounding_boxes = {}
32
+ @char_widths = {}
31
33
  @has_kerning_data = @ttf.kerning.exists? && @ttf.kerning.tables.any?
32
34
 
33
35
  @ascender = Integer(@ttf.ascent * scale_factor)
@@ -42,26 +44,26 @@ module Prawn
42
44
  kern(string).inject(0) do |s,r|
43
45
  if r.is_a?(Numeric)
44
46
  s - r
45
- else
47
+ else
46
48
  r.inject(s) { |s2, u| s2 + character_width_by_code(u) }
47
49
  end
48
50
  end * scale
49
51
  else
50
- string.unpack("U*").inject(0) do |s,r|
52
+ string.codepoints.inject(0) do |s,r|
51
53
  s + character_width_by_code(r)
52
54
  end * scale
53
55
  end
54
- end
55
-
56
+ end
57
+
56
58
  # The font bbox, as an array of integers
57
- #
59
+ #
58
60
  def bbox
59
61
  @bbox ||= @ttf.bbox.map { |i| Integer(i * scale_factor) }
60
62
  end
61
63
 
62
64
  # Returns true if the font has kerning data, false otherwise
63
65
  def has_kerning_data?
64
- @has_kerning_data
66
+ @has_kerning_data
65
67
  end
66
68
 
67
69
  # Perform any changes to the string that need to happen
@@ -77,7 +79,7 @@ module Prawn
77
79
 
78
80
  if options[:kerning]
79
81
  last_subset = nil
80
- kern(text).inject([]) do |result, element|
82
+ kern(text).inject([]) do |result, element|
81
83
  if element.is_a?(Numeric)
82
84
  result.last[1] = [result.last[1]] unless result.last[1].is_a?(Array)
83
85
  result.last[1] << element
@@ -102,7 +104,7 @@ module Prawn
102
104
  @subsets.encode(text.unpack("U*"))
103
105
  end
104
106
  end
105
-
107
+
106
108
  def basename
107
109
  @basename ||= @ttf.name.postscript_name
108
110
  end
@@ -126,7 +128,7 @@ module Prawn
126
128
  def cap_height
127
129
  @cap_height ||= begin
128
130
  height = @ttf.os2.exists? && @ttf.os2.cap_height || 0
129
- height == 0 ? ascender : height
131
+ height == 0 ? @ascender : height
130
132
  end
131
133
  end
132
134
 
@@ -160,42 +162,34 @@ module Prawn
160
162
  end
161
163
 
162
164
  def normalize_encoding(text)
163
- if text.respond_to?(:encode)
164
- # if we're running under a M17n aware VM, ensure the string provided is
165
- # UTF-8 (by converting it if necessary)
166
- begin
167
- text.encode("UTF-8")
168
- rescue
169
- raise Prawn::Errors::IncompatibleStringEncoding, "Encoding " +
165
+ begin
166
+ text.encode(::Encoding::UTF_8)
167
+ rescue => e
168
+ puts e
169
+ raise Prawn::Errors::IncompatibleStringEncoding, "Encoding " +
170
170
  "#{text.encoding} can not be transparently converted to UTF-8. " +
171
171
  "Please ensure the encoding of the string you are attempting " +
172
172
  "to use is set correctly"
173
- end
174
- else
175
- # on a non M17N aware VM, use unpack as a hackish way to verify the
176
- # string is valid utf-8. I thought it was better than loading iconv
177
- # though.
178
- begin
179
- text.unpack("U*")
180
- return text.dup
181
- rescue
182
- raise Prawn::Errors::IncompatibleStringEncoding, "The string you " +
183
- "are attempting to render is not encoded in valid UTF-8."
184
- end
185
173
  end
186
174
  end
187
175
 
188
176
  def glyph_present?(char)
189
- code = char.unpack("U*").first
177
+ code = char.codepoints.first
190
178
  cmap[code] > 0
191
179
  end
192
180
 
181
+ # Returns the number of characters in +str+ (a UTF-8-encoded string).
182
+ #
183
+ def character_count(str)
184
+ str.length
185
+ end
186
+
193
187
  private
194
188
 
195
189
  def cmap
196
190
  @cmap ||= @ttf.cmap.unicode.first or raise("no unicode cmap for font")
197
191
  end
198
-
192
+
199
193
  # +string+ must be UTF8-encoded.
200
194
  #
201
195
  # Returns an array. If an element is a numeric, it represents the
@@ -204,7 +198,7 @@ module Prawn
204
198
  def kern(string)
205
199
  a = []
206
200
 
207
- string.unpack("U*").each do |r|
201
+ string.each_codepoint do |r|
208
202
  if a.empty?
209
203
  a << [r]
210
204
  elsif (kern = kern_pairs_table[[cmap[a.last.last], cmap[r]]])
@@ -231,10 +225,15 @@ module Prawn
231
225
  @hmtx ||= @ttf.horizontal_metrics
232
226
  end
233
227
 
234
- def character_width_by_code(code)
228
+ def character_width_by_code(code)
235
229
  return 0 unless cmap[code]
230
+
231
+ # Some TTF fonts have nonzero widths for \n (UTF-8 / ASCII code: 10).
232
+ # Patch around this as we'll never be drawing a newline with a width.
233
+ return 0.0 if code == 10
234
+
236
235
  @char_widths[code] ||= Integer(hmtx.widths[cmap[code]] * scale_factor)
237
- end
236
+ end
238
237
 
239
238
  def scale_factor
240
239
  @scale ||= 1000.0 / @ttf.header.units_per_em
@@ -244,7 +243,7 @@ module Prawn
244
243
  temp_name = @ttf.name.postscript_name.gsub("\0","").to_sym
245
244
  ref = @document.ref!(:Type => :Font, :BaseFont => temp_name)
246
245
 
247
- # Embed the font metrics in the document after everything has been
246
+ # Embed the font metrics in the document after everything has been
248
247
  # drawn, just before the document is emitted.
249
248
  @document.before_render { |doc| embed(ref, subset) }
250
249
 
@@ -265,12 +264,9 @@ module Prawn
265
264
 
266
265
  raise "Can't detect a postscript name for #{file}" if basename.nil?
267
266
 
268
- compressed_font = Zlib::Deflate.deflate(font_content)
269
-
270
- fontfile = @document.ref!(:Length => compressed_font.size,
271
- :Length1 => font_content.size,
272
- :Filter => :FlateDecode )
273
- fontfile << compressed_font
267
+ fontfile = @document.ref!(:Length1 => font_content.size)
268
+ fontfile.stream << font_content
269
+ fontfile.stream.compress!
274
270
 
275
271
  descriptor = @document.ref!(:Type => :FontDescriptor,
276
272
  :FontName => basename.to_sym,
@@ -279,8 +275,8 @@ module Prawn
279
275
  :Flags => pdf_flags,
280
276
  :StemV => stemV,
281
277
  :ItalicAngle => italic_angle,
282
- :Ascent => ascender,
283
- :Descent => descender,
278
+ :Ascent => @ascender,
279
+ :Descent => @descender,
284
280
  :CapHeight => cap_height,
285
281
  :XHeight => x_height)
286
282
 
@@ -301,7 +297,7 @@ module Prawn
301
297
  map = @subsets[subset].to_unicode_map
302
298
 
303
299
  ranges = [[]]
304
- lines = map.keys.sort.inject("") do |s, code|
300
+ map.keys.sort.inject("") do |s, code|
305
301
  ranges << [] if ranges.last.length >= 100
306
302
  unicode = map[code]
307
303
  ranges.last << "<%02x><%04x>" % [code, unicode]
@@ -315,7 +311,7 @@ module Prawn
315
311
 
316
312
  cmap = @document.ref!({})
317
313
  cmap << to_unicode_cmap
318
- cmap.compress_stream
314
+ cmap.stream.compress!
319
315
 
320
316
  reference.data.update(:Subtype => :TrueType,
321
317
  :BaseFont => basename.to_sym,