hexapdf 0.11.9 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (270) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +157 -0
  3. data/LICENSE +1 -1
  4. data/examples/001-hello_world.rb +1 -1
  5. data/examples/002-graphics.rb +1 -1
  6. data/examples/003-arcs.rb +1 -1
  7. data/examples/004-optimizing.rb +1 -1
  8. data/examples/005-merging.rb +1 -1
  9. data/examples/006-standard_pdf_fonts.rb +1 -1
  10. data/examples/007-truetype.rb +1 -1
  11. data/examples/008-show_char_bboxes.rb +1 -1
  12. data/examples/009-text_layouter_alignment.rb +1 -1
  13. data/examples/010-text_layouter_inline_boxes.rb +1 -1
  14. data/examples/011-text_layouter_line_wrapping.rb +1 -1
  15. data/examples/012-text_layouter_styling.rb +1 -1
  16. data/examples/013-text_layouter_shapes.rb +1 -1
  17. data/examples/014-text_in_polygon.rb +1 -1
  18. data/examples/015-boxes.rb +1 -1
  19. data/examples/016-frame_automatic_box_placement.rb +1 -1
  20. data/examples/017-frame_text_flow.rb +1 -1
  21. data/examples/018-composer.rb +1 -1
  22. data/examples/019-acro_form.rb +51 -0
  23. data/lib/hexapdf.rb +1 -1
  24. data/lib/hexapdf/cli.rb +3 -1
  25. data/lib/hexapdf/cli/batch.rb +1 -1
  26. data/lib/hexapdf/cli/command.rb +22 -11
  27. data/lib/hexapdf/cli/files.rb +1 -1
  28. data/lib/hexapdf/cli/form.rb +240 -0
  29. data/lib/hexapdf/cli/image2pdf.rb +3 -2
  30. data/lib/hexapdf/cli/images.rb +1 -1
  31. data/lib/hexapdf/cli/info.rb +52 -3
  32. data/lib/hexapdf/cli/inspect.rb +31 -9
  33. data/lib/hexapdf/cli/merge.rb +2 -2
  34. data/lib/hexapdf/cli/modify.rb +1 -1
  35. data/lib/hexapdf/cli/optimize.rb +1 -1
  36. data/lib/hexapdf/cli/split.rb +1 -1
  37. data/lib/hexapdf/cli/watermark.rb +1 -1
  38. data/lib/hexapdf/composer.rb +2 -2
  39. data/lib/hexapdf/configuration.rb +81 -11
  40. data/lib/hexapdf/content.rb +3 -1
  41. data/lib/hexapdf/content/canvas.rb +5 -18
  42. data/lib/hexapdf/content/color_space.rb +111 -32
  43. data/lib/hexapdf/content/graphic_object.rb +1 -1
  44. data/lib/hexapdf/content/graphic_object/arc.rb +4 -4
  45. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
  46. data/lib/hexapdf/content/graphic_object/geom2d.rb +1 -1
  47. data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
  48. data/lib/hexapdf/content/graphics_state.rb +1 -1
  49. data/lib/hexapdf/content/operator.rb +9 -9
  50. data/lib/hexapdf/content/parser.rb +18 -5
  51. data/lib/hexapdf/content/processor.rb +1 -1
  52. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  53. data/lib/hexapdf/data_dir.rb +1 -1
  54. data/lib/hexapdf/dictionary.rb +5 -5
  55. data/lib/hexapdf/dictionary_fields.rb +2 -10
  56. data/lib/hexapdf/document.rb +45 -17
  57. data/lib/hexapdf/document/files.rb +1 -2
  58. data/lib/hexapdf/document/fonts.rb +1 -1
  59. data/lib/hexapdf/document/images.rb +1 -1
  60. data/lib/hexapdf/document/pages.rb +3 -14
  61. data/lib/hexapdf/encryption.rb +1 -1
  62. data/lib/hexapdf/encryption/aes.rb +1 -1
  63. data/lib/hexapdf/encryption/arc4.rb +1 -1
  64. data/lib/hexapdf/encryption/fast_aes.rb +1 -1
  65. data/lib/hexapdf/encryption/fast_arc4.rb +2 -2
  66. data/lib/hexapdf/encryption/identity.rb +1 -1
  67. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  68. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  69. data/lib/hexapdf/encryption/security_handler.rb +2 -1
  70. data/lib/hexapdf/encryption/standard_security_handler.rb +2 -1
  71. data/lib/hexapdf/error.rb +1 -1
  72. data/lib/hexapdf/filter.rb +3 -3
  73. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  74. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  75. data/lib/hexapdf/filter/encryption.rb +1 -1
  76. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  77. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  78. data/lib/hexapdf/filter/{jpx_decode.rb → pass_through.rb} +5 -5
  79. data/lib/hexapdf/filter/predictor.rb +1 -1
  80. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  81. data/lib/hexapdf/font/cmap.rb +2 -5
  82. data/lib/hexapdf/font/cmap/parser.rb +1 -1
  83. data/lib/hexapdf/font/cmap/writer.rb +1 -1
  84. data/lib/hexapdf/font/encoding.rb +1 -1
  85. data/lib/hexapdf/font/encoding/base.rb +9 -1
  86. data/lib/hexapdf/font/encoding/difference_encoding.rb +7 -1
  87. data/lib/hexapdf/font/encoding/glyph_list.rb +1 -1
  88. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  89. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
  90. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  91. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  92. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +1 -1
  93. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  94. data/lib/hexapdf/font/invalid_glyph.rb +1 -1
  95. data/lib/hexapdf/font/true_type.rb +1 -1
  96. data/lib/hexapdf/font/true_type/builder.rb +1 -1
  97. data/lib/hexapdf/font/true_type/font.rb +1 -1
  98. data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
  99. data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
  100. data/lib/hexapdf/font/true_type/table.rb +1 -1
  101. data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
  102. data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
  103. data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
  104. data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
  105. data/lib/hexapdf/font/true_type/table/head.rb +2 -1
  106. data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
  107. data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
  108. data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
  109. data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
  110. data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
  111. data/lib/hexapdf/font/true_type/table/name.rb +1 -1
  112. data/lib/hexapdf/font/true_type/table/os2.rb +3 -1
  113. data/lib/hexapdf/font/true_type/table/post.rb +1 -1
  114. data/lib/hexapdf/font/true_type_wrapper.rb +54 -51
  115. data/lib/hexapdf/font/type1.rb +1 -1
  116. data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
  117. data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
  118. data/lib/hexapdf/font/type1/font.rb +1 -1
  119. data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
  120. data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
  121. data/lib/hexapdf/font/type1_wrapper.rb +68 -52
  122. data/lib/hexapdf/font_loader.rb +1 -1
  123. data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
  124. data/lib/hexapdf/font_loader/from_file.rb +1 -1
  125. data/lib/hexapdf/font_loader/standard14.rb +1 -1
  126. data/lib/hexapdf/image_loader.rb +1 -1
  127. data/lib/hexapdf/image_loader/jpeg.rb +1 -1
  128. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  129. data/lib/hexapdf/image_loader/png.rb +4 -3
  130. data/lib/hexapdf/importer.rb +2 -4
  131. data/lib/hexapdf/layout.rb +1 -1
  132. data/lib/hexapdf/layout/box.rb +1 -1
  133. data/lib/hexapdf/layout/frame.rb +1 -1
  134. data/lib/hexapdf/layout/image_box.rb +1 -1
  135. data/lib/hexapdf/layout/inline_box.rb +1 -1
  136. data/lib/hexapdf/layout/line.rb +2 -2
  137. data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
  138. data/lib/hexapdf/layout/style.rb +24 -24
  139. data/lib/hexapdf/layout/text_box.rb +1 -1
  140. data/lib/hexapdf/layout/text_fragment.rb +1 -1
  141. data/lib/hexapdf/layout/text_layouter.rb +1 -1
  142. data/lib/hexapdf/layout/text_shaper.rb +4 -3
  143. data/lib/hexapdf/layout/width_from_polygon.rb +1 -1
  144. data/lib/hexapdf/name_tree_node.rb +1 -1
  145. data/lib/hexapdf/number_tree_node.rb +1 -1
  146. data/lib/hexapdf/object.rb +32 -27
  147. data/lib/hexapdf/parser.rb +69 -6
  148. data/lib/hexapdf/pdf_array.rb +10 -3
  149. data/lib/hexapdf/rectangle.rb +31 -1
  150. data/lib/hexapdf/reference.rb +1 -1
  151. data/lib/hexapdf/revision.rb +2 -1
  152. data/lib/hexapdf/revisions.rb +30 -22
  153. data/lib/hexapdf/serializer.rb +2 -2
  154. data/lib/hexapdf/stream.rb +1 -1
  155. data/lib/hexapdf/task.rb +1 -1
  156. data/lib/hexapdf/task/dereference.rb +1 -1
  157. data/lib/hexapdf/task/optimize.rb +7 -5
  158. data/lib/hexapdf/tokenizer.rb +5 -4
  159. data/lib/hexapdf/type.rb +1 -1
  160. data/lib/hexapdf/type/acro_form.rb +7 -1
  161. data/lib/hexapdf/type/acro_form/appearance_generator.rb +405 -0
  162. data/lib/hexapdf/type/acro_form/button_field.rb +305 -0
  163. data/lib/hexapdf/type/acro_form/choice_field.rb +220 -0
  164. data/lib/hexapdf/type/acro_form/field.rb +250 -17
  165. data/lib/hexapdf/type/acro_form/form.rb +159 -7
  166. data/lib/hexapdf/type/acro_form/text_field.rb +187 -0
  167. data/lib/hexapdf/type/acro_form/variable_text_field.rb +122 -0
  168. data/lib/hexapdf/type/action.rb +1 -1
  169. data/lib/hexapdf/type/actions.rb +1 -1
  170. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  171. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  172. data/lib/hexapdf/type/actions/launch.rb +1 -1
  173. data/lib/hexapdf/type/actions/uri.rb +4 -3
  174. data/lib/hexapdf/type/annotation.rb +73 -3
  175. data/lib/hexapdf/type/annotations.rb +1 -1
  176. data/lib/hexapdf/type/annotations/link.rb +2 -2
  177. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  178. data/lib/hexapdf/type/annotations/text.rb +1 -1
  179. data/lib/hexapdf/type/annotations/widget.rb +238 -2
  180. data/lib/hexapdf/type/catalog.rb +23 -3
  181. data/lib/hexapdf/type/cid_font.rb +1 -1
  182. data/lib/hexapdf/type/embedded_file.rb +1 -1
  183. data/lib/hexapdf/type/file_specification.rb +2 -2
  184. data/lib/hexapdf/type/font.rb +18 -1
  185. data/lib/hexapdf/type/font_descriptor.rb +2 -2
  186. data/lib/hexapdf/type/font_simple.rb +4 -2
  187. data/lib/hexapdf/type/font_true_type.rb +7 -3
  188. data/lib/hexapdf/type/font_type0.rb +2 -2
  189. data/lib/hexapdf/type/font_type1.rb +16 -1
  190. data/lib/hexapdf/type/font_type3.rb +1 -1
  191. data/lib/hexapdf/type/form.rb +12 -2
  192. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  193. data/lib/hexapdf/type/icon_fit.rb +1 -1
  194. data/lib/hexapdf/type/image.rb +5 -3
  195. data/lib/hexapdf/type/info.rb +1 -1
  196. data/lib/hexapdf/type/names.rb +1 -1
  197. data/lib/hexapdf/type/object_stream.rb +1 -1
  198. data/lib/hexapdf/type/page.rb +36 -12
  199. data/lib/hexapdf/type/page_tree_node.rb +37 -16
  200. data/lib/hexapdf/type/resources.rb +17 -3
  201. data/lib/hexapdf/type/trailer.rb +4 -6
  202. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  203. data/lib/hexapdf/type/xref_stream.rb +1 -1
  204. data/lib/hexapdf/utils/bit_field.rb +38 -24
  205. data/lib/hexapdf/utils/bit_stream.rb +1 -1
  206. data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
  207. data/lib/hexapdf/utils/lru_cache.rb +1 -1
  208. data/lib/hexapdf/utils/math_helpers.rb +1 -1
  209. data/lib/hexapdf/utils/object_hash.rb +1 -1
  210. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  211. data/lib/hexapdf/utils/sorted_tree_node.rb +19 -16
  212. data/lib/hexapdf/version.rb +2 -2
  213. data/lib/hexapdf/writer.rb +1 -1
  214. data/lib/hexapdf/xref_section.rb +1 -1
  215. data/test/hexapdf/common_tokenizer_tests.rb +6 -1
  216. data/test/hexapdf/content/common.rb +2 -2
  217. data/test/hexapdf/content/graphic_object/test_arc.rb +4 -4
  218. data/test/hexapdf/content/test_canvas.rb +3 -3
  219. data/test/hexapdf/content/test_color_space.rb +71 -8
  220. data/test/hexapdf/content/test_operator.rb +22 -22
  221. data/test/hexapdf/content/test_parser.rb +14 -0
  222. data/test/hexapdf/document/test_fonts.rb +1 -1
  223. data/test/hexapdf/document/test_pages.rb +6 -6
  224. data/test/hexapdf/encryption/test_aes.rb +4 -4
  225. data/test/hexapdf/encryption/test_standard_security_handler.rb +11 -11
  226. data/test/hexapdf/filter/test_ascii85_decode.rb +1 -1
  227. data/test/hexapdf/filter/test_ascii_hex_decode.rb +1 -1
  228. data/test/hexapdf/font/encoding/test_base.rb +10 -0
  229. data/test/hexapdf/font/encoding/test_difference_encoding.rb +8 -0
  230. data/test/hexapdf/font/test_true_type_wrapper.rb +10 -7
  231. data/test/hexapdf/font/test_type1_wrapper.rb +33 -8
  232. data/test/hexapdf/layout/test_style.rb +1 -1
  233. data/test/hexapdf/layout/test_text_layouter.rb +3 -4
  234. data/test/hexapdf/test_configuration.rb +2 -2
  235. data/test/hexapdf/test_dictionary.rb +3 -1
  236. data/test/hexapdf/test_dictionary_fields.rb +2 -2
  237. data/test/hexapdf/test_document.rb +16 -4
  238. data/test/hexapdf/test_object.rb +44 -26
  239. data/test/hexapdf/test_parser.rb +125 -55
  240. data/test/hexapdf/test_pdf_array.rb +7 -0
  241. data/test/hexapdf/test_rectangle.rb +14 -0
  242. data/test/hexapdf/test_revision.rb +3 -0
  243. data/test/hexapdf/test_revisions.rb +35 -0
  244. data/test/hexapdf/test_writer.rb +2 -2
  245. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +521 -0
  246. data/test/hexapdf/type/acro_form/test_button_field.rb +281 -0
  247. data/test/hexapdf/type/acro_form/test_choice_field.rb +137 -0
  248. data/test/hexapdf/type/acro_form/test_field.rb +163 -6
  249. data/test/hexapdf/type/acro_form/test_form.rb +189 -22
  250. data/test/hexapdf/type/acro_form/test_text_field.rb +121 -0
  251. data/test/hexapdf/type/acro_form/test_variable_text_field.rb +77 -0
  252. data/test/hexapdf/type/annotations/test_text.rb +1 -1
  253. data/test/hexapdf/type/annotations/test_widget.rb +199 -0
  254. data/test/hexapdf/type/test_annotation.rb +45 -0
  255. data/test/hexapdf/type/test_catalog.rb +18 -0
  256. data/test/hexapdf/type/test_font.rb +5 -0
  257. data/test/hexapdf/type/test_font_simple.rb +2 -1
  258. data/test/hexapdf/type/test_font_true_type.rb +6 -0
  259. data/test/hexapdf/type/test_font_type1.rb +8 -0
  260. data/test/hexapdf/type/test_form.rb +19 -1
  261. data/test/hexapdf/type/test_image.rb +7 -0
  262. data/test/hexapdf/type/test_page.rb +45 -7
  263. data/test/hexapdf/type/test_page_tree_node.rb +62 -12
  264. data/test/hexapdf/type/test_resources.rb +20 -0
  265. data/test/hexapdf/type/test_trailer.rb +4 -0
  266. data/test/hexapdf/utils/test_bit_field.rb +15 -1
  267. data/test/hexapdf/utils/test_sorted_tree_node.rb +10 -9
  268. data/test/test_helper.rb +1 -1
  269. metadata +34 -21
  270. data/lib/hexapdf/filter/dct_decode.rb +0 -60
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -104,23 +104,33 @@ module HexaPDF
104
104
  # Returns the wrapped Type1 font object.
105
105
  attr_reader :wrapped_font
106
106
 
107
- # The PDF font dictionary representing the wrapped font.
108
- attr_reader :dict
107
+ # Returns the PDF object associated with the wrapper.
108
+ attr_reader :pdf_object
109
109
 
110
- # Creates a new object wrapping the Type1 font for the PDF document.
110
+ # Creates a new Type1Wrapper object wrapping the Type1 font.
111
111
  #
112
- # The optional argument +custom_encoding+ can be set to +true+ so that a custom encoding
113
- # instead of the WinAnsiEncoding is used.
114
- def initialize(document, font, custom_encoding: false)
115
- @document = document
112
+ # The optional argument +pdf_object+ can be used to set the PDF font object that this wrapper
113
+ # should be associated with. If no object is set, a suitable one is automatically created.
114
+ #
115
+ # If +pdf_object+ is provided, the PDF object's encoding is used. Otherwise, the
116
+ # WinAnsiEncoding or, for 'Special' fonts, the font's internal encoding is used. The optional
117
+ # argument +custom_encoding+ can be set to +true+ so that a custom encoding is used (only
118
+ # respected if +pdf_object+ is not provided).
119
+ def initialize(document, font, pdf_object: nil, custom_encoding: false)
116
120
  @wrapped_font = font
121
+ @pdf_object = pdf_object || create_pdf_object(document)
122
+ @missing_glyph_callable = document.config['font.on_missing_glyph']
117
123
 
118
- @dict = build_font_dict
119
- @document.register_listener(:complete_objects, &method(:complete_font_dict))
120
- if @wrapped_font.metrics.character_set == 'Special' || custom_encoding
124
+ if pdf_object
125
+ @encoding = pdf_object.encoding
126
+ @max_code = 255 # Encoding is not modified
127
+ elsif custom_encoding
121
128
  @encoding = Encoding::Base.new
122
129
  @encoding.code_to_name[32] = :space
123
130
  @max_code = 32 # 32 = space
131
+ elsif @wrapped_font.metrics.character_set == 'Special'
132
+ @encoding = @wrapped_font.encoding
133
+ @max_code = 255 # Encoding is not modified
124
134
  else
125
135
  @encoding = Encoding.for_name(:WinAnsiEncoding)
126
136
  @max_code = 255 # Encoding is not modified
@@ -150,17 +160,25 @@ module HexaPDF
150
160
  if @wrapped_font.metrics.character_metrics.key?(name)
151
161
  Glyph.new(@wrapped_font, name, str)
152
162
  else
153
- @document.config['font.on_missing_glyph'].call(str, font_type, @wrapped_font)
163
+ @missing_glyph_callable.call(str, font_type, @wrapped_font)
154
164
  end
155
165
  end
156
166
  end
157
167
 
158
168
  # Returns an array of glyph objects representing the characters in the UTF-8 encoded string.
169
+ #
170
+ # If a Unicode codepoint is not available as glyph object, it is tried to map the codepoint
171
+ # using the font's internal encoding. This is useful, for example, for the ZapfDingbats font
172
+ # to use ASCII characters for accessing the glyphs.
159
173
  def decode_utf8(str)
160
174
  str.codepoints.map! do |c|
161
175
  @codepoint_to_glyph[c] ||=
162
176
  begin
163
177
  name = Encoding::GlyphList.unicode_to_name(+'' << c, **@zapf_dingbats_opt)
178
+ if @wrapped_font.metrics.character_set == 'Special' &&
179
+ (name == :'.notdef' || !@wrapped_font.metrics.character_metrics.key?(name))
180
+ name = @encoding.name(c)
181
+ end
164
182
  name = +"u" << c.to_s(16).rjust(6, '0') if name == :'.notdef'
165
183
  glyph(name)
166
184
  end
@@ -174,7 +192,7 @@ module HexaPDF
174
192
  if glyph.name == @wrapped_font.missing_glyph_id
175
193
  raise HexaPDF::Error, "Glyph for #{glyph.str.inspect} missing"
176
194
  end
177
- code = @encoding.code_to_name.key(glyph.name)
195
+ code = @encoding.code(glyph.name)
178
196
  if code
179
197
  code.chr.freeze
180
198
  elsif @max_code < 255
@@ -189,49 +207,47 @@ module HexaPDF
189
207
 
190
208
  private
191
209
 
192
- # Builds a generic Type1 font dictionary for the wrapped font.
193
- #
194
- # Generic in the sense that no information regarding the encoding or widths is included.
195
- def build_font_dict
196
- unless defined?(@fd)
197
- @fd = @document.wrap({Type: :FontDescriptor,
198
- FontName: @wrapped_font.font_name.intern,
199
- FontWeight: @wrapped_font.weight_class,
200
- FontBBox: @wrapped_font.bounding_box,
201
- ItalicAngle: @wrapped_font.italic_angle || 0,
202
- Ascent: @wrapped_font.ascender || 0,
203
- Descent: @wrapped_font.descender || 0,
204
- CapHeight: @wrapped_font.cap_height,
205
- XHeight: @wrapped_font.x_height,
206
- StemH: @wrapped_font.dominant_horizontal_stem_width,
207
- StemV: @wrapped_font.dominant_vertical_stem_width || 0})
208
- @fd.flag(:fixed_pitch) if @wrapped_font.metrics.is_fixed_pitch
209
- @fd.flag(@wrapped_font.metrics.character_set == 'Special' ? :symbolic : :nonsymbolic)
210
- @fd.must_be_indirect = true
211
- end
212
-
213
- @document.wrap({Type: :Font, Subtype: :Type1,
214
- BaseFont: @wrapped_font.font_name.intern, Encoding: :WinAnsiEncoding,
215
- FontDescriptor: @fd})
216
- end
217
-
218
210
  # Array of valid encoding names in PDF
219
211
  VALID_ENCODING_NAMES = [:WinAnsiEncoding, :MacRomanEncoding, :MacExpertEncoding].freeze
220
212
 
221
- # Completes the font dictionary by filling in the values that depend on the used encoding.
222
- def complete_font_dict
223
- min, max = @encoding.code_to_name.keys.minmax
224
- @dict[:FirstChar] = min
225
- @dict[:LastChar] = max
226
- @dict[:Widths] = (min..max).map {|code| glyph(@encoding.name(code)).width }
227
-
228
- if VALID_ENCODING_NAMES.include?(@encoding.encoding_name)
229
- @dict[:Encoding] = @encoding.encoding_name
230
- else
231
- differences = [min]
232
- (min..max).each {|code| differences << @encoding.name(code) }
233
- @dict[:Encoding] = {Differences: differences}
213
+ # Creates a PDF object representing the wrapped font for the given PDF document.
214
+ def create_pdf_object(document)
215
+ fd = document.wrap({Type: :FontDescriptor,
216
+ FontName: @wrapped_font.font_name.intern,
217
+ FontWeight: @wrapped_font.weight_class,
218
+ FontBBox: @wrapped_font.bounding_box,
219
+ ItalicAngle: @wrapped_font.italic_angle || 0,
220
+ Ascent: @wrapped_font.ascender || 0,
221
+ Descent: @wrapped_font.descender || 0,
222
+ CapHeight: @wrapped_font.cap_height,
223
+ XHeight: @wrapped_font.x_height,
224
+ StemH: @wrapped_font.dominant_horizontal_stem_width,
225
+ StemV: @wrapped_font.dominant_vertical_stem_width || 0})
226
+ fd.flag(:fixed_pitch) if @wrapped_font.metrics.is_fixed_pitch
227
+ fd.flag(@wrapped_font.metrics.character_set == 'Special' ? :symbolic : :nonsymbolic)
228
+ fd.must_be_indirect = true
229
+
230
+ dict = document.wrap({Type: :Font, Subtype: :Type1,
231
+ BaseFont: @wrapped_font.font_name.intern,
232
+ FontDescriptor: fd})
233
+ dict.font_wrapper = self
234
+
235
+ document.register_listener(:complete_objects) do
236
+ min, max = @encoding.code_to_name.keys.minmax
237
+ dict[:FirstChar] = min
238
+ dict[:LastChar] = max
239
+ dict[:Widths] = (min..max).map {|code| glyph(@encoding.name(code)).width }
240
+
241
+ if VALID_ENCODING_NAMES.include?(@encoding.encoding_name)
242
+ dict[:Encoding] = @encoding.encoding_name
243
+ elsif @encoding != @wrapped_font.encoding
244
+ differences = [min]
245
+ (min..max).each {|code| differences << @encoding.name(code) }
246
+ dict[:Encoding] = {Differences: differences}
247
+ end
234
248
  end
249
+
250
+ dict
235
251
  end
236
252
 
237
253
  end
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -162,9 +162,10 @@ module HexaPDF
162
162
  io.seek(length, IO::SEEK_CUR)
163
163
  end
164
164
  when 'tRNS' # PNG s11.3.2
165
- if @color_type == INDEXED
165
+ case @color_type
166
+ when INDEXED
166
167
  trns = io.read(length).unpack('C*')
167
- elsif @color_type == TRUECOLOR || @color_type == GREYSCALE
168
+ when TRUECOLOR, GREYSCALE
168
169
  dict[:Mask] = io.read(length).unpack('n*').map {|val| [val, val] }.flatten
169
170
  else
170
171
  io.seek(length, IO::SEEK_CUR)
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -109,9 +109,7 @@ module HexaPDF
109
109
  def duplicate(object)
110
110
  case object
111
111
  when Hash
112
- object.each_with_object({}) do |(k, v), obj|
113
- obj[k] = duplicate(v)
114
- end
112
+ object.transform_values {|v| duplicate(v) }
115
113
  when Array
116
114
  object.map {|v| duplicate(v) }
117
115
  when HexaPDF::Reference
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -198,7 +198,7 @@ module HexaPDF
198
198
  # Note: The cache is not cleared!
199
199
  def add(item)
200
200
  last = @items.last
201
- if last.class == item.class && item.kind_of?(TextFragment) && last.style == item.style
201
+ if last.instance_of?(item.class) && item.kind_of?(TextFragment) && last.style == item.style
202
202
  if last.items.frozen?
203
203
  @items[-1] = last = last.dup
204
204
  last.items = last.items.dup
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -4,7 +4,7 @@
4
4
  # This file is part of HexaPDF.
5
5
  #
6
6
  # HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
7
- # Copyright (C) 2014-2019 Thomas Leitner
7
+ # Copyright (C) 2014-2020 Thomas Leitner
8
8
  #
9
9
  # HexaPDF is free software: you can redistribute it and/or modify it
10
10
  # under the terms of the GNU Affero General Public License version 3 as
@@ -524,7 +524,7 @@ module HexaPDF
524
524
  # Style.new(font_size: 15, align: :center, valign: center)
525
525
  def initialize(**properties)
526
526
  update(**properties)
527
- @scaled_item_widths = {}
527
+ @scaled_item_widths = {}.compare_by_identity
528
528
  end
529
529
 
530
530
  # Duplicates the complex properties that can be modified, as well as the cache.
@@ -883,41 +883,41 @@ module HexaPDF
883
883
  [:text_rise, 0],
884
884
  [:font_features, {}],
885
885
  [:text_rendering_mode, "Content::TextRenderingMode::FILL",
886
- setter: "Content::TextRenderingMode.normalize(value)"],
886
+ {setter: "Content::TextRenderingMode.normalize(value)"}],
887
887
  [:subscript, false,
888
- setter: "value; superscript(false) if superscript",
889
- valid_values: [true, false]],
888
+ {setter: "value; superscript(false) if superscript",
889
+ valid_values: [true, false]}],
890
890
  [:superscript, false,
891
- setter: "value; subscript(false) if subscript",
892
- valid_values: [true, false]],
893
- [:underline, false, valid_values: [true, false]],
894
- [:strikeout, false, valid_values: [true, false]],
891
+ {setter: "value; subscript(false) if subscript",
892
+ valid_values: [true, false]}],
893
+ [:underline, false, {valid_values: [true, false]}],
894
+ [:strikeout, false, {valid_values: [true, false]}],
895
895
  [:fill_color, "default_color"],
896
896
  [:fill_alpha, 1],
897
897
  [:stroke_color, "default_color"],
898
898
  [:stroke_alpha, 1],
899
899
  [:stroke_width, 1],
900
900
  [:stroke_cap_style, "Content::LineCapStyle::BUTT_CAP",
901
- setter: "Content::LineCapStyle.normalize(value)"],
901
+ {setter: "Content::LineCapStyle.normalize(value)"}],
902
902
  [:stroke_join_style, "Content::LineJoinStyle::MITER_JOIN",
903
- setter: "Content::LineJoinStyle.normalize(value)"],
903
+ {setter: "Content::LineJoinStyle.normalize(value)"}],
904
904
  [:stroke_miter_limit, 10.0],
905
905
  [:stroke_dash_pattern, "Content::LineDashPattern.new",
906
- setter: "Content::LineDashPattern.normalize(value, phase)", extra_args: ", phase = 0"],
907
- [:align, :left, valid_values: [:left, :center, :right, :justify]],
908
- [:valign, :top, valid_values: [:top, :center, :bottom]],
906
+ {setter: "Content::LineDashPattern.normalize(value, phase)", extra_args: ", phase = 0"}],
907
+ [:align, :left, {valid_values: [:left, :center, :right, :justify]}],
908
+ [:valign, :top, {valid_values: [:top, :center, :bottom]}],
909
909
  [:text_indent, 0],
910
910
  [:line_spacing, "LineSpacing.new(type: :single)",
911
- setter: "LineSpacing.new(**(value.kind_of?(Symbol) ? {type: value, value: extra_arg} : value))",
912
- extra_args: ", extra_arg = nil"],
913
- [:last_line_gap, false, valid_values: [true, false]],
911
+ {setter: "LineSpacing.new(**(value.kind_of?(Symbol) ? {type: value, value: extra_arg} : value))",
912
+ extra_args: ", extra_arg = nil"}],
913
+ [:last_line_gap, false, {valid_values: [true, false]}],
914
914
  [:background_color, nil],
915
- [:padding, "Quad.new(0)", setter: "Quad.new(value)"],
916
- [:margin, "Quad.new(0)", setter: "Quad.new(value)"],
917
- [:border, "Border.new", setter: "Border.new(**value)"],
918
- [:overlays, "Layers.new", setter: "Layers.new(value)"],
919
- [:underlays, "Layers.new", setter: "Layers.new(value)"],
920
- [:position, :default, valid_values: [:default, :float, :flow, :absolute]],
915
+ [:padding, "Quad.new(0)", {setter: "Quad.new(value)"}],
916
+ [:margin, "Quad.new(0)", {setter: "Quad.new(value)"}],
917
+ [:border, "Border.new", {setter: "Border.new(**value)"}],
918
+ [:overlays, "Layers.new", {setter: "Layers.new(value)"}],
919
+ [:underlays, "Layers.new", {setter: "Layers.new(value)"}],
920
+ [:position, :default, {valid_values: [:default, :float, :flow, :absolute]}],
921
921
  [:position_hint, nil],
922
922
  ].each do |name, default, options = {}|
923
923
  default = default.inspect unless default.kind_of?(String)
@@ -1075,7 +1075,7 @@ module HexaPDF
1075
1075
  # The item may be a (singleton) glyph object or an integer/float, i.e. items that can appear
1076
1076
  # inside a TextFragment.
1077
1077
  def scaled_item_width(item)
1078
- @scaled_item_widths[item.object_id] ||=
1078
+ @scaled_item_widths[item] ||=
1079
1079
  begin
1080
1080
  if item.kind_of?(Numeric)
1081
1081
  -item * scaled_font_size