hexapdf 0.32.2 → 0.33.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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +63 -1
  3. data/README.md +9 -0
  4. data/examples/002-graphics.rb +15 -17
  5. data/examples/003-arcs.rb +9 -9
  6. data/examples/009-text_layouter_alignment.rb +1 -1
  7. data/examples/010-text_layouter_inline_boxes.rb +2 -2
  8. data/examples/011-text_layouter_line_wrapping.rb +1 -1
  9. data/examples/012-text_layouter_styling.rb +7 -7
  10. data/examples/013-text_layouter_shapes.rb +1 -1
  11. data/examples/014-text_in_polygon.rb +1 -1
  12. data/examples/015-boxes.rb +8 -7
  13. data/examples/016-frame_automatic_box_placement.rb +2 -2
  14. data/examples/017-frame_text_flow.rb +2 -1
  15. data/examples/018-composer.rb +1 -1
  16. data/examples/020-column_box.rb +2 -1
  17. data/examples/025-table_box.rb +46 -0
  18. data/lib/hexapdf/cli/command.rb +5 -2
  19. data/lib/hexapdf/cli/form.rb +5 -5
  20. data/lib/hexapdf/cli/inspect.rb +3 -3
  21. data/lib/hexapdf/composer.rb +104 -52
  22. data/lib/hexapdf/configuration.rb +44 -39
  23. data/lib/hexapdf/content/canvas.rb +393 -267
  24. data/lib/hexapdf/content/color_space.rb +72 -25
  25. data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
  26. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
  27. data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
  28. data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
  29. data/lib/hexapdf/content/graphic_object.rb +6 -7
  30. data/lib/hexapdf/content/graphics_state.rb +54 -45
  31. data/lib/hexapdf/content/operator.rb +52 -54
  32. data/lib/hexapdf/content/parser.rb +2 -2
  33. data/lib/hexapdf/content/processor.rb +15 -15
  34. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  35. data/lib/hexapdf/content.rb +5 -0
  36. data/lib/hexapdf/dictionary.rb +6 -5
  37. data/lib/hexapdf/dictionary_fields.rb +42 -14
  38. data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
  39. data/lib/hexapdf/digital_signature/handler.rb +1 -1
  40. data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
  41. data/lib/hexapdf/digital_signature/signature.rb +6 -6
  42. data/lib/hexapdf/digital_signature/signatures.rb +13 -12
  43. data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
  44. data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
  45. data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
  46. data/lib/hexapdf/digital_signature/signing.rb +4 -0
  47. data/lib/hexapdf/digital_signature/verification_result.rb +2 -2
  48. data/lib/hexapdf/digital_signature.rb +7 -2
  49. data/lib/hexapdf/document/destinations.rb +12 -11
  50. data/lib/hexapdf/document/files.rb +1 -1
  51. data/lib/hexapdf/document/fonts.rb +1 -1
  52. data/lib/hexapdf/document/layout.rb +167 -39
  53. data/lib/hexapdf/document/pages.rb +3 -2
  54. data/lib/hexapdf/document.rb +89 -55
  55. data/lib/hexapdf/encryption/aes.rb +5 -5
  56. data/lib/hexapdf/encryption/arc4.rb +1 -1
  57. data/lib/hexapdf/encryption/fast_aes.rb +2 -2
  58. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  59. data/lib/hexapdf/encryption/identity.rb +1 -1
  60. data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
  61. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  62. data/lib/hexapdf/encryption/security_handler.rb +31 -24
  63. data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
  64. data/lib/hexapdf/encryption.rb +7 -2
  65. data/lib/hexapdf/error.rb +18 -0
  66. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  67. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  68. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  69. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  70. data/lib/hexapdf/filter/pass_through.rb +1 -1
  71. data/lib/hexapdf/filter/predictor.rb +1 -1
  72. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  73. data/lib/hexapdf/filter.rb +55 -6
  74. data/lib/hexapdf/font/cmap/parser.rb +2 -2
  75. data/lib/hexapdf/font/cmap.rb +1 -1
  76. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  77. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  78. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
  79. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  80. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  81. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +3 -3
  82. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  83. data/lib/hexapdf/font/invalid_glyph.rb +3 -0
  84. data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
  85. data/lib/hexapdf/font/type1_wrapper.rb +19 -4
  86. data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
  87. data/lib/hexapdf/font_loader/from_file.rb +5 -5
  88. data/lib/hexapdf/font_loader/standard14.rb +3 -3
  89. data/lib/hexapdf/font_loader.rb +3 -0
  90. data/lib/hexapdf/image_loader/jpeg.rb +2 -2
  91. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  92. data/lib/hexapdf/image_loader/png.rb +2 -2
  93. data/lib/hexapdf/image_loader.rb +1 -1
  94. data/lib/hexapdf/importer.rb +13 -0
  95. data/lib/hexapdf/layout/box.rb +9 -2
  96. data/lib/hexapdf/layout/box_fitter.rb +2 -2
  97. data/lib/hexapdf/layout/column_box.rb +18 -4
  98. data/lib/hexapdf/layout/frame.rb +30 -12
  99. data/lib/hexapdf/layout/image_box.rb +5 -0
  100. data/lib/hexapdf/layout/inline_box.rb +1 -0
  101. data/lib/hexapdf/layout/list_box.rb +17 -1
  102. data/lib/hexapdf/layout/page_style.rb +4 -4
  103. data/lib/hexapdf/layout/style.rb +18 -3
  104. data/lib/hexapdf/layout/table_box.rb +682 -0
  105. data/lib/hexapdf/layout/text_box.rb +5 -3
  106. data/lib/hexapdf/layout/text_fragment.rb +1 -1
  107. data/lib/hexapdf/layout/text_layouter.rb +12 -4
  108. data/lib/hexapdf/layout.rb +1 -0
  109. data/lib/hexapdf/name_tree_node.rb +1 -1
  110. data/lib/hexapdf/number_tree_node.rb +1 -1
  111. data/lib/hexapdf/object.rb +18 -7
  112. data/lib/hexapdf/parser.rb +7 -7
  113. data/lib/hexapdf/pdf_array.rb +1 -1
  114. data/lib/hexapdf/rectangle.rb +1 -1
  115. data/lib/hexapdf/reference.rb +1 -1
  116. data/lib/hexapdf/revision.rb +1 -1
  117. data/lib/hexapdf/revisions.rb +3 -3
  118. data/lib/hexapdf/serializer.rb +15 -15
  119. data/lib/hexapdf/stream.rb +4 -2
  120. data/lib/hexapdf/tokenizer.rb +14 -14
  121. data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
  122. data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
  123. data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
  124. data/lib/hexapdf/type/acro_form/field.rb +2 -2
  125. data/lib/hexapdf/type/acro_form/form.rb +1 -1
  126. data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
  127. data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
  128. data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
  129. data/lib/hexapdf/type/acro_form.rb +1 -1
  130. data/lib/hexapdf/type/action.rb +1 -1
  131. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  132. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  133. data/lib/hexapdf/type/actions/launch.rb +1 -1
  134. data/lib/hexapdf/type/actions/uri.rb +1 -1
  135. data/lib/hexapdf/type/actions.rb +1 -1
  136. data/lib/hexapdf/type/annotation.rb +3 -3
  137. data/lib/hexapdf/type/annotations/link.rb +1 -1
  138. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  139. data/lib/hexapdf/type/annotations/text.rb +1 -1
  140. data/lib/hexapdf/type/annotations/widget.rb +2 -2
  141. data/lib/hexapdf/type/annotations.rb +1 -1
  142. data/lib/hexapdf/type/catalog.rb +1 -1
  143. data/lib/hexapdf/type/cid_font.rb +3 -3
  144. data/lib/hexapdf/type/embedded_file.rb +1 -1
  145. data/lib/hexapdf/type/file_specification.rb +2 -2
  146. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  147. data/lib/hexapdf/type/font_simple.rb +2 -2
  148. data/lib/hexapdf/type/font_type0.rb +3 -3
  149. data/lib/hexapdf/type/font_type3.rb +1 -1
  150. data/lib/hexapdf/type/form.rb +1 -1
  151. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  152. data/lib/hexapdf/type/icon_fit.rb +1 -1
  153. data/lib/hexapdf/type/image.rb +1 -1
  154. data/lib/hexapdf/type/info.rb +1 -1
  155. data/lib/hexapdf/type/mark_information.rb +1 -1
  156. data/lib/hexapdf/type/names.rb +2 -2
  157. data/lib/hexapdf/type/object_stream.rb +2 -1
  158. data/lib/hexapdf/type/outline.rb +1 -1
  159. data/lib/hexapdf/type/outline_item.rb +1 -1
  160. data/lib/hexapdf/type/page.rb +19 -10
  161. data/lib/hexapdf/type/page_label.rb +1 -1
  162. data/lib/hexapdf/type/page_tree_node.rb +1 -1
  163. data/lib/hexapdf/type/resources.rb +1 -1
  164. data/lib/hexapdf/type/trailer.rb +2 -2
  165. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  166. data/lib/hexapdf/type/xref_stream.rb +2 -2
  167. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
  168. data/lib/hexapdf/version.rb +1 -1
  169. data/lib/hexapdf/writer.rb +4 -4
  170. data/lib/hexapdf/xref_section.rb +2 -2
  171. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
  172. data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
  173. data/test/hexapdf/content/test_canvas.rb +0 -1
  174. data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
  175. data/test/hexapdf/document/test_files.rb +2 -2
  176. data/test/hexapdf/document/test_layout.rb +98 -0
  177. data/test/hexapdf/encryption/test_security_handler.rb +12 -11
  178. data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
  179. data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
  180. data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
  181. data/test/hexapdf/layout/test_box.rb +1 -1
  182. data/test/hexapdf/layout/test_column_box.rb +65 -21
  183. data/test/hexapdf/layout/test_frame.rb +14 -14
  184. data/test/hexapdf/layout/test_image_box.rb +4 -0
  185. data/test/hexapdf/layout/test_inline_box.rb +5 -0
  186. data/test/hexapdf/layout/test_list_box.rb +40 -6
  187. data/test/hexapdf/layout/test_page_style.rb +3 -2
  188. data/test/hexapdf/layout/test_style.rb +50 -0
  189. data/test/hexapdf/layout/test_table_box.rb +722 -0
  190. data/test/hexapdf/layout/test_text_box.rb +18 -0
  191. data/test/hexapdf/layout/test_text_layouter.rb +4 -0
  192. data/test/hexapdf/test_dictionary_fields.rb +4 -1
  193. data/test/hexapdf/test_document.rb +1 -0
  194. data/test/hexapdf/test_filter.rb +8 -0
  195. data/test/hexapdf/test_importer.rb +9 -0
  196. data/test/hexapdf/test_object.rb +16 -5
  197. data/test/hexapdf/test_stream.rb +7 -0
  198. data/test/hexapdf/test_writer.rb +3 -3
  199. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
  200. data/test/hexapdf/type/acro_form/test_form.rb +4 -3
  201. data/test/hexapdf/type/test_page.rb +18 -4
  202. metadata +17 -8
@@ -107,6 +107,14 @@ describe HexaPDF::Layout::TextBox do
107
107
  assert_equal([nil, box], box.split(100, 100, @frame))
108
108
  end
109
109
 
110
+ it "works if the box fits exactly (+/- float divergence)" do
111
+ box = create_box([@inline_box] * 5)
112
+ box.fit(50, 10, @frame)
113
+ box.instance_variable_set(:@width, 50.00000000006)
114
+ box.instance_variable_set(:@height, 10.00000000003)
115
+ assert_equal([box], box.split(50, 10, @frame))
116
+ end
117
+
110
118
  it "splits the box if necessary when using non-flowing text" do
111
119
  box = create_box([@inline_box] * 10)
112
120
  boxes = box.split(50, 10, @frame)
@@ -125,6 +133,16 @@ describe HexaPDF::Layout::TextBox do
125
133
  assert_equal(box, boxes[0])
126
134
  assert_equal(5, boxes[1].instance_variable_get(:@items).length)
127
135
  end
136
+
137
+ it "correctly handles text indentation for split boxes" do
138
+ [{}, {position: :flow}].each do |styles|
139
+ box = create_box([@inline_box] * 202, style: {text_indent: 50, **styles})
140
+ boxes = box.split(100, 100, @frame)
141
+ assert_equal(107, boxes[1].instance_variable_get(:@items).length)
142
+ boxes = boxes[1].split(100, 100, @frame)
143
+ assert_equal(7, boxes[1].instance_variable_get(:@items).length)
144
+ end
145
+ end
128
146
  end
129
147
 
130
148
  describe "draw" do
@@ -419,6 +419,10 @@ describe HexaPDF::Layout::TextLayouter do
419
419
  assert(result.remaining_items.empty?)
420
420
  assert_equal(:success, result.status)
421
421
  end
422
+
423
+ result = @layouter.fit(boxes([20, 20], [20, 20], [20, 20], [20, 20]), 60, 200,
424
+ apply_first_text_indent: false)
425
+ assert_equal([60, 20], result.lines.map(&:width))
422
426
  end
423
427
 
424
428
  it "fits using a limited height" do
@@ -188,8 +188,11 @@ describe HexaPDF::DictionaryFields do
188
188
  ["D:19981223-08'00'", [1998, 12, 23, 00, 00, 00, "-08:00"]],
189
189
  ["D:199812-08'00'", [1998, 12, 01, 00, 00, 00, "-08:00"]],
190
190
  ["D:1998-08'00'", [1998, 01, 01, 00, 00, 00, "-08:00"]],
191
+ ["D:19981223195210Z", [1998, 12, 23, 19, 52, 10, "+00:00"]],
192
+ ["D:19981223195210Z00", [1998, 12, 23, 19, 52, 10, "+00:00"]],
193
+ ["D:19981223195210Z00'00", [1998, 12, 23, 19, 52, 10, "+00:00"]],
191
194
  ["D:19981223195210-08", [1998, 12, 23, 19, 52, 10, "-08:00"]], # missing '
192
- ["D:19981223195210-08'00", [1998, 12, 23, 19, 52, 10, "-08:00"]], # missing '
195
+ ["D:19981223195210-08'00", [1998, 12, 23, 19, 52, 10, "-08:00"]], # no trailing ', as per PDF 2.0
193
196
  ["D:19981223195210-54'00", [1998, 12, 23, 19, 52, 10, "-23:59:59"]], # TZ hour too large
194
197
  ["D:19981223195210+10'65", [1998, 12, 23, 19, 52, 10, "+11:05"]], # TZ min too large
195
198
  ["D:19982423195210-08'00'", [1998, 12, 23, 19, 52, 10, "-08:00"]], # months too large
@@ -240,6 +240,7 @@ describe HexaPDF::Document do
240
240
  assert_kind_of(@myclass2, @doc.wrap({Subtype: :Global, Test: "true"}))
241
241
  assert_kind_of(@myclass2, @doc.wrap({Type: :MyClass, S: :TheSecond}))
242
242
  assert_kind_of(@myclass, @doc.wrap({Type: :MyClass, Subtype: :TheThird}))
243
+ assert_kind_of(HexaPDF::Type::FontTrueType, @doc.wrap({Subtype: :TrueType, BaseFont: :Help}))
243
244
  end
244
245
 
245
246
  it "respects the given type/subtype arguments" do
@@ -12,6 +12,14 @@ describe HexaPDF::Filter do
12
12
  40.times { @str << [rand(2**32)].pack('N') }
13
13
  end
14
14
 
15
+ describe "source_from_proc" do
16
+ it "returns the whole string, once" do
17
+ fib = @obj.source_from_proc { @str }
18
+ assert_equal(@str, collector(fib))
19
+ assert_equal('', collector(fib))
20
+ end
21
+ end
22
+
15
23
  describe "source_from_string" do
16
24
  it "doesn't modify the given string" do
17
25
  str = @str.dup
@@ -40,6 +40,15 @@ describe HexaPDF::Importer do
40
40
  end
41
41
  end
42
42
 
43
+ describe "::copy" do
44
+ it "copies a complete object including references" do
45
+ obj1 = HexaPDF::Importer.copy(@dest, @obj)
46
+ obj2 = HexaPDF::Importer.copy(@dest, @obj)
47
+ refute_same(obj1, obj2)
48
+ refute_same(obj1[:ref], obj2[:ref])
49
+ end
50
+ end
51
+
43
52
  describe "import" do
44
53
  it "updates the associated document" do
45
54
  obj = @importer.import(@obj)
@@ -50,26 +50,37 @@ describe HexaPDF::Object do
50
50
  @doc = HexaPDF::Document.new
51
51
  end
52
52
 
53
- it "doesn't touch wrapped direct objects" do
53
+ it "makes values of wrapped direct objects also direct" do
54
54
  obj = HexaPDF::Object.new(5)
55
- assert_same(obj, HexaPDF::Object.make_direct(obj))
55
+ assert_same(obj, HexaPDF::Object.make_direct(obj, @doc))
56
+ obj = HexaPDF::Dictionary.new({a: 5, b: HexaPDF::Object.new(:a, oid: 3, document: @doc)})
57
+ assert_same(obj, HexaPDF::Object.make_direct(obj, @doc))
58
+ assert_equal(:a, obj[:b])
56
59
  end
57
60
 
58
61
  it "works for simple values" do
59
62
  obj = HexaPDF::Object.new(5, oid: 1, document: @doc)
60
- assert_same(5, HexaPDF::Object.make_direct(obj))
63
+ assert_same(5, HexaPDF::Object.make_direct(obj, @doc))
61
64
  end
62
65
 
63
66
  it "works for hashes" do
64
67
  obj = HexaPDF::Dictionary.new({a: 5, b: HexaPDF::Object.new(:a, oid: 3, document: @doc)},
65
68
  oid: 1, document: @doc)
66
- assert_equal({a: 5, b: :a}, HexaPDF::Object.make_direct(obj))
69
+ assert_equal({a: 5, b: :a}, HexaPDF::Object.make_direct(obj, @doc))
67
70
  end
68
71
 
69
72
  it "works for arrays" do
70
73
  obj = HexaPDF::PDFArray.new([:b, HexaPDF::Object.new(:a, oid: 3, document: @doc)],
71
74
  oid: 1, document: @doc)
72
- assert_equal([:b, :a], HexaPDF::Object.make_direct(obj))
75
+ assert_equal([:b, :a], HexaPDF::Object.make_direct(obj, @doc))
76
+ end
77
+
78
+ it "resolves references" do
79
+ @doc.add(:Test, oid: 1)
80
+ obj = HexaPDF::PDFArray.new([HexaPDF::Reference.new(1, 0)],
81
+ oid: 2, document: @doc)
82
+ assert_equal([:Test], HexaPDF::Object.make_direct(obj, @doc))
83
+ assert(@doc.object(1).null?)
73
84
  end
74
85
  end
75
86
 
@@ -31,6 +31,13 @@ describe HexaPDF::StreamData do
31
31
  end
32
32
 
33
33
  describe "fiber" do
34
+ it "returns a duplicate for a FiberDoubleForString source" do
35
+ source = HexaPDF::Filter.source_from_string("str")
36
+ fiber = HexaPDF::StreamData.new(source).fiber
37
+ assert_equal("str", fiber.resume)
38
+ refute_same(source, fiber)
39
+ end
40
+
34
41
  it "returns a fiber for a Proc source" do
35
42
  s = HexaPDF::StreamData.new(proc { :source })
36
43
  assert_equal(:source, s.fiber.resume)
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
40
40
  219
41
41
  %%EOF
42
42
  3 0 obj
43
- <</Producer(HexaPDF version 0.32.2)>>
43
+ <</Producer(HexaPDF version 0.33.0)>>
44
44
  endobj
45
45
  xref
46
46
  3 1
@@ -72,7 +72,7 @@ describe HexaPDF::Writer do
72
72
  141
73
73
  %%EOF
74
74
  6 0 obj
75
- <</Producer(HexaPDF version 0.32.2)>>
75
+ <</Producer(HexaPDF version 0.33.0)>>
76
76
  endobj
77
77
  2 0 obj
78
78
  <</Length 10>>stream
@@ -214,7 +214,7 @@ describe HexaPDF::Writer do
214
214
  <</Type/Page/MediaBox[0 0 595 842]/Parent 2 0 R/Resources<<>>>>
215
215
  endobj
216
216
  5 0 obj
217
- <</Producer(HexaPDF version 0.32.2)>>
217
+ <</Producer(HexaPDF version 0.33.0)>>
218
218
  endobj
219
219
  4 0 obj
220
220
  <</Root 1 0 R/Info 5 0 R/Size 6/Type/XRef/W[1 1 2]/Index[0 6]/Filter/FlateDecode/DecodeParms<</Columns 4/Predictor 12>>/Length 33>>stream
@@ -467,12 +467,20 @@ describe HexaPDF::Type::AcroForm::AppearanceGenerator do
467
467
  it "calculates the font size based on the rectangle height and border width" do
468
468
  @generator.create_appearances
469
469
  assert_operators(@widget[:AP][:N].stream,
470
- [:set_font_and_size, [:F1, 12.923875]],
470
+ [:set_font_and_size, [:F1, 13.235294]],
471
471
  range: 5)
472
472
  @widget.border_style(width: 2, color: :transparent)
473
473
  @generator.create_appearances
474
474
  assert_operators(@widget[:AP][:N].stream,
475
- [:set_font_and_size, [:F1, 11.487889]],
475
+ [:set_font_and_size, [:F1, 11.764706]],
476
+ range: 5)
477
+ end
478
+
479
+ it "shrinks the font size if necessary to fit the rectangle width" do
480
+ @field.field_value = "This is some arbitrary, long text"
481
+ @generator.create_appearances
482
+ assert_operators(@widget[:AP][:N].stream,
483
+ [:set_font_and_size, [:F1, 6.909955]],
476
484
  range: 5)
477
485
  end
478
486
 
@@ -573,7 +581,7 @@ describe HexaPDF::Type::AcroForm::AppearanceGenerator do
573
581
  assert_format("2, 3, #{style}, 0, \"E\", true",
574
582
  [[:set_device_rgb_non_stroking_color, [style % 2, 0.0, 0.0]],
575
583
  [:begin_text],
576
- [:set_text_matrix, [1, 0, 0, 1, 2, 3.240724]],
584
+ [:set_text_matrix, [1, 0, 0, 1, 2, 3.183272]],
577
585
  [:show_text, [result]]], 6..9)
578
586
  end
579
587
  end
@@ -598,10 +606,10 @@ describe HexaPDF::Type::AcroForm::AppearanceGenerator do
598
606
  [:append_rectangle, [1, 1, 98, 9.25]],
599
607
  [:clip_path_non_zero],
600
608
  [:end_path],
601
- [:set_font_and_size, [:F1, 6.641436]],
609
+ [:set_font_and_size, [:F1, 6.801471]],
602
610
  [:set_device_rgb_non_stroking_color, [1.0, 0.0, 0.0]],
603
611
  [:begin_text],
604
- [:set_text_matrix, [1, 0, 0, 1, 2, 3.240724]],
612
+ [:set_text_matrix, [1, 0, 0, 1, 2, 3.183272]],
605
613
  [:show_text, ["Text"]],
606
614
  [:end_text],
607
615
  [:restore_graphics_state],
@@ -42,11 +42,12 @@ describe HexaPDF::Type::AcroForm::Form do
42
42
  end
43
43
 
44
44
  it "finds the root fields" do
45
- @doc.pages.add[:Annots] = [{FT: :Tx}, {FT: :Tx2, Parent: {FT: :Tx3}}]
46
- @doc.pages.add[:Annots] = [{Subtype: :Widget}]
45
+ @doc.pages.add[:Annots] = [{Subtype: :Widget, Rect: [0, 0, 0, 0], FT: :Tx},
46
+ {Subtype: :Widget, Rect: [0, 0, 0, 0], FT: :Tx, Parent: {FT: :Tx}}]
47
+ @doc.pages.add[:Annots] = [{Subtype: :Widget, Rect: [0, 0, 0, 0]}]
47
48
  @doc.pages.add
48
49
 
49
- result = [{FT: :Tx}, {FT: :Tx3}]
50
+ result = [{Subtype: :Widget, Rect: [0, 0, 0, 0], FT: :Tx}, {FT: :Tx}]
50
51
  root_fields = @acro_form.find_root_fields
51
52
  assert_equal(result, root_fields.map(&:value))
52
53
  assert_kind_of(HexaPDF::Type::AcroForm::TextField, root_fields[0])
@@ -557,7 +557,7 @@ describe HexaPDF::Type::Page do
557
557
  @page = @doc.pages.add
558
558
  @appearance = @doc.add({Type: :XObject, Subtype: :Form, BBox: [-10, -5, 50, 20]}, stream: "")
559
559
  @annot1 = @doc.add({Type: :Annot, Subtype: :Text, Rect: [100, 100, 160, 125], AP: {N: @appearance}})
560
- @annot2 = @doc.add({Rect: [10, 10, 70, 35], AP: {N: @appearance}})
560
+ @annot2 = @doc.add({Type: :Annot, Subtype: :Text, Rect: [10, 10, 70, 35], AP: {N: @appearance}})
561
561
  @page[:Annots] = [@annot1, @annot2]
562
562
  @canvas = @page.canvas(type: :overlay)
563
563
  end
@@ -591,6 +591,18 @@ describe HexaPDF::Type::Page do
591
591
  assert(@annot2.null?)
592
592
  end
593
593
 
594
+ it "gracefully handles invalid /Annot key values" do
595
+ @page[:Annots] << nil << @doc.add({}, stream: '')
596
+ result = @page.flatten_annotations
597
+ assert(result.empty?)
598
+ assert(@annot1.null?)
599
+ assert(@annot2.null?)
600
+
601
+ @page[:Annots] = @doc.add({}, stream: '')
602
+ result = @page.flatten_annotations
603
+ assert(result.empty?)
604
+ end
605
+
594
606
  it "only deletes the widget annotation of a form field even if it is embedded in the field object" do
595
607
  form = @doc.acro_form(create: true)
596
608
  field = form.create_text_field('test')
@@ -631,7 +643,7 @@ describe HexaPDF::Type::Page do
631
643
  [:restore_graphics_state]])
632
644
  end
633
645
 
634
- it "ignores annotations without appearane stream" do
646
+ it "ignores annotations without appearance stream" do
635
647
  @annot1.delete(:AP)
636
648
  result = @page.flatten_annotations
637
649
  assert_equal([@annot1], result)
@@ -708,10 +720,12 @@ describe HexaPDF::Type::Page do
708
720
  it "yields each annotation" do
709
721
  page = @doc.pages.add
710
722
  annot1 = @doc.add({Type: :Annot, Subtype: :Text, Rect: [100, 100, 160, 125]})
711
- annot2 = @doc.add({Rect: [10, 10, 70, 35]})
712
- page[:Annots] = [annot1, nil, annot2]
723
+ annot2 = @doc.add({Subtype: :Unknown, Rect: [10, 10, 70, 35]})
724
+ not_an_annot = @doc.add({}, stream: '')
725
+ page[:Annots] = [not_an_annot, annot1, nil, annot2]
713
726
 
714
727
  annotations = page.each_annotation.to_a
728
+ assert_equal(2, annotations.size)
715
729
  assert_equal([100, 100, 160, 125], annotations[0][:Rect])
716
730
  assert_equal(:Annot, annotations[0].type)
717
731
  assert_equal(:Annot, annotations[1].type)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hexapdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.32.2
4
+ version: 0.33.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Leitner
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-06 00:00:00.000000000 Z
11
+ date: 2023-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse
@@ -36,14 +36,20 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '0.3'
39
+ version: '0.4'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.4.1
40
43
  type: :runtime
41
44
  prerelease: false
42
45
  version_requirements: !ruby/object:Gem::Requirement
43
46
  requirements:
44
47
  - - "~>"
45
48
  - !ruby/object:Gem::Version
46
- version: '0.3'
49
+ version: '0.4'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.4.1
47
53
  - !ruby/object:Gem::Dependency
48
54
  name: openssl
49
55
  requirement: !ruby/object:Gem::Requirement
@@ -292,6 +298,7 @@ files:
292
298
  - examples/022-outline.rb
293
299
  - examples/023-images.rb
294
300
  - examples/024-digital-signatures.rb
301
+ - examples/025-table_box.rb
295
302
  - examples/emoji-smile.png
296
303
  - examples/emoji-wink.png
297
304
  - examples/machupicchu.jpg
@@ -430,6 +437,7 @@ files:
430
437
  - lib/hexapdf/layout/numeric_refinements.rb
431
438
  - lib/hexapdf/layout/page_style.rb
432
439
  - lib/hexapdf/layout/style.rb
440
+ - lib/hexapdf/layout/table_box.rb
433
441
  - lib/hexapdf/layout/text_box.rb
434
442
  - lib/hexapdf/layout/text_fragment.rb
435
443
  - lib/hexapdf/layout/text_layouter.rb
@@ -682,6 +690,7 @@ files:
682
690
  - test/hexapdf/layout/test_list_box.rb
683
691
  - test/hexapdf/layout/test_page_style.rb
684
692
  - test/hexapdf/layout/test_style.rb
693
+ - test/hexapdf/layout/test_table_box.rb
685
694
  - test/hexapdf/layout/test_text_box.rb
686
695
  - test/hexapdf/layout/test_text_fragment.rb
687
696
  - test/hexapdf/layout/test_text_layouter.rb
@@ -760,7 +769,7 @@ licenses:
760
769
  - AGPL-3.0
761
770
  - Nonstandard
762
771
  metadata: {}
763
- post_install_message:
772
+ post_install_message:
764
773
  rdoc_options: []
765
774
  require_paths:
766
775
  - lib
@@ -775,8 +784,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
775
784
  - !ruby/object:Gem::Version
776
785
  version: '0'
777
786
  requirements: []
778
- rubygems_version: 3.4.1
779
- signing_key:
787
+ rubygems_version: 3.5.0.dev
788
+ signing_key:
780
789
  specification_version: 4
781
790
  summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
782
791
  test_files: []