hexapdf 0.34.1 → 0.35.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -0
  3. data/examples/009-text_layouter_alignment.rb +7 -7
  4. data/examples/010-text_layouter_inline_boxes.rb +1 -1
  5. data/examples/011-text_layouter_line_wrapping.rb +2 -4
  6. data/examples/013-text_layouter_shapes.rb +9 -11
  7. data/examples/014-text_in_polygon.rb +2 -2
  8. data/examples/016-frame_automatic_box_placement.rb +6 -7
  9. data/examples/017-frame_text_flow.rb +2 -2
  10. data/examples/018-composer.rb +5 -6
  11. data/examples/020-column_box.rb +2 -2
  12. data/examples/021-list_box.rb +1 -1
  13. data/examples/027-composer_optional_content.rb +5 -5
  14. data/examples/028-frame_mask_mode.rb +23 -0
  15. data/examples/029-composer_fallback_fonts.rb +22 -0
  16. data/lib/hexapdf/cli/info.rb +1 -0
  17. data/lib/hexapdf/cli/inspect.rb +55 -2
  18. data/lib/hexapdf/composer.rb +4 -3
  19. data/lib/hexapdf/configuration.rb +61 -1
  20. data/lib/hexapdf/content/canvas.rb +63 -0
  21. data/lib/hexapdf/content/canvas_composer.rb +142 -0
  22. data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +2 -8
  23. data/lib/hexapdf/content.rb +1 -0
  24. data/lib/hexapdf/dictionary.rb +14 -3
  25. data/lib/hexapdf/document/layout.rb +35 -13
  26. data/lib/hexapdf/document.rb +1 -0
  27. data/lib/hexapdf/encryption/standard_security_handler.rb +15 -0
  28. data/lib/hexapdf/error.rb +2 -1
  29. data/lib/hexapdf/font/invalid_glyph.rb +22 -6
  30. data/lib/hexapdf/font/true_type_wrapper.rb +48 -20
  31. data/lib/hexapdf/font/type1_wrapper.rb +48 -24
  32. data/lib/hexapdf/layout/box.rb +14 -10
  33. data/lib/hexapdf/layout/column_box.rb +5 -3
  34. data/lib/hexapdf/layout/frame.rb +78 -40
  35. data/lib/hexapdf/layout/image_box.rb +3 -3
  36. data/lib/hexapdf/layout/list_box.rb +20 -19
  37. data/lib/hexapdf/layout/style.rb +173 -68
  38. data/lib/hexapdf/layout/table_box.rb +3 -3
  39. data/lib/hexapdf/layout/text_box.rb +5 -5
  40. data/lib/hexapdf/layout/text_fragment.rb +50 -0
  41. data/lib/hexapdf/layout/text_layouter.rb +7 -6
  42. data/lib/hexapdf/layout/width_from_polygon.rb +1 -1
  43. data/lib/hexapdf/object.rb +5 -2
  44. data/lib/hexapdf/pdf_array.rb +5 -0
  45. data/lib/hexapdf/type/acro_form/appearance_generator.rb +16 -11
  46. data/lib/hexapdf/type/icon_fit.rb +2 -2
  47. data/lib/hexapdf/type/page.rb +35 -35
  48. data/lib/hexapdf/utils/sorted_tree_node.rb +0 -10
  49. data/lib/hexapdf/utils.rb +66 -0
  50. data/lib/hexapdf/version.rb +1 -1
  51. data/test/hexapdf/content/test_canvas.rb +37 -0
  52. data/test/hexapdf/content/test_canvas_composer.rb +112 -0
  53. data/test/hexapdf/document/test_layout.rb +40 -12
  54. data/test/hexapdf/document/test_pages.rb +5 -5
  55. data/test/hexapdf/encryption/test_standard_security_handler.rb +43 -0
  56. data/test/hexapdf/font/test_invalid_glyph.rb +13 -1
  57. data/test/hexapdf/font/test_true_type_wrapper.rb +15 -2
  58. data/test/hexapdf/font/test_type1_wrapper.rb +21 -2
  59. data/test/hexapdf/layout/test_box.rb +7 -0
  60. data/test/hexapdf/layout/test_column_box.rb +18 -4
  61. data/test/hexapdf/layout/test_frame.rb +181 -95
  62. data/test/hexapdf/layout/test_list_box.rb +7 -7
  63. data/test/hexapdf/layout/test_page_style.rb +5 -5
  64. data/test/hexapdf/layout/test_style.rb +14 -10
  65. data/test/hexapdf/layout/test_table_box.rb +3 -3
  66. data/test/hexapdf/layout/test_text_box.rb +2 -2
  67. data/test/hexapdf/layout/test_text_fragment.rb +37 -0
  68. data/test/hexapdf/layout/test_text_layouter.rb +10 -10
  69. data/test/hexapdf/test_composer.rb +13 -13
  70. data/test/hexapdf/test_configuration.rb +49 -0
  71. data/test/hexapdf/test_dictionary.rb +1 -1
  72. data/test/hexapdf/test_object.rb +13 -12
  73. data/test/hexapdf/test_pdf_array.rb +9 -0
  74. data/test/hexapdf/test_utils.rb +20 -0
  75. data/test/hexapdf/test_writer.rb +3 -3
  76. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +41 -13
  77. data/test/hexapdf/type/test_page.rb +3 -3
  78. data/test/hexapdf/type/test_page_tree_node.rb +1 -1
  79. data/test/hexapdf/utils/test_sorted_tree_node.rb +1 -1
  80. metadata +9 -3
@@ -69,12 +69,26 @@ describe HexaPDF::Layout::ColumnBox do
69
69
  it "respects the set initial width, position #{position}" do
70
70
  box = create_box(children: @text_boxes[0..1], width: 50, style: {position: position})
71
71
  check_box(box, 50, 80)
72
+
73
+ box = create_box(columns: 1, children: @fixed_size_boxes[0..0], width: 50,
74
+ style: {position: position})
75
+ check_box(box, 50, 10)
76
+
77
+ box = create_box(children: @fixed_size_boxes[0..0], width: 110)
78
+ refute(box.fit(@frame.available_width, @frame.available_height, @frame))
72
79
  end
73
80
 
74
81
  it "respects the set initial height, position #{position}" do
75
82
  box = create_box(children: @text_boxes[0..1], height: 50, equal_height: false,
76
83
  style: {position: position})
77
84
  check_box(box, 100, 50)
85
+
86
+ box = create_box(children: @text_boxes[0..1], height: 50, equal_height: true,
87
+ style: {position: position})
88
+ check_box(box, 100, 50)
89
+
90
+ box = create_box(children: @fixed_size_boxes[0..0], height: 110)
91
+ refute(box.fit(@frame.available_width, @frame.available_height, @frame))
78
92
  end
79
93
 
80
94
  it "respects the border and padding around all columns, position #{position}" do
@@ -178,19 +192,19 @@ describe HexaPDF::Layout::ColumnBox do
178
192
  end
179
193
 
180
194
  it "takes a different final location into account" do
181
- box = create_box(children: @fixed_size_boxes[0, 2])
195
+ box = create_box(children: @fixed_size_boxes[0, 2], style: {padding: [2, 4, 6, 8]})
182
196
  box.fit(100, 100, @frame)
183
197
  box.draw(@canvas, 20, 10)
184
198
  operators = [
185
199
  [:save_graphics_state],
186
- [:concatenate_matrix, [1, 0, 0, 1, 20, -80]],
200
+ [:concatenate_matrix, [1, 0, 0, 1, 20, -72]],
187
201
  [:save_graphics_state],
188
- [:concatenate_matrix, [1, 0, 0, 1, 0, 90]],
202
+ [:concatenate_matrix, [1, 0, 0, 1, 8, 88]],
189
203
  [:move_to, [0, 0]],
190
204
  [:end_path],
191
205
  [:restore_graphics_state],
192
206
  [:save_graphics_state],
193
- [:concatenate_matrix, [1, 0, 0, 1, 55, 90]],
207
+ [:concatenate_matrix, [1, 0, 0, 1, 57, 88]],
194
208
  [:move_to, [0, 0]],
195
209
  [:end_path],
196
210
  [:restore_graphics_state],
@@ -114,15 +114,22 @@ describe HexaPDF::Layout::Frame do
114
114
  when :left then Geom2D::Rectangle(10, 10, 10, 100)
115
115
  when :right then Geom2D::Rectangle(100, 10, 10, 100)
116
116
  when :top then Geom2D::Rectangle(10, 100, 100, 10)
117
+ when :bottom then Geom2D::Rectangle(10, 10, 100, 10)
117
118
  end
118
119
  )
119
120
  end
120
121
  end
121
122
 
123
+ it "fails if an unkown position value is provided" do
124
+ box = HexaPDF::Layout::Box.create(position: :unknown)
125
+ exception = assert_raises(HexaPDF::Error) { @frame.fit(box) }
126
+ assert_match(/Invalid value 'unknown'/, exception.message)
127
+ end
128
+
122
129
  describe "absolute position" do
123
130
  it "draws the box at the given absolute position" do
124
131
  check_box(
125
- {width: 50, height: 50, position: :absolute, position_hint: [10, 10]},
132
+ {width: 50, height: 50, position: [10, 10]},
126
133
  [20, 20],
127
134
  [20, 20, 70, 70],
128
135
  [[[10, 10], [110, 10], [110, 110], [10, 110]],
@@ -132,22 +139,12 @@ describe HexaPDF::Layout::Frame do
132
139
 
133
140
  it "determines the available space for #fit by using the space to the right and above" do
134
141
  check_box(
135
- {position: :absolute, position_hint: [10, 10]},
142
+ {position: [10, 10]},
136
143
  [20, 20],
137
144
  [20, 20, 110, 110],
138
145
  [[[10, 10], [110, 10], [110, 20], [20, 20], [20, 110], [10, 110]]]
139
146
  )
140
147
  end
141
-
142
- it "always removes the whole margin box from the frame" do
143
- check_box(
144
- {width: 50, height: 50, position: :absolute, position_hint: [10, 10],
145
- margin: [10, 20, 30, 40]},
146
- [20, 20],
147
- [-20, -10, 90, 80],
148
- [[[10, 80], [90, 80], [90, 10], [110, 10], [110, 110], [10, 110]]]
149
- )
150
- end
151
148
  end
152
149
 
153
150
  describe "default position" do
@@ -159,40 +156,52 @@ describe HexaPDF::Layout::Frame do
159
156
  end
160
157
 
161
158
  it "draws the box on the right side" do
162
- check_box({width: 50, height: 50, position_hint: :right},
159
+ check_box({width: 50, height: 50, align: :right},
163
160
  [60, 60],
164
161
  [10, 60, 110, 110],
165
162
  [[[10, 10], [110, 10], [110, 60], [10, 60]]])
166
163
  end
167
164
 
168
165
  it "draws the box in the center" do
169
- check_box({width: 50, height: 50, position_hint: :center},
166
+ check_box({width: 50, height: 50, align: :center},
170
167
  [35, 60],
171
168
  [10, 60, 110, 110],
172
169
  [[[10, 10], [110, 10], [110, 60], [10, 60]]])
173
170
  end
174
171
 
172
+ it "draws the box vertically in the center" do
173
+ check_box({width: 50, height: 50, valign: :center},
174
+ [10, 35],
175
+ [10, 35, 110, 110],
176
+ [[[10, 10], [110, 10], [110, 35], [10, 35]]])
177
+ end
178
+
179
+ it "draws the box vertically at the bottom" do
180
+ check_box({width: 50, height: 50, valign: :bottom},
181
+ [10, 10], [10, 10, 110, 110], [])
182
+ end
183
+
175
184
  describe "with margin" do
176
185
  [:left, :center, :right].each do |hint|
177
- it "ignores all margins if the box fills the whole frame, with position hint #{hint}" do
178
- check_box({margin: 10, position_hint: hint},
186
+ it "ignores all margins if the box fills the whole frame, with alignment #{hint}" do
187
+ check_box({margin: 10, align: hint},
179
188
  [10, 10], [10, 10, 110, 110], [])
180
189
  assert_equal(100, @box.width)
181
190
  assert_equal(100, @box.height)
182
191
  end
183
192
 
184
193
  it "ignores the left/top/right margin if the available bounds coincide with the " \
185
- "frame's, with position hint #{hint}" do
186
- check_box({height: 50, margin: 10, position_hint: hint},
194
+ "frame's, with alignment #{hint}" do
195
+ check_box({height: 50, margin: 10, align: hint},
187
196
  [10, 60],
188
197
  [10, 50, 110, 110],
189
198
  [[[10, 10], [110, 10], [110, 50], [10, 50]]])
190
199
  end
191
200
 
192
201
  it "doesn't ignore top margin if the available bounds' top doesn't coincide with the " \
193
- "frame's top, with position hint #{hint}" do
202
+ "frame's top, with alignment #{hint}" do
194
203
  remove_area(:top)
195
- check_box({height: 50, margin: 10, position_hint: hint},
204
+ check_box({height: 50, margin: 10, align: hint},
196
205
  [10, 40],
197
206
  [10, 30, 110, 100],
198
207
  [[[10, 10], [110, 10], [110, 30], [10, 30]]])
@@ -200,9 +209,9 @@ describe HexaPDF::Layout::Frame do
200
209
  end
201
210
 
202
211
  it "doesn't ignore left margin if the available bounds' left doesn't coincide with the " \
203
- "frame's left, with position hint #{hint}" do
212
+ "frame's left, with alignment #{hint}" do
204
213
  remove_area(:left)
205
- check_box({height: 50, margin: 10, position_hint: hint},
214
+ check_box({height: 50, margin: 10, align: hint},
206
215
  [30, 60],
207
216
  [10, 50, 110, 110],
208
217
  [[[20, 10], [110, 10], [110, 50], [20, 50]]])
@@ -210,9 +219,9 @@ describe HexaPDF::Layout::Frame do
210
219
  end
211
220
 
212
221
  it "doesn't ignore right margin if the available bounds' right doesn't coincide with " \
213
- "the frame's right, with position hint #{hint}" do
222
+ "the frame's right, with alignment #{hint}" do
214
223
  remove_area(:right)
215
- check_box({height: 50, margin: 10, position_hint: hint},
224
+ check_box({height: 50, margin: 10, align: hint},
216
225
  [10, 60],
217
226
  [10, 50, 110, 110],
218
227
  [[[10, 10], [100, 10], [100, 50], [10, 50]]])
@@ -220,117 +229,194 @@ describe HexaPDF::Layout::Frame do
220
229
  end
221
230
  end
222
231
 
223
- it "perfectly centers a box if possible, margins ignored" do
224
- check_box({width: 50, height: 10, margin: [10, 10, 10, 20], position_hint: :center},
232
+ [:top, :center, :bottom].each do |hint|
233
+ it "ignores all margins if the box fills the whole frame, with vertical alignment #{hint}" do
234
+ check_box({margin: 10, valign: hint},
235
+ [10, 10], [10, 10, 110, 110], [])
236
+ assert_equal(100, @box.width)
237
+ assert_equal(100, @box.height)
238
+ end
239
+
240
+ it "ignores the left/top/bottom margin if the available bounds coincide with the " \
241
+ "frame's, with vertical alignment #{hint}" do
242
+ check_box({width: 50, margin: 10, valign: hint},
243
+ [10, 10], [10, 10, 110, 110], [])
244
+ assert_equal(100, @box.height)
245
+ end
246
+
247
+ it "doesn't ignore top margin if the available bounds' top doesn't coincide with the " \
248
+ "frame's top, with vertical alignment #{hint}" do
249
+ remove_area(:top)
250
+ check_box({width: 50, margin: 10, valign: hint},
251
+ [10, 10], [10, 10, 110, 100], [])
252
+ assert_equal(80, @box.height)
253
+ end
254
+
255
+ it "doesn't ignore left margin if the available bounds' left doesn't coincide with the " \
256
+ "frame's left, with vertical alignment #{hint}" do
257
+ remove_area(:left)
258
+ check_box({width: 50, margin: 10, valign: hint},
259
+ [30, 10], [10, 10, 110, 110], [])
260
+ assert_equal(100, @box.height)
261
+ end
262
+
263
+ it "doesn't ignore bottom margin if the available bounds' bottom doesn't coincide with " \
264
+ "the frame's bottom, with vertical alignment #{hint}" do
265
+ remove_area(:bottom)
266
+ check_box({width: 50, margin: 10, valign: hint},
267
+ [10, 30], [10, 20, 110, 110], [])
268
+ assert_equal(80, @box.height)
269
+ end
270
+ end
271
+
272
+ it "perfectly centers a box horizontally if possible, margins ignored" do
273
+ check_box({width: 50, height: 10, margin: [10, 10, 10, 20], align: :center},
225
274
  [35, 100],
226
275
  [10, 90, 110, 110],
227
276
  [[[10, 10], [110, 10], [110, 90], [10, 90]]])
228
277
  end
229
278
 
230
- it "perfectly centers a box if possible, margins not ignored" do
279
+ it "perfectly centers a box horizontally if possible, margins not ignored" do
231
280
  remove_area(:left, :right)
232
- check_box({width: 40, height: 10, margin: [10, 10, 10, 20], position_hint: :center},
281
+ check_box({width: 40, height: 10, margin: [10, 10, 10, 20], align: :center},
233
282
  [40, 100],
234
283
  [10, 90, 110, 110],
235
284
  [[[20, 10], [100, 10], [100, 90], [20, 90]]])
236
285
  end
237
286
 
238
- it "centers a box as good as possible when margins aren't equal" do
287
+ it "horizontally centers a box as good as possible when margins aren't equal" do
239
288
  remove_area(:left, :right)
240
- check_box({width: 20, height: 10, margin: [10, 10, 10, 40], position_hint: :center},
289
+ check_box({width: 20, height: 10, margin: [10, 10, 10, 40], align: :center},
241
290
  [65, 100],
242
291
  [10, 90, 110, 110],
243
292
  [[[20, 10], [100, 10], [100, 90], [20, 90]]])
244
293
  end
294
+
295
+ it "perfectly centers a box vertically if possible, margins ignored" do
296
+ check_box({width: 10, height: 50, margin: [10, 10, 20, 10], valign: :center},
297
+ [10, 35],
298
+ [10, 15, 110, 110],
299
+ [[[10, 10], [110, 10], [110, 15], [10, 15]]])
300
+ end
301
+
302
+ it "perfectly centers a box vertically if possible, margins not ignored" do
303
+ remove_area(:top, :bottom)
304
+ check_box({width: 10, height: 40, margin: [10, 10, 20, 10], valign: :center},
305
+ [10, 40], [10, 20, 110, 100], [])
306
+ end
307
+
308
+ it "vertically centers a box as good as possible when margins aren't equal" do
309
+ remove_area(:top, :bottom)
310
+ check_box({width: 10, height: 20, margin: [10, 10, 40, 10], valign: :center},
311
+ [10, 65],
312
+ [10, 25, 110, 100],
313
+ [[[10, 20], [110, 20], [110, 25], [10, 25]]])
314
+ end
245
315
  end
246
316
  end
247
317
 
248
- describe "floating boxes" do
249
- it "draws the box on the left side" do
250
- check_box({width: 50, height: 50, position: :float},
251
- [10, 60],
252
- [10, 60, 60, 110],
253
- [[[10, 10], [110, 10], [110, 110], [60, 110], [60, 60], [10, 60]]])
318
+ describe "flowing boxes" do
319
+ it "flows inside the frame's outline" do
320
+ check_box({width: 10, height: 20, margin: 10, position: :flow},
321
+ [0, 90],
322
+ [10, 80, 110, 110],
323
+ [[[10, 10], [110, 10], [110, 80], [10, 80]]])
254
324
  end
255
325
 
256
- it "draws the box on the right side" do
257
- check_box({width: 50, height: 50, position: :float, position_hint: :right},
258
- [60, 60],
259
- [60, 60, 110, 110],
260
- [[[10, 10], [110, 10], [110, 60], [60, 60], [60, 110], [10, 110]]])
326
+ it "uses position=default if the box indicates it doesn't support flowing contents" do
327
+ check_box({width: 10, height: 20, margin: 10, position: :flow, doesnt_support_position_flow: true},
328
+ [10, 90],
329
+ [10, 80, 110, 110],
330
+ [[[10, 10], [110, 10], [110, 80], [10, 80]]])
261
331
  end
332
+ end
262
333
 
263
- it "draws the box in the center" do
264
- check_box({width: 50, height: 50, position: :float, position_hint: :center},
265
- [35, 60],
266
- [35, 60, 85, 110],
267
- [[[10, 10], [110, 10], [110, 110], [85, 110], [85, 60], [35, 60],
268
- [35, 110], [10, 110]]])
334
+ describe "mask mode" do
335
+ describe "none" do
336
+ it "doesn't remove any area" do
337
+ check_box({width: 50, height: 50, mask_mode: :none},
338
+ [10, 60],
339
+ [10, 60, 10, 60],
340
+ [[[10, 10], [110, 10], [110, 110], [10, 110]]]
341
+ )
342
+ end
269
343
  end
270
344
 
271
- describe "with margin" do
272
- [:left, :center, :right].each do |hint|
273
- it "ignores all margins if the box fills the whole frame, with position hint #{hint}" do
274
- check_box({margin: 10, position: :float, position_hint: hint},
275
- [10, 10], [10, 10, 110, 110], [])
276
- assert_equal(100, @box.width)
277
- assert_equal(100, @box.height)
278
- end
345
+ describe "box" do
346
+ it "removes the box area" do
347
+ check_box({width: 50, height: 50, mask_mode: :box},
348
+ [10, 60],
349
+ [10, 60, 60, 110],
350
+ [[[10, 10], [110, 10], [110, 110], [60, 110], [60, 60], [10, 60]]])
279
351
  end
280
352
 
281
- it "ignores the left, but not the right margin if aligned left to the frame border" do
282
- check_box({width: 50, height: 50, margin: 10, position: :float, position_hint: :left},
283
- [10, 60],
284
- [10, 50, 70, 110],
285
- [[[10, 10], [110, 10], [110, 110], [70, 110], [70, 50], [10, 50]]])
353
+ it "ignores the margin if sides are on the frame border" do
354
+ check_box({margin: 10, mask_mode: :box},
355
+ [10, 10], [10, 10, 110, 110], [])
286
356
  end
287
357
 
288
- it "uses the left and the right margin if aligned left and not to the frame border" do
289
- remove_area(:left)
290
- check_box({width: 50, height: 50, margin: 10, position: :float, position_hint: :left},
291
- [30, 60],
292
- [20, 50, 90, 110],
293
- [[[20, 10], [110, 10], [110, 110], [90, 110], [90, 50], [20, 50]]])
358
+ it "uses the margin if sides are not on the frame border" do
359
+ remove_area(:left, :right, :top, :bottom)
360
+ check_box({margin: 10, mask_mode: :box},
361
+ [30, 30], [20, 20, 100, 100], [])
294
362
  end
363
+ end
295
364
 
296
- it "uses the left and the right margin if aligned center" do
297
- check_box({width: 50, height: 50, margin: 10, position: :float, position_hint: :center},
298
- [35, 60],
299
- [25, 50, 95, 110],
300
- [[[10, 10], [110, 10], [110, 110], [95, 110], [95, 50], [25, 50],
301
- [25, 110], [10, 110]]])
365
+ describe "fill_horizontal" do
366
+ it "removes the horizontal part to the bottom of the box in the current region" do
367
+ remove_area(:left, :right)
368
+ check_box({width: 50, height: 50, mask_mode: :fill_horizontal},
369
+ [20, 60],
370
+ [20, 60, 100, 110],
371
+ [[[20, 10], [100, 10], [100, 60], [20, 60]]])
302
372
  end
303
373
 
304
- it "ignores the right, but not the left margin if aligned right to the frame border" do
305
- check_box({width: 50, height: 50, margin: 10, position: :float, position_hint: :right},
306
- [60, 60],
307
- [50, 50, 110, 110],
308
- [[[10, 10], [110, 10], [110, 50], [50, 50], [50, 110], [10, 110]]])
374
+ it "respects the top and bottom margins for the mask" do
375
+ remove_area(:top, :bottom)
376
+ check_box({width: 50, margin: 10, mask_mode: :fill_horizontal},
377
+ [10, 30], [10, 20, 110, 100], [])
378
+ end
379
+ end
380
+
381
+ describe "fill_frame_horizontal" do
382
+ it "removes the horizontal part to the bottom of the box in the frame" do
383
+ remove_area(:left, :right)
384
+ check_box({width: 50, height: 50, mask_mode: :fill_frame_horizontal},
385
+ [20, 60],
386
+ [10, 60, 110, 110],
387
+ [[[20, 10], [100, 10], [100, 60], [20, 60]]])
309
388
  end
310
389
 
311
- it "uses the left and the right margin if aligned right and not to the frame border" do
312
- remove_area(:right)
313
- check_box({width: 50, height: 50, margin: 10, position: :float, position_hint: :right},
314
- [40, 60],
315
- [30, 50, 100, 110],
316
- [[[10, 10], [100, 10], [100, 50], [30, 50], [30, 110], [10, 110]]])
390
+ it "respects the bottom margin for the mask" do
391
+ remove_area(:left, :right, :top, :bottom)
392
+ check_box({width: 50, margin: 10, mask_mode: :fill_frame_horizontal},
393
+ [30, 30], [10, 20, 110, 100], [])
317
394
  end
318
395
  end
319
- end
320
396
 
321
- describe "flowing boxes" do
322
- it "flows inside the frame's outline" do
323
- check_box({width: 10, height: 20, margin: 10, position: :flow},
324
- [0, 90],
325
- [10, 80, 110, 110],
326
- [[[10, 10], [110, 10], [110, 80], [10, 80]]])
397
+ describe "fill_vertical" do
398
+ it "removes the vertical part covering the box in the current region" do
399
+ check_box({width: 50, height: 50, mask_mode: :fill_vertical, align: :center},
400
+ [35, 60],
401
+ [35, 10, 85, 110],
402
+ [[[10, 10], [35, 10], [35, 110], [10, 110]],
403
+ [[85, 10], [110, 10], [110, 110], [85, 110]]])
404
+ end
405
+
406
+ it "respects the left and right margins for the mask" do
407
+ check_box({width: 50, height: 50, margin: 10, mask_mode: :fill_vertical, align: :center},
408
+ [35, 60],
409
+ [25, 10, 95, 110],
410
+ [[[10, 10], [25, 10], [25, 110], [10, 110]],
411
+ [[95, 10], [110, 10], [110, 110], [95, 110]]])
412
+ end
327
413
  end
328
414
 
329
- it "uses position=default if the box indicates it doesn't support flowing contents" do
330
- check_box({width: 10, height: 20, margin: 10, position: :flow, doesnt_support_position_flow: true},
331
- [10, 90],
332
- [10, 80, 110, 110],
333
- [[[10, 10], [110, 10], [110, 80], [10, 80]]])
415
+ describe "fill" do
416
+ it "removes the current region completely" do
417
+ check_box({width: 50, height: 50, mask_mode: :fill},
418
+ [10, 60], [10, 10, 110, 110], [])
419
+ end
334
420
  end
335
421
  end
336
422
 
@@ -38,10 +38,10 @@ describe HexaPDF::Layout::ListBox do
38
38
 
39
39
  describe "initialize" do
40
40
  it "creates a new instance with the given arguments" do
41
- box = create_box(children: [:a], item_type: :circle, content_indentation: 15,
41
+ box = create_box(children: [:a], marker_type: :circle, content_indentation: 15,
42
42
  start_number: 4, item_spacing: 20)
43
43
  assert_equal([:a], box.children)
44
- assert_equal(:circle, box.item_type)
44
+ assert_equal(:circle, box.marker_type)
45
45
  assert_equal(15, box.content_indentation)
46
46
  assert_equal(4, box.start_number)
47
47
  assert_equal(20, box.item_spacing)
@@ -109,7 +109,7 @@ describe HexaPDF::Layout::ListBox do
109
109
  end
110
110
 
111
111
  it "fails for unknown item types" do
112
- box = create_box(children: @text_boxes[0, 1], item_type: :unknown)
112
+ box = create_box(children: @text_boxes[0, 1], marker_type: :unknown)
113
113
  assert_raises(HexaPDF::Error) { box.fit(100, 100, @frame) }
114
114
  end
115
115
  end
@@ -179,7 +179,7 @@ describe HexaPDF::Layout::ListBox do
179
179
  end
180
180
 
181
181
  it "draws a circle as marker" do
182
- box = create_box(children: @fixed_size_boxes[0, 1], item_type: :circle,
182
+ box = create_box(children: @fixed_size_boxes[0, 1], marker_type: :circle,
183
183
  style: {font_size: 11, fill_color: 0.5})
184
184
  box.fit(100, 100, @frame)
185
185
  box.draw(@canvas, 0, 100 - box.height)
@@ -201,7 +201,7 @@ describe HexaPDF::Layout::ListBox do
201
201
  end
202
202
 
203
203
  it "draws a square as marker" do
204
- box = create_box(children: @fixed_size_boxes[0, 1], item_type: :square,
204
+ box = create_box(children: @fixed_size_boxes[0, 1], marker_type: :square,
205
205
  style: {font_size: 11, fill_color: 0.5})
206
206
  box.fit(100, 100, @frame)
207
207
  box.draw(@canvas, 0, 100 - box.height)
@@ -223,7 +223,7 @@ describe HexaPDF::Layout::ListBox do
223
223
  end
224
224
 
225
225
  it "draws decimal numbers as marker" do
226
- box = create_box(children: @fixed_size_boxes[0, 2], item_type: :decimal,
226
+ box = create_box(children: @fixed_size_boxes[0, 2], marker_type: :decimal,
227
227
  style: {font_size: 11, fill_color: 0.5},
228
228
  content_indentation: 20)
229
229
  box.fit(100, 100, @frame)
@@ -260,7 +260,7 @@ describe HexaPDF::Layout::ListBox do
260
260
  marker = lambda do |_doc, _list_box, _index|
261
261
  HexaPDF::Layout::Box.create(width: 10, height: 10) {}
262
262
  end
263
- box = create_box(children: @fixed_size_boxes[0, 1], item_type: marker)
263
+ box = create_box(children: @fixed_size_boxes[0, 1], marker_type: marker)
264
264
  box.fit(100, 100, @frame)
265
265
  box.draw(@canvas, 0, 100 - box.height)
266
266
  operators = [
@@ -35,7 +35,7 @@ describe HexaPDF::Layout::PageStyle do
35
35
  istyle.next_style = :other
36
36
  end
37
37
  page = style.create_page(@doc)
38
- assert_equal([0, 0, 595, 842], page.box(:media))
38
+ assert_equal([0, 0, 595.275591, 841.889764], page.box(:media))
39
39
  assert_equal("0 0 10 10 re\nS\n", page.contents)
40
40
  assert_equal(:frame, style.frame)
41
41
  assert_equal(:other, style.next_style)
@@ -54,8 +54,8 @@ describe HexaPDF::Layout::PageStyle do
54
54
  assert_kind_of(HexaPDF::Layout::Frame, style.frame)
55
55
  assert_equal(36, style.frame.left)
56
56
  assert_equal(36, style.frame.bottom)
57
- assert_equal(523, style.frame.width)
58
- assert_equal(770, style.frame.height)
57
+ assert_equal(523.275591, style.frame.width)
58
+ assert_equal(769.889764, style.frame.height)
59
59
  end
60
60
  end
61
61
 
@@ -65,7 +65,7 @@ describe HexaPDF::Layout::PageStyle do
65
65
  frame = style.create_frame(style.create_page(doc), [15, 10])
66
66
  assert_equal(10, frame.left)
67
67
  assert_equal(15, frame.bottom)
68
- assert_equal(575, frame.width)
69
- assert_equal(812, frame.height)
68
+ assert_equal(575.275591, frame.width)
69
+ assert_equal(811.889764, frame.height)
70
70
  end
71
71
  end
@@ -767,8 +767,8 @@ describe HexaPDF::Layout::Style do
767
767
  assert_equal(HexaPDF::Content::LineCapStyle::BUTT_CAP, @style.stroke_cap_style)
768
768
  assert_equal(HexaPDF::Content::LineJoinStyle::MITER_JOIN, @style.stroke_join_style)
769
769
  assert_equal(10.0, @style.stroke_miter_limit)
770
- assert_equal(:left, @style.align)
771
- assert_equal(:top, @style.valign)
770
+ assert_equal(:left, @style.text_align)
771
+ assert_equal(:top, @style.text_valign)
772
772
  assert_equal(0, @style.text_indent)
773
773
  assert_nil(@style.background_color)
774
774
  assert_equal(1, @style.background_alpha)
@@ -785,6 +785,10 @@ describe HexaPDF::Layout::Style do
785
785
  refute(@style.fill_horizontal)
786
786
  assert_kind_of(HexaPDF::Layout::Style::Layers, @style.underlays)
787
787
  assert_kind_of(HexaPDF::Layout::Style::Layers, @style.overlays)
788
+ assert_equal(:default, @style.position)
789
+ assert_equal(:left, @style.align)
790
+ assert_equal(:top, @style.valign)
791
+ assert_equal(:default, @style.mask_mode)
788
792
  end
789
793
 
790
794
  it "allows using a non-standard setter for generated properties" do
@@ -800,18 +804,18 @@ describe HexaPDF::Layout::Style do
800
804
  end
801
805
 
802
806
  it "allows checking for valid values" do
803
- error = assert_raises(ArgumentError) { @style.align = :none }
804
- assert_match(/not a valid align value \(:left, :center, :right, :justify\)/, error.message)
807
+ error = assert_raises(ArgumentError) { @style.text_align = :none }
808
+ assert_match(/not a valid text_align value \(:left, :center, :right, :justify\)/, error.message)
805
809
  end
806
810
 
807
811
  it "allows checking whether a property has been set or accessed" do
808
- refute(@style.align?)
809
- assert_equal(:left, @style.align)
810
- assert(@style.align?)
812
+ refute(@style.text_align?)
813
+ assert_equal(:left, @style.text_align)
814
+ assert(@style.text_align?)
811
815
 
812
- refute(@style.valign?)
813
- @style.valign = :bottom
814
- assert(@style.valign?)
816
+ refute(@style.text_valign?)
817
+ @style.text_valign = :bottom
818
+ assert(@style.text_valign?)
815
819
  end
816
820
 
817
821
  it "has several dynamically generated properties with default values that take blocks" do
@@ -83,7 +83,7 @@ describe HexaPDF::Layout::TableBox::Cell do
83
83
  end
84
84
 
85
85
  it "fits a single box with horizontal aligning not being :left" do
86
- cell = create_cell(children: HexaPDF::Layout::Box.create(width: 20, height: 10, position_hint: :center))
86
+ cell = create_cell(children: HexaPDF::Layout::Box.create(width: 20, height: 10, align: :center))
87
87
  cell.fit(100, 100, @frame)
88
88
  assert_equal(66, cell.preferred_width)
89
89
  end
@@ -100,7 +100,7 @@ describe HexaPDF::Layout::TableBox::Cell do
100
100
  end
101
101
 
102
102
  it "fits multiple boxes with horizontal aligning not being :left" do
103
- box1 = HexaPDF::Layout::Box.create(width: 20, height: 10, position_hint: :center)
103
+ box1 = HexaPDF::Layout::Box.create(width: 20, height: 10, align: :center)
104
104
  box2 = HexaPDF::Layout::Box.create(width: 50, height: 15)
105
105
  cell = create_cell(children: [box1, box2])
106
106
  cell.fit(100, 100, @frame)
@@ -130,7 +130,7 @@ describe HexaPDF::Layout::TableBox::Cell do
130
130
 
131
131
  it "draws the boxes at the correct location" do
132
132
  draw_block = lambda {|canvas, _| canvas.move_to(0, 0).end_path }
133
- box1 = HexaPDF::Layout::Box.create(width: 20, height: 10, position_hint: :center, &draw_block)
133
+ box1 = HexaPDF::Layout::Box.create(width: 20, height: 10, align: :center, &draw_block)
134
134
  box2 = HexaPDF::Layout::Box.create(width: 50, height: 15, &draw_block)
135
135
  box = create_cell(children: [box1, box2])
136
136
  box.fit(100, 100, @frame)
@@ -66,7 +66,7 @@ describe HexaPDF::Layout::TextBox do
66
66
 
67
67
  it "uses the whole available width when aligning to the center or right" do
68
68
  [:center, :right].each do |align|
69
- box = create_box([@inline_box], style: {align: align})
69
+ box = create_box([@inline_box], style: {text_align: align})
70
70
  assert(box.fit(100, 100, @frame))
71
71
  assert_equal(100, box.width)
72
72
  end
@@ -74,7 +74,7 @@ describe HexaPDF::Layout::TextBox do
74
74
 
75
75
  it "uses the whole available height when vertically aligning to the center or bottom" do
76
76
  [:center, :bottom].each do |valign|
77
- box = create_box([@inline_box], style: {valign: valign})
77
+ box = create_box([@inline_box], style: {text_valign: valign})
78
78
  assert(box.fit(100, 100, @frame))
79
79
  assert_equal(100, box.height)
80
80
  end