hexapdf 0.32.2 → 0.34.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 (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +104 -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/examples/026-optional_content.rb +55 -0
  19. data/examples/027-composer_optional_content.rb +83 -0
  20. data/lib/hexapdf/cli/command.rb +12 -3
  21. data/lib/hexapdf/cli/fonts.rb +1 -1
  22. data/lib/hexapdf/cli/form.rb +5 -5
  23. data/lib/hexapdf/cli/inspect.rb +5 -7
  24. data/lib/hexapdf/composer.rb +106 -53
  25. data/lib/hexapdf/configuration.rb +65 -40
  26. data/lib/hexapdf/content/canvas.rb +445 -267
  27. data/lib/hexapdf/content/color_space.rb +72 -25
  28. data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
  29. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
  30. data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
  31. data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
  32. data/lib/hexapdf/content/graphic_object.rb +6 -7
  33. data/lib/hexapdf/content/graphics_state.rb +54 -45
  34. data/lib/hexapdf/content/operator.rb +54 -54
  35. data/lib/hexapdf/content/parser.rb +2 -2
  36. data/lib/hexapdf/content/processor.rb +15 -15
  37. data/lib/hexapdf/content/transformation_matrix.rb +1 -1
  38. data/lib/hexapdf/content.rb +5 -0
  39. data/lib/hexapdf/dictionary.rb +7 -5
  40. data/lib/hexapdf/dictionary_fields.rb +43 -16
  41. data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
  42. data/lib/hexapdf/digital_signature/handler.rb +1 -1
  43. data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
  44. data/lib/hexapdf/digital_signature/signature.rb +6 -6
  45. data/lib/hexapdf/digital_signature/signatures.rb +13 -12
  46. data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
  47. data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
  48. data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
  49. data/lib/hexapdf/digital_signature/signing.rb +4 -0
  50. data/lib/hexapdf/digital_signature/verification_result.rb +3 -4
  51. data/lib/hexapdf/digital_signature.rb +7 -2
  52. data/lib/hexapdf/document/destinations.rb +12 -11
  53. data/lib/hexapdf/document/files.rb +1 -1
  54. data/lib/hexapdf/document/fonts.rb +1 -1
  55. data/lib/hexapdf/document/layout.rb +170 -39
  56. data/lib/hexapdf/document/pages.rb +4 -3
  57. data/lib/hexapdf/document.rb +96 -55
  58. data/lib/hexapdf/encryption/aes.rb +5 -5
  59. data/lib/hexapdf/encryption/arc4.rb +1 -1
  60. data/lib/hexapdf/encryption/fast_aes.rb +2 -2
  61. data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
  62. data/lib/hexapdf/encryption/identity.rb +1 -1
  63. data/lib/hexapdf/encryption/ruby_aes.rb +11 -21
  64. data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
  65. data/lib/hexapdf/encryption/security_handler.rb +31 -24
  66. data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
  67. data/lib/hexapdf/encryption.rb +7 -2
  68. data/lib/hexapdf/error.rb +18 -0
  69. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  70. data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
  71. data/lib/hexapdf/filter/flate_decode.rb +1 -1
  72. data/lib/hexapdf/filter/lzw_decode.rb +1 -1
  73. data/lib/hexapdf/filter/pass_through.rb +1 -1
  74. data/lib/hexapdf/filter/predictor.rb +1 -1
  75. data/lib/hexapdf/filter/run_length_decode.rb +1 -1
  76. data/lib/hexapdf/filter.rb +55 -6
  77. data/lib/hexapdf/font/cmap/parser.rb +2 -2
  78. data/lib/hexapdf/font/cmap.rb +1 -1
  79. data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
  80. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
  81. data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
  82. data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
  83. data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
  84. data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +3 -3
  85. data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
  86. data/lib/hexapdf/font/invalid_glyph.rb +3 -0
  87. data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
  88. data/lib/hexapdf/font/type1_wrapper.rb +19 -4
  89. data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
  90. data/lib/hexapdf/font_loader/from_file.rb +5 -5
  91. data/lib/hexapdf/font_loader/standard14.rb +3 -3
  92. data/lib/hexapdf/font_loader.rb +3 -0
  93. data/lib/hexapdf/image_loader/jpeg.rb +2 -2
  94. data/lib/hexapdf/image_loader/pdf.rb +1 -1
  95. data/lib/hexapdf/image_loader/png.rb +2 -2
  96. data/lib/hexapdf/image_loader.rb +1 -1
  97. data/lib/hexapdf/importer.rb +13 -0
  98. data/lib/hexapdf/layout/box.rb +32 -5
  99. data/lib/hexapdf/layout/box_fitter.rb +2 -2
  100. data/lib/hexapdf/layout/column_box.rb +20 -5
  101. data/lib/hexapdf/layout/frame.rb +53 -18
  102. data/lib/hexapdf/layout/image_box.rb +5 -0
  103. data/lib/hexapdf/layout/inline_box.rb +21 -9
  104. data/lib/hexapdf/layout/list_box.rb +50 -20
  105. data/lib/hexapdf/layout/page_style.rb +6 -5
  106. data/lib/hexapdf/layout/style.rb +64 -9
  107. data/lib/hexapdf/layout/table_box.rb +684 -0
  108. data/lib/hexapdf/layout/text_box.rb +12 -3
  109. data/lib/hexapdf/layout/text_fragment.rb +29 -3
  110. data/lib/hexapdf/layout/text_layouter.rb +32 -8
  111. data/lib/hexapdf/layout.rb +1 -0
  112. data/lib/hexapdf/name_tree_node.rb +1 -1
  113. data/lib/hexapdf/number_tree_node.rb +1 -1
  114. data/lib/hexapdf/object.rb +18 -7
  115. data/lib/hexapdf/parser.rb +7 -7
  116. data/lib/hexapdf/pdf_array.rb +1 -1
  117. data/lib/hexapdf/rectangle.rb +1 -1
  118. data/lib/hexapdf/reference.rb +1 -1
  119. data/lib/hexapdf/revision.rb +1 -1
  120. data/lib/hexapdf/revisions.rb +3 -3
  121. data/lib/hexapdf/serializer.rb +15 -15
  122. data/lib/hexapdf/stream.rb +5 -4
  123. data/lib/hexapdf/tokenizer.rb +14 -14
  124. data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
  125. data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
  126. data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
  127. data/lib/hexapdf/type/acro_form/field.rb +2 -2
  128. data/lib/hexapdf/type/acro_form/form.rb +1 -1
  129. data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
  130. data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
  131. data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
  132. data/lib/hexapdf/type/acro_form.rb +1 -1
  133. data/lib/hexapdf/type/action.rb +1 -1
  134. data/lib/hexapdf/type/actions/go_to.rb +1 -1
  135. data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
  136. data/lib/hexapdf/type/actions/launch.rb +1 -1
  137. data/lib/hexapdf/type/actions/set_ocg_state.rb +86 -0
  138. data/lib/hexapdf/type/actions/uri.rb +1 -1
  139. data/lib/hexapdf/type/actions.rb +2 -1
  140. data/lib/hexapdf/type/annotation.rb +3 -3
  141. data/lib/hexapdf/type/annotations/link.rb +1 -1
  142. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  143. data/lib/hexapdf/type/annotations/text.rb +2 -3
  144. data/lib/hexapdf/type/annotations/widget.rb +2 -2
  145. data/lib/hexapdf/type/annotations.rb +1 -1
  146. data/lib/hexapdf/type/catalog.rb +11 -2
  147. data/lib/hexapdf/type/cid_font.rb +18 -4
  148. data/lib/hexapdf/type/embedded_file.rb +1 -1
  149. data/lib/hexapdf/type/file_specification.rb +2 -2
  150. data/lib/hexapdf/type/font_descriptor.rb +1 -1
  151. data/lib/hexapdf/type/font_simple.rb +2 -2
  152. data/lib/hexapdf/type/font_type0.rb +3 -3
  153. data/lib/hexapdf/type/font_type3.rb +1 -1
  154. data/lib/hexapdf/type/form.rb +76 -6
  155. data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
  156. data/lib/hexapdf/type/icon_fit.rb +1 -1
  157. data/lib/hexapdf/type/image.rb +1 -1
  158. data/lib/hexapdf/type/info.rb +1 -1
  159. data/lib/hexapdf/type/mark_information.rb +1 -1
  160. data/lib/hexapdf/type/names.rb +2 -2
  161. data/lib/hexapdf/type/object_stream.rb +2 -1
  162. data/lib/hexapdf/type/optional_content_configuration.rb +170 -0
  163. data/lib/hexapdf/type/optional_content_group.rb +370 -0
  164. data/lib/hexapdf/type/optional_content_membership.rb +63 -0
  165. data/lib/hexapdf/type/optional_content_properties.rb +158 -0
  166. data/lib/hexapdf/type/outline.rb +1 -1
  167. data/lib/hexapdf/type/outline_item.rb +1 -1
  168. data/lib/hexapdf/type/page.rb +46 -21
  169. data/lib/hexapdf/type/page_label.rb +5 -9
  170. data/lib/hexapdf/type/page_tree_node.rb +1 -1
  171. data/lib/hexapdf/type/resources.rb +1 -1
  172. data/lib/hexapdf/type/trailer.rb +2 -2
  173. data/lib/hexapdf/type/viewer_preferences.rb +1 -1
  174. data/lib/hexapdf/type/xref_stream.rb +2 -2
  175. data/lib/hexapdf/type.rb +4 -0
  176. data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -2
  177. data/lib/hexapdf/version.rb +1 -1
  178. data/lib/hexapdf/writer.rb +4 -4
  179. data/lib/hexapdf/xref_section.rb +2 -2
  180. data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
  181. data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
  182. data/test/hexapdf/content/test_canvas.rb +49 -1
  183. data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
  184. data/test/hexapdf/document/test_files.rb +2 -2
  185. data/test/hexapdf/document/test_layout.rb +105 -2
  186. data/test/hexapdf/document/test_pages.rb +6 -6
  187. data/test/hexapdf/encryption/test_security_handler.rb +12 -11
  188. data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
  189. data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
  190. data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
  191. data/test/hexapdf/layout/test_box.rb +14 -5
  192. data/test/hexapdf/layout/test_column_box.rb +65 -21
  193. data/test/hexapdf/layout/test_frame.rb +27 -15
  194. data/test/hexapdf/layout/test_image_box.rb +4 -0
  195. data/test/hexapdf/layout/test_inline_box.rb +17 -3
  196. data/test/hexapdf/layout/test_list_box.rb +84 -33
  197. data/test/hexapdf/layout/test_page_style.rb +3 -2
  198. data/test/hexapdf/layout/test_style.rb +60 -0
  199. data/test/hexapdf/layout/test_table_box.rb +728 -0
  200. data/test/hexapdf/layout/test_text_box.rb +26 -0
  201. data/test/hexapdf/layout/test_text_fragment.rb +33 -0
  202. data/test/hexapdf/layout/test_text_layouter.rb +36 -5
  203. data/test/hexapdf/test_composer.rb +10 -0
  204. data/test/hexapdf/test_dictionary.rb +10 -0
  205. data/test/hexapdf/test_dictionary_fields.rb +4 -1
  206. data/test/hexapdf/test_document.rb +5 -0
  207. data/test/hexapdf/test_filter.rb +8 -0
  208. data/test/hexapdf/test_importer.rb +9 -0
  209. data/test/hexapdf/test_object.rb +16 -5
  210. data/test/hexapdf/test_stream.rb +7 -0
  211. data/test/hexapdf/test_writer.rb +3 -3
  212. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
  213. data/test/hexapdf/type/acro_form/test_form.rb +4 -3
  214. data/test/hexapdf/type/actions/test_set_ocg_state.rb +40 -0
  215. data/test/hexapdf/type/test_catalog.rb +11 -0
  216. data/test/hexapdf/type/test_form.rb +119 -0
  217. data/test/hexapdf/type/test_optional_content_configuration.rb +112 -0
  218. data/test/hexapdf/type/test_optional_content_group.rb +158 -0
  219. data/test/hexapdf/type/test_optional_content_properties.rb +109 -0
  220. data/test/hexapdf/type/test_page.rb +20 -6
  221. metadata +28 -8
@@ -6,7 +6,9 @@ require 'hexapdf/layout/list_box'
6
6
 
7
7
  describe HexaPDF::Layout::ListBox do
8
8
  before do
9
- @frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100)
9
+ @doc = HexaPDF::Document.new
10
+ @page = @doc.pages.add
11
+ @frame = HexaPDF::Layout::Frame.new(0, 0, 100, 100, context: @page)
10
12
  inline_box = HexaPDF::Layout::InlineBox.create(width: 10, height: 10) {}
11
13
  @text_boxes = 5.times.map do
12
14
  HexaPDF::Layout::TextBox.new(items: [inline_box] * 15, style: {position: :default})
@@ -18,13 +20,13 @@ describe HexaPDF::Layout::ListBox do
18
20
  end
19
21
 
20
22
  def check_box(box, width, height, fit_pos = nil)
21
- assert(box.fit(@frame.available_width, @frame.available_height, @frame), "box fit?")
23
+ assert(box.fit(@frame.available_width, @frame.available_height, @frame), "box didn't fit")
22
24
  assert_equal(width, box.width, "box width")
23
25
  assert_equal(height, box.height, "box height")
24
26
  if fit_pos
25
27
  results = box.instance_variable_get(:@results)
26
- results.each_with_index do |box_fitter, item_index|
27
- box_fitter.fit_results.each_with_index do |fit_result, result_index|
28
+ results.each_with_index do |item_result, item_index|
29
+ item_result.box_fitter.fit_results.each_with_index do |fit_result, result_index|
28
30
  x, y = fit_pos.shift
29
31
  assert_equal(x, fit_result.x, "item #{item_index}, result #{result_index}, x")
30
32
  assert_equal(y, fit_result.y, "item #{item_index}, result #{result_index}, y")
@@ -47,6 +49,18 @@ describe HexaPDF::Layout::ListBox do
47
49
  end
48
50
  end
49
51
 
52
+ describe "empty?" do
53
+ it "is empty if nothing was fit yet" do
54
+ assert(create_box.empty?)
55
+ end
56
+
57
+ it "is empty if nothing could be fit" do
58
+ box = create_box(children: [@text_boxes[0]], width: 5)
59
+ box.fit(@frame.available_width, @frame.available_height, @frame)
60
+ assert(box.empty?)
61
+ end
62
+ end
63
+
50
64
  describe "fit" do
51
65
  [:default, :flow].each do |position|
52
66
  it "respects the set initial width, position #{position}" do
@@ -78,6 +92,12 @@ describe HexaPDF::Layout::ListBox do
78
92
  check_box(box, 100, 90, [[10, 80], [10, 60], [10, 40], [50, 10]])
79
93
  end
80
94
 
95
+ it "calculates the correct height if the marker is higher than the content" do
96
+ box = create_box(children: @text_boxes[0, 1], content_indentation: 20,
97
+ style: {font_size: 30})
98
+ check_box(box, 100, 27, [[20, 80]])
99
+ end
100
+
81
101
  it "respects the content indentation" do
82
102
  box = create_box(children: @text_boxes[0, 1], content_indentation: 30)
83
103
  check_box(box, 100, 30, [[30, 70]])
@@ -87,6 +107,11 @@ describe HexaPDF::Layout::ListBox do
87
107
  box = create_box(children: @text_boxes[0, 2], item_spacing: 30)
88
108
  check_box(box, 100, 70, [[10, 80], [10, 30]])
89
109
  end
110
+
111
+ it "fails for unknown item types" do
112
+ box = create_box(children: @text_boxes[0, 1], item_type: :unknown)
113
+ assert_raises(HexaPDF::Error) { box.fit(100, 100, @frame) }
114
+ end
90
115
  end
91
116
 
92
117
  describe "split" do
@@ -96,7 +121,7 @@ describe HexaPDF::Layout::ListBox do
96
121
  box_a, box_b = box.split(100, 100, @frame)
97
122
  assert_same(box, box_a)
98
123
  assert_equal(:show_first_marker, box_b.split_box?)
99
- assert_equal(1, box_a.instance_variable_get(:@results)[0].fit_results.size)
124
+ assert_equal(1, box_a.instance_variable_get(:@results)[0].box_fitter.fit_results.size)
100
125
  assert_equal(1, box_b.children.size)
101
126
  assert_equal(2, box_b.start_number)
102
127
  end
@@ -107,7 +132,7 @@ describe HexaPDF::Layout::ListBox do
107
132
  box_a, box_b = box.split(100, 100, @frame)
108
133
  assert_same(box, box_a)
109
134
  assert_equal(:hide_first_marker, box_b.split_box?)
110
- assert_equal(1, box_a.instance_variable_get(:@results)[0].fit_results.size)
135
+ assert_equal(1, box_a.instance_variable_get(:@results)[0].box_fitter.fit_results.size)
111
136
  assert_equal(2, box_b.children.size)
112
137
  assert_equal(1, box_b.start_number)
113
138
  end
@@ -115,20 +140,22 @@ describe HexaPDF::Layout::ListBox do
115
140
 
116
141
  describe "draw" do
117
142
  before do
118
- @canvas = HexaPDF::Document.new.pages.add.canvas
143
+ @canvas = @page.canvas
119
144
  draw_block = lambda {|canvas, box| }
120
145
  @fixed_size_boxes = 5.times.map { HexaPDF::Layout::Box.new(width: 20, height: 10, &draw_block) }
121
146
  end
122
147
 
123
148
  it "draws the result" do
124
- box = create_box(children: @fixed_size_boxes[0, 2])
149
+ box = create_box(children: @fixed_size_boxes[0, 2],
150
+ style: {font_size: 11, fill_color: 0.5})
125
151
  box.fit(100, 100, @frame)
126
- box.draw(@canvas, 0, 0)
152
+ box.draw(@canvas, 0, 100 - box.height)
127
153
  operators = [
128
154
  [:save_graphics_state],
129
- [:set_font_and_size, [:F1, 10]],
155
+ [:set_font_and_size, [:F1, 11]],
156
+ [:set_device_gray_non_stroking_color, [0.5]],
130
157
  [:begin_text],
131
- [:set_text_matrix, [1, 0, 0, 1, 1.5, 93.17]],
158
+ [:set_text_matrix, [1, 0, 0, 1, 1.15, 92.487]],
132
159
  [:show_text, ["\x95".b]],
133
160
  [:end_text],
134
161
  [:restore_graphics_state],
@@ -137,9 +164,10 @@ describe HexaPDF::Layout::ListBox do
137
164
  [:restore_graphics_state],
138
165
 
139
166
  [:save_graphics_state],
140
- [:set_font_and_size, [:F1, 10]],
167
+ [:set_font_and_size, [:F1, 11]],
168
+ [:set_device_gray_non_stroking_color, [0.5]],
141
169
  [:begin_text],
142
- [:set_text_matrix, [1, 0, 0, 1, 1.5, 83.17]],
170
+ [:set_text_matrix, [1, 0, 0, 1, 1.15, 82.487]],
143
171
  [:show_text, ["\x95".b]],
144
172
  [:end_text],
145
173
  [:restore_graphics_state],
@@ -150,16 +178,18 @@ describe HexaPDF::Layout::ListBox do
150
178
  assert_operators(@canvas.contents, operators)
151
179
  end
152
180
 
153
- it "draws a cicle as marker" do
154
- box = create_box(children: @fixed_size_boxes[0, 1], item_type: :circle)
181
+ it "draws a circle as marker" do
182
+ box = create_box(children: @fixed_size_boxes[0, 1], item_type: :circle,
183
+ style: {font_size: 11, fill_color: 0.5})
155
184
  box.fit(100, 100, @frame)
156
- box.draw(@canvas, 0, 0)
185
+ box.draw(@canvas, 0, 100 - box.height)
157
186
  operators = [
158
187
  [:save_graphics_state],
159
- [:set_font_and_size, [:F1, 5]],
160
- [:set_text_rise, [-5.555556]],
188
+ [:set_font_and_size, [:F1, 5.5]],
189
+ [:set_text_rise, [-6.111111]],
190
+ [:set_device_gray_non_stroking_color, [0.5]],
161
191
  [:begin_text],
162
- [:set_text_matrix, [1, 0, 0, 1, 0.635, 100]],
192
+ [:set_text_matrix, [1, 0, 0, 1, 0.1985, 100]],
163
193
  [:show_text, ["m".b]],
164
194
  [:end_text],
165
195
  [:restore_graphics_state],
@@ -171,15 +201,17 @@ describe HexaPDF::Layout::ListBox do
171
201
  end
172
202
 
173
203
  it "draws a square as marker" do
174
- box = create_box(children: @fixed_size_boxes[0, 1], item_type: :square)
204
+ box = create_box(children: @fixed_size_boxes[0, 1], item_type: :square,
205
+ style: {font_size: 11, fill_color: 0.5})
175
206
  box.fit(100, 100, @frame)
176
- box.draw(@canvas, 0, 0)
207
+ box.draw(@canvas, 0, 100 - box.height)
177
208
  operators = [
178
209
  [:save_graphics_state],
179
- [:set_font_and_size, [:F1, 5]],
180
- [:set_text_rise, [-5.555556]],
210
+ [:set_font_and_size, [:F1, 5.5]],
211
+ [:set_text_rise, [-6.111111]],
212
+ [:set_device_gray_non_stroking_color, [0.5]],
181
213
  [:begin_text],
182
- [:set_text_matrix, [1, 0, 0, 1, 1.195, 100]],
214
+ [:set_text_matrix, [1, 0, 0, 1, 0.8145, 100]],
183
215
  [:show_text, ["n".b]],
184
216
  [:end_text],
185
217
  [:restore_graphics_state],
@@ -192,14 +224,16 @@ describe HexaPDF::Layout::ListBox do
192
224
 
193
225
  it "draws decimal numbers as marker" do
194
226
  box = create_box(children: @fixed_size_boxes[0, 2], item_type: :decimal,
227
+ style: {font_size: 11, fill_color: 0.5},
195
228
  content_indentation: 20)
196
229
  box.fit(100, 100, @frame)
197
- box.draw(@canvas, 0, 0)
230
+ box.draw(@canvas, 0, 100 - box.height)
198
231
  operators = [
199
232
  [:save_graphics_state],
200
- [:set_font_and_size, [:F1, 10]],
233
+ [:set_font_and_size, [:F1, 11]],
234
+ [:set_device_gray_non_stroking_color, [0.5]],
201
235
  [:begin_text],
202
- [:set_text_matrix, [1, 0, 0, 1, 7.5, 93.17]],
236
+ [:set_text_matrix, [1, 0, 0, 1, 6.75, 92.487]],
203
237
  [:show_text, ["1.".b]],
204
238
  [:end_text],
205
239
  [:restore_graphics_state],
@@ -208,9 +242,10 @@ describe HexaPDF::Layout::ListBox do
208
242
  [:restore_graphics_state],
209
243
 
210
244
  [:save_graphics_state],
211
- [:set_font_and_size, [:F1, 10]],
245
+ [:set_font_and_size, [:F1, 11]],
246
+ [:set_device_gray_non_stroking_color, [0.5]],
212
247
  [:begin_text],
213
- [:set_text_matrix, [1, 0, 0, 1, 7.5, 83.17]],
248
+ [:set_text_matrix, [1, 0, 0, 1, 6.75, 82.487]],
214
249
  [:show_text, ["2.".b]],
215
250
  [:end_text],
216
251
  [:restore_graphics_state],
@@ -227,7 +262,7 @@ describe HexaPDF::Layout::ListBox do
227
262
  end
228
263
  box = create_box(children: @fixed_size_boxes[0, 1], item_type: marker)
229
264
  box.fit(100, 100, @frame)
230
- box.draw(@canvas, 0, 0)
265
+ box.draw(@canvas, 0, 100 - box.height)
231
266
  operators = [
232
267
  [:save_graphics_state],
233
268
  [:concatenate_matrix, [1, 0, 0, 1, 0, 90]],
@@ -239,10 +274,26 @@ describe HexaPDF::Layout::ListBox do
239
274
  assert_operators(@canvas.contents, operators)
240
275
  end
241
276
 
242
- it "fails for unknown item types" do
243
- box = create_box(children: @fixed_size_boxes[0, 1], item_type: :unknown)
277
+ it "takes a different final location into account" do
278
+ box = create_box(children: @fixed_size_boxes[0, 1])
244
279
  box.fit(100, 100, @frame)
245
- assert_raises(HexaPDF::Error) { box.draw(@canvas, 0, 0) }
280
+ box.draw(@canvas, 20, 10)
281
+ operators = [
282
+ [:save_graphics_state],
283
+ [:concatenate_matrix, [1, 0, 0, 1, 20, -80]],
284
+ [:save_graphics_state],
285
+ [:set_font_and_size, [:F1, 10]],
286
+ [:begin_text],
287
+ [:set_text_matrix, [1, 0, 0, 1, 1.5, 93.17]],
288
+ [:show_text, ["\x95".b]],
289
+ [:end_text],
290
+ [:restore_graphics_state],
291
+ [:save_graphics_state],
292
+ [:concatenate_matrix, [1, 0, 0, 1, 10, 90]],
293
+ [:restore_graphics_state],
294
+ [:restore_graphics_state],
295
+ ]
296
+ assert_operators(@canvas.contents, operators)
246
297
  end
247
298
  end
248
299
  end
@@ -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
@@ -530,7 +580,10 @@ describe HexaPDF::Layout::Style::LinkLayer do
530
580
  it "fails if more than one possible target is chosen" do
531
581
  assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(dest: true, uri: true) }
532
582
  assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(dest: true, file: true) }
583
+ assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(dest: true, action: true) }
533
584
  assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(uri: true, file: true) }
585
+ assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(uri: true, action: true) }
586
+ assert_raises(ArgumentError) { HexaPDF::Layout::Style::LinkLayer.new(file: true, action: true) }
534
587
  end
535
588
 
536
589
  it "fails if an invalid border is provided" do
@@ -606,6 +659,12 @@ describe HexaPDF::Layout::Style::LinkLayer do
606
659
  assert_nil(annot[:Dest])
607
660
  end
608
661
 
662
+ it "works for actions" do
663
+ annot = call_link(action: {Type: :Action, S: :SetOCGState})
664
+ assert_equal({Type: :Action, S: :SetOCGState}, annot[:A].value)
665
+ assert_nil(annot[:Dest])
666
+ end
667
+
609
668
  it "works for destinations set via the 'link' custom box property" do
610
669
  @box.properties['link'] = [@canvas.context, :FitH]
611
670
  annot = call_link({})
@@ -723,6 +782,7 @@ describe HexaPDF::Layout::Style do
723
782
  refute(@style.subscript)
724
783
  refute(@style.superscript)
725
784
  refute(@style.last_line_gap)
785
+ refute(@style.fill_horizontal)
726
786
  assert_kind_of(HexaPDF::Layout::Style::Layers, @style.underlays)
727
787
  assert_kind_of(HexaPDF::Layout::Style::Layers, @style.overlays)
728
788
  end