hexapdf 0.34.1 → 0.35.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +59 -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 +2 -2
  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.rb +1 -0
  23. data/lib/hexapdf/dictionary.rb +14 -3
  24. data/lib/hexapdf/document/layout.rb +35 -13
  25. data/lib/hexapdf/encryption/standard_security_handler.rb +15 -0
  26. data/lib/hexapdf/error.rb +2 -1
  27. data/lib/hexapdf/font/invalid_glyph.rb +22 -6
  28. data/lib/hexapdf/font/true_type_wrapper.rb +48 -20
  29. data/lib/hexapdf/font/type1_wrapper.rb +48 -24
  30. data/lib/hexapdf/layout/box.rb +11 -8
  31. data/lib/hexapdf/layout/column_box.rb +5 -3
  32. data/lib/hexapdf/layout/frame.rb +77 -39
  33. data/lib/hexapdf/layout/image_box.rb +3 -3
  34. data/lib/hexapdf/layout/list_box.rb +20 -19
  35. data/lib/hexapdf/layout/style.rb +173 -68
  36. data/lib/hexapdf/layout/table_box.rb +3 -3
  37. data/lib/hexapdf/layout/text_box.rb +5 -5
  38. data/lib/hexapdf/layout/text_fragment.rb +50 -0
  39. data/lib/hexapdf/layout/text_layouter.rb +7 -6
  40. data/lib/hexapdf/object.rb +5 -2
  41. data/lib/hexapdf/pdf_array.rb +5 -0
  42. data/lib/hexapdf/type/acro_form/appearance_generator.rb +16 -11
  43. data/lib/hexapdf/utils/sorted_tree_node.rb +0 -10
  44. data/lib/hexapdf/version.rb +1 -1
  45. data/test/hexapdf/content/test_canvas.rb +37 -0
  46. data/test/hexapdf/content/test_canvas_composer.rb +112 -0
  47. data/test/hexapdf/document/test_layout.rb +40 -12
  48. data/test/hexapdf/encryption/test_standard_security_handler.rb +43 -0
  49. data/test/hexapdf/font/test_invalid_glyph.rb +13 -1
  50. data/test/hexapdf/font/test_true_type_wrapper.rb +15 -2
  51. data/test/hexapdf/font/test_type1_wrapper.rb +21 -2
  52. data/test/hexapdf/layout/test_column_box.rb +14 -0
  53. data/test/hexapdf/layout/test_frame.rb +181 -95
  54. data/test/hexapdf/layout/test_list_box.rb +7 -7
  55. data/test/hexapdf/layout/test_style.rb +14 -10
  56. data/test/hexapdf/layout/test_table_box.rb +3 -3
  57. data/test/hexapdf/layout/test_text_box.rb +2 -2
  58. data/test/hexapdf/layout/test_text_fragment.rb +37 -0
  59. data/test/hexapdf/layout/test_text_layouter.rb +10 -10
  60. data/test/hexapdf/test_configuration.rb +49 -0
  61. data/test/hexapdf/test_dictionary.rb +1 -1
  62. data/test/hexapdf/test_object.rb +13 -12
  63. data/test/hexapdf/test_pdf_array.rb +9 -0
  64. data/test/hexapdf/test_writer.rb +3 -3
  65. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +41 -13
  66. data/test/hexapdf/utils/test_sorted_tree_node.rb +1 -1
  67. metadata +7 -3
@@ -48,8 +48,8 @@ module HexaPDF
48
48
  # Represents a single glyph of the wrapped font.
49
49
  class Glyph
50
50
 
51
- # The associated font object.
52
- attr_reader :font
51
+ # The associated Type1Wrapper object.
52
+ attr_reader :font_wrapper
53
53
 
54
54
  # The name of the glyph.
55
55
  attr_reader :name
@@ -59,35 +59,35 @@ module HexaPDF
59
59
  attr_reader :str
60
60
 
61
61
  # Creates a new Glyph object.
62
- def initialize(font, name, str)
63
- @font = font
62
+ def initialize(font_wrapper, name, str)
63
+ @font_wrapper = font_wrapper
64
64
  @name = name
65
65
  @str = str
66
66
  end
67
67
 
68
68
  # Returns the glyph's minimum x coordinate.
69
69
  def x_min
70
- @font.metrics.character_metrics[name].bbox[0]
70
+ @font_wrapper.wrapped_font.metrics.character_metrics[name].bbox[0]
71
71
  end
72
72
 
73
73
  # Returns the glyph's maximum x coordinate.
74
74
  def x_max
75
- @font.metrics.character_metrics[name].bbox[2]
75
+ @font_wrapper.wrapped_font.metrics.character_metrics[name].bbox[2]
76
76
  end
77
77
 
78
78
  # Returns the glyph's minimum y coordinate.
79
79
  def y_min
80
- @font.metrics.character_metrics[name].bbox[1]
80
+ @font_wrapper.wrapped_font.metrics.character_metrics[name].bbox[1]
81
81
  end
82
82
 
83
83
  # Returns the glyph's maximum y coordinate.
84
84
  def y_max
85
- @font.metrics.character_metrics[name].bbox[3]
85
+ @font_wrapper.wrapped_font.metrics.character_metrics[name].bbox[3]
86
86
  end
87
87
 
88
88
  # Returns the width of the glyph.
89
89
  def width
90
- @width ||= @font.width(name)
90
+ @width ||= @font_wrapper.wrapped_font.width(name)
91
91
  end
92
92
 
93
93
  # Returns +true+ if the word spacing parameter needs to be applied for the glyph.
@@ -95,9 +95,15 @@ module HexaPDF
95
95
  @name == :space
96
96
  end
97
97
 
98
+ # Returns +true+ since this is a valid glyph.
99
+ def valid?
100
+ true
101
+ end
102
+
98
103
  #:nodoc:
99
104
  def inspect
100
- "#<#{self.class.name} font=#{@font.full_name.inspect} id=#{name.inspect} #{str.inspect}>"
105
+ "#<#{self.class.name} font=#{@font_wrapper.wrapped_font.full_name.inspect} " \
106
+ "id=#{name.inspect} #{str.inspect}>"
101
107
  end
102
108
 
103
109
  end
@@ -154,13 +160,23 @@ module HexaPDF
154
160
  1
155
161
  end
156
162
 
163
+ # Returns +true+ if the font contains bold glyphs.
164
+ def bold?
165
+ @wrapped_font.weight_class > 500
166
+ end
167
+
168
+ # Returns +true+ if the font contains glyphs with an incline (italic or slant).
169
+ def italic?
170
+ @wrapped_font.italic_angle.to_i != 0
171
+ end
172
+
157
173
  # Returns a Glyph object for the given glyph name.
158
174
  def glyph(name)
159
175
  @name_to_glyph[name] ||=
160
176
  begin
161
177
  str = Encoding::GlyphList.name_to_unicode(name, **@zapf_dingbats_opt)
162
178
  if @wrapped_font.metrics.character_metrics.key?(name)
163
- Glyph.new(@wrapped_font, name, str)
179
+ Glyph.new(self, name, str)
164
180
  else
165
181
  @pdf_object.document.config['font.on_missing_glyph'].call(str, self)
166
182
  end
@@ -178,27 +194,35 @@ module HexaPDF
178
194
  raise HexaPDF::Error, "Glyph named #{name.inspect} not found in " \
179
195
  "font '#{@wrapped_font.full_name}'"
180
196
  end
181
- Glyph.new(@wrapped_font, name, string)
197
+ Glyph.new(self, name, string)
182
198
  end
183
199
 
184
200
  # Returns an array of glyph objects representing the characters in the UTF-8 encoded string.
185
201
  #
202
+ # See #decode_codepoint for details.
203
+ def decode_utf8(str)
204
+ str.codepoints.map! {|c| @codepoint_to_glyph[c] || decode_codepoint(c) }
205
+ end
206
+
207
+ # Returns a glyph object for the given Unicode codepoint.
208
+ #
186
209
  # If a Unicode codepoint is not available as glyph object, it is tried to map the codepoint
187
210
  # using the font's internal encoding. This is useful, for example, for the ZapfDingbats font
188
211
  # to use ASCII characters for accessing the glyphs.
189
- def decode_utf8(str)
190
- str.codepoints.map! do |c|
191
- @codepoint_to_glyph[c] ||=
192
- begin
193
- name = Encoding::GlyphList.unicode_to_name(+'' << c, **@zapf_dingbats_opt)
194
- if @wrapped_font.metrics.character_set == 'Special' &&
195
- (name == :'.notdef' || !@wrapped_font.metrics.character_metrics.key?(name))
196
- name = @encoding.name(c)
197
- end
198
- name = +"u" << c.to_s(16).rjust(6, '0') if name == :'.notdef'
199
- glyph(name)
212
+ #
213
+ # The configuration option 'font.on_missing_glyph' is invoked if no glyph for a given
214
+ # codepoint is available.
215
+ def decode_codepoint(codepoint)
216
+ @codepoint_to_glyph[codepoint] ||=
217
+ begin
218
+ name = Encoding::GlyphList.unicode_to_name(+'' << codepoint, **@zapf_dingbats_opt)
219
+ if @wrapped_font.metrics.character_set == 'Special' &&
220
+ (name == :'.notdef' || !@wrapped_font.metrics.character_metrics.key?(name))
221
+ name = @encoding.name(codepoint)
200
222
  end
201
- end
223
+ name = +"u" << codepoint.to_s(16).rjust(6, '0') if name == :'.notdef'
224
+ glyph(name)
225
+ end
202
226
  end
203
227
 
204
228
  # Encodes the glyph and returns the code string.
@@ -71,7 +71,7 @@ module HexaPDF
71
71
  # If the subclass supports the value :flow of the 'position' style property, this method
72
72
  # needs to be overridden to return +true+.
73
73
  #
74
- # #split:: This method splits the content so that the available space is used as good as
74
+ # #split:: This method splits the content so that the current region is used as good as
75
75
  # possible. The default implementation should be fine for most use-cases, so only
76
76
  # #split_content needs to be implemented. The method #create_split_box should be used
77
77
  # for getting a basic cloned box.
@@ -186,26 +186,29 @@ module HexaPDF
186
186
 
187
187
  # Fits the box into the Frame and returns +true+ if fitting was successful.
188
188
  #
189
- # The default implementation uses the whole available space for width and height if they were
190
- # initially set to 0. Otherwise the specified dimensions are used.
189
+ # The arguments +available_width+ and +available_height+ are the width and height of the
190
+ # current region of the frame. The frame itself is provided as third argument.
191
+ #
192
+ # The default implementation uses the available width and height for the box width and height
193
+ # if they were initially set to 0. Otherwise the specified dimensions are used.
191
194
  def fit(available_width, available_height, _frame)
192
195
  @width = (@initial_width > 0 ? @initial_width : available_width)
193
196
  @height = (@initial_height > 0 ? @initial_height : available_height)
194
197
  @fit_successful = (@width <= available_width && @height <= available_height)
195
198
  end
196
199
 
197
- # Tries to split the box into two, the first of which needs to fit into the available space,
198
- # and returns the parts as array.
200
+ # Tries to split the box into two, the first of which needs to fit into the current region of
201
+ # the frame, and returns the parts as array.
199
202
  #
200
203
  # If the first item in the result array is not +nil+, it needs to be this box and it means
201
204
  # that even when #fit fails, a part of the box may still fit. Note that #fit should not be
202
205
  # called before #draw on the first box since it is already fitted. If not even a part of this
203
- # box fits into the available space, +nil+ should be returned as the first array element.
206
+ # box fits into the current region, +nil+ should be returned as the first array element.
204
207
  #
205
208
  # Possible return values:
206
209
  #
207
- # [self]:: The box fully fits into the available space.
208
- # [nil, self]:: The box can't be split or no part of the box fits into the available space.
210
+ # [self]:: The box fully fits into the current region.
211
+ # [nil, self]:: The box can't be split or no part of the box fits into the current region.
209
212
  # [self, new_box]:: A part of the box fits and a new box is returned for the rest.
210
213
  #
211
214
  # This default implementation provides the basic functionality based on the #fit result that
@@ -138,12 +138,14 @@ module HexaPDF
138
138
  super && (!@box_fitter || @box_fitter.fit_results.empty?)
139
139
  end
140
140
 
141
- # Fits the column box into the available space.
141
+ # Fits the column box into the current region of the frame.
142
142
  #
143
143
  # If the style property 'position' is set to :flow, the columns might not be rectangles but
144
144
  # arbitrary (sets of) polygons since the +frame+s shape is taken into account.
145
145
  def fit(available_width, available_height, frame)
146
- initial_fit_successful = (@equal_height ? nil : false)
146
+ return false if @initial_height > available_height || @initial_width > available_width
147
+
148
+ initial_fit_successful = (@equal_height && @columns.size > 1 ? nil : false)
147
149
  tries = 0
148
150
  @width = if style.position == :flow
149
151
  (@initial_width > 0 ? @initial_width : frame.width) - reserved_width
@@ -205,7 +207,7 @@ module HexaPDF
205
207
  end
206
208
 
207
209
  @width = columns[-1].sum + reserved_width
208
- @height = @box_fitter.content_heights.max + reserved_height
210
+ @height = (@initial_height > 0 ? @initial_height : @box_fitter.content_heights.max + reserved_height)
209
211
  @draw_pos_x = frame.x + reserved_width_left
210
212
  @draw_pos_y = frame.y - @height + reserved_height_bottom
211
213
 
@@ -53,8 +53,8 @@ module HexaPDF
53
53
  # available space. If fitting is successful, the box can be drawn using #draw.
54
54
  #
55
55
  # The method #fit is also called for absolutely positioned boxes but since these boxes are not
56
- # subject to the normal constraints, the available space used is the width and height inside
57
- # the frame to the right and top of the bottom-left corner of the box.
56
+ # subject to the normal constraints, the provided available width and height are the width and
57
+ # height inside the frame to the right and top of the bottom-left corner of the box.
58
58
  #
59
59
  # * If the box didn't fit, call #find_next_region to determine the next region for placing the
60
60
  # box. If a new region was found, start over with #fit. Otherwise the frame has no more space
@@ -71,9 +71,9 @@ module HexaPDF
71
71
  #
72
72
  # == Used Box Properties
73
73
  #
74
- # The style properties "position", "position_hint" and "margin" are taken into account when
75
- # fitting, splitting or drawing a box. Note that the margin is ignored if a box's side coincides
76
- # with the frame's original boundary.
74
+ # The style properties 'position', 'align', 'valign', 'margin' and 'mask_mode' are taken into
75
+ # account when fitting, splitting or drawing a box. Note that the margin is ignored if a box's
76
+ # side coincides with the frame's original boundary.
77
77
  #
78
78
  # == Frame Shape
79
79
  #
@@ -178,12 +178,12 @@ module HexaPDF
178
178
  # Also see the note in the #x documentation for further information.
179
179
  attr_reader :y
180
180
 
181
- # The available width for placing a box.
181
+ # The available width of the current region for placing a box.
182
182
  #
183
183
  # Also see the note in the #x documentation for further information.
184
184
  attr_reader :available_width
185
185
 
186
- # The available height for placing a box.
186
+ # The available height of the current region for placing a box.
187
187
  #
188
188
  # Also see the note in the #x documentation for further information.
189
189
  attr_reader :available_height
@@ -219,19 +219,24 @@ module HexaPDF
219
219
  # Fits the given box into the current region of available space and returns a FitResult
220
220
  # object.
221
221
  #
222
+ # Fitting a box takes the style properties 'position', 'align', 'valign', 'margin', and
223
+ # 'mask_mode' into account.
224
+ #
222
225
  # Use the FitResult#success? method to determine whether fitting was successful.
223
226
  def fit(box)
224
227
  fit_result = FitResult.new(box)
225
228
  return fit_result if full?
226
229
 
230
+ margin = box.style.margin if box.style.margin?
231
+
227
232
  position = if box.style.position != :flow || box.supports_position_flow?
228
233
  box.style.position
229
234
  else
230
235
  :default
231
236
  end
232
237
 
233
- if position == :absolute
234
- x, y = box.style.position_hint
238
+ if position.kind_of?(Array)
239
+ x, y = box.style.position
235
240
 
236
241
  aw = width - x
237
242
  ah = height - y
@@ -240,23 +245,15 @@ module HexaPDF
240
245
 
241
246
  x += left
242
247
  y += bottom
243
- rectangle = if box.style.margin?
244
- margin = box.style.margin
245
- create_rectangle(x - margin.left, y - margin.bottom,
246
- x + box.width + margin.right, y + box.height + margin.top)
247
- else
248
- create_rectangle(x, y, x + box.width, y + box.height)
249
- end
250
248
  else
251
249
  aw = available_width
252
250
  ah = available_height
253
251
 
254
- margin_top = margin_right = margin_left = 0
255
- if box.style.margin?
256
- margin = box.style.margin
252
+ margin_top = margin_right = margin_left = margin_bottom = 0
253
+ if margin
257
254
  aw -= margin_right = margin.right unless float_equal(@x + aw, @left + @width)
258
255
  aw -= margin_left = margin.left unless float_equal(@x, @left)
259
- ah -= margin.bottom unless float_equal(@y - ah, @bottom)
256
+ ah -= margin_bottom = margin.bottom unless float_equal(@y - ah, @bottom)
260
257
  ah -= margin_top = margin.top unless float_equal(@y, @bottom + @height)
261
258
  end
262
259
 
@@ -266,14 +263,9 @@ module HexaPDF
266
263
  height = box.height
267
264
 
268
265
  case position
269
- when :flow
270
- x = 0
271
- y = @y - height
272
- rectangle = create_rectangle(left, [bottom, y - (margin&.bottom || 0)].max,
273
- left + self.width, @y)
274
- else
275
- x = case box.style.position_hint
276
- when nil, :left
266
+ when :default, :float
267
+ x = case box.style.align
268
+ when :left
277
269
  @x + margin_left
278
270
  when :right
279
271
  @x + margin_left + aw - width
@@ -286,19 +278,63 @@ module HexaPDF
286
278
  @x + margin_left + (aw - width) / 2.0
287
279
  end
288
280
  end
289
- y = @y - height - margin_top
290
- rectangle = if position == :float
291
- create_rectangle([left, x - (margin&.left || 0)].max,
292
- [bottom, y - (margin&.bottom || 0)].max,
293
- [left + self.width, x + width + (margin&.right || 0)].min,
294
- @y)
295
- else
296
- create_rectangle(left, [bottom, y - (margin&.bottom || 0)].max,
297
- left + self.width, @y)
298
- end
281
+ y = case box.style.valign
282
+ when :top
283
+ @y - margin_top - height
284
+ when :bottom
285
+ @y - available_height + margin_bottom
286
+ when :center
287
+ max_margin = [margin_top, margin_bottom].max
288
+ # If we have enough space left for equal margins, we center perfectly
289
+ if available_height - height >= 2 * max_margin
290
+ @y - height - (available_height - height) / 2.0
291
+ else
292
+ @y - margin_top - height - (ah - height) / 2.0
293
+ end
294
+ end
295
+ when :flow
296
+ x = 0
297
+ y = @y - height
298
+ else
299
+ raise HexaPDF::Error, "Invalid value '#{position}' for style property position"
299
300
  end
300
301
  end
301
302
 
303
+ mask_mode = if box.style.mask_mode == :default
304
+ case position
305
+ when :default, :flow then :fill_frame_horizontal
306
+ else :box
307
+ end
308
+ else
309
+ box.style.mask_mode
310
+ end
311
+ rectangle =
312
+ case mask_mode
313
+ when :none
314
+ create_rectangle(x, y, x, y)
315
+ when :box
316
+ if margin
317
+ create_rectangle([left, x - (margin&.left || 0)].max,
318
+ [bottom, y - (margin&.bottom || 0)].max,
319
+ [left + self.width, x + box.width + (margin&.right || 0)].min,
320
+ [bottom + self.height, y + box.height + (margin&.top || 0)].min)
321
+ else
322
+ create_rectangle(x, y, x + box.width, y + box.height)
323
+ end
324
+ when :fill_horizontal
325
+ create_rectangle(@x, [bottom, y - (margin&.bottom || 0)].max,
326
+ @x + available_width,
327
+ [@y, y + box.height + (margin&.top || 0)].min)
328
+ when :fill_frame_horizontal
329
+ create_rectangle(left, [bottom, y - (margin&.bottom || 0)].max,
330
+ left + self.width, @y)
331
+ when :fill_vertical
332
+ create_rectangle([@x, x - (margin&.left || 0)].max, @y - available_height,
333
+ [@x + available_width, x + box.width + (margin&.right || 0)].min, @y)
334
+ when :fill
335
+ create_rectangle(@x, @y - available_height, @x + available_width, @y)
336
+ end
337
+
302
338
  fit_result.available_width = aw
303
339
  fit_result.available_height = ah
304
340
  fit_result.x = x
@@ -326,7 +362,7 @@ module HexaPDF
326
362
 
327
363
  # Finds the next region for placing boxes. Returns +false+ if no useful region was found.
328
364
  #
329
- # This method should be called after drawing a box using #draw was not successful. It finds a
365
+ # This method should be called after fitting or drawing a box was not successful. It finds a
330
366
  # different region on each invocation. So if a box doesn't fit into the first region, this
331
367
  # method should be called again to find another region and to try again.
332
368
  #
@@ -363,6 +399,8 @@ module HexaPDF
363
399
 
364
400
  # Removes the given *rectilinear* polygon from the frame's shape.
365
401
  def remove_area(polygon)
402
+ return if polygon.kind_of?(Geom2D::Rectangle) && (polygon.width == 0 || polygon.height == 0)
403
+
366
404
  @shape = if @shape.kind_of?(Geom2D::Rectangle) && polygon.kind_of?(Geom2D::Rectangle) &&
367
405
  float_equal(@shape.x, polygon.x) && float_equal(@shape.width, polygon.width) &&
368
406
  float_equal(@shape.y + @shape.height, polygon.y + polygon.height)
@@ -56,7 +56,7 @@ module HexaPDF
56
56
  # #>pdf-composer100
57
57
  # composer.image(machu_picchu, width: 100, height: 30)
58
58
  #
59
- # * If neither has been set, the image is scaled to fit the available space.
59
+ # * If neither has been set, the image is scaled to fit the current region.
60
60
  #
61
61
  # #>pdf-composer100
62
62
  # composer.image(machu_picchu)
@@ -79,8 +79,8 @@ module HexaPDF
79
79
  false
80
80
  end
81
81
 
82
- # Fits the image into the available space, taking the initially set width and height into
83
- # account (see the class description for details).
82
+ # Fits the image into the current region of the frame, taking the initially set width and
83
+ # height into account (see the class description for details).
84
84
  def fit(available_width, available_height, _frame)
85
85
  image_width = @image.width.to_f
86
86
  image_height = @image.height.to_f
@@ -44,9 +44,10 @@ module HexaPDF
44
44
 
45
45
  # A ListBox arranges its children as unordered or ordered list items.
46
46
  #
47
- # The indentation of the contents from the left (#content_indentation) as well as the type of
48
- # item (#item_type) can be specified. Additionally, it is possible to define the start number
49
- # for ordered lists (#start_number) and the amount of spacing between items (#item_spacing).
47
+ # The indentation of the contents from the left (#content_indentation) as well as the marker
48
+ # type of the items (#marker_type) can be specified. Additionally, it is possible to define the
49
+ # start number for ordered lists (#start_number) and the amount of spacing between items
50
+ # (#item_spacing).
50
51
  #
51
52
  # If the list box has padding and/or borders specified, they are handled like with any other
52
53
  # box. This means they are around all items and their contents and are not used separately for
@@ -75,7 +76,7 @@ module HexaPDF
75
76
  # Draws a filled disc for the items of the unordered list.
76
77
  #
77
78
  # #>pdf-composer100
78
- # composer.box(:list, item_type: :disc) do |list|
79
+ # composer.box(:list, marker_type: :disc) do |list|
79
80
  # list.lorem_ipsum_box(sentences: 1)
80
81
  # end
81
82
  #
@@ -84,7 +85,7 @@ module HexaPDF
84
85
  # Draws an unfilled circle for the items of the unordered list.
85
86
  #
86
87
  # #>pdf-composer100
87
- # composer.box(:list, item_type: :circle) do |list|
88
+ # composer.box(:list, marker_type: :circle) do |list|
88
89
  # list.lorem_ipsum_box(sentences: 1)
89
90
  # end
90
91
  #
@@ -93,7 +94,7 @@ module HexaPDF
93
94
  # Draws a filled square for the items of the unordered list.
94
95
  #
95
96
  # #>pdf-composer100
96
- # composer.box(:list, item_type: :square) do |list|
97
+ # composer.box(:list, marker_type: :square) do |list|
97
98
  # list.lorem_ipsum_box(sentences: 1)
98
99
  # end
99
100
  #
@@ -103,7 +104,7 @@ module HexaPDF
103
104
  # the ordered list.
104
105
  #
105
106
  # #>pdf-composer100
106
- # composer.box(:list, item_type: :decimal) do |list|
107
+ # composer.box(:list, marker_type: :decimal) do |list|
107
108
  # 5.times { list.lorem_ipsum_box(sentences: 1) }
108
109
  # end
109
110
  #
@@ -118,19 +119,19 @@ module HexaPDF
118
119
  # image = lambda do |document, box, index|
119
120
  # document.layout.image_box(machu_picchu, height: box.style.font_size)
120
121
  # end
121
- # composer.box(:list, item_type: image) do |list|
122
+ # composer.box(:list, marker_type: image) do |list|
122
123
  # 2.times { list.lorem_ipsum_box(sentences: 1) }
123
124
  # end
124
- attr_reader :item_type
125
+ attr_reader :marker_type
125
126
 
126
- # The start number when using an #item_type that represents an ordered list.
127
+ # The start number when using a #marker_type that represents an ordered list.
127
128
  #
128
129
  # The default value for this is 1.
129
130
  #
130
131
  # Example:
131
132
  #
132
133
  # #>pdf-composer100
133
- # composer.box(:list, item_type: :decimal, start_number: 3) do |list|
134
+ # composer.box(:list, marker_type: :decimal, start_number: 3) do |list|
134
135
  # 2.times { list.lorem_ipsum_box(sentences: 1) }
135
136
  # end
136
137
  attr_reader :start_number
@@ -162,11 +163,11 @@ module HexaPDF
162
163
  attr_reader :item_spacing
163
164
 
164
165
  # Creates a new ListBox object for the given child boxes in +children+.
165
- def initialize(children: [], item_type: :disc, content_indentation: nil, start_number: 1,
166
+ def initialize(children: [], marker_type: :disc, content_indentation: nil, start_number: 1,
166
167
  item_spacing: 0, **kwargs)
167
168
  super(**kwargs)
168
169
  @children = children
169
- @item_type = item_type
170
+ @marker_type = marker_type
170
171
  @content_indentation = content_indentation || 2 * style.font_size
171
172
  @start_number = start_number
172
173
  @item_spacing = item_spacing
@@ -185,7 +186,7 @@ module HexaPDF
185
186
  super && (!@results || @results.all? {|result| result.box_fitter.fit_results.empty? })
186
187
  end
187
188
 
188
- # Fits the list box into the available space.
189
+ # Fits the list box into the current region of the frame.
189
190
  def fit(available_width, available_height, frame)
190
191
  @width = if @initial_width > 0
191
192
  @initial_width
@@ -322,10 +323,10 @@ module HexaPDF
322
323
  # Creates a box for the item marker at the given item index, using #item_style to decide on
323
324
  # its contents.
324
325
  def item_marker_box(document, index)
325
- return @item_type.call(document, self, index) if @item_type.kind_of?(Proc)
326
+ return @marker_type.call(document, self, index) if @marker_type.kind_of?(Proc)
326
327
  return @item_marker_box if defined?(@item_marker_box)
327
328
 
328
- fragment = case @item_type
329
+ fragment = case @marker_type
329
330
  when :disc
330
331
  TextFragment.create("•", font: document.fonts.add("Times"),
331
332
  font_size: style.font_size, fill_color: style.fill_color)
@@ -347,10 +348,10 @@ module HexaPDF
347
348
  }
348
349
  TextFragment.create(text, decimal_style)
349
350
  else
350
- raise HexaPDF::Error, "Unknown list item type #{@item_type.inspect}"
351
+ raise HexaPDF::Error, "Unknown list marker type #{@marker_type.inspect}"
351
352
  end
352
- box = TextBox.new(items: [fragment], style: {align: :right, padding: [0, 5, 0, 0]})
353
- @item_marker_box = box unless @item_type == :decimal
353
+ box = TextBox.new(items: [fragment], style: {text_align: :right, padding: [0, 5, 0, 0]})
354
+ @item_marker_box = box unless @marker_type == :decimal
354
355
  box
355
356
  end
356
357