giga-fast-kit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/giga-fast-kit.gemspec +12 -0
  3. data/prawn-2.5.0/COPYING +2 -0
  4. data/prawn-2.5.0/GPLv2 +339 -0
  5. data/prawn-2.5.0/GPLv3 +674 -0
  6. data/prawn-2.5.0/LICENSE +56 -0
  7. data/prawn-2.5.0/data/fonts/Courier-Bold.afm +342 -0
  8. data/prawn-2.5.0/data/fonts/Courier-BoldOblique.afm +342 -0
  9. data/prawn-2.5.0/data/fonts/Courier-Oblique.afm +342 -0
  10. data/prawn-2.5.0/data/fonts/Courier.afm +342 -0
  11. data/prawn-2.5.0/data/fonts/Helvetica-Bold.afm +2827 -0
  12. data/prawn-2.5.0/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  13. data/prawn-2.5.0/data/fonts/Helvetica-Oblique.afm +3051 -0
  14. data/prawn-2.5.0/data/fonts/Helvetica.afm +3051 -0
  15. data/prawn-2.5.0/data/fonts/MustRead.html +19 -0
  16. data/prawn-2.5.0/data/fonts/Symbol.afm +213 -0
  17. data/prawn-2.5.0/data/fonts/Times-Bold.afm +2588 -0
  18. data/prawn-2.5.0/data/fonts/Times-BoldItalic.afm +2384 -0
  19. data/prawn-2.5.0/data/fonts/Times-Italic.afm +2667 -0
  20. data/prawn-2.5.0/data/fonts/Times-Roman.afm +2419 -0
  21. data/prawn-2.5.0/data/fonts/ZapfDingbats.afm +225 -0
  22. data/prawn-2.5.0/lib/prawn/document/bounding_box.rb +625 -0
  23. data/prawn-2.5.0/lib/prawn/document/column_box.rb +177 -0
  24. data/prawn-2.5.0/lib/prawn/document/internals.rb +76 -0
  25. data/prawn-2.5.0/lib/prawn/document/span.rb +65 -0
  26. data/prawn-2.5.0/lib/prawn/document.rb +846 -0
  27. data/prawn-2.5.0/lib/prawn/encoding.rb +85 -0
  28. data/prawn-2.5.0/lib/prawn/errors.rb +73 -0
  29. data/prawn-2.5.0/lib/prawn/font.rb +567 -0
  30. data/prawn-2.5.0/lib/prawn/font_metric_cache.rb +50 -0
  31. data/prawn-2.5.0/lib/prawn/fonts/afm.rb +332 -0
  32. data/prawn-2.5.0/lib/prawn/fonts/dfont.rb +42 -0
  33. data/prawn-2.5.0/lib/prawn/fonts/otf.rb +14 -0
  34. data/prawn-2.5.0/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
  35. data/prawn-2.5.0/lib/prawn/fonts/ttc.rb +41 -0
  36. data/prawn-2.5.0/lib/prawn/fonts/ttf.rb +615 -0
  37. data/prawn-2.5.0/lib/prawn/fonts.rb +14 -0
  38. data/prawn-2.5.0/lib/prawn/graphics/blend_mode.rb +62 -0
  39. data/prawn-2.5.0/lib/prawn/graphics/cap_style.rb +44 -0
  40. data/prawn-2.5.0/lib/prawn/graphics/color.rb +257 -0
  41. data/prawn-2.5.0/lib/prawn/graphics/dash.rb +123 -0
  42. data/prawn-2.5.0/lib/prawn/graphics/join_style.rb +60 -0
  43. data/prawn-2.5.0/lib/prawn/graphics/patterns.rb +389 -0
  44. data/prawn-2.5.0/lib/prawn/graphics/transformation.rb +172 -0
  45. data/prawn-2.5.0/lib/prawn/graphics/transparency.rb +79 -0
  46. data/prawn-2.5.0/lib/prawn/graphics.rb +791 -0
  47. data/prawn-2.5.0/lib/prawn/grid.rb +449 -0
  48. data/prawn-2.5.0/lib/prawn/image_handler.rb +61 -0
  49. data/prawn-2.5.0/lib/prawn/images/image.rb +48 -0
  50. data/prawn-2.5.0/lib/prawn/images/jpg.rb +121 -0
  51. data/prawn-2.5.0/lib/prawn/images/png.rb +383 -0
  52. data/prawn-2.5.0/lib/prawn/images.rb +195 -0
  53. data/prawn-2.5.0/lib/prawn/measurement_extensions.rb +82 -0
  54. data/prawn-2.5.0/lib/prawn/measurements.rb +129 -0
  55. data/prawn-2.5.0/lib/prawn/outline.rb +316 -0
  56. data/prawn-2.5.0/lib/prawn/repeater.rb +140 -0
  57. data/prawn-2.5.0/lib/prawn/security/arcfour.rb +54 -0
  58. data/prawn-2.5.0/lib/prawn/security.rb +308 -0
  59. data/prawn-2.5.0/lib/prawn/soft_mask.rb +105 -0
  60. data/prawn-2.5.0/lib/prawn/stamp.rb +147 -0
  61. data/prawn-2.5.0/lib/prawn/text/box.rb +192 -0
  62. data/prawn-2.5.0/lib/prawn/text/formatted/arranger.rb +396 -0
  63. data/prawn-2.5.0/lib/prawn/text/formatted/box.rb +725 -0
  64. data/prawn-2.5.0/lib/prawn/text/formatted/fragment.rb +373 -0
  65. data/prawn-2.5.0/lib/prawn/text/formatted/line_wrap.rb +335 -0
  66. data/prawn-2.5.0/lib/prawn/text/formatted/parser.rb +284 -0
  67. data/prawn-2.5.0/lib/prawn/text/formatted/wrap.rb +166 -0
  68. data/prawn-2.5.0/lib/prawn/text/formatted.rb +82 -0
  69. data/prawn-2.5.0/lib/prawn/text.rb +701 -0
  70. data/prawn-2.5.0/lib/prawn/transformation_stack.rb +63 -0
  71. data/prawn-2.5.0/lib/prawn/utilities.rb +34 -0
  72. data/prawn-2.5.0/lib/prawn/version.rb +6 -0
  73. data/prawn-2.5.0/lib/prawn/view.rb +116 -0
  74. data/prawn-2.5.0/lib/prawn.rb +83 -0
  75. metadata +114 -0
@@ -0,0 +1,625 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prawn
4
+ class Document # rubocop: disable Style/Documentation
5
+ # @group Stable API
6
+
7
+ # A bounding box serves two important purposes:
8
+ # * Provide bounds for flowing text, starting at a given point
9
+ # * Translate the origin (0, 0) for graphics primitives
10
+ #
11
+ # #### Positioning
12
+ #
13
+ # Bounding boxes are positioned relative to their top left corner and
14
+ # the width measurement is towards the right and height measurement is
15
+ # downwards.
16
+ #
17
+ # Usage:
18
+ #
19
+ # * Bounding box 100pt×100pt in the absolute bottom left of the
20
+ # containing box:
21
+ #
22
+ # ```ruby
23
+ # pdf.bounding_box([0, 100], width: 100, height: 100)
24
+ # stroke_bounds
25
+ # end
26
+ # ```
27
+ #
28
+ # * Bounding box 200pt×400pt high in the center of the page:
29
+ #
30
+ # ```ruby
31
+ # x_pos = ((bounds.width / 2) - 150)
32
+ # y_pos = ((bounds.height / 2) + 200)
33
+ # pdf.bounding_box([x_pos, y_pos], width: 300, height: 400) do
34
+ # stroke_bounds
35
+ # end
36
+ # ```
37
+ #
38
+ # #### Flowing Text
39
+ #
40
+ # When flowing text, the usage of a bounding box is simple. Text will
41
+ # begin at the point specified, flowing the width of the bounding box.
42
+ # After the block exits, the cursor position will be moved to
43
+ # the bottom of the bounding box (y - height). If flowing text exceeds
44
+ # the height of the bounding box, the text will be continued on the next
45
+ # page, starting again at the top-left corner of the bounding box.
46
+ #
47
+ # Usage:
48
+ #
49
+ # ```ruby
50
+ # pdf.bounding_box([100, 500], width: 100, height: 300) do
51
+ # pdf.text "This text will flow in a very narrow box starting" +
52
+ # "from [100, 500]. The pointer will then be moved to [100, 200]" +
53
+ # "and return to the margin_box"
54
+ # end
55
+ # ```
56
+ #
57
+ # Note, this is a low level tool and is designed primarily for building
58
+ # other abstractions. If you just need to flow text on the page, you
59
+ # will want to look at {span} and {text_box} instead.
60
+ #
61
+ # #### Translating Coordinates
62
+ #
63
+ # When translating coordinates, the idea is to allow the user to draw
64
+ # relative to the origin, and then translate their drawing to a specified
65
+ # area of the document, rather than adjust all their drawing coordinates
66
+ # to match this new region.
67
+ #
68
+ # Take for example two triangles which share one point, drawn from the
69
+ # origin:
70
+ #
71
+ # ```ruby
72
+ # pdf.polygon [0, 250], [0, 0], [150, 100]
73
+ # pdf.polygon [100, 0], [150, 100], [200, 0]
74
+ # ```
75
+ #
76
+ # It would be easy enough to translate these triangles to another point,
77
+ # e.g `[200, 200]`
78
+ #
79
+ # ```ruby
80
+ # pdf.polygon [200, 450], [200, 200], [350, 300]
81
+ # pdf.polygon [300, 200], [350, 300], [400, 200]
82
+ # ```
83
+ #
84
+ # However, each time you want to move the drawing, you'd need to alter
85
+ # every point in the drawing calls, which as you might imagine, can become
86
+ # tedious.
87
+ #
88
+ # If instead, we think of the drawing as being bounded by a box, we can
89
+ # see that the image is 200 points wide by 250 points tall.
90
+ #
91
+ # To translate it to a new origin, we simply select a point at
92
+ # (x, y + height).
93
+ #
94
+ # Using the [200, 200] example:
95
+ #
96
+ # ```ruby
97
+ # pdf.bounding_box([200, 450], width: 200, height: 250) do
98
+ # pdf.stroke do
99
+ # pdf.polygon [0, 250], [0, 0], [150, 100]
100
+ # pdf.polygon [100, 0], [150, 100], [200, 0]
101
+ # end
102
+ # end
103
+ # ```
104
+ #
105
+ # Notice that the drawing is still relative to the origin. If we want to
106
+ # move this drawing around the document, we simply need to recalculate the
107
+ # top-left corner of the rectangular bounding-box, and all of our graphics
108
+ # calls remain unmodified.
109
+ #
110
+ # #### Nesting Bounding Boxes
111
+ #
112
+ # At the top level, bounding boxes are specified relative to the document's
113
+ # margin_box (which is itself a bounding box). You can also nest bounding
114
+ # boxes, allowing you to build components which are relative to each other
115
+ #
116
+ # Usage:
117
+ #
118
+ # ```ruby
119
+ # pdf.bounding_box([200, 450], width: 200, height: 250) do
120
+ # pdf.stroke_bounds # Show the containing bounding box
121
+ # pdf.bounding_box([50, 200], width: 50, height: 50) do
122
+ # # a 50x50 bounding box that starts 50 pixels left and 50 pixels down
123
+ # # the parent bounding box.
124
+ # pdf.stroke_bounds
125
+ # end
126
+ # end
127
+ # ```
128
+ #
129
+ # #### Stretchiness
130
+ #
131
+ # If you do not specify a height to a bounding box, it will become stretchy
132
+ # and its height will be calculated automatically as you stretch the box
133
+ # downwards.
134
+ #
135
+ # pdf.bounding_box([100, 400], width: 400) do
136
+ # pdf.text("The height of this box is #{pdf.bounds.height}")
137
+ # pdf.text('this is some text')
138
+ # pdf.text('this is some more text')
139
+ # pdf.text('and finally a bit more')
140
+ # pdf.text("Now the height of this box is #{pdf.bounds.height}")
141
+ # end
142
+ #
143
+ # #### Absolute Positioning
144
+ #
145
+ # If you wish to position the bounding boxes at absolute coordinates rather
146
+ # than relative to the margins or other bounding boxes, you can use canvas()
147
+ #
148
+ # ```ruby
149
+ # pdf.bounding_box([50, 500], width: 200, height: 300) do
150
+ # pdf.stroke_bounds
151
+ # pdf.canvas do
152
+ # Positioned outside the containing box at the 'real' (300, 450)
153
+ # pdf.bounding_box([300, 450], width: 200, height: 200) do
154
+ # pdf.stroke_bounds
155
+ # end
156
+ # end
157
+ # end
158
+ # ```
159
+ #
160
+ # Of course, if you use canvas, you will be responsible for ensuring that
161
+ # you remain within the printable area of your document.
162
+ #
163
+ # @overload bounding_box(point, options = {}, &block)
164
+ # @param point [Array(Number, Number)]
165
+ # top left corner of the new bounding box
166
+ # @param options [Hash{Symbol => any}]
167
+ # @option options :width [Number]
168
+ # width of the new bounding box, must be specified.
169
+ # @option options :height [Number]
170
+ # height of the new bounding box, stretchy box if omitted.
171
+ # @yieldparam parent_box [BoundingBox] parent bounding box
172
+ # @yieldreturn [void]
173
+ # @return [void]
174
+ def bounding_box(point, *args, &block)
175
+ init_bounding_box(block) do |parent_box|
176
+ point = map_to_absolute(point)
177
+ @bounding_box = BoundingBox.new(self, parent_box, point, *args)
178
+ end
179
+ end
180
+
181
+ # A shortcut to produce a bounding box which is mapped to the document's
182
+ # absolute coordinates, regardless of how things are nested or margin sizes.
183
+ #
184
+ # @example
185
+ # pdf.canvas do
186
+ # pdf.line pdf.bounds.bottom_left, pdf.bounds.top_right
187
+ # end
188
+ #
189
+ # @yieldreturn [void]
190
+ # @return [void]
191
+ def canvas(&block)
192
+ init_bounding_box(block, hold_position: true) do |_|
193
+ # Canvas bbox acts like margin_box in that its parent bounds are unset.
194
+ @bounding_box = BoundingBox.new(
195
+ self,
196
+ nil,
197
+ [0, page.dimensions[3]],
198
+ width: page.dimensions[2],
199
+ height: page.dimensions[3],
200
+ )
201
+ end
202
+ end
203
+
204
+ private
205
+
206
+ def init_bounding_box(user_block, options = {})
207
+ unless user_block
208
+ raise ArgumentError,
209
+ 'bounding boxes require a block to be drawn within the box'
210
+ end
211
+
212
+ parent_box = @bounding_box
213
+
214
+ original_ypos = y
215
+
216
+ yield(parent_box)
217
+
218
+ self.y = @bounding_box.absolute_top
219
+ user_block.call
220
+
221
+ # If the user actions did not modify the y position
222
+ # restore the original y position before the bounding
223
+ # box was created.
224
+
225
+ if y == @bounding_box.absolute_top
226
+ self.y = original_ypos
227
+ end
228
+
229
+ unless options[:hold_position] || @bounding_box.stretchy?
230
+ self.y = @bounding_box.absolute_bottom
231
+ end
232
+
233
+ created_box = @bounding_box
234
+ @bounding_box = parent_box
235
+
236
+ created_box
237
+ end
238
+
239
+ # Low level layout helper that simplifies coordinate math.
240
+ #
241
+ # See {Prawn::Document#bounding_box} for a description of what this class
242
+ # is used for.
243
+ class BoundingBox
244
+ # Indicates absence of a reference bounding box of a fixed height.
245
+ class NoReferenceBounds < StandardError
246
+ def initialize(message = "Can't find reference bounds: my parent is unset")
247
+ super
248
+ end
249
+ end
250
+
251
+ # @private
252
+ # @param document [Prawn::Document] ownding document
253
+ # @param parent [BoundingBox?] parent bounding box
254
+ # @param point [Array(Number, Number)] coordinates of the top left corner
255
+ # @param options [Hash{Symbol => any}]
256
+ # @option options :width [Number] width
257
+ # @option options :height [Number] optional height
258
+ def initialize(document, parent, point, options = {})
259
+ unless options[:width]
260
+ raise ArgumentError, 'BoundingBox needs the :width option to be set'
261
+ end
262
+
263
+ @document = document
264
+ @parent = parent
265
+ @x, @y = point
266
+ @width = options[:width]
267
+ @height = options[:height]
268
+ @total_left_padding = 0
269
+ @total_right_padding = 0
270
+ @stretched_height = nil
271
+ end
272
+
273
+ # Owning document.
274
+ #
275
+ # @private
276
+ # @return [Prawn::Document]
277
+ attr_reader :document
278
+
279
+ # Parent bounding box.
280
+ #
281
+ # @private
282
+ # @return [BoundingBox?]
283
+ attr_reader :parent
284
+
285
+ # The current indentation of the left side of the bounding box.
286
+ #
287
+ # @private
288
+ # @return [Number]
289
+ attr_reader :total_left_padding
290
+
291
+ # The current indentation of the right side of the bounding box.
292
+ #
293
+ # @private
294
+ # @return [Number]
295
+ attr_reader :total_right_padding
296
+
297
+ # The translated origin (x, y - height) which describes the location of
298
+ # the bottom left corner of the bounding box.
299
+ #
300
+ # @private
301
+ # @return [Array(Number, Number)]
302
+ def anchor
303
+ [@x, @y - height]
304
+ end
305
+
306
+ # Relative left x-coordinate of the bounding box. Always 0.
307
+ #
308
+ # @example Position some text 3 pts from the left of the containing box
309
+ # draw_text('hello', at: [(bounds.left + 3), 0])
310
+ #
311
+ # @return [Number]
312
+ def left
313
+ 0
314
+ end
315
+
316
+ # Temporarily adjust the x coordinate to allow for left padding
317
+ #
318
+ # @example
319
+ # indent 20 do
320
+ # text "20 points in"
321
+ # indent 30 do
322
+ # text "50 points in"
323
+ # end
324
+ # end
325
+ #
326
+ # indent 20, 20 do
327
+ # text "indented on both sides"
328
+ # end
329
+ #
330
+ # @private
331
+ # @param left_padding [Number]
332
+ # @param right_padding [Number]
333
+ # @return [void]
334
+ def indent(left_padding, right_padding = 0)
335
+ add_left_padding(left_padding)
336
+ add_right_padding(right_padding)
337
+ yield
338
+ ensure
339
+ @document.bounds.subtract_left_padding(left_padding)
340
+ @document.bounds.subtract_right_padding(right_padding)
341
+ end
342
+
343
+ # Increase the left padding of the bounding box.
344
+ #
345
+ # @private
346
+ # @param left_padding [Number]
347
+ # @return [void]
348
+ def add_left_padding(left_padding)
349
+ @total_left_padding += left_padding
350
+ @x += left_padding
351
+ @width -= left_padding
352
+ end
353
+
354
+ # Decrease the left padding of the bounding box.
355
+ #
356
+ # @private
357
+ # @param left_padding [Number]
358
+ # @return [void]
359
+ def subtract_left_padding(left_padding)
360
+ @total_left_padding -= left_padding
361
+ @x -= left_padding
362
+ @width += left_padding
363
+ end
364
+
365
+ # Increase the right padding of the bounding box.
366
+ #
367
+ # @private
368
+ # @param right_padding [Number]
369
+ # @return [void]
370
+ def add_right_padding(right_padding)
371
+ @total_right_padding += right_padding
372
+ @width -= right_padding
373
+ end
374
+
375
+ # Decrease the right padding of the bounding box.
376
+ #
377
+ # @private
378
+ # @param right_padding [Number]
379
+ # @return [void]
380
+ def subtract_right_padding(right_padding)
381
+ @total_right_padding -= right_padding
382
+ @width += right_padding
383
+ end
384
+
385
+ # Relative right x-coordinate of the bounding box. Equal to the box width.
386
+ #
387
+ # @example Position some text 3 pts from the right of the containing box
388
+ # draw_text('hello', at: [(bounds.right - 3), 0])
389
+ #
390
+ # @return [Number]
391
+ def right
392
+ @width
393
+ end
394
+
395
+ # Relative top y-coordinate of the bounding box. Equal to the box height.
396
+ #
397
+ # @example Position some text 3 pts from the top of the containing box
398
+ # draw_text('hello', at: [0, (bounds.top - 3)])
399
+ #
400
+ # @return [Number]
401
+ def top
402
+ height
403
+ end
404
+
405
+ # Relative bottom y-coordinate of the bounding box. Always 0.
406
+ #
407
+ # @example Position some text 3 pts from the bottom of the containing box
408
+ # draw_text('hello', at: [0, (bounds.bottom + 3)])
409
+ #
410
+ # @return [Number]
411
+ def bottom
412
+ 0
413
+ end
414
+
415
+ # Relative top-left point of the bounding_box.
416
+ #
417
+ # @example Draw a line from the top left of the box diagonally to the bottom right
418
+ # stroke do
419
+ # line(bounds.top_left, bounds.bottom_right)
420
+ # end
421
+ #
422
+ # @return [Array(Number, Number)]
423
+ def top_left
424
+ [left, top]
425
+ end
426
+
427
+ # Relative top-right point of the bounding box.
428
+ #
429
+ # @example Draw a line from the top_right of the box diagonally to the bottom left
430
+ # stroke do
431
+ # line(bounds.top_right, bounds.bottom_left)
432
+ # end
433
+ #
434
+ # @return [Array(Number, Number)]
435
+ def top_right
436
+ [right, top]
437
+ end
438
+
439
+ # Relative bottom-right point of the bounding box.
440
+ #
441
+ # @example Draw a line along the right hand side of the page
442
+ # stroke do
443
+ # line(bounds.bottom_right, bounds.top_right)
444
+ # end
445
+ #
446
+ # @return [Array(Number, Number)]
447
+ def bottom_right
448
+ [right, bottom]
449
+ end
450
+
451
+ # Relative bottom-left point of the bounding box.
452
+ #
453
+ # @example Draw a line along the left hand side of the page
454
+ # stroke do
455
+ # line(bounds.bottom_left, bounds.top_left)
456
+ # end
457
+ #
458
+ # @return [Array(Number, Number)]
459
+ def bottom_left
460
+ [left, bottom]
461
+ end
462
+
463
+ # Absolute left x-coordinate of the bounding box.
464
+ #
465
+ # @return [Number]
466
+ def absolute_left
467
+ @x
468
+ end
469
+
470
+ # Absolute right x-coordinate of the bounding box.
471
+ #
472
+ # @return [Number]
473
+ def absolute_right
474
+ @x + width
475
+ end
476
+
477
+ # Absolute top y-coordinate of the bounding box.
478
+ #
479
+ # @return [Number]
480
+ def absolute_top
481
+ @y
482
+ end
483
+
484
+ # Absolute bottom y-coordinate of the bottom box.
485
+ #
486
+ # @return [Number]
487
+ def absolute_bottom
488
+ @y - height
489
+ end
490
+
491
+ # Absolute top-left point of the bounding box.
492
+ #
493
+ # @return [Array(Number, Number)]
494
+ def absolute_top_left
495
+ [absolute_left, absolute_top]
496
+ end
497
+
498
+ # Absolute top-right point of the bounding box.
499
+ #
500
+ # @return [Array(Number, Number)]
501
+ def absolute_top_right
502
+ [absolute_right, absolute_top]
503
+ end
504
+
505
+ # Absolute bottom-left point of the bounding box.
506
+ #
507
+ # @return [Array(Number, Number)]
508
+ def absolute_bottom_left
509
+ [absolute_left, absolute_bottom]
510
+ end
511
+
512
+ # Absolute bottom-left point of the bounding box.
513
+ #
514
+ # @return [Array(Number, Number)]
515
+ def absolute_bottom_right
516
+ [absolute_right, absolute_bottom]
517
+ end
518
+
519
+ # Width of the bounding box.
520
+ #
521
+ # @return [Number]
522
+ attr_reader :width
523
+
524
+ # Height of the bounding box. If the box is 'stretchy' (unspecified
525
+ # height attribute), height is calculated as the distance from the top of
526
+ # the box to the current drawing position.
527
+ #
528
+ # @return [Number]
529
+ def height
530
+ return @height if @height
531
+
532
+ @stretched_height = [
533
+ (absolute_top - @document.y),
534
+ Float(@stretched_height || 0.0),
535
+ ].max
536
+ end
537
+
538
+ # An alias for {absolute_left}.
539
+ #
540
+ # @private
541
+ # @return [Number]
542
+ def left_side
543
+ absolute_left
544
+ end
545
+
546
+ # An alias for {absolute_right}.
547
+ #
548
+ # @private
549
+ # @return [Number]
550
+ def right_side
551
+ absolute_right
552
+ end
553
+
554
+ # @group Extension API
555
+
556
+ # Moves to the top of the next page of the document, starting a new page
557
+ # if necessary.
558
+ #
559
+ # @return [void]
560
+ def move_past_bottom
561
+ if @document.page_number == @document.page_count
562
+ @document.start_new_page
563
+ else
564
+ @document.go_to_page(@document.page_number + 1)
565
+ end
566
+ end
567
+
568
+ # Returns `false` when the box has a defined height, `true` when the
569
+ # height is being calculated on the fly based on the current vertical
570
+ # position.
571
+ #
572
+ # @return [Boolean]
573
+ def stretchy?
574
+ !@height
575
+ end
576
+
577
+ # Returns the innermost non-stretchy bounding box.
578
+ #
579
+ # @return [BoundingBox]
580
+ # @raise [NoReferenceBounds]
581
+ def reference_bounds
582
+ if stretchy?
583
+ raise NoReferenceBounds unless @parent
584
+
585
+ @parent.reference_bounds
586
+ else
587
+ self
588
+ end
589
+ end
590
+
591
+ alias update_height height
592
+
593
+ # Returns a deep copy of these bounds (including all parent bounds but
594
+ # not copying the reference to the Document).
595
+ #
596
+ # @private
597
+ # @return [BoundingBox]
598
+ def deep_copy
599
+ copy = dup
600
+ # Deep-copy the parent bounds
601
+ copy.instance_variable_set(
602
+ :@parent,
603
+ if @parent.is_a?(BoundingBox)
604
+ @parent.deep_copy
605
+ end,
606
+ )
607
+ copy.instance_variable_set(:@document, nil)
608
+ copy
609
+ end
610
+
611
+ # Restores a copy of the bounds taken by {BoundingBox#deep_copy} in the
612
+ # context of the given `document`. Does *not* set the bounds of the
613
+ # document to the resulting {BoundingBox}, only returns it.
614
+ #
615
+ # @private
616
+ # @param bounds [BoundingBox]
617
+ # @param document [Prawn::Document]
618
+ # @return [BoundingBox]
619
+ def self.restore_deep_copy(bounds, document)
620
+ bounds.instance_variable_set(:@document, document)
621
+ bounds
622
+ end
623
+ end
624
+ end
625
+ end