hexapdf 0.38.0 → 0.39.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6df8bc8bdf189f60287c3dc0a0eccb1e1bca2a8b4310c1d5c2bb5d6661bae11
4
- data.tar.gz: a28fc9d3319f596774bda74476fbc77fe40ba8e29a2dcd1e588c18f0928e8538
3
+ metadata.gz: d0a43d232528df9bfc4a2c9baddd9cd1ddbd33fe7cce9d146b4e25760f25429b
4
+ data.tar.gz: 37cb10752d22bbc89fd18a779152ef7b5e02e6237318006a4b0e0a420d2890e2
5
5
  SHA512:
6
- metadata.gz: 11a382eceaa702705fe15484314e8d8b21c26ce2bf50d082be5e4ae27749251562474bfe1f4d410e53008120b37b6f43b42b1f9ecaca0ce123a672a6868a0515
7
- data.tar.gz: ef98043f0d6460bbfd4819ba34fd2fab4d9e7426b04d0005f1f65ae88d813ff92db6f9cb89cb3e88997c8b68dea7e7631ceb873f5091a6c1b8bd6aa72075ab32
6
+ metadata.gz: 79a27b101c502261e1bca7a25fa26fa434d38cec09a2ccb28a698a4364d8ed337ee63d82ce8cd4dd3097334ed54f0877565c25e20c2494c0ae7029156dc188ef
7
+ data.tar.gz: 69befc3a7066eb90a58ad4a65243939930f26ecc461e0f6f7c9bf0894ddfa58bf1a02567563caa453b0c6e745421de75e7dd433926d2a56b96aa4d71557059f5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 0.39.0 - 2024-03-18
2
+
3
+ ### Added
4
+
5
+ * Hierarchical box information to the document layout engine
6
+ * Style property 'text_overflow' for controlling how overflowing text should be
7
+ handled
8
+
9
+ ### Changed
10
+
11
+ * [HexaPDF::Layout::Frame::FitResult#draw] to provide better optional content
12
+ group names
13
+
14
+ ### Fixed
15
+
16
+ * [HexaPDF::Layout::TextBox] to correctly respect a set height
17
+
18
+
1
19
  ## 0.38.0 - 2024-03-10
2
20
 
3
21
  ### Added
data/examples/030-pdfa.rb CHANGED
@@ -1,4 +1,4 @@
1
- # # PDF/A Compliance
1
+ # # PDF/A Conformance
2
2
  #
3
3
  # This example shows how to create a PDF file that is PDF/A compliant.
4
4
  #
@@ -179,8 +179,8 @@ module HexaPDF
179
179
  [column_left, column_bottom + height])
180
180
  shape = Geom2D::Algorithms::PolygonOperation.run(frame.shape, rect, :intersection)
181
181
  end
182
- column_frame = Frame.new(column_left, column_bottom, column_width, height,
183
- shape: shape, context: frame.context)
182
+ column_frame = frame.child_frame(column_left, column_bottom, column_width, height,
183
+ shape: shape, box: self)
184
184
  @box_fitter << column_frame
185
185
  end
186
186
 
@@ -131,8 +131,9 @@ module HexaPDF
131
131
 
132
132
  # Fits the children into the container.
133
133
  def fit_content(_available_width, _available_height, frame)
134
- my_frame = Frame.new(frame.x + reserved_width_left, frame.y - @height + reserved_height_bottom,
135
- content_width, content_height, context: frame.context)
134
+ my_frame = frame.child_frame(frame.x + reserved_width_left,
135
+ frame.y - @height + reserved_height_bottom,
136
+ content_width, content_height, box: self)
136
137
  @box_fitter = BoxFitter.new([my_frame])
137
138
  children.each {|box| @box_fitter.fit(box) }
138
139
 
@@ -91,6 +91,9 @@ module HexaPDF
91
91
  # Stores the result of fitting a box in a Frame.
92
92
  class FitResult
93
93
 
94
+ # The frame into which the box was fitted.
95
+ attr_accessor :frame
96
+
94
97
  # The box that was fitted into the frame.
95
98
  attr_accessor :box
96
99
 
@@ -110,8 +113,9 @@ module HexaPDF
110
113
  # drawing the box.
111
114
  attr_accessor :mask
112
115
 
113
- # Initialize the result object for the given box.
114
- def initialize(box)
116
+ # Initialize the result object for the given frame and box.
117
+ def initialize(frame, box)
118
+ @frame = frame
115
119
  @box = box
116
120
  @available_width = 0
117
121
  @available_height = 0
@@ -138,7 +142,10 @@ module HexaPDF
138
142
  def draw(canvas, dx: 0, dy: 0)
139
143
  doc = canvas.context.document
140
144
  if doc.config['debug']
141
- name = "#{box.class} (#{x.to_i},#{y.to_i}-#{box.width.to_i}x#{box.height.to_i})"
145
+ name = (frame.parent_boxes + [box]).map do |box|
146
+ box.class.to_s.sub(/.*::/, '')
147
+ end.join('-') << "##{box.object_id}"
148
+ name = "#{name} (#{(x + dx).to_i},#{(y + dy).to_i}-#{mask.width.to_i}x#{mask.height.to_i})"
142
149
  ocg = doc.optional_content.ocg(name)
143
150
  canvas.optional_content(ocg) do
144
151
  canvas.translate(dx, dy) do
@@ -147,7 +154,8 @@ module HexaPDF
147
154
  draw(:geom2d, object: mask, path_only: true).fill_stroke
148
155
  end
149
156
  end
150
- doc.optional_content.default_configuration.add_ocg_to_ui(ocg, path: 'Debug')
157
+ page = "Page #{canvas.context.index + 1}" rescue "XObject"
158
+ doc.optional_content.default_configuration.add_ocg_to_ui(ocg, path: ['Debug', page])
151
159
  end
152
160
  box.draw(canvas, x + dx, y + dy)
153
161
  end
@@ -195,14 +203,21 @@ module HexaPDF
195
203
  # should be used.
196
204
  attr_reader :context
197
205
 
206
+ # An array of box objects representing the parent boxes.
207
+ #
208
+ # The immediate parent is the last array entry, the top most parent the first one. All boxes
209
+ # that are fitted into this frame have to be child boxes of the immediate parent box.
210
+ attr_reader :parent_boxes
211
+
198
212
  # Creates a new Frame object for the given rectangular area.
199
- def initialize(left, bottom, width, height, shape: nil, context: nil)
213
+ def initialize(left, bottom, width, height, shape: nil, context: nil, parent_boxes: [])
200
214
  @left = left
201
215
  @bottom = bottom
202
216
  @width = width
203
217
  @height = height
204
218
  @shape = shape || create_rectangle(left, bottom, left + width, bottom + height)
205
219
  @context = context
220
+ @parent_boxes = parent_boxes.freeze
206
221
 
207
222
  @x = left
208
223
  @y = bottom + height
@@ -213,6 +228,25 @@ module HexaPDF
213
228
  @region_selection = :max_height
214
229
  end
215
230
 
231
+ # Creates a new Frame object based on this one.
232
+ #
233
+ # If the +init_args+ arguments are provided, a new Frame is created using the constructor. The
234
+ # optional +shape+ argument is then also passed to the constructor.
235
+ #
236
+ # Otherwise, this frame is duplicated. This kind of invocation is only useful if the +box+
237
+ # argument is provided (because otherwise there would be no difference to this frame).
238
+ #
239
+ # The +box+ argument can be used to add the appropriate parent box to the list of
240
+ # #parent_boxes for the newly created frame.
241
+ def child_frame(*init_args, shape: nil, box: nil)
242
+ parent_boxes = (box ? @parent_boxes.dup << box : @parent_boxes)
243
+ if init_args.empty?
244
+ dup.tap {|result| result.instance_variable_set(:@parent_boxes, parent_boxes) }
245
+ else
246
+ self.class.new(*init_args, shape: shape, context: @context, parent_boxes: parent_boxes)
247
+ end
248
+ end
249
+
216
250
  # Returns the HexaPDF::Document instance (through #context) that is associated with this Frame
217
251
  # object or +nil+ if no context object has been set.
218
252
  def document
@@ -227,7 +261,7 @@ module HexaPDF
227
261
  #
228
262
  # Use the FitResult#success? method to determine whether fitting was successful.
229
263
  def fit(box)
230
- fit_result = FitResult.new(box)
264
+ fit_result = FitResult.new(self, box)
231
265
  return fit_result if full?
232
266
 
233
267
  margin = box.style.margin if box.style.margin?
@@ -126,10 +126,17 @@ module HexaPDF
126
126
  height
127
127
  end
128
128
 
129
- # Fits the wrapped box, using the given context (see Frame#context).
130
- def fit_wrapped_box(context)
131
- @fit_result = Frame.new(0, 0, box.width, box.height == 0 ? 100_000 : box.height,
132
- context: context).fit(box)
129
+ # Fits the wrapped box.
130
+ #
131
+ # If the +frame+ argument is +nil+, a custom frame is created. Otherwise the given +frame+ is
132
+ # used for the fitting operation.
133
+ def fit_wrapped_box(frame)
134
+ frame = if frame
135
+ frame.child_frame(0, 0, box.width, box.height == 0 ? 100_000 : box.height)
136
+ else
137
+ Frame.new(0, 0, box.width, box.height == 0 ? 100_000 : box.height)
138
+ end
139
+ @fit_result = frame.fit(box)
133
140
  if !@fit_result.success?
134
141
  raise HexaPDF::Error, "Box for inline use could not be fit"
135
142
  elsif box.height > 99_000
@@ -227,12 +227,12 @@ module HexaPDF
227
227
  remove_indent_from_frame_shape(shape) unless shape.polygons.empty?
228
228
  end
229
229
 
230
- item_frame = Frame.new(item_frame_left, top - height, item_frame_width, height,
231
- shape: shape, context: frame.context)
230
+ item_frame = frame.child_frame(item_frame_left, top - height, item_frame_width, height,
231
+ shape: shape, box: self)
232
232
 
233
233
  if index != 0 || !split_box? || @split_box == :show_first_marker
234
234
  box = item_marker_box(frame.document, index)
235
- marker_frame = Frame.new(0, 0, content_indentation, height, context: frame.context)
235
+ marker_frame = frame.child_frame(0, 0, content_indentation, height, box: self)
236
236
  break unless box.fit(content_indentation, height, marker_frame)
237
237
  item_result.marker = box
238
238
  item_result.marker_pos_x = item_frame.x - content_indentation
@@ -1084,6 +1084,25 @@ module HexaPDF
1084
1084
  # 'Centered',
1085
1085
  # {text: "\u{00a0}", fill_horizontal: 1, overlays: overlays}])
1086
1086
 
1087
+ ##
1088
+ # :method: text_overflow
1089
+ # :call-seq:
1090
+ # text_overflow(mode = nil)
1091
+ #
1092
+ # Specifies how text overflowing a box with a given initial height should be handled:
1093
+ #
1094
+ # Possible values:
1095
+ #
1096
+ # :error:: An error is raised (default).
1097
+ # :truncate:: Truncates the overflowing text.
1098
+ #
1099
+ # Examples:
1100
+ #
1101
+ # #>pdf-composer100
1102
+ # composer.text("This is some longer text that does appear in two lines.")
1103
+ # composer.text("This is some longer text that does not appear in two lines.",
1104
+ # height: 15, text_overflow: :truncate)
1105
+
1087
1106
  ##
1088
1107
  # :method: background_color
1089
1108
  # :call-seq:
@@ -1435,6 +1454,7 @@ module HexaPDF
1435
1454
  extra_args: ", extra_arg = nil"}],
1436
1455
  [:last_line_gap, false, {valid_values: [true, false]}],
1437
1456
  [:fill_horizontal, nil],
1457
+ [:text_overflow, :error],
1438
1458
  [:background_color, nil],
1439
1459
  [:background_alpha, 1],
1440
1460
  [:padding, "Quad.new(0)", {setter: "Quad.new(value)"}],
@@ -218,7 +218,7 @@ module HexaPDF
218
218
  height = available_height - reserved_height
219
219
  return false if width <= 0 || height <= 0
220
220
 
221
- frame = Frame.new(0, 0, width, height, context: frame.context)
221
+ frame = frame.child_frame(0, 0, width, height, box: self)
222
222
  case children
223
223
  when Box
224
224
  fit_result = frame.fit(children)
@@ -607,6 +607,7 @@ module HexaPDF
607
607
  columns = calculate_column_widths(width)
608
608
  return false if columns.empty?
609
609
 
610
+ frame = frame.child_frame(box: self)
610
611
  @special_cells_fit_not_successful = false
611
612
  [@header_cells, @footer_cells].each do |special_cells|
612
613
  next unless special_cells
@@ -79,6 +79,7 @@ module HexaPDF
79
79
  return false if (@initial_width > 0 && @initial_width > available_width) ||
80
80
  (@initial_height > 0 && @initial_height > available_height)
81
81
 
82
+ frame = frame.child_frame(box: self)
82
83
  @width = @height = 0
83
84
  @result = if style.position == :flow
84
85
  @tl.fit(@items, frame.width_specification, frame.shape.bbox.height,
@@ -104,7 +105,8 @@ module HexaPDF
104
105
  @height += style.line_spacing.gap(@result.lines.last, @result.lines.last)
105
106
  end
106
107
 
107
- @result.status == :success
108
+ @result.status == :success ||
109
+ (@result.status == :height && @initial_height > 0 && style.text_overflow == :truncate)
108
110
  end
109
111
 
110
112
  # Splits the text box into two boxes if necessary and possible.
@@ -132,7 +134,14 @@ module HexaPDF
132
134
 
133
135
  # Draws the text into the box.
134
136
  def draw_content(canvas, x, y)
135
- return unless @result && !@result.lines.empty?
137
+ return unless @result
138
+
139
+ if @result.status == :height && @initial_height > 0 && style.text_overflow == :error
140
+ raise HexaPDF::Error, "Text doesn't fit into box with limited height and " \
141
+ "style property text_overflow is set to :error"
142
+ end
143
+
144
+ return if @result.lines.empty?
136
145
  @result.draw(canvas, x, y + content_height)
137
146
  end
138
147
 
@@ -307,10 +307,15 @@ module HexaPDF
307
307
  class SimpleLineWrapping
308
308
 
309
309
  # :call-seq:
310
- # SimpleLineWrapping.call(items, width_block) {|line, item| block } -> rest
310
+ # SimpleLineWrapping.call(items, width_block, frame = nil) {|line, item| block } -> rest
311
311
  #
312
312
  # Arranges the items into lines.
313
313
  #
314
+ # The optional +frame+ argument needs to be a Frame object that is used when fitting inline
315
+ # boxes. If not provided, a custom Frame object is used. However, if the items contain
316
+ # inline boxes that need to access a frame's context object, it is mandatory to provide an
317
+ # appropriate Frame object.
318
+ #
314
319
  # The +width_block+ argument has to be a callable object that returns the width of the line:
315
320
  #
316
321
  # * If the line width doesn't depend on the height or the vertical position of the line
@@ -340,7 +345,7 @@ module HexaPDF
340
345
  # current start of the line index should be stored for later use.
341
346
  #
342
347
  # After the algorithm is finished, it returns the unused items.
343
- def self.call(items, width_block, frame, &block)
348
+ def self.call(items, width_block, frame = nil, &block)
344
349
  obj = new(items, width_block, frame)
345
350
  if width_block.arity == 1
346
351
  obj.variable_width_wrapping(&block)
@@ -507,7 +512,7 @@ module HexaPDF
507
512
  #
508
513
  # Returns +true+ if the item could be added and +false+ otherwise.
509
514
  def add_box_item(item)
510
- item.fit_wrapped_box(@frame&.context) if item.kind_of?(InlineBox)
515
+ item.fit_wrapped_box(@frame) if item.kind_of?(InlineBox)
511
516
  return false unless @width + item.width <= @available_width
512
517
  @line_items.concat(@glue_items).push(item)
513
518
  @width += item.width
@@ -718,6 +723,10 @@ module HexaPDF
718
723
  # Specifies whether style.text_indent should be applied to the first line. This should be
719
724
  # set to +false+ if the items start with a continuation of a paragraph instead of starting
720
725
  # a new paragraph (e.g. after a page break).
726
+ #
727
+ # +frame+::
728
+ # If used with the document layout functionality, this should be the frame into which the
729
+ # text is laid out.
721
730
  def fit(items, width, height, apply_first_text_indent: true, frame: nil)
722
731
  unless items.empty? || items[0].respond_to?(:type)
723
732
  items = style.text_segmentation_algorithm.call(items)
@@ -37,6 +37,6 @@
37
37
  module HexaPDF
38
38
 
39
39
  # The version of HexaPDF.
40
- VERSION = '0.38.0'
40
+ VERSION = '0.39.0'
41
41
 
42
42
  end
@@ -10,7 +10,8 @@ describe HexaPDF::Layout::Frame::FitResult do
10
10
  doc = HexaPDF::Document.new(config: {'debug' => true})
11
11
  canvas = doc.pages.add.canvas
12
12
  box = HexaPDF::Layout::Box.create(width: 20, height: 20) {}
13
- result = HexaPDF::Layout::Frame::FitResult.new(box)
13
+ frame = HexaPDF::Layout::Frame.new(5, 10, 100, 150)
14
+ result = HexaPDF::Layout::Frame::FitResult.new(frame, box)
14
15
  result.mask = Geom2D::Rectangle(0, 0, 20, 20)
15
16
  result.x = result.y = 0
16
17
  result.draw(canvas, dx: 10, dy: 15)
@@ -30,7 +31,8 @@ describe HexaPDF::Layout::Frame::FitResult do
30
31
  Q
31
32
  CONTENTS
32
33
  ocg = doc.optional_content.ocgs.first
33
- assert_equal([['Debug', ocg]], doc.optional_content.default_configuration[:Order])
34
+ assert_equal([['Debug', ['Page 1', ocg]]], doc.optional_content.default_configuration[:Order])
35
+ assert_match(/10,15-20x20/, ocg.name)
34
36
  end
35
37
  end
36
38
 
@@ -61,6 +63,11 @@ describe HexaPDF::Layout::Frame do
61
63
  assert_equal(150, @frame.available_height)
62
64
  end
63
65
 
66
+ it "allows access to the frame's parent boxes" do
67
+ frame = HexaPDF::Layout::Frame.new(5, 10, 100, 150, parent_boxes: [:a])
68
+ assert_equal([:a], frame.parent_boxes)
69
+ end
70
+
64
71
  it "allows setting the shape of the frame on initialization" do
65
72
  shape = Geom2D::Polygon([50, 10], [55, 100], [105, 100], [105, 10])
66
73
  frame = HexaPDF::Layout::Frame.new(5, 10, 100, 150, shape: shape)
@@ -71,6 +78,27 @@ describe HexaPDF::Layout::Frame do
71
78
  assert_equal(90, frame.available_height)
72
79
  end
73
80
 
81
+ describe "child_frame" do
82
+ before do
83
+ @frame = HexaPDF::Layout::Frame.new(10, 10, 100, 100, parent_boxes: [:a])
84
+ end
85
+
86
+ it "duplicates the frame setting the parent boxes appropriately" do
87
+ assert_same(@frame.parent_boxes, @frame.child_frame.parent_boxes)
88
+ frame = @frame.child_frame(box: :b)
89
+ assert_equal([:a, :b], frame.parent_boxes)
90
+ end
91
+
92
+ it "creates a new frame, optionally adding a parent box" do
93
+ shape = Geom2D::Rectangle(0, 0, 20, 20)
94
+ frame = @frame.child_frame(0, 0, 20, 20, shape: shape)
95
+ assert_same(@frame.parent_boxes, frame.parent_boxes)
96
+ assert_equal(shape, frame.shape)
97
+ frame = @frame.child_frame(0, 0, 20, 20, box: :b)
98
+ assert_equal([:a, :b], frame.parent_boxes)
99
+ end
100
+ end
101
+
74
102
  it "returns an appropriate width specification object" do
75
103
  ws = @frame.width_specification(10)
76
104
  assert_kind_of(HexaPDF::Layout::WidthFromPolygon, ws)
@@ -97,6 +125,7 @@ describe HexaPDF::Layout::Frame do
97
125
  @canvas.expect(:translate, nil, pos)
98
126
  fit_result = @frame.fit(@box)
99
127
  refute_nil(fit_result)
128
+ assert_same(@frame, fit_result.frame)
100
129
  @frame.draw(@canvas, fit_result)
101
130
  assert_equal(mask, fit_result.mask.bbox.to_a)
102
131
  if @frame.shape.respond_to?(:polygons)
@@ -31,7 +31,14 @@ describe HexaPDF::Layout::InlineBox do
31
31
  end
32
32
 
33
33
  describe "fit_wrapped_box" do
34
- it "automatically fits the provided box into a frame" do
34
+ it "automatically fits the provided box into the given frame" do
35
+ ibox = inline_box(HexaPDF::Document.new.layout.text("test is going good", width: 20))
36
+ ibox.fit_wrapped_box(HexaPDF::Layout::Frame.new(0, 0, 50, 50))
37
+ assert_equal(20, ibox.width)
38
+ assert_equal(45, ibox.height)
39
+ end
40
+
41
+ it "automatically fits the provided box into a custom frame" do
35
42
  ibox = inline_box(HexaPDF::Document.new.layout.text("test is going good", width: 20))
36
43
  ibox.fit_wrapped_box(nil)
37
44
  assert_equal(20, ibox.width)
@@ -783,6 +783,7 @@ describe HexaPDF::Layout::Style do
783
783
  refute(@style.superscript)
784
784
  refute(@style.last_line_gap)
785
785
  refute(@style.fill_horizontal)
786
+ assert_equal(:error, @style.text_overflow)
786
787
  assert_kind_of(HexaPDF::Layout::Style::Layers, @style.underlays)
787
788
  assert_kind_of(HexaPDF::Layout::Style::Layers, @style.overlays)
788
789
  assert_equal(:default, @style.position)
@@ -50,8 +50,7 @@ describe HexaPDF::Layout::TextBox do
50
50
  end
51
51
 
52
52
  it "fits into the frame's outline" do
53
- inline_box = HexaPDF::Layout::InlineBox.create(width: 10, height: 10) {}
54
- box = create_box([inline_box] * 20, style: {position: :flow})
53
+ box = create_box([@inline_box] * 20, style: {position: :flow})
55
54
  assert(box.fit(100, 100, @frame))
56
55
  assert_equal(100, box.width)
57
56
  assert_equal(20, box.height)
@@ -80,6 +79,16 @@ describe HexaPDF::Layout::TextBox do
80
79
  end
81
80
  end
82
81
 
82
+ it "respects the style property text_overflow when fitting too much text" do
83
+ box = create_box([@inline_box] * 20, height: 15)
84
+ refute(box.fit(100, 100, @frame))
85
+ box.style.text_overflow = :truncate
86
+ assert(box.fit(100, 100, @frame))
87
+
88
+ box = create_box([@inline_box] * 20, style: {text_overflow: :truncate})
89
+ refute(box.fit(100, 15, @frame))
90
+ end
91
+
83
92
  it "can't fit the text box if the set width is bigger than the available width" do
84
93
  box = create_box([@inline_box], width: 101)
85
94
  refute(box.fit(100, 100, @frame))
@@ -154,13 +163,16 @@ describe HexaPDF::Layout::TextBox do
154
163
  end
155
164
 
156
165
  describe "draw" do
166
+ before do
167
+ @canvas = HexaPDF::Document.new.pages.add.canvas
168
+ end
169
+
157
170
  it "draws the layed out inline items onto the canvas" do
158
171
  inline_box = HexaPDF::Layout::InlineBox.create(width: 10, height: 10,
159
172
  border: {width: 1})
160
173
  box = create_box([inline_box], width: 100, height: 30, style: {padding: [10, 5]})
161
- box.fit(100, 100, nil)
174
+ box.fit(100, 100, @frame)
162
175
 
163
- @canvas = HexaPDF::Document.new.pages.add.canvas
164
176
  box.draw(@canvas, 0, 0)
165
177
  assert_operators(@canvas.contents, [[:save_graphics_state],
166
178
  [:restore_graphics_state],
@@ -179,11 +191,16 @@ describe HexaPDF::Layout::TextBox do
179
191
  end
180
192
 
181
193
  it "draws nothing onto the canvas if the box is empty" do
182
- @canvas = HexaPDF::Document.new.pages.add.canvas
183
194
  box = create_box([])
184
195
  box.draw(@canvas, 5, 5)
185
196
  assert_operators(@canvas.contents, [])
186
197
  end
198
+
199
+ it "raises an error if there is too much content for a set height with text_overlow=:error" do
200
+ box = create_box([@inline_box] * 20, height: 15)
201
+ box.fit(100, 100, @frame)
202
+ assert_raises(HexaPDF::Error) { box.draw(@canvas, 0, 0) }
203
+ end
187
204
  end
188
205
 
189
206
  it "is empty if there is a result without any text lines" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hexapdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.38.0
4
+ version: 0.39.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Leitner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-10 00:00:00.000000000 Z
11
+ date: 2024-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse