hexapdf 0.11.9 → 0.13.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 (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
@@ -54,8 +54,7 @@ module HexaPDF
54
54
  # HexaPDF::Revision object's trailer dictionary is always of this type. Only when a
55
55
  # cross-reference stream is written is the trailer integrated into the stream's dictionary.
56
56
  #
57
- # See: PDF1.7 s7.5.5, s14.4
58
- # XRefStream
57
+ # See: PDF1.7 s7.5.5, s14.4; XRefStream
59
58
  class Trailer < Dictionary
60
59
 
61
60
  define_type :XXTrailer
@@ -98,7 +97,7 @@ module HexaPDF
98
97
  private
99
98
 
100
99
  # Validates the trailer.
101
- def perform_validation
100
+ def perform_validation(&block)
102
101
  super
103
102
  unless value[:ID]
104
103
  msg = if value[:Encrypt]
@@ -112,8 +111,7 @@ module HexaPDF
112
111
 
113
112
  unless value[:Root]
114
113
  yield("A PDF document must have a Catalog dictionary", true)
115
- value[:Root] = document.add({Type: :Catalog})
116
- value[:Root].validate {|message, correctable| yield(message, correctable) }
114
+ catalog.validate(&block)
117
115
  end
118
116
 
119
117
  if value[:Encrypt] && (!document.security_handler ||
@@ -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
@@ -43,45 +43,59 @@ module HexaPDF
43
43
 
44
44
  # Creates a bit field for managing the integer attribute +name+.
45
45
  #
46
- # The +mapping+ argument specifies the mapping of names to bit indices which allows one to use
47
- # either the bit name or its index when getting or setting. When using an unknown bit name or
48
- # bit index, an error is raised.
46
+ # The +mapping+ argument specifies the mapping of names to zero-based bit indices which allows
47
+ # one to use either the bit name or its index when getting or setting. When using an unknown
48
+ # bit name or bit index, an error is raised.
49
49
  #
50
50
  # The calling class needs to respond to \#name and \#name= because these methods are used to
51
- # get and set the raw integer value.
51
+ # get and set the raw integer value; or provide custom method names using the +value_getter+
52
+ # and +value_setter+ arguments.
52
53
  #
53
- # After invoking the method the calling class has three new instance methods:
54
+ # After invoking the method the calling class has four new instance methods:
54
55
  #
55
56
  # * NAME_values which returns an array of bit names representing the set bits.
56
57
  # * NAME_include?(bit) which returns true if the given bit is set.
57
58
  # * set_NAME(*bits, clear_existing: false) for setting the given bits.
59
+ # * unset_NAME(*bits) for clearing the given bits.
58
60
  #
59
- # The method names can be overridden using the arguments +lister+, +getter+ and +setter+.
61
+ # The method names can be overridden using the arguments +lister+, +getter+, +setter+ and
62
+ # +unsetter+.
60
63
  def bit_field(name, mapping, lister: "#{name}_values", getter: "#{name}_include?",
61
- setter: "set_#{name}")
62
- bit_names = mapping.keys
64
+ setter: "set_#{name}", unsetter: "unset_#{name}", value_getter: name,
65
+ value_setter: "self.#{name}")
63
66
  mapping.default_proc = proc do |h, k|
64
67
  if h.value?(k)
65
- h[k] = k
68
+ k
66
69
  else
67
70
  raise ArgumentError, "Invalid bit field name or index '#{k}' for #{self.name}##{name}"
68
71
  end
69
72
  end
70
- value_getter = name
71
- value_setter = "#{name}="
72
73
 
73
- define_method(lister) do
74
- bit_names.map {|n| send(getter, n) ? n : nil }.compact
75
- end
76
- define_method(getter) do |bit|
77
- (send(value_getter) || 0)[mapping[bit]] == 1
78
- end
79
- define_method(setter) do |*bits, clear_existing: false|
80
- send(value_setter, 0) if clear_existing || send(value_getter).nil?
81
- result = send(value_getter)
82
- bits.each {|bit| result |= 1 << mapping[bit] }
83
- send(value_setter, result)
84
- end
74
+ module_eval(<<-EOF, __FILE__, __LINE__ + 1)
75
+ #{name.upcase}_BIT_MAPPING = mapping.freeze
76
+
77
+ def #{lister}
78
+ self.class::#{name.upcase}_BIT_MAPPING.keys.map {|n| #{getter}(n) ? n : nil }.compact
79
+ end
80
+
81
+ def #{getter}(bit)
82
+ (#{value_getter} || 0)[self.class::#{name.upcase}_BIT_MAPPING[bit]] == 1
83
+ end
84
+
85
+ def #{setter}(*bits, clear_existing: false)
86
+ #{value_setter} = 0 if clear_existing || #{value_getter}.nil?
87
+ result = #{value_getter}
88
+ bits.each {|bit| result |= 1 << self.class::#{name.upcase}_BIT_MAPPING[bit] }
89
+ #{value_setter} = result
90
+ end
91
+
92
+ def #{unsetter}(*bits)
93
+ result = #{value_getter} || 0
94
+ return if result == 0
95
+ bits.each {|bit| result &= ~(1 << self.class::#{name.upcase}_BIT_MAPPING[bit]) }
96
+ #{value_setter} = result
97
+ end
98
+ EOF
85
99
  end
86
100
 
87
101
  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
@@ -143,12 +143,12 @@ module HexaPDF
143
143
  stack.reverse_each.inject do |nested_node, node|
144
144
  if (!nested_node[container_name] || nested_node[container_name].empty?) &&
145
145
  (!nested_node[:Kids] || nested_node[:Kids].empty?)
146
- node[:Kids].delete_at(node[:Kids].index {|n| document.deref(n) == nested_node })
146
+ node[:Kids].delete(nested_node)
147
147
  document.delete(nested_node)
148
148
  end
149
149
  if !node[:Kids].empty? && node[:Limits]
150
- node[:Limits][0] = document.deref(node[:Kids][0])[:Limits][0]
151
- node[:Limits][1] = document.deref(node[:Kids][-1])[:Limits][1]
150
+ node[:Limits][0] = node[:Kids][0][:Limits][0]
151
+ node[:Limits][1] = node[:Kids][-1][:Limits][1]
152
152
  end
153
153
  node
154
154
  end
@@ -167,11 +167,11 @@ module HexaPDF
167
167
  if node.key?(container_name)
168
168
  index = find_in_leaf_node(node[container_name], key)
169
169
  if node[container_name][index] == key
170
- result = document.deref(node[container_name][index + 1])
170
+ result = node[container_name][index + 1]
171
171
  end
172
172
  elsif node.key?(:Kids)
173
173
  index = find_in_intermediate_node(node[:Kids], key)
174
- node = document.deref(node[:Kids][index])
174
+ node = node[:Kids][index]
175
175
  break unless key >= node[:Limits][0] && key <= node[:Limits][1]
176
176
  else
177
177
  break
@@ -192,12 +192,12 @@ module HexaPDF
192
192
  container_name = leaf_node_container_name
193
193
  stack = [self]
194
194
  until stack.empty?
195
- node = document.deref(stack.pop)
195
+ node = stack.pop
196
196
  if node.key?(container_name)
197
197
  data = node[container_name]
198
198
  index = 0
199
199
  while index < data.length
200
- yield(data[index], document.deref(data[index + 1]))
200
+ yield(data[index], data[index + 1])
201
201
  index += 2
202
202
  end
203
203
  elsif node.key?(:Kids)
@@ -215,7 +215,7 @@ module HexaPDF
215
215
  def path_to_key(node, key, stack)
216
216
  return unless node.key?(:Kids)
217
217
  index = find_in_intermediate_node(node[:Kids], key)
218
- stack << document.deref(node[:Kids][index])
218
+ stack << node[:Kids][index]
219
219
  path_to_key(stack.last, key, stack)
220
220
  end
221
221
 
@@ -226,7 +226,7 @@ module HexaPDF
226
226
  right = array.length - 1
227
227
  while left < right
228
228
  mid = (left + right) / 2
229
- limits = document.deref(array[mid])[:Limits]
229
+ limits = array[mid][:Limits]
230
230
  if limits[1] < key
231
231
  left = mid + 1
232
232
  elsif limits[0] > key
@@ -295,7 +295,7 @@ module HexaPDF
295
295
  node[container_name] = leaf_node[container_name].slice!(split_point..-1)
296
296
  node[:Limits] = node[container_name].values_at(0, -2)
297
297
  leaf_node[:Limits][1] = leaf_node[container_name][-2]
298
- index = 1 + parent[:Kids].index {|o| document.deref(o) == leaf_node }
298
+ index = 1 + parent[:Kids].index {|o| o == leaf_node }
299
299
  parent[:Kids].insert(index, node)
300
300
  end
301
301
  end
@@ -307,10 +307,10 @@ module HexaPDF
307
307
 
308
308
  # All kids entries must be indirect objects
309
309
  if key?(:Kids)
310
- self[:Kids].each do |kid|
311
- unless (kid.kind_of?(HexaPDF::Object) && kid.indirect?) ||
312
- kid.kind_of?(HexaPDF::Reference)
313
- yield("Child entries of sorted tree nodes must be indirect objects", false)
310
+ self[:Kids].each_with_index do |kid, index|
311
+ unless kid.kind_of?(HexaPDF::Object) && kid.indirect?
312
+ yield("Child entries of sorted tree nodes must be indirect objects", true)
313
+ value[:Kids][index] = document.add(kid)
314
314
  end
315
315
  end
316
316
  end
@@ -321,15 +321,18 @@ module HexaPDF
321
321
  container = self[container_name]
322
322
  if container.length.odd?
323
323
  yield("Sorted tree leaf node contains odd number of entries", false)
324
+ return
324
325
  end
325
326
  index = 0
326
327
  old = nil
327
328
  while index < container.length
328
- key = document.unwrap(container[index])
329
+ key = container[index]
329
330
  if !key.kind_of?(key_type)
330
331
  yield("A key must be a #{key_type} object, not a #{key.class}", false)
332
+ return
331
333
  elsif old && old > key
332
334
  yield("Sorted tree leaf node entries are not correctly sorted", false)
335
+ return
333
336
  end
334
337
  old = key
335
338
  index += 2
@@ -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
@@ -37,6 +37,6 @@
37
37
  module HexaPDF
38
38
 
39
39
  # The version of HexaPDF.
40
- VERSION = '0.11.9'
40
+ VERSION = '0.13.0'
41
41
 
42
42
  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
@@ -121,6 +121,11 @@ module CommonTokenizerTests
121
121
  assert(token.kind_of?(HexaPDF::Tokenizer::Token))
122
122
  end
123
123
 
124
+ it "next_token: should not fail when reading super long numbers" do
125
+ create_tokenizer("1" << "0" * 10_000)
126
+ assert_equal(10**10_000, @tokenizer.next_token)
127
+ end
128
+
124
129
  it "next_object: works for all PDF object types, including array and dictionary" do
125
130
  create_tokenizer(<<-EOF.chomp.gsub(/^ {8}/, ''))
126
131
  true false null 123 34.5 (string) <4E6F76> /Name
@@ -157,7 +162,7 @@ module CommonTokenizerTests
157
162
  end
158
163
 
159
164
  it "returns the correct position on operations" do
160
- create_tokenizer("hallo du" + " " * 50000 + "hallo du")
165
+ create_tokenizer("hallo du" << " " * 50000 << "hallo du")
161
166
  @tokenizer.next_token
162
167
  assert_equal(5, @tokenizer.pos)
163
168
 
@@ -29,10 +29,10 @@ module TestHelper
29
29
  end
30
30
 
31
31
  # Asserts that the content string contains the operators.
32
- def assert_operators(content, operators, only_names: false)
32
+ def assert_operators(content, operators, only_names: false, range: 0..-1)
33
33
  processor = TestHelper::OperatorRecorder.new
34
34
  HexaPDF::Content::Parser.new.parse(content, processor)
35
- result = processor.recorded_ops
35
+ result = processor.recorded_ops[range]
36
36
  result.map!(&:first) if only_names
37
37
  assert_equal(operators, result)
38
38
  end
@@ -68,14 +68,14 @@ describe HexaPDF::Content::GraphicObject::Arc do
68
68
  arc.max_curves = 4
69
69
  curves = arc.curves
70
70
  assert_equal(2, curves.size)
71
- assert_curve_values([0, 1, p1: [1, 0.548584], p2: [0.548584, 1]], curves[0])
72
- assert_curve_values([-1, 0, p1: [-0.548584, 1], p2: [-1, 0.548584]], curves[1])
71
+ assert_curve_values([0, 1, {p1: [1, 0.548584], p2: [0.548584, 1]}], curves[0])
72
+ assert_curve_values([-1, 0, {p1: [-0.548584, 1], p2: [-1, 0.548584]}], curves[1])
73
73
 
74
74
  arc.configure(clockwise: true)
75
75
  curves = arc.curves
76
76
  assert_equal(2, curves.size)
77
- assert_curve_values([0, -1, p1: [1, -0.548584], p2: [0.548584, -1]], curves[0])
78
- assert_curve_values([-1, 0, p1: [-0.548584, -1], p2: [-1, -0.548584]], curves[1])
77
+ assert_curve_values([0, -1, {p1: [1, -0.548584], p2: [0.548584, -1]}], curves[0])
78
+ assert_curve_values([-1, 0, {p1: [-0.548584, -1], p2: [-1, -0.548584]}], curves[1])
79
79
  end
80
80
  end
81
81
 
@@ -531,7 +531,7 @@ describe HexaPDF::Content::Canvas do
531
531
  end
532
532
 
533
533
  it "invokes the polygon method when radius != 0" do
534
- args = [0, 0, 10, 0, 10, 10, 0, 10, radius: 5]
534
+ args = [0, 0, 10, 0, 10, 10, 0, 10, {radius: 5}]
535
535
  assert_method_invoked(@canvas, :polygon, args) do
536
536
  @canvas.rectangle(0, 0, 10, 10, radius: 5)
537
537
  end
@@ -631,7 +631,7 @@ describe HexaPDF::Content::Canvas do
631
631
 
632
632
  describe "circle" do
633
633
  it "uses arc for the hard work" do
634
- assert_method_invoked(@canvas, :arc, [5, 6, a: 7]) do
634
+ assert_method_invoked(@canvas, :arc, [5, 6, {a: 7}]) do
635
635
  @canvas.graphics_object = :path
636
636
  @canvas.circle(5, 6, 7)
637
637
  end
@@ -651,7 +651,7 @@ describe HexaPDF::Content::Canvas do
651
651
 
652
652
  describe "ellipse" do
653
653
  it "uses arc for the hard work" do
654
- assert_method_invoked(@canvas, :ellipse, [5, 6, a: 7, b: 5, inclination: 10]) do
654
+ assert_method_invoked(@canvas, :ellipse, [5, 6, {a: 7, b: 5, inclination: 10}]) do
655
655
  @canvas.ellipse(5, 6, a: 7, b: 5, inclination: 10)
656
656
  end
657
657
  end
@@ -27,6 +27,10 @@ module CommonColorSpaceTests
27
27
  assert_equal(@color_space_family, @color_space.family)
28
28
  end
29
29
 
30
+ it "the color space returns the correct color space definition" do
31
+ assert_equal(@color_space_definition, @color_space.definition)
32
+ end
33
+
30
34
  it "the color responds to :components" do
31
35
  assert(@color.respond_to?(:components))
32
36
  end
@@ -43,14 +47,70 @@ module CommonColorSpaceTests
43
47
  assert_equal(@components, @color_space.color(*@components).components)
44
48
  end
45
49
 
50
+ it "normalizes the colors when using the #color method" do
51
+ return unless defined?(@colors)
52
+ assert_equal(@components, @color_space.color(*@colors).components)
53
+ end
54
+
55
+ it "doesn't normalize the colors when using the #prenormalized_color method" do
56
+ return unless defined?(@colors)
57
+ assert_equal(@colors, @color_space.prenormalized_color(*@colors).components)
58
+ end
59
+
60
+ end
61
+
62
+ describe HexaPDF::Content::ColorSpace do
63
+ before do
64
+ @class = HexaPDF::Content::ColorSpace
65
+ end
66
+
67
+ describe "self.device_color_from_specification" do
68
+ it "works for gray values" do
69
+ assert_equal([0.2], @class.device_color_from_specification(51).components)
70
+ end
71
+
72
+ it "works for RGB values" do
73
+ assert_equal([0.2, 1, 0], @class.device_color_from_specification(51, 255, 0).components)
74
+ end
75
+
76
+ it "works for RGB values given as string" do
77
+ assert_equal([0.2, 1, 0], @class.device_color_from_specification("33FF00").components)
78
+ end
79
+
80
+ it "works for CMYK values" do
81
+ assert_equal([0.51, 0.9, 1, 0.5],
82
+ @class.device_color_from_specification(51, 90, 100, 50).components)
83
+ end
84
+
85
+ it "works when an array is given" do
86
+ assert_equal([0.2], @class.device_color_from_specification([51]).components)
87
+ end
88
+ end
89
+
90
+ it "returns a device color object for prenormalized color values" do
91
+ assert_equal([5, 6, 7], @class.prenormalized_device_color([5, 6, 7]).components)
92
+ end
93
+
94
+ describe "self.for_components" do
95
+ it "returns the correct device color space name" do
96
+ assert_equal(:DeviceGray, @class.for_components([1]))
97
+ assert_equal(:DeviceRGB, @class.for_components([1, 2, 3]))
98
+ assert_equal(:DeviceCMYK, @class.for_components([1, 2, 3, 4]))
99
+ end
100
+
101
+ it "fails if an array with an invalid length is passed" do
102
+ assert_raises(ArgumentError) { @class.for_components([]) }
103
+ end
104
+ end
46
105
  end
47
106
 
48
107
  describe HexaPDF::Content::ColorSpace::Universal do
49
108
  include CommonColorSpaceTests
50
109
 
51
110
  before do
52
- @color_space = HexaPDF::Content::ColorSpace::Universal.new([:test])
111
+ @color_space = HexaPDF::Content::ColorSpace::Universal.new([:test, :value])
53
112
  @color_space_family = :test
113
+ @color_space_definition = [:test, :value]
54
114
  @color = @color_space.default_color
55
115
  @other_color = @color_space.color(128, 5, 6, 7, 8)
56
116
  @components = [5, 6, 7, 8]
@@ -58,7 +118,7 @@ describe HexaPDF::Content::ColorSpace::Universal do
58
118
 
59
119
  it "can be compared to another universal color space" do
60
120
  other = HexaPDF::Content::ColorSpace::Universal.new([:other])
61
- same = HexaPDF::Content::ColorSpace::Universal.new([:test])
121
+ same = HexaPDF::Content::ColorSpace::Universal.new([:test, :value])
62
122
  assert_equal(same, @color_space)
63
123
  refute_equal(other, @color_space)
64
124
  end
@@ -69,10 +129,11 @@ describe HexaPDF::Content::ColorSpace::DeviceRGB do
69
129
 
70
130
  before do
71
131
  @color_space = HexaPDF::Content::ColorSpace::DeviceRGB.new
72
- @color_space_family = :DeviceRGB
132
+ @color_space_family = @color_space_definition = :DeviceRGB
73
133
  @color = @color_space.default_color
74
134
  @other_color = @color_space.color(128, 0, 0)
75
- @components = [0.5, 0.2, 0.3]
135
+ @colors = [128, 0, 255]
136
+ @components = @colors.map {|c| c.to_f / 255 }
76
137
  end
77
138
  end
78
139
 
@@ -81,10 +142,11 @@ describe HexaPDF::Content::ColorSpace::DeviceCMYK do
81
142
 
82
143
  before do
83
144
  @color_space = HexaPDF::Content::ColorSpace::DeviceCMYK.new
84
- @color_space_family = :DeviceCMYK
145
+ @color_space_family = @color_space_definition = :DeviceCMYK
85
146
  @color = @color_space.default_color
86
147
  @other_color = @color_space.color(128, 0, 0, 128)
87
- @components = [0.1, 0.2, 0.3, 0.4]
148
+ @colors = [0, 20, 40, 80]
149
+ @components = [0.0, 0.2, 0.4, 0.8]
88
150
  end
89
151
  end
90
152
 
@@ -93,9 +155,10 @@ describe HexaPDF::Content::ColorSpace::DeviceGray do
93
155
 
94
156
  before do
95
157
  @color_space = HexaPDF::Content::ColorSpace::DeviceGray.new
96
- @color_space_family = :DeviceGray
158
+ @color_space_family = @color_space_definition = :DeviceGray
97
159
  @color = @color_space.default_color
98
160
  @other_color = @color_space.color(128)
99
- @components = [0.1]
161
+ @colors = [128]
162
+ @components = [128.0 / 255]
100
163
  end
101
164
  end