prawn 0.13.0 → 2.4.0

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 (348) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +10 -0
  4. data/GPLv2 +20 -21
  5. data/Gemfile +3 -16
  6. data/Rakefile +17 -39
  7. data/lib/prawn/document/bounding_box.rb +85 -42
  8. data/lib/prawn/document/column_box.rb +21 -11
  9. data/lib/prawn/document/internals.rb +40 -147
  10. data/lib/prawn/document/span.rb +25 -17
  11. data/lib/prawn/document.rb +286 -245
  12. data/lib/prawn/encoding.rb +68 -101
  13. data/lib/prawn/errors.rb +47 -43
  14. data/lib/prawn/font.rb +204 -155
  15. data/lib/prawn/font_metric_cache.rb +25 -21
  16. data/lib/prawn/fonts/afm.rb +292 -0
  17. data/lib/prawn/{font → fonts}/dfont.rb +7 -13
  18. data/lib/prawn/fonts/otf.rb +11 -0
  19. data/lib/prawn/fonts/ttc.rb +36 -0
  20. data/lib/prawn/{font → fonts}/ttf.rb +142 -80
  21. data/lib/prawn/graphics/blend_mode.rb +65 -0
  22. data/lib/prawn/graphics/cap_style.rb +6 -5
  23. data/lib/prawn/graphics/color.rb +47 -44
  24. data/lib/prawn/graphics/dash.rb +30 -13
  25. data/lib/prawn/graphics/join_style.rb +13 -6
  26. data/lib/prawn/graphics/patterns.rb +221 -90
  27. data/lib/prawn/graphics/transformation.rb +21 -12
  28. data/lib/prawn/graphics/transparency.rb +21 -17
  29. data/lib/prawn/graphics.rb +155 -128
  30. data/lib/prawn/{layout/grid.rb → grid.rb} +110 -47
  31. data/lib/prawn/image_handler.rb +16 -2
  32. data/lib/prawn/images/image.rb +4 -2
  33. data/lib/prawn/images/jpg.rb +39 -30
  34. data/lib/prawn/images/png.rb +132 -169
  35. data/lib/prawn/images.rb +70 -62
  36. data/lib/prawn/measurement_extensions.rb +15 -10
  37. data/lib/prawn/measurements.rb +22 -23
  38. data/lib/prawn/outline.rb +301 -13
  39. data/lib/prawn/repeater.rb +19 -17
  40. data/lib/prawn/security/arcfour.rb +54 -0
  41. data/lib/prawn/security.rb +108 -86
  42. data/lib/prawn/soft_mask.rb +40 -41
  43. data/lib/prawn/stamp.rb +29 -12
  44. data/lib/prawn/text/box.rb +27 -29
  45. data/lib/prawn/text/formatted/arranger.rb +110 -67
  46. data/lib/prawn/text/formatted/box.rb +233 -165
  47. data/lib/prawn/text/formatted/fragment.rb +27 -27
  48. data/lib/prawn/text/formatted/line_wrap.rb +137 -97
  49. data/lib/prawn/text/formatted/parser.rb +149 -127
  50. data/lib/prawn/text/formatted/wrap.rb +57 -37
  51. data/lib/prawn/text/formatted.rb +6 -4
  52. data/lib/prawn/text.rb +105 -73
  53. data/lib/prawn/transformation_stack.rb +44 -0
  54. data/lib/prawn/utilities.rb +11 -21
  55. data/lib/prawn/version.rb +5 -0
  56. data/lib/prawn/view.rb +101 -0
  57. data/lib/prawn.rb +42 -68
  58. data/{data/images/fractal.jpg → manual/absolute_position.pdf} +0 -0
  59. data/manual/basic_concepts/adding_pages.rb +9 -10
  60. data/manual/basic_concepts/basic_concepts.rb +33 -24
  61. data/manual/basic_concepts/creation.rb +10 -11
  62. data/manual/basic_concepts/cursor.rb +9 -10
  63. data/manual/basic_concepts/measurement.rb +10 -11
  64. data/manual/basic_concepts/origin.rb +8 -9
  65. data/manual/basic_concepts/other_cursor_helpers.rb +17 -18
  66. data/manual/basic_concepts/view.rb +48 -0
  67. data/manual/bounding_box/bounding_box.rb +31 -29
  68. data/manual/bounding_box/bounds.rb +17 -18
  69. data/manual/bounding_box/canvas.rb +8 -9
  70. data/manual/bounding_box/creation.rb +8 -9
  71. data/manual/bounding_box/indentation.rb +22 -23
  72. data/manual/bounding_box/nesting.rb +32 -25
  73. data/manual/bounding_box/russian_boxes.rb +19 -19
  74. data/manual/bounding_box/stretchy.rb +18 -20
  75. data/manual/contents.rb +35 -0
  76. data/manual/cover.rb +43 -0
  77. data/manual/document_and_page_options/background.rb +16 -14
  78. data/manual/document_and_page_options/document_and_page_options.rb +26 -23
  79. data/manual/document_and_page_options/metadata.rb +21 -19
  80. data/manual/document_and_page_options/page_margins.rb +20 -22
  81. data/manual/document_and_page_options/page_size.rb +15 -15
  82. data/manual/document_and_page_options/print_scaling.rb +23 -0
  83. data/manual/example_helper.rb +5 -408
  84. data/manual/graphics/blend_mode.rb +52 -0
  85. data/manual/graphics/circle_and_ellipse.rb +8 -9
  86. data/manual/graphics/color.rb +11 -13
  87. data/manual/graphics/common_lines.rb +13 -12
  88. data/manual/graphics/fill_and_stroke.rb +10 -11
  89. data/manual/graphics/fill_rules.rb +13 -12
  90. data/manual/graphics/gradients.rb +28 -22
  91. data/manual/graphics/graphics.rb +52 -46
  92. data/manual/graphics/helper.rb +20 -10
  93. data/manual/graphics/line_width.rb +13 -12
  94. data/manual/graphics/lines_and_curves.rb +13 -14
  95. data/manual/graphics/polygon.rb +10 -12
  96. data/manual/graphics/rectangle.rb +7 -8
  97. data/manual/graphics/rotate.rb +9 -12
  98. data/manual/graphics/scale.rb +19 -18
  99. data/manual/graphics/soft_masks.rb +5 -7
  100. data/manual/graphics/stroke_cap.rb +10 -11
  101. data/manual/graphics/stroke_dash.rb +16 -17
  102. data/manual/graphics/stroke_join.rb +10 -11
  103. data/manual/graphics/translate.rb +13 -13
  104. data/manual/graphics/transparency.rb +11 -13
  105. data/manual/{manual/how_to_read_this_manual.rb → how_to_read_this_manual.rb} +23 -25
  106. data/manual/images/absolute_position.rb +9 -10
  107. data/manual/images/fit.rb +9 -10
  108. data/manual/images/horizontal.rb +13 -14
  109. data/manual/images/images.rb +31 -30
  110. data/manual/images/plain_image.rb +6 -7
  111. data/manual/images/scale.rb +12 -13
  112. data/manual/images/vertical.rb +19 -17
  113. data/manual/images/width_and_height.rb +13 -14
  114. data/manual/layout/boxes.rb +14 -15
  115. data/manual/layout/content.rb +12 -13
  116. data/manual/layout/layout.rb +19 -20
  117. data/manual/layout/simple_grid.rb +8 -9
  118. data/manual/outline/add_subsection_to.rb +26 -27
  119. data/manual/outline/insert_section_after.rb +19 -20
  120. data/manual/outline/outline.rb +23 -22
  121. data/manual/outline/sections_and_pages.rb +24 -25
  122. data/manual/repeatable_content/alternate_page_numbering.rb +36 -0
  123. data/manual/repeatable_content/page_numbering.rb +20 -19
  124. data/manual/repeatable_content/repeatable_content.rb +26 -22
  125. data/manual/repeatable_content/repeater.rb +18 -19
  126. data/manual/repeatable_content/stamp.rb +18 -19
  127. data/manual/security/encryption.rb +8 -11
  128. data/manual/security/permissions.rb +20 -15
  129. data/manual/security/security.rb +20 -20
  130. data/manual/table.rb +16 -0
  131. data/manual/text/alignment.rb +17 -18
  132. data/manual/text/color.rb +13 -13
  133. data/manual/text/column_box.rb +10 -12
  134. data/manual/text/fallback_fonts.rb +29 -25
  135. data/manual/text/font.rb +17 -18
  136. data/manual/text/font_size.rb +21 -22
  137. data/manual/text/font_style.rb +12 -10
  138. data/manual/text/formatted_callbacks.rb +36 -26
  139. data/manual/text/formatted_text.rb +41 -34
  140. data/manual/text/free_flowing_text.rb +28 -29
  141. data/manual/text/inline.rb +23 -26
  142. data/manual/text/kerning_and_character_spacing.rb +20 -21
  143. data/manual/text/leading.rb +10 -11
  144. data/manual/text/line_wrapping.rb +40 -21
  145. data/manual/text/paragraph_indentation.rb +17 -12
  146. data/manual/text/positioned_text.rb +19 -20
  147. data/manual/text/registering_families.rb +33 -30
  148. data/manual/text/rendering_and_color.rb +11 -12
  149. data/manual/text/right_to_left_text.rb +31 -20
  150. data/manual/text/rotation.rb +36 -27
  151. data/manual/text/single_usage.rb +13 -14
  152. data/manual/text/text.rb +62 -62
  153. data/manual/text/text_box_excess.rb +22 -19
  154. data/manual/text/text_box_extensions.rb +21 -18
  155. data/manual/text/text_box_overflow.rb +28 -21
  156. data/manual/text/utf8.rb +16 -17
  157. data/manual/text/win_ansi_charset.rb +29 -26
  158. data/prawn.gemspec +45 -43
  159. data/spec/extensions/encoding_helpers.rb +4 -3
  160. data/spec/prawn/document/bounding_box_spec.rb +550 -0
  161. data/spec/prawn/document/column_box_spec.rb +75 -0
  162. data/spec/prawn/document/security_spec.rb +176 -0
  163. data/spec/prawn/document_annotations_spec.rb +76 -0
  164. data/spec/prawn/document_destinations_spec.rb +15 -0
  165. data/spec/prawn/document_grid_spec.rb +99 -0
  166. data/spec/prawn/document_reference_spec.rb +27 -0
  167. data/spec/prawn/document_span_spec.rb +44 -0
  168. data/spec/prawn/document_spec.rb +805 -0
  169. data/spec/prawn/font_metric_cache_spec.rb +54 -0
  170. data/spec/prawn/font_spec.rb +544 -0
  171. data/spec/prawn/graphics/blend_mode_spec.rb +63 -0
  172. data/spec/prawn/graphics/transparency_spec.rb +81 -0
  173. data/spec/prawn/graphics_spec.rb +872 -0
  174. data/spec/prawn/graphics_stroke_styles_spec.rb +229 -0
  175. data/spec/prawn/image_handler_spec.rb +53 -0
  176. data/spec/prawn/images/jpg_spec.rb +20 -0
  177. data/spec/prawn/images/png_spec.rb +283 -0
  178. data/spec/prawn/images_spec.rb +229 -0
  179. data/spec/prawn/measurements_extensions_spec.rb +24 -0
  180. data/spec/prawn/outline_spec.rb +512 -0
  181. data/spec/prawn/repeater_spec.rb +166 -0
  182. data/spec/prawn/soft_mask_spec.rb +74 -0
  183. data/spec/prawn/stamp_spec.rb +173 -0
  184. data/spec/prawn/text/box_spec.rb +1110 -0
  185. data/spec/prawn/text/formatted/arranger_spec.rb +466 -0
  186. data/spec/prawn/text/formatted/box_spec.rb +849 -0
  187. data/spec/prawn/text/formatted/fragment_spec.rb +343 -0
  188. data/spec/prawn/text/formatted/line_wrap_spec.rb +495 -0
  189. data/spec/prawn/text/formatted/parser_spec.rb +697 -0
  190. data/spec/prawn/text_draw_text_spec.rb +150 -0
  191. data/spec/prawn/text_rendering_mode_spec.rb +48 -0
  192. data/spec/prawn/text_spacing_spec.rb +95 -0
  193. data/spec/prawn/text_spec.rb +603 -0
  194. data/spec/prawn/text_with_inline_formatting_spec.rb +35 -0
  195. data/spec/prawn/transformation_stack_spec.rb +66 -0
  196. data/spec/prawn/view_spec.rb +63 -0
  197. data/spec/prawn_manual_spec.rb +35 -0
  198. data/spec/spec_helper.rb +22 -21
  199. data.tar.gz.sig +0 -0
  200. metadata +168 -307
  201. metadata.gz.sig +0 -0
  202. data/README.md +0 -109
  203. data/data/encodings/win_ansi.txt +0 -29
  204. data/data/images/16bit.alpha +0 -0
  205. data/data/images/16bit.dat +0 -0
  206. data/data/images/16bit.png +0 -0
  207. data/data/images/arrow.png +0 -0
  208. data/data/images/arrow2.png +0 -0
  209. data/data/images/barcode_issue.png +0 -0
  210. data/data/images/dice.alpha +0 -0
  211. data/data/images/dice.dat +0 -0
  212. data/data/images/dice.png +0 -0
  213. data/data/images/dice_interlaced.png +0 -0
  214. data/data/images/indexed_color.dat +0 -0
  215. data/data/images/indexed_color.png +0 -0
  216. data/data/images/letterhead.jpg +0 -0
  217. data/data/images/page_white_text.alpha +0 -0
  218. data/data/images/page_white_text.dat +0 -0
  219. data/data/images/page_white_text.png +0 -0
  220. data/data/images/pigs.jpg +0 -0
  221. data/data/images/prawn.png +0 -0
  222. data/data/images/ruport.png +0 -0
  223. data/data/images/ruport_data.dat +0 -0
  224. data/data/images/ruport_transparent.png +0 -0
  225. data/data/images/ruport_type0.png +0 -0
  226. data/data/images/stef.jpg +0 -0
  227. data/data/images/tru256.bmp +0 -0
  228. data/data/images/web-links.dat +0 -1
  229. data/data/images/web-links.png +0 -0
  230. data/data/pdfs/complex_template.pdf +0 -0
  231. data/data/pdfs/contains_ttf_font.pdf +0 -0
  232. data/data/pdfs/encrypted.pdf +0 -0
  233. data/data/pdfs/form.pdf +1 -819
  234. data/data/pdfs/hexagon.pdf +0 -61
  235. data/data/pdfs/indirect_reference.pdf +0 -86
  236. data/data/pdfs/multipage_template.pdf +0 -127
  237. data/data/pdfs/nested_pages.pdf +0 -118
  238. data/data/pdfs/page_without_mediabox.pdf +0 -193
  239. data/data/pdfs/resources_as_indirect_object.pdf +0 -83
  240. data/data/pdfs/two_hexagons.pdf +0 -90
  241. data/data/pdfs/version_1_6.pdf +0 -61
  242. data/data/shift_jis_text.txt +0 -1
  243. data/lib/pdf/core/annotations.rb +0 -60
  244. data/lib/pdf/core/byte_string.rb +0 -9
  245. data/lib/pdf/core/destinations.rb +0 -90
  246. data/lib/pdf/core/document_state.rb +0 -78
  247. data/lib/pdf/core/filter_list.rb +0 -51
  248. data/lib/pdf/core/filters.rb +0 -36
  249. data/lib/pdf/core/graphics_state.rb +0 -68
  250. data/lib/pdf/core/literal_string.rb +0 -16
  251. data/lib/pdf/core/name_tree.rb +0 -177
  252. data/lib/pdf/core/object_store.rb +0 -320
  253. data/lib/pdf/core/outline.rb +0 -315
  254. data/lib/pdf/core/page.rb +0 -212
  255. data/lib/pdf/core/page_geometry.rb +0 -126
  256. data/lib/pdf/core/pdf_object.rb +0 -124
  257. data/lib/pdf/core/reference.rb +0 -103
  258. data/lib/pdf/core/stream.rb +0 -98
  259. data/lib/pdf/core/text.rb +0 -275
  260. data/lib/pdf/core.rb +0 -35
  261. data/lib/prawn/compatibility.rb +0 -91
  262. data/lib/prawn/document/graphics_state.rb +0 -73
  263. data/lib/prawn/document/snapshot.rb +0 -89
  264. data/lib/prawn/font/afm.rb +0 -203
  265. data/lib/prawn/layout.rb +0 -20
  266. data/lib/prawn/table/cell/image.rb +0 -70
  267. data/lib/prawn/table/cell/in_table.rb +0 -27
  268. data/lib/prawn/table/cell/span_dummy.rb +0 -92
  269. data/lib/prawn/table/cell/subtable.rb +0 -65
  270. data/lib/prawn/table/cell/text.rb +0 -153
  271. data/lib/prawn/table/cell.rb +0 -770
  272. data/lib/prawn/table/cells.rb +0 -295
  273. data/lib/prawn/table.rb +0 -643
  274. data/manual/example_file.rb +0 -116
  275. data/manual/example_package.rb +0 -53
  276. data/manual/example_section.rb +0 -46
  277. data/manual/manual/cover.rb +0 -35
  278. data/manual/manual/foreword.rb +0 -85
  279. data/manual/manual/manual.rb +0 -35
  280. data/manual/syntax_highlight.rb +0 -52
  281. data/manual/table/basic_block.rb +0 -53
  282. data/manual/table/before_rendering_page.rb +0 -26
  283. data/manual/table/cell_border_lines.rb +0 -24
  284. data/manual/table/cell_borders_and_bg.rb +0 -31
  285. data/manual/table/cell_dimensions.rb +0 -30
  286. data/manual/table/cell_text.rb +0 -38
  287. data/manual/table/column_widths.rb +0 -30
  288. data/manual/table/content_and_subtables.rb +0 -39
  289. data/manual/table/creation.rb +0 -27
  290. data/manual/table/filtering.rb +0 -36
  291. data/manual/table/flow_and_header.rb +0 -17
  292. data/manual/table/image_cells.rb +0 -33
  293. data/manual/table/position.rb +0 -29
  294. data/manual/table/row_colors.rb +0 -20
  295. data/manual/table/span.rb +0 -30
  296. data/manual/table/style.rb +0 -22
  297. data/manual/table/table.rb +0 -52
  298. data/manual/table/width.rb +0 -27
  299. data/manual/templates/full_template.rb +0 -25
  300. data/manual/templates/page_template.rb +0 -48
  301. data/manual/templates/templates.rb +0 -27
  302. data/manual/text/group.rb +0 -29
  303. data/spec/acceptance/png.rb +0 -23
  304. data/spec/annotations_spec.rb +0 -74
  305. data/spec/bounding_box_spec.rb +0 -493
  306. data/spec/cell_spec.rb +0 -628
  307. data/spec/column_box_spec.rb +0 -33
  308. data/spec/destinations_spec.rb +0 -15
  309. data/spec/document_spec.rb +0 -761
  310. data/spec/extensions/mocha.rb +0 -44
  311. data/spec/filters_spec.rb +0 -34
  312. data/spec/font_metric_cache_spec.rb +0 -52
  313. data/spec/font_spec.rb +0 -464
  314. data/spec/formatted_text_arranger_spec.rb +0 -421
  315. data/spec/formatted_text_box_spec.rb +0 -650
  316. data/spec/formatted_text_fragment_spec.rb +0 -298
  317. data/spec/graphics_spec.rb +0 -651
  318. data/spec/grid_spec.rb +0 -85
  319. data/spec/image_handler_spec.rb +0 -42
  320. data/spec/images_spec.rb +0 -157
  321. data/spec/inline_formatted_text_parser_spec.rb +0 -564
  322. data/spec/jpg_spec.rb +0 -25
  323. data/spec/line_wrap_spec.rb +0 -333
  324. data/spec/measurement_units_spec.rb +0 -23
  325. data/spec/name_tree_spec.rb +0 -112
  326. data/spec/object_store_spec.rb +0 -170
  327. data/spec/outline_spec.rb +0 -448
  328. data/spec/pdf_object_spec.rb +0 -172
  329. data/spec/png_spec.rb +0 -240
  330. data/spec/reference_spec.rb +0 -82
  331. data/spec/repeater_spec.rb +0 -158
  332. data/spec/security_spec.rb +0 -158
  333. data/spec/snapshot_spec.rb +0 -186
  334. data/spec/soft_mask_spec.rb +0 -117
  335. data/spec/span_spec.rb +0 -44
  336. data/spec/stamp_spec.rb +0 -158
  337. data/spec/stream_spec.rb +0 -58
  338. data/spec/stroke_styles_spec.rb +0 -211
  339. data/spec/table/span_dummy_spec.rb +0 -17
  340. data/spec/table_spec.rb +0 -1355
  341. data/spec/template_spec.rb +0 -351
  342. data/spec/text_at_spec.rb +0 -130
  343. data/spec/text_box_spec.rb +0 -1030
  344. data/spec/text_rendering_mode_spec.rb +0 -45
  345. data/spec/text_spacing_spec.rb +0 -93
  346. data/spec/text_spec.rb +0 -425
  347. data/spec/text_with_inline_formatting_spec.rb +0 -35
  348. data/spec/transparency_spec.rb +0 -89
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # prawn/font/ttf.rb : Implements AFM font support for Prawn
4
4
  #
@@ -11,43 +11,68 @@ require 'ttfunk'
11
11
  require 'ttfunk/subset_collection'
12
12
 
13
13
  module Prawn
14
- class Font
14
+ module Fonts
15
+ # @private
15
16
  class TTF < Font
17
+ class Error < StandardError
18
+ DEFAULT_MESSAGE = 'TTF font error'
19
+ MESSAGE_WITH_FONT = 'TTF font error in font %<font>s'
20
+
21
+ def initialize(message = DEFAULT_MESSAGE, font: nil)
22
+ if font && message == DEFAULT_MESSAGE
23
+ super format(MESSAGE_WITH_FONT, font: font)
24
+ else
25
+ super message
26
+ end
27
+ end
28
+ end
29
+
30
+ class NoUnicodeCMap < Error
31
+ DEFAULT_MESSAGE = 'No unicode cmap found in font'
32
+ MESSAGE_WITH_FONT = 'No unicode cmap found in font %<font>s'
33
+ end
34
+
35
+ class NoPostscriptName < Error
36
+ DEFAULT_MESSAGE = 'Can not detect a postscript name'
37
+ MESSAGE_WITH_FONT = 'Can not detect a postscript name in font %<font>s'
38
+ end
39
+
16
40
  attr_reader :ttf, :subsets
17
41
 
18
42
  def unicode?
19
43
  true
20
44
  end
21
45
 
22
- def initialize(document, name, options={})
46
+ def initialize(document, name, options = {})
23
47
  super
24
48
 
25
- @ttf = read_ttf_file
26
- @subsets = TTFunk::SubsetCollection.new(@ttf)
49
+ @ttf = read_ttf_file
50
+ @subsets = TTFunk::SubsetCollection.new(@ttf)
51
+ @italic_angle = nil
27
52
 
28
- @attributes = {}
29
- @bounding_boxes = {}
30
- @char_widths = {}
53
+ @attributes = {}
54
+ @bounding_boxes = {}
55
+ @char_widths = {}
31
56
  @has_kerning_data = @ttf.kerning.exists? && @ttf.kerning.tables.any?
32
57
 
33
- @ascender = Integer(@ttf.ascent * scale_factor)
34
- @descender = Integer(@ttf.descent * scale_factor)
35
- @line_gap = Integer(@ttf.line_gap * scale_factor)
58
+ @ascender = Integer(@ttf.ascent * scale_factor)
59
+ @descender = Integer(@ttf.descent * scale_factor)
60
+ @line_gap = Integer(@ttf.line_gap * scale_factor)
36
61
  end
37
62
 
38
63
  # NOTE: +string+ must be UTF8-encoded.
39
- def compute_width_of(string, options={}) #:nodoc:
64
+ def compute_width_of(string, options = {}) #:nodoc:
40
65
  scale = (options[:size] || size) / 1000.0
41
66
  if options[:kerning]
42
- kern(string).inject(0) do |s,r|
67
+ kern(string).reduce(0) do |s, r|
43
68
  if r.is_a?(Numeric)
44
69
  s - r
45
70
  else
46
- r.inject(s) { |s2, u| s2 + character_width_by_code(u) }
71
+ r.reduce(s) { |a, e| a + character_width_by_code(e) }
47
72
  end
48
73
  end * scale
49
74
  else
50
- string.codepoints.inject(0) do |s,r|
75
+ string.codepoints.reduce(0) do |s, r|
51
76
  s + character_width_by_code(r)
52
77
  end * scale
53
78
  end
@@ -60,9 +85,12 @@ module Prawn
60
85
  end
61
86
 
62
87
  # Returns true if the font has kerning data, false otherwise
88
+ #
89
+ # rubocop: disable Naming/PredicateName
63
90
  def has_kerning_data?
64
91
  @has_kerning_data
65
92
  end
93
+ # rubocop: enable Naming/PredicateName
66
94
 
67
95
  # Perform any changes to the string that need to happen
68
96
  # before it is rendered to the canvas. Returns an array of
@@ -72,14 +100,16 @@ module Prawn
72
100
  #
73
101
  # The +text+ parameter must be UTF8-encoded.
74
102
  #
75
- def encode_text(text,options={})
103
+ def encode_text(text, options = {})
76
104
  text = text.chomp
77
105
 
78
106
  if options[:kerning]
79
107
  last_subset = nil
80
- kern(text).inject([]) do |result, element|
108
+ kern(text).reduce([]) do |result, element|
81
109
  if element.is_a?(Numeric)
82
- result.last[1] = [result.last[1]] unless result.last[1].is_a?(Array)
110
+ unless result.last[1].is_a?(Array)
111
+ result.last[1] = [result.last[1]]
112
+ end
83
113
  result.last[1] << element
84
114
  result
85
115
  else
@@ -99,7 +129,7 @@ module Prawn
99
129
  end
100
130
  end
101
131
  else
102
- @subsets.encode(text.unpack("U*"))
132
+ @subsets.encode(text.unpack('U*'))
103
133
  end
104
134
  end
105
135
 
@@ -108,26 +138,32 @@ module Prawn
108
138
  end
109
139
 
110
140
  # not sure how to compute this for true-type fonts...
111
- def stemV
141
+ def stem_v
112
142
  0
113
143
  end
114
144
 
115
145
  def italic_angle
116
- @italic_angle ||= if @ttf.postscript.exists?
146
+ return @italic_angle if @italic_angle
147
+
148
+ if @ttf.postscript.exists?
117
149
  raw = @ttf.postscript.italic_angle
118
- hi, low = raw >> 16, raw & 0xFF
150
+ hi = raw >> 16
151
+ low = raw & 0xFF
119
152
  hi = -((hi ^ 0xFFFF) + 1) if hi & 0x8000 != 0
120
- "#{hi}.#{low}".to_f
153
+ @italic_angle = "#{hi}.#{low}".to_f
121
154
  else
122
- 0
155
+ @italic_angle = 0
123
156
  end
157
+
158
+ @italic_angle
124
159
  end
125
160
 
126
161
  def cap_height
127
- @cap_height ||= begin
128
- height = @ttf.os2.exists? && @ttf.os2.cap_height || 0
129
- height == 0 ? @ascender : height
130
- end
162
+ @cap_height ||=
163
+ begin
164
+ height = @ttf.os2.exists? && @ttf.os2.cap_height || 0
165
+ height.zero? ? @ascender : height
166
+ end
131
167
  end
132
168
 
133
169
  def x_height
@@ -141,7 +177,7 @@ module Prawn
141
177
  end
142
178
 
143
179
  def serif?
144
- @serif ||= [1,2,3,4,5,7].include?(family_class)
180
+ @serif ||= [1, 2, 3, 4, 5, 7].include?(family_class)
145
181
  end
146
182
 
147
183
  def script?
@@ -149,35 +185,47 @@ module Prawn
149
185
  end
150
186
 
151
187
  def pdf_flags
152
- @flags ||= begin
153
- flags = 0
154
- flags |= 0x0001 if @ttf.postscript.fixed_pitch?
155
- flags |= 0x0002 if serif?
156
- flags |= 0x0008 if script?
157
- flags |= 0x0040 if italic_angle != 0
158
- flags |= 0x0004 # assume the font contains at least some non-latin characters
159
- end
188
+ @pdf_flags ||=
189
+ begin
190
+ flags = 0
191
+ flags |= 0x0001 if @ttf.postscript.fixed_pitch?
192
+ flags |= 0x0002 if serif?
193
+ flags |= 0x0008 if script?
194
+ flags |= 0x0040 if italic_angle != 0
195
+ # Assume the font contains at least some non-latin characters
196
+ flags | 0x0004
197
+ end
160
198
  end
161
199
 
162
200
  def normalize_encoding(text)
163
- text.normalize_to_utf8
201
+ text.encode(::Encoding::UTF_8)
202
+ rescue StandardError => e
203
+ puts e
204
+ raise Prawn::Errors::IncompatibleStringEncoding,
205
+ "Encoding #{text.encoding} can not be transparently converted to UTF-8. " \
206
+ 'Please ensure the encoding of the string you are attempting ' \
207
+ 'to use is set correctly'
208
+ end
209
+
210
+ def to_utf8(text)
211
+ text.encode('UTF-8')
164
212
  end
165
213
 
166
214
  def glyph_present?(char)
167
215
  code = char.codepoints.first
168
- cmap[code] > 0
216
+ cmap[code].positive?
169
217
  end
170
218
 
171
219
  # Returns the number of characters in +str+ (a UTF-8-encoded string).
172
220
  #
173
221
  def character_count(str)
174
- str.unicode_length
222
+ str.length
175
223
  end
176
224
 
177
225
  private
178
226
 
179
227
  def cmap
180
- @cmap ||= @ttf.cmap.unicode.first or raise("no unicode cmap for font")
228
+ (@cmap ||= @ttf.cmap.unicode.first) || raise(NoUnicodeCMap.new(font: name))
181
229
  end
182
230
 
183
231
  # +string+ must be UTF8-encoded.
@@ -203,12 +251,12 @@ module Prawn
203
251
  end
204
252
 
205
253
  def kern_pairs_table
206
- @kerning_data ||= has_kerning_data? ? @ttf.kerning.tables.first.pairs : {}
207
- end
208
-
209
- def cid_to_gid_map
210
- max = cmap.code_map.keys.max
211
- (0..max).map { |cid| cmap[cid] }.pack("n*")
254
+ @kern_pairs_table ||=
255
+ if has_kerning_data?
256
+ @ttf.kerning.tables.first.pairs
257
+ else
258
+ {}
259
+ end
212
260
  end
213
261
 
214
262
  def hmtx
@@ -226,16 +274,16 @@ module Prawn
226
274
  end
227
275
 
228
276
  def scale_factor
229
- @scale ||= 1000.0 / @ttf.header.units_per_em
277
+ @scale_factor ||= 1000.0 / @ttf.header.units_per_em
230
278
  end
231
279
 
232
280
  def register(subset)
233
- temp_name = @ttf.name.postscript_name.gsub("\0","").to_sym
234
- ref = @document.ref!(:Type => :Font, :BaseFont => temp_name)
281
+ temp_name = @ttf.name.postscript_name.delete("\0").to_sym
282
+ ref = @document.ref!(Type: :Font, BaseFont: temp_name)
235
283
 
236
284
  # Embed the font metrics in the document after everything has been
237
285
  # drawn, just before the document is emitted.
238
- @document.before_render { |doc| embed(ref, subset) }
286
+ @document.renderer.before_render { |_doc| embed(ref, subset) }
239
287
 
240
288
  ref
241
289
  end
@@ -250,29 +298,32 @@ module Prawn
250
298
 
251
299
  # empirically, it looks like Adobe Reader will not display fonts
252
300
  # if their font name is more than 33 bytes long. Strange. But true.
253
- basename = font.name.postscript_name[0, 33].gsub("\0","")
301
+ basename = font.name.postscript_name[0, 33].delete("\0")
254
302
 
255
- raise "Can't detect a postscript name for #{file}" if basename.nil?
303
+ raise NoPostscriptName.new(font: font) if basename.nil?
256
304
 
257
- fontfile = @document.ref!(:Length1 => font_content.size)
305
+ fontfile = @document.ref!(Length1: font_content.size)
258
306
  fontfile.stream << font_content
259
307
  fontfile.stream.compress!
260
308
 
261
- descriptor = @document.ref!(:Type => :FontDescriptor,
262
- :FontName => basename.to_sym,
263
- :FontFile2 => fontfile,
264
- :FontBBox => bbox,
265
- :Flags => pdf_flags,
266
- :StemV => stemV,
267
- :ItalicAngle => italic_angle,
268
- :Ascent => @ascender,
269
- :Descent => @descender,
270
- :CapHeight => cap_height,
271
- :XHeight => x_height)
309
+ descriptor = @document.ref!(
310
+ Type: :FontDescriptor,
311
+ FontName: basename.to_sym,
312
+ FontFile2: fontfile,
313
+ FontBBox: bbox,
314
+ Flags: pdf_flags,
315
+ StemV: stem_v,
316
+ ItalicAngle: italic_angle,
317
+ Ascent: @ascender,
318
+ Descent: @descender,
319
+ CapHeight: cap_height,
320
+ XHeight: x_height
321
+ )
272
322
 
273
323
  hmtx = font.horizontal_metrics
274
- widths = font.cmap.tables.first.code_map.map { |gid|
275
- Integer(hmtx.widths[gid] * scale_factor) }[32..-1]
324
+ widths = font.cmap.tables.first.code_map.map do |gid|
325
+ Integer(hmtx.widths[gid] * scale_factor)
326
+ end[32..-1]
276
327
 
277
328
  # It would be nice to have Encoding set for the macroman subsets,
278
329
  # and only do a ToUnicode cmap for non-encoded unicode subsets.
@@ -287,15 +338,24 @@ module Prawn
287
338
  map = @subsets[subset].to_unicode_map
288
339
 
289
340
  ranges = [[]]
290
- map.keys.sort.inject("") do |s, code|
341
+ map.keys.sort.reduce('') do |_s, code|
291
342
  ranges << [] if ranges.last.length >= 100
292
343
  unicode = map[code]
293
- ranges.last << "<%02x><%04x>" % [code, unicode]
344
+ ranges.last << format(
345
+ '<%<code>02x><%<unicode>04x>',
346
+ code: code,
347
+ unicode: unicode
348
+ )
294
349
  end
295
350
 
296
- range_blocks = ranges.inject("") do |s, list|
297
- s << "%d beginbfchar\n%s\nendbfchar\n" % [list.length, list.join("\n")]
298
- end
351
+ range_blocks =
352
+ ranges.reduce(+'') do |s, list|
353
+ s << format(
354
+ "%<lenght>d beginbfchar\n%<list>s\nendbfchar\n",
355
+ lenght: list.length,
356
+ list: list.join("\n")
357
+ )
358
+ end
299
359
 
300
360
  to_unicode_cmap = UNICODE_CMAP_TEMPLATE % range_blocks.strip
301
361
 
@@ -303,16 +363,18 @@ module Prawn
303
363
  cmap << to_unicode_cmap
304
364
  cmap.stream.compress!
305
365
 
306
- reference.data.update(:Subtype => :TrueType,
307
- :BaseFont => basename.to_sym,
308
- :FontDescriptor => descriptor,
309
- :FirstChar => 32,
310
- :LastChar => 255,
311
- :Widths => @document.ref!(widths),
312
- :ToUnicode => cmap)
366
+ reference.data.update(
367
+ Subtype: :TrueType,
368
+ BaseFont: basename.to_sym,
369
+ FontDescriptor: descriptor,
370
+ FirstChar: 32,
371
+ LastChar: 255,
372
+ Widths: @document.ref!(widths),
373
+ ToUnicode: cmap
374
+ )
313
375
  end
314
376
 
315
- UNICODE_CMAP_TEMPLATE = <<-STR.strip.gsub(/^\s*/, "")
377
+ UNICODE_CMAP_TEMPLATE = <<-STR.strip.gsub(/^\s*/, '')
316
378
  /CIDInit /ProcSet findresource begin
317
379
  12 dict begin
318
380
  begincmap
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ # blend_mode.rb : Implements blend modes
4
+ #
5
+ # Contributed by John Ford. October, 2015
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+ #
9
+
10
+ module Prawn
11
+ module Graphics
12
+ # The Prawn::BlendMode module is used to change the way
13
+ # two layers are blended together.
14
+ #
15
+ # Passing an array of blend modes is allowed. PDF viewers should
16
+ # blend layers based on the first recognized blend mode.
17
+ #
18
+ # Valid blend modes in v1.4 of the PDF spec include :Normal, :Multiply,
19
+ # :Screen, :Overlay, :Darken, :Lighten, :ColorDodge, :ColorBurn, :HardLight,
20
+ # :SoftLight, :Difference, :Exclusion, :Hue, :Saturation, :Color, and
21
+ # :Luminosity.
22
+ #
23
+ # Example:
24
+ # pdf.fill_color('0000ff')
25
+ # pdf.fill_rectangle([x, y+25], 50, 50)
26
+ # pdf.blend_mode(:Multiply) do
27
+ # pdf.fill_color('ff0000')
28
+ # pdf.fill_circle([x, y], 25)
29
+ # end
30
+ #
31
+ module BlendMode
32
+ # @group Stable API
33
+
34
+ def blend_mode(blend_mode = :Normal)
35
+ renderer.min_version(1.4)
36
+
37
+ save_graphics_state if block_given?
38
+ renderer.add_content "/#{blend_mode_dictionary_name(blend_mode)} gs"
39
+ if block_given?
40
+ yield
41
+ restore_graphics_state
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def blend_mode_dictionary_registry
48
+ @blend_mode_dictionary_registry ||= {}
49
+ end
50
+
51
+ def blend_mode_dictionary_name(blend_mode)
52
+ key = Array(blend_mode).join('')
53
+ dictionary_name = "BM#{key}"
54
+
55
+ dictionary = blend_mode_dictionary_registry[dictionary_name] ||= ref!(
56
+ Type: :ExtGState,
57
+ BM: blend_mode
58
+ )
59
+
60
+ page.ext_gstates[dictionary_name] = dictionary
61
+ dictionary_name
62
+ end
63
+ end
64
+ end
65
+ end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # cap_style.rb : Implements stroke cap styling
4
4
  #
@@ -9,8 +9,9 @@
9
9
  module Prawn
10
10
  module Graphics
11
11
  module CapStyle
12
+ # @group Stable API
12
13
 
13
- CAP_STYLES = { :butt => 0, :round => 1, :projecting_square => 2 }
14
+ CAP_STYLES = { butt: 0, round: 1, projecting_square: 2 }.freeze
14
15
 
15
16
  # Sets the cap style for stroked lines and curves
16
17
  #
@@ -18,7 +19,7 @@ module Prawn
18
19
  #
19
20
  # NOTE: If this method is never called, :butt will be used by default.
20
21
  #
21
- def cap_style(style=nil)
22
+ def cap_style(style = nil)
22
23
  return current_cap_style || :butt if style.nil?
23
24
 
24
25
  self.current_cap_style = style
@@ -26,7 +27,7 @@ module Prawn
26
27
  write_stroke_cap_style
27
28
  end
28
29
 
29
- alias_method :cap_style=, :cap_style
30
+ alias cap_style= cap_style
30
31
 
31
32
  private
32
33
 
@@ -39,7 +40,7 @@ module Prawn
39
40
  end
40
41
 
41
42
  def write_stroke_cap_style
42
- add_content "#{CAP_STYLES[current_cap_style]} J"
43
+ renderer.add_content "#{CAP_STYLES[current_cap_style]} J"
43
44
  end
44
45
  end
45
46
  end
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # color.rb : Implements color handling
4
4
  #
@@ -9,6 +9,7 @@
9
9
  module Prawn
10
10
  module Graphics
11
11
  module Color
12
+ # @group Stable API
12
13
 
13
14
  # Sets or returns the fill color.
14
15
  #
@@ -26,11 +27,12 @@ module Prawn
26
27
  #
27
28
  def fill_color(*color)
28
29
  return current_fill_color if color.empty?
30
+
29
31
  self.current_fill_color = process_color(*color)
30
32
  set_fill_color
31
33
  end
32
34
 
33
- alias_method :fill_color=, :fill_color
35
+ alias fill_color= fill_color
34
36
 
35
37
  # Sets or returns the line stroking color.
36
38
  #
@@ -48,12 +50,13 @@ module Prawn
48
50
  #
49
51
  def stroke_color(*color)
50
52
  return current_stroke_color if color.empty?
53
+
51
54
  color = process_color(*color)
52
55
  self.current_stroke_color = color
53
56
  set_stroke_color(color)
54
57
  end
55
58
 
56
- alias_method :stroke_color=, :stroke_color
59
+ alias stroke_color= stroke_color
57
60
 
58
61
  module_function
59
62
 
@@ -64,7 +67,7 @@ module Prawn
64
67
  # => "ff7808"
65
68
  #
66
69
  def rgb2hex(rgb)
67
- rgb.map { |e| "%02x" % e }.join
70
+ rgb.map { |e| format '%<value>02x', value: e }.join
68
71
  end
69
72
 
70
73
  # Converts hex string into RGB value array:
@@ -73,14 +76,16 @@ module Prawn
73
76
  # => [255, 120, 8]
74
77
  #
75
78
  def hex2rgb(hex)
76
- r,g,b = hex[0..1], hex[2..3], hex[4..5]
77
- [r,g,b].map { |e| e.to_i(16) }
79
+ r = hex[0..1]
80
+ g = hex[2..3]
81
+ b = hex[4..5]
82
+ [r, g, b].map { |e| e.to_i(16) }
78
83
  end
79
84
 
80
85
  private
81
86
 
82
87
  def process_color(*color)
83
- case(color.size)
88
+ case color.size
84
89
  when 1
85
90
  color[0]
86
91
  when 4
@@ -93,7 +98,11 @@ module Prawn
93
98
  def color_type(color)
94
99
  case color
95
100
  when String
96
- :RGB
101
+ if /\A\h{6}\z/.match?(color)
102
+ :RGB
103
+ else
104
+ raise ArgumentError, "Unknown type of color: #{color.inspect}"
105
+ end
97
106
  when Array
98
107
  case color.length
99
108
  when 3
@@ -109,16 +118,16 @@ module Prawn
109
118
  def normalize_color(color)
110
119
  case color_type(color)
111
120
  when :RGB
112
- r,g,b = hex2rgb(color)
121
+ r, g, b = hex2rgb(color)
113
122
  [r / 255.0, g / 255.0, b / 255.0]
114
123
  when :CMYK
115
- c,m,y,k = *color
124
+ c, m, y, k = *color
116
125
  [c / 100.0, m / 100.0, y / 100.0, k / 100.0]
117
126
  end
118
127
  end
119
128
 
120
129
  def color_to_s(color)
121
- normalize_color(color).map { |c| '%.3f' % c }.join(' ')
130
+ PDF::Core.real_params normalize_color(color)
122
131
  end
123
132
 
124
133
  def color_space(color)
@@ -130,42 +139,48 @@ module Prawn
130
139
  end
131
140
  end
132
141
 
133
- COLOR_SPACES = [:DeviceRGB, :DeviceCMYK, :Pattern]
142
+ COLOR_SPACES = %i[DeviceRGB DeviceCMYK Pattern].freeze
134
143
 
135
144
  def set_color_space(type, color_space)
136
145
  # don't set the same color space again
137
- return if current_color_space(type) == color_space && !state.page.in_stamp_stream?
146
+ if current_color_space(type) == color_space &&
147
+ !state.page.in_stamp_stream?
148
+ return
149
+ end
150
+
138
151
  set_current_color_space(color_space, type)
139
152
 
140
153
  unless COLOR_SPACES.include?(color_space)
141
154
  raise ArgumentError, "unknown color space: '#{color_space}'"
142
155
  end
143
156
 
144
- operator = case type
145
- when :fill
146
- 'cs'
147
- when :stroke
148
- 'CS'
149
- else
150
- raise ArgumentError, "unknown type '#{type}'"
151
- end
157
+ operator =
158
+ case type
159
+ when :fill
160
+ 'cs'
161
+ when :stroke
162
+ 'CS'
163
+ else
164
+ raise ArgumentError, "unknown type '#{type}'"
165
+ end
152
166
 
153
- add_content "/#{color_space} #{operator}"
167
+ renderer.add_content "/#{color_space} #{operator}"
154
168
  end
155
169
 
156
170
  def set_color(type, color, options = {})
157
- operator = case type
158
- when :fill
159
- 'scn'
160
- when :stroke
161
- 'SCN'
162
- else
163
- raise ArgumentError, "unknown type '#{type}'"
164
- end
171
+ operator =
172
+ case type
173
+ when :fill
174
+ 'scn'
175
+ when :stroke
176
+ 'SCN'
177
+ else
178
+ raise ArgumentError, "unknown type '#{type}'"
179
+ end
165
180
 
166
181
  if options[:pattern]
167
182
  set_color_space type, :Pattern
168
- add_content "/#{color} #{operator}"
183
+ renderer.add_content "/#{color} #{operator}"
169
184
  else
170
185
  set_color_space type, color_space(color)
171
186
  color = color_to_s(color)
@@ -186,8 +201,6 @@ module Prawn
186
201
  set_stroke_color
187
202
  end
188
203
 
189
- private
190
-
191
204
  def current_color_space(type)
192
205
  graphic_state.color_space[type]
193
206
  end
@@ -213,19 +226,9 @@ module Prawn
213
226
  graphic_state.stroke_color = color
214
227
  end
215
228
 
216
- def write_fill_color
217
- write_color(current_fill_color, 'scn')
218
- end
219
-
220
- def write_stroke_color
221
- write_color(current_fill_color, 'SCN')
222
- end
223
-
224
229
  def write_color(color, operator)
225
- add_content "#{color} #{operator}"
230
+ renderer.add_content "#{color} #{operator}"
226
231
  end
227
-
228
232
  end
229
233
  end
230
234
  end
231
-