hexapdf 0.32.2 → 0.33.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -11,7 +11,7 @@ describe HexaPDF::Layout::Frame do
11
11
  canvas = doc.pages.add.canvas
12
12
  box = HexaPDF::Layout::Box.create(width: 20, height: 20) {}
13
13
  result = HexaPDF::Layout::Frame::FitResult.new(box)
14
- result.mask = Geom2D::Polygon([0, 0], [0, 20], [20, 20], [20, 0])
14
+ result.mask = Geom2D::Rectangle(0, 0, 20, 20)
15
15
  result.x = result.y = 0
16
16
  result.draw(canvas)
17
17
  assert_equal(<<~CONTENTS, canvas.contents)
@@ -19,11 +19,7 @@ describe HexaPDF::Layout::Frame do
19
19
  0.0 0.501961 0.0 rg
20
20
  0.0 0.392157 0.0 RG
21
21
  /GS1 gs
22
- 0 0 m
23
- 0 20 l
24
- 20 20 l
25
- 20 0 l
26
- h
22
+ 0 0 20 20 re
27
23
  B
28
24
  Q
29
25
  q
@@ -90,7 +86,11 @@ describe HexaPDF::Layout::Frame do
90
86
  refute_nil(fit_result)
91
87
  @frame.draw(@canvas, fit_result)
92
88
  assert_equal(mask, fit_result.mask.bbox.to_a)
93
- assert_equal(points, @frame.shape.polygons.map(&:to_a))
89
+ if @frame.shape.respond_to?(:polygons)
90
+ assert_equal(points, @frame.shape.polygons.map(&:to_a))
91
+ else
92
+ assert_equal(points, [@frame.shape.to_a])
93
+ end
94
94
  @canvas.verify
95
95
  end
96
96
 
@@ -99,9 +99,9 @@ describe HexaPDF::Layout::Frame do
99
99
  areas.each do |area|
100
100
  @frame.remove_area(
101
101
  case area
102
- when :left then Geom2D::Polygon([10, 10], [10, 110], [20, 110], [20, 10])
103
- when :right then Geom2D::Polygon([100, 10], [100, 110], [110, 110], [110, 10])
104
- when :top then Geom2D::Polygon([10, 110], [110, 110], [110, 100], [10, 100])
102
+ when :left then Geom2D::Rectangle(10, 10, 10, 100)
103
+ when :right then Geom2D::Rectangle(100, 10, 10, 100)
104
+ when :top then Geom2D::Rectangle(10, 100, 100, 10)
105
105
  end
106
106
  )
107
107
  end
@@ -323,7 +323,7 @@ describe HexaPDF::Layout::Frame do
323
323
  end
324
324
 
325
325
  it "can't fit the box if there is no available space" do
326
- @frame.remove_area(Geom2D::Polygon([0, 0], [110, 0], [110, 110], [0, 110]))
326
+ @frame.remove_area(Geom2D::Rectangle(0, 0, 110, 110))
327
327
  box = HexaPDF::Layout::Box.create
328
328
  refute(@frame.fit(box).success?)
329
329
  end
@@ -388,7 +388,7 @@ describe HexaPDF::Layout::Frame do
388
388
  # +--------+
389
389
  it "works for a region with a hole" do
390
390
  frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100)
391
- frame.remove_area(Geom2D::Polygon([20, 20], [80, 20], [80, 80], [20, 80]))
391
+ frame.remove_area(Geom2D::Rectangle(20, 20, 60, 60))
392
392
  check_regions(frame, [[0, 100, 100, 20], [0, 100, 20, 100],
393
393
  [0, 80, 20, 80], [0, 20, 100, 20]])
394
394
  end
@@ -400,7 +400,7 @@ describe HexaPDF::Layout::Frame do
400
400
  # +--------+
401
401
  it "works for a u-shaped frame" do
402
402
  frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100)
403
- frame.remove_area(Geom2D::Polygon([30, 100], [70, 100], [70, 60], [30, 60]))
403
+ frame.remove_area(Geom2D::Rectangle(30, 60, 40, 40))
404
404
  check_regions(frame, [[0, 100, 30, 100], [0, 60, 100, 60]])
405
405
  end
406
406
 
@@ -415,7 +415,7 @@ describe HexaPDF::Layout::Frame do
415
415
  it "works for a complicated frame" do
416
416
  frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100)
417
417
  top_cut = Geom2D::Polygon([20, 100], [20, 80], [40, 80], [40, 90], [60, 90], [60, 100])
418
- left_cut = Geom2D::Polygon([0, 20], [30, 20], [30, 40], [0, 40])
418
+ left_cut = Geom2D::Rectangle(0, 20, 30, 20)
419
419
  frame.remove_area(Geom2D::PolygonSet(top_cut, left_cut))
420
420
 
421
421
  check_regions(frame, [[0, 100, 20, 60], [0, 90, 20, 50], [0, 80, 100, 40],
@@ -56,6 +56,10 @@ describe HexaPDF::Layout::ImageBox do
56
56
  end
57
57
  end
58
58
 
59
+ it "always returns false for empty?" do
60
+ refute(create_box.empty?)
61
+ end
62
+
59
63
  describe "draw" do
60
64
  it "draws the image" do
61
65
  box = create_box(height: 40, style: {padding: [10, 4, 6, 2]})
@@ -30,6 +30,11 @@ describe HexaPDF::Layout::InlineBox do
30
30
  assert_equal(45, ibox.height)
31
31
  end
32
32
 
33
+ it "fails if the wrapped box has not width set" do
34
+ box = HexaPDF::Document.new.layout.text("test is not going good")
35
+ assert_raises(HexaPDF::Error) { inline_box(box) }
36
+ end
37
+
33
38
  it "fails if the wrapped box could not be fit" do
34
39
  box = HexaPDF::Document.new.layout.text("test is not going good", width: 1)
35
40
  assert_raises(HexaPDF::Error) { inline_box(box) }
@@ -18,7 +18,7 @@ describe HexaPDF::Layout::ListBox do
18
18
  end
19
19
 
20
20
  def check_box(box, width, height, fit_pos = nil)
21
- assert(box.fit(@frame.available_width, @frame.available_height, @frame), "box fit?")
21
+ assert(box.fit(@frame.available_width, @frame.available_height, @frame), "box didn't fit")
22
22
  assert_equal(width, box.width, "box width")
23
23
  assert_equal(height, box.height, "box height")
24
24
  if fit_pos
@@ -47,6 +47,18 @@ describe HexaPDF::Layout::ListBox do
47
47
  end
48
48
  end
49
49
 
50
+ describe "empty?" do
51
+ it "is empty if nothing was fit yet" do
52
+ assert(create_box.empty?)
53
+ end
54
+
55
+ it "is empty if nothing could be fit" do
56
+ box = create_box(children: [@text_boxes[0]], width: 5)
57
+ box.fit(@frame.available_width, @frame.available_height, @frame)
58
+ assert(create_box.empty?)
59
+ end
60
+ end
61
+
50
62
  describe "fit" do
51
63
  [:default, :flow].each do |position|
52
64
  it "respects the set initial width, position #{position}" do
@@ -123,7 +135,7 @@ describe HexaPDF::Layout::ListBox do
123
135
  it "draws the result" do
124
136
  box = create_box(children: @fixed_size_boxes[0, 2])
125
137
  box.fit(100, 100, @frame)
126
- box.draw(@canvas, 0, 0)
138
+ box.draw(@canvas, 0, 100 - box.height)
127
139
  operators = [
128
140
  [:save_graphics_state],
129
141
  [:set_font_and_size, [:F1, 10]],
@@ -153,7 +165,7 @@ describe HexaPDF::Layout::ListBox do
153
165
  it "draws a cicle as marker" do
154
166
  box = create_box(children: @fixed_size_boxes[0, 1], item_type: :circle)
155
167
  box.fit(100, 100, @frame)
156
- box.draw(@canvas, 0, 0)
168
+ box.draw(@canvas, 0, 100 - box.height)
157
169
  operators = [
158
170
  [:save_graphics_state],
159
171
  [:set_font_and_size, [:F1, 5]],
@@ -173,7 +185,7 @@ describe HexaPDF::Layout::ListBox do
173
185
  it "draws a square as marker" do
174
186
  box = create_box(children: @fixed_size_boxes[0, 1], item_type: :square)
175
187
  box.fit(100, 100, @frame)
176
- box.draw(@canvas, 0, 0)
188
+ box.draw(@canvas, 0, 100 - box.height)
177
189
  operators = [
178
190
  [:save_graphics_state],
179
191
  [:set_font_and_size, [:F1, 5]],
@@ -194,7 +206,7 @@ describe HexaPDF::Layout::ListBox do
194
206
  box = create_box(children: @fixed_size_boxes[0, 2], item_type: :decimal,
195
207
  content_indentation: 20)
196
208
  box.fit(100, 100, @frame)
197
- box.draw(@canvas, 0, 0)
209
+ box.draw(@canvas, 0, 100 - box.height)
198
210
  operators = [
199
211
  [:save_graphics_state],
200
212
  [:set_font_and_size, [:F1, 10]],
@@ -227,7 +239,7 @@ describe HexaPDF::Layout::ListBox do
227
239
  end
228
240
  box = create_box(children: @fixed_size_boxes[0, 1], item_type: marker)
229
241
  box.fit(100, 100, @frame)
230
- box.draw(@canvas, 0, 0)
242
+ box.draw(@canvas, 0, 100 - box.height)
231
243
  operators = [
232
244
  [:save_graphics_state],
233
245
  [:concatenate_matrix, [1, 0, 0, 1, 0, 90]],
@@ -239,6 +251,28 @@ describe HexaPDF::Layout::ListBox do
239
251
  assert_operators(@canvas.contents, operators)
240
252
  end
241
253
 
254
+ it "takes a different final location into account" do
255
+ box = create_box(children: @fixed_size_boxes[0, 1])
256
+ box.fit(100, 100, @frame)
257
+ box.draw(@canvas, 20, 10)
258
+ operators = [
259
+ [:save_graphics_state],
260
+ [:concatenate_matrix, [1, 0, 0, 1, 20, -80]],
261
+ [:save_graphics_state],
262
+ [:set_font_and_size, [:F1, 10]],
263
+ [:begin_text],
264
+ [:set_text_matrix, [1, 0, 0, 1, 1.5, 93.17]],
265
+ [:show_text, ["\x95".b]],
266
+ [:end_text],
267
+ [:restore_graphics_state],
268
+ [:save_graphics_state],
269
+ [:concatenate_matrix, [1, 0, 0, 1, 10, 90]],
270
+ [:restore_graphics_state],
271
+ [:restore_graphics_state],
272
+ ]
273
+ assert_operators(@canvas.contents, operators)
274
+ end
275
+
242
276
  it "fails for unknown item types" do
243
277
  box = create_box(children: @fixed_size_boxes[0, 1], item_type: :unknown)
244
278
  box.fit(100, 100, @frame)
@@ -5,11 +5,12 @@ require 'hexapdf/layout/page_style'
5
5
  require 'hexapdf/document'
6
6
 
7
7
  describe HexaPDF::Layout::PageStyle do
8
- it "allows assigning the page size, orientation and template on initialization" do
8
+ it "allows assigning the page size, orientation, next style and template on initialization" do
9
9
  block = lambda {}
10
- style = HexaPDF::Layout::PageStyle.new(page_size: :A3, orientation: :landscape, &block)
10
+ style = HexaPDF::Layout::PageStyle.new(page_size: :A3, orientation: :landscape, next_style: :a, &block)
11
11
  assert_equal(:A3, style.page_size)
12
12
  assert_equal(:landscape, style.orientation)
13
+ assert_equal(:a, style.next_style)
13
14
  assert_same(block, style.template)
14
15
  end
15
16
 
@@ -156,15 +156,24 @@ describe HexaPDF::Layout::Style::Border do
156
156
  assert_kind_of(HexaPDF::Layout::Style::Quad, border.style)
157
157
  end
158
158
 
159
+ it "has an accessor for the draw-on-bounds option" do
160
+ border = create_border
161
+ refute(border.draw_on_bounds)
162
+ border.draw_on_bounds = true
163
+ assert(border.draw_on_bounds)
164
+ end
165
+
159
166
  it "can be duplicated" do
160
167
  border = create_border
161
168
  copy = border.dup
162
169
  border.width.top = 10
163
170
  border.color.top = :red
164
171
  border.style.top = :dotted
172
+ border.draw_on_bounds = true
165
173
  assert_equal(0, copy.width.top)
166
174
  assert_equal(0, copy.color.top)
167
175
  assert_equal(:solid, copy.style.top)
176
+ refute(copy.draw_on_bounds)
168
177
  end
169
178
 
170
179
  it "can be asked whether a border is defined" do
@@ -259,6 +268,19 @@ describe HexaPDF::Layout::Style::Border do
259
268
  [:restore_graphics_state]]
260
269
  assert_operators(@canvas.contents, ops)
261
270
  end
271
+
272
+ it "works if the border is drawn on the bounds" do
273
+ border = create_border(width: 10, color: 0.5, style: :solid, draw_on_bounds: true)
274
+ border.draw(@canvas, 0, 0, 100, 100)
275
+ assert_operators(@canvas.contents, [[:save_graphics_state],
276
+ [:set_device_gray_stroking_color, [0.5]],
277
+ [:set_line_width, [10]],
278
+ [:append_rectangle, [-5, -5, 110, 110]],
279
+ [:clip_path_non_zero], [:end_path],
280
+ [:append_rectangle, [0, 0, 100, 100]],
281
+ [:stroke_path],
282
+ [:restore_graphics_state]])
283
+ end
262
284
  end
263
285
 
264
286
  describe "complex borders where edges have different width/color/style values" do
@@ -369,6 +391,34 @@ describe HexaPDF::Layout::Style::Border do
369
391
  [:restore_graphics_state], [:restore_graphics_state]]
370
392
  assert_operators(@canvas.contents, ops)
371
393
  end
394
+
395
+ it "works if the border is drawn on the bounds" do
396
+ border = create_border(width: [20, 10, 40, 30], draw_on_bounds: true)
397
+ border.draw(@canvas, 0, 0, 100, 200)
398
+ ops = [[:save_graphics_state],
399
+ [:save_graphics_state],
400
+ [:move_to, [-15, 210]], [:line_to, [105, 210]],
401
+ [:line_to, [95, 190]], [:line_to, [15, 190]], [:clip_path_non_zero], [:end_path],
402
+ [:set_line_width, [20]],
403
+ [:move_to, [-15, 200]], [:line_to, [105, 200]], [:stroke_path],
404
+ [:restore_graphics_state], [:save_graphics_state],
405
+ [:move_to, [105, 210]], [:line_to, [105, -20]],
406
+ [:line_to, [95, 20]], [:line_to, [95, 190]], [:clip_path_non_zero], [:end_path],
407
+ [:set_line_width, [10]],
408
+ [:move_to, [100, 210]], [:line_to, [100, -20]], [:stroke_path],
409
+ [:restore_graphics_state], [:save_graphics_state],
410
+ [:move_to, [105, -20]], [:line_to, [-15, -20]],
411
+ [:line_to, [15, 20]], [:line_to, [95, 20]], [:clip_path_non_zero], [:end_path],
412
+ [:set_line_width, [40]],
413
+ [:move_to, [105, 0]], [:line_to, [-15, 0]], [:stroke_path],
414
+ [:restore_graphics_state], [:save_graphics_state],
415
+ [:move_to, [-15, -20]], [:line_to, [-15, 210]],
416
+ [:line_to, [15, 190]], [:line_to, [15, 20]], [:clip_path_non_zero], [:end_path],
417
+ [:set_line_width, [30]],
418
+ [:move_to, [0, -20]], [:line_to, [0, 210]], [:stroke_path],
419
+ [:restore_graphics_state], [:restore_graphics_state]]
420
+ assert_operators(@canvas.contents, ops)
421
+ end
372
422
  end
373
423
 
374
424
  describe "border width greater than edge length" do