pdfrb 0.7.10 → 0.7.12
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 +4 -4
- data/lib/pdfrb/composer.rb +25 -6
- data/lib/pdfrb/layout/frame.rb +52 -11
- data/lib/pdfrb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 26e34e7b8d5b74f8a2f8a89b36b3ea7ae028b0cf8944707aeed0a3ddde8270fc
|
|
4
|
+
data.tar.gz: 9bae4c50eff54052d0cc173559625fb0de3ff782bb567b9ac0bf7f85be951aea
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c12a6ae1950e81e8bb5fc181dc35aa63fcb6c0671bf0ab9e3becc92b3ebbb28e2210eb0be966ca4cefb6baf97688b1e7ba8115629d08647493680f5f42c6588
|
|
7
|
+
data.tar.gz: 87eb412507356b781a33f96f3d58aa6a14acb5284664091879c23c699e70bd3a2ee4e5f0dbd64c7958361544e1ecc3a23f71b00e2d95b3fe9f2805ab9ad441ed
|
data/lib/pdfrb/composer.rb
CHANGED
|
@@ -57,6 +57,8 @@ module Pdfrb
|
|
|
57
57
|
def new_page(style_name = nil)
|
|
58
58
|
@current_style_name = style_name || next_style_name
|
|
59
59
|
style_obj = @page_styles[@current_style_name]
|
|
60
|
+
# Reset the frame cursor for the new page.
|
|
61
|
+
reset_frame_cursor(style_obj)
|
|
60
62
|
page = @document.pages.add
|
|
61
63
|
page.value[:MediaBox] = [0, 0, style_obj.width, style_obj.height]
|
|
62
64
|
@current_page = page
|
|
@@ -64,6 +66,11 @@ module Pdfrb
|
|
|
64
66
|
page
|
|
65
67
|
end
|
|
66
68
|
|
|
69
|
+
def reset_frame_cursor(style_obj)
|
|
70
|
+
style_obj&.frame&.reset!
|
|
71
|
+
end
|
|
72
|
+
private :reset_frame_cursor
|
|
73
|
+
|
|
67
74
|
def x
|
|
68
75
|
@cursor_x || 50
|
|
69
76
|
end
|
|
@@ -143,17 +150,29 @@ module Pdfrb
|
|
|
143
150
|
|
|
144
151
|
style_obj = @page_styles[@current_style_name]
|
|
145
152
|
frame = style_obj.frame
|
|
146
|
-
cursor_y = frame.top
|
|
147
153
|
|
|
148
154
|
@pending_boxes.each do |box|
|
|
149
|
-
|
|
155
|
+
available_h = frame.available_height.positive? ? frame.available_height : (frame.top - frame.bottom)
|
|
156
|
+
unless box.fit?(frame.width, available_h)
|
|
150
157
|
new_page
|
|
151
|
-
|
|
152
|
-
|
|
158
|
+
style_obj = @page_styles[@current_style_name]
|
|
159
|
+
frame = style_obj.frame
|
|
160
|
+
available_h = frame.top - frame.bottom
|
|
161
|
+
box.fit?(frame.width, available_h)
|
|
153
162
|
end
|
|
163
|
+
|
|
164
|
+
position = frame.find_available_area(box.width || frame.width, box.height || available_h)
|
|
165
|
+
if position
|
|
166
|
+
draw_x, draw_y, = position
|
|
167
|
+
else
|
|
168
|
+
draw_x = frame.left
|
|
169
|
+
draw_y = frame.cursor_y - (box.height || 0)
|
|
170
|
+
end
|
|
171
|
+
|
|
154
172
|
canvas = @current_page.canvas
|
|
155
|
-
box.draw(canvas,
|
|
156
|
-
|
|
173
|
+
box.draw(canvas, draw_x, draw_y)
|
|
174
|
+
box_h = box.height || available_h
|
|
175
|
+
frame.remove_area(draw_x, draw_y, box.width || frame.width, box_h)
|
|
157
176
|
end
|
|
158
177
|
@pending_boxes = []
|
|
159
178
|
end
|
data/lib/pdfrb/layout/frame.rb
CHANGED
|
@@ -9,8 +9,14 @@ module Pdfrb
|
|
|
9
9
|
# Simple case: the Frame is a plain rectangle. Advanced: the
|
|
10
10
|
# +shape+ polygon allows non-rectangular regions (L-shaped, with
|
|
11
11
|
# cutouts around images).
|
|
12
|
+
#
|
|
13
|
+
# Area tracking: +remove_area+ marks a rectangle as used. The
|
|
14
|
+
# Frame maintains a +cursor_y+ that tracks the lowest free
|
|
15
|
+
# vertical position. +find_available_area+ returns the next
|
|
16
|
+
# position at or above the cursor where the requested
|
|
17
|
+
# (width × height) fits without overlapping any removed area.
|
|
12
18
|
class Frame
|
|
13
|
-
attr_reader :left, :bottom, :width, :height, :shape
|
|
19
|
+
attr_reader :left, :bottom, :width, :height, :shape, :cursor_y
|
|
14
20
|
|
|
15
21
|
def initialize(left:, bottom:, width:, height:, shape: nil)
|
|
16
22
|
@left = left.to_f
|
|
@@ -18,6 +24,8 @@ module Pdfrb
|
|
|
18
24
|
@width = width.to_f
|
|
19
25
|
@height = height.to_f
|
|
20
26
|
@shape = shape || default_shape
|
|
27
|
+
@cursor_y = top
|
|
28
|
+
@removed_areas = []
|
|
21
29
|
end
|
|
22
30
|
|
|
23
31
|
def right
|
|
@@ -28,37 +36,70 @@ module Pdfrb
|
|
|
28
36
|
@bottom + @height
|
|
29
37
|
end
|
|
30
38
|
|
|
31
|
-
# Locate the next free area of (width × height) within this
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
39
|
+
# Locate the next free area of (width × height) within this
|
|
40
|
+
# Frame. Scans from the cursor_y downward, checking each
|
|
41
|
+
# candidate y against the removed-areas list. Returns
|
|
42
|
+
# [x, y, w, h] or nil if nothing fits.
|
|
35
43
|
def find_available_area(width, height)
|
|
36
44
|
w = width.to_f
|
|
37
45
|
h = height.to_f
|
|
38
46
|
return nil if w > @width || h > @height
|
|
47
|
+
return nil if h > available_height
|
|
48
|
+
|
|
49
|
+
y = @cursor_y - h
|
|
50
|
+
while y >= @bottom
|
|
51
|
+
if area_free?(@left, y, w, h)
|
|
52
|
+
@cursor_y = y
|
|
53
|
+
return [@left, y, w, h]
|
|
54
|
+
end
|
|
39
55
|
|
|
40
|
-
|
|
56
|
+
y -= 1
|
|
57
|
+
end
|
|
58
|
+
nil
|
|
41
59
|
end
|
|
42
60
|
|
|
43
61
|
# Mark the rectangle at (x, y) of (w × h) as filled. Subsequent
|
|
44
|
-
# +find_available_area+ calls avoid this region.
|
|
62
|
+
# +find_available_area+ calls avoid this region. Moves the
|
|
63
|
+
# cursor down when the removed area is at the current cursor.
|
|
45
64
|
def remove_area(x, y, w, h)
|
|
46
65
|
return if x.nil? || y.nil?
|
|
47
66
|
|
|
48
|
-
@
|
|
49
|
-
|
|
67
|
+
@removed_areas << [x.to_f, y.to_f, w.to_f, h.to_f]
|
|
68
|
+
# If the removed area touches the cursor, advance it.
|
|
69
|
+
if (y + h) >= @cursor_y - 1
|
|
70
|
+
@cursor_y = [@cursor_y, y].min
|
|
71
|
+
end
|
|
50
72
|
end
|
|
51
73
|
|
|
52
74
|
def full?
|
|
53
|
-
@
|
|
75
|
+
@cursor_y <= @bottom
|
|
54
76
|
end
|
|
55
77
|
|
|
56
78
|
def empty?
|
|
57
|
-
|
|
79
|
+
@removed_areas.empty?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def available_height
|
|
83
|
+
@cursor_y - @bottom
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Reset the cursor and removed-areas list. Used by the
|
|
87
|
+
# Composer when starting a new page with the same Frame.
|
|
88
|
+
def reset!
|
|
89
|
+
@cursor_y = top
|
|
90
|
+
@removed_areas = []
|
|
58
91
|
end
|
|
59
92
|
|
|
60
93
|
private
|
|
61
94
|
|
|
95
|
+
def area_free?(x, y, w, h)
|
|
96
|
+
@removed_areas.none? { |rx, ry, rw, rh| rectangles_overlap?(x, y, w, h, rx, ry, rw, rh) }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def rectangles_overlap?(x1, y1, w1, h1, x2, y2, w2, h2)
|
|
100
|
+
x1 < x2 + w2 && x1 + w1 > x2 && y1 < y2 + h2 && y1 + h1 > y2
|
|
101
|
+
end
|
|
102
|
+
|
|
62
103
|
def default_shape
|
|
63
104
|
[[@left, @bottom], [right, @bottom], [right, top], [@left, top]]
|
|
64
105
|
end
|
data/lib/pdfrb/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pdfrb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.12
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: thor
|