hexapdf 0.32.2 → 0.34.0

Sign up to get free protection for your applications and to get access to all the features.
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