prawn-html 0.3.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -2
- data/lib/prawn-html.rb +9 -5
- data/lib/prawn_html/attributes.rb +45 -33
- data/lib/prawn_html/callbacks/background.rb +19 -0
- data/lib/prawn_html/callbacks/strike_through.rb +4 -4
- data/lib/prawn_html/context.rb +22 -11
- data/lib/prawn_html/document_renderer.rb +56 -45
- data/lib/prawn_html/html_parser.rb +38 -13
- data/lib/prawn_html/pdf_wrapper.rb +141 -0
- data/lib/prawn_html/tag.rb +18 -23
- data/lib/prawn_html/tags/a.rb +7 -1
- data/lib/prawn_html/tags/b.rb +1 -3
- data/lib/prawn_html/tags/blockquote.rb +25 -0
- data/lib/prawn_html/tags/body.rb +4 -0
- data/lib/prawn_html/tags/br.rb +3 -4
- data/lib/prawn_html/tags/code.rb +13 -0
- data/lib/prawn_html/tags/del.rb +1 -3
- data/lib/prawn_html/tags/h.rb +21 -21
- data/lib/prawn_html/tags/hr.rb +6 -16
- data/lib/prawn_html/tags/i.rb +1 -3
- data/lib/prawn_html/tags/img.rb +6 -5
- data/lib/prawn_html/tags/li.rb +20 -7
- data/lib/prawn_html/tags/mark.rb +1 -3
- data/lib/prawn_html/tags/ol.rb +20 -5
- data/lib/prawn_html/tags/p.rb +6 -6
- data/lib/prawn_html/tags/pre.rb +25 -0
- data/lib/prawn_html/tags/sub.rb +13 -0
- data/lib/prawn_html/tags/sup.rb +13 -0
- data/lib/prawn_html/tags/u.rb +1 -3
- data/lib/prawn_html/tags/ul.rb +23 -4
- data/lib/prawn_html/utils.rb +48 -11
- data/lib/prawn_html/version.rb +1 -1
- metadata +9 -3
- data/lib/prawn_html/callbacks/highlight.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e82e0a464e39fd4c47c399cb043ceefe090524b29ead1c06795a484d4c648388
|
4
|
+
data.tar.gz: e124a7fb9800a434f42d403b478c6a6cb30b4e7d1e7e540d015028dec6daaa59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c08e1252e2c9c8f1591840179549d3e14483d91361b1a9f56d96f23cfa30829b98d8d2ace33808a73a9467e1ff37054d7f462d1c7170db273a4ff83b203d807f
|
7
|
+
data.tar.gz: '0979bd9a66e463ee8e4ea3c141a2d4e2fcc0e3b1bc82397aeda2e357c10c4518b00b1e1e4fc3f2ec786070c6d229241423cd5933a89fbc9137bdccc211d22a44'
|
data/README.md
CHANGED
@@ -39,7 +39,9 @@ HTML tags:
|
|
39
39
|
|
40
40
|
- **a**: link
|
41
41
|
- **b**: bold
|
42
|
+
- **blockquote**: block quotation element
|
42
43
|
- **br**: new line
|
44
|
+
- **code**: inline code element
|
43
45
|
- **del**: strike-through
|
44
46
|
- **div**: block element
|
45
47
|
- **em**: italic
|
@@ -52,16 +54,21 @@ HTML tags:
|
|
52
54
|
- **mark**: highlight
|
53
55
|
- **ol**: ordered list
|
54
56
|
- **p**: block element
|
57
|
+
- **pre**: preformatted text element
|
55
58
|
- **s**: strike-through
|
56
59
|
- **small**: smaller text
|
57
60
|
- **span**: inline element
|
58
61
|
- **strong**: bold
|
62
|
+
- **sub**: subscript element
|
63
|
+
- **sup**: superscript element
|
59
64
|
- **u**: underline
|
60
65
|
- **ul**: unordered list
|
61
66
|
|
62
67
|
CSS attributes (dimensional units are ignored and considered in pixel):
|
63
68
|
|
64
69
|
- **background**: for *mark* tag (3/6 hex digits or RGB or color name), ex. `style="background: #FECD08"`
|
70
|
+
- **break-after**: go to a new page after some elements, ex. `style="break-after: auto"`
|
71
|
+
- **break-before**: go to a new page before some elements, ex. `style="break-before: auto"`
|
65
72
|
- **color**: (3/6 hex digits or RGB or color name) ex. `style="color: #FB1"`
|
66
73
|
- **font-family**: font must be registered, quotes are optional, ex. `style="font-family: Courier"`
|
67
74
|
- **font-size**: ex. `style="font-size: 20px"`
|
@@ -98,8 +105,7 @@ Some custom data attributes are used to pass options:
|
|
98
105
|
|
99
106
|
## Document styles
|
100
107
|
|
101
|
-
|
102
|
-
Only single CSS selectors and basic ones are supported. Example:
|
108
|
+
You can define document CSS rules inside an _head_ tag. Example:
|
103
109
|
|
104
110
|
```html
|
105
111
|
<!DOCTYPE html>
|
data/lib/prawn-html.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'prawn'
|
4
|
-
|
5
3
|
module PrawnHtml
|
6
|
-
PX = 0.
|
4
|
+
PX = 0.6 # conversion constant for pixel sixes
|
7
5
|
|
8
6
|
COLORS = {
|
9
7
|
'aliceblue' => 'f0f8ff',
|
@@ -157,20 +155,26 @@ module PrawnHtml
|
|
157
155
|
}.freeze
|
158
156
|
|
159
157
|
def append_html(pdf, html)
|
160
|
-
|
158
|
+
pdf_wrapper = PdfWrapper.new(pdf)
|
159
|
+
renderer = DocumentRenderer.new(pdf_wrapper)
|
160
|
+
html_parser = PrawnHtml::HtmlParser.new(renderer)
|
161
161
|
html_parser.process(html)
|
162
162
|
end
|
163
163
|
|
164
164
|
module_function :append_html
|
165
165
|
end
|
166
166
|
|
167
|
+
require 'prawn'
|
168
|
+
|
167
169
|
require 'prawn_html/utils'
|
168
170
|
|
171
|
+
Dir["#{__dir__}/prawn_html/callbacks/*.rb"].sort.each { |f| require f }
|
172
|
+
|
169
173
|
require 'prawn_html/tag'
|
170
174
|
Dir["#{__dir__}/prawn_html/tags/*.rb"].sort.each { |f| require f }
|
171
|
-
Dir["#{__dir__}/prawn_html/callbacks/*.rb"].sort.each { |f| require f }
|
172
175
|
|
173
176
|
require 'prawn_html/attributes'
|
174
177
|
require 'prawn_html/context'
|
178
|
+
require 'prawn_html/pdf_wrapper'
|
175
179
|
require 'prawn_html/document_renderer'
|
176
180
|
require 'prawn_html/html_parser'
|
@@ -7,39 +7,44 @@ module PrawnHtml
|
|
7
7
|
attr_reader :styles
|
8
8
|
|
9
9
|
STYLES_APPLY = {
|
10
|
-
block: %i[align leading left margin_left padding_left position top],
|
11
|
-
tag_close: %i[margin_bottom padding_bottom],
|
12
|
-
tag_open: %i[margin_top padding_top],
|
13
|
-
text_node: %i[
|
10
|
+
block: %i[align bottom leading left margin_left padding_left position right top],
|
11
|
+
tag_close: %i[margin_bottom padding_bottom break_after],
|
12
|
+
tag_open: %i[margin_top padding_top break_before],
|
13
|
+
text_node: %i[callback character_spacing color font link list_style_type size styles white_space]
|
14
14
|
}.freeze
|
15
15
|
|
16
16
|
STYLES_LIST = {
|
17
17
|
# text node styles
|
18
|
-
'background' => { key: :
|
19
|
-
'callback' => { key: :callback, set: :copy_value },
|
18
|
+
'background' => { key: :callback, set: :callback_background },
|
20
19
|
'color' => { key: :color, set: :convert_color },
|
21
20
|
'font-family' => { key: :font, set: :unquote },
|
22
21
|
'font-size' => { key: :size, set: :convert_size },
|
23
|
-
'font-style' => { key: :styles, set: :
|
24
|
-
'font-weight' => { key: :styles, set: :
|
22
|
+
'font-style' => { key: :styles, set: :append_styles },
|
23
|
+
'font-weight' => { key: :styles, set: :append_styles },
|
25
24
|
'href' => { key: :link, set: :copy_value },
|
26
25
|
'letter-spacing' => { key: :character_spacing, set: :convert_float },
|
27
26
|
'list-style-type' => { key: :list_style_type, set: :unquote },
|
28
|
-
'text-decoration' => { key: :styles, set: :
|
27
|
+
'text-decoration' => { key: :styles, set: :append_text_decoration },
|
28
|
+
'vertical-align' => { key: :styles, set: :append_styles },
|
29
|
+
'white-space' => { key: :white_space, set: :convert_symbol },
|
29
30
|
# tag opening styles
|
31
|
+
'break-before' => { key: :break_before, set: :convert_symbol },
|
30
32
|
'margin-top' => { key: :margin_top, set: :convert_size },
|
31
33
|
'padding-top' => { key: :padding_top, set: :convert_size },
|
32
34
|
# tag closing styles
|
35
|
+
'break-after' => { key: :break_after, set: :convert_symbol },
|
33
36
|
'margin-bottom' => { key: :margin_bottom, set: :convert_size },
|
34
37
|
'padding-bottom' => { key: :padding_bottom, set: :convert_size },
|
35
38
|
# block styles
|
36
|
-
'
|
39
|
+
'bottom' => { key: :bottom, set: :convert_size, options: :height },
|
40
|
+
'left' => { key: :left, set: :convert_size, options: :width },
|
37
41
|
'line-height' => { key: :leading, set: :convert_size },
|
38
42
|
'margin-left' => { key: :margin_left, set: :convert_size },
|
39
43
|
'padding-left' => { key: :padding_left, set: :convert_size },
|
40
44
|
'position' => { key: :position, set: :convert_symbol },
|
45
|
+
'right' => { key: :right, set: :convert_size, options: :width },
|
41
46
|
'text-align' => { key: :align, set: :convert_symbol },
|
42
|
-
'top' => { key: :top, set: :convert_size }
|
47
|
+
'top' => { key: :top, set: :convert_size, options: :height }
|
43
48
|
}.freeze
|
44
49
|
|
45
50
|
STYLES_MERGE = %i[margin_left padding_left].freeze
|
@@ -48,10 +53,6 @@ module PrawnHtml
|
|
48
53
|
def initialize(attributes = {})
|
49
54
|
super
|
50
55
|
@styles = {} # result styles
|
51
|
-
return unless style
|
52
|
-
|
53
|
-
styles_hash = Attributes.parse_styles(style)
|
54
|
-
process_styles(styles_hash)
|
55
56
|
end
|
56
57
|
|
57
58
|
# Processes the data attributes
|
@@ -64,21 +65,13 @@ module PrawnHtml
|
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
67
|
-
# Merge
|
68
|
+
# Merge text styles
|
68
69
|
#
|
69
|
-
# @param
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
# Processes the styles attributes
|
75
|
-
#
|
76
|
-
# @param styles_hash [Hash] hash of styles attributes
|
77
|
-
def process_styles(styles_hash)
|
78
|
-
styles_hash.each do |key, value|
|
79
|
-
apply_rule!(@styles, STYLES_LIST[key], value)
|
80
|
-
end
|
81
|
-
@styles
|
70
|
+
# @param text_styles [String] styles to parse and process
|
71
|
+
# @param options [Hash] options (container width/height/etc.)
|
72
|
+
def merge_text_styles!(text_styles, options: {})
|
73
|
+
hash_styles = Attributes.parse_styles(text_styles)
|
74
|
+
process_styles(hash_styles, options: options) unless hash_styles.empty?
|
82
75
|
end
|
83
76
|
|
84
77
|
class << self
|
@@ -109,13 +102,32 @@ module PrawnHtml
|
|
109
102
|
|
110
103
|
private
|
111
104
|
|
112
|
-
def
|
105
|
+
def process_styles(hash_styles, options:)
|
106
|
+
hash_styles.each do |key, value|
|
107
|
+
rule = evaluate_rule(key, value)
|
108
|
+
apply_rule!(merged_styles: @styles, rule: rule, value: value, options: options)
|
109
|
+
end
|
110
|
+
@styles
|
111
|
+
end
|
112
|
+
|
113
|
+
def evaluate_rule(rule_key, attr_value)
|
114
|
+
rule = STYLES_LIST[rule_key]
|
115
|
+
if rule && rule[:set] == :append_text_decoration
|
116
|
+
return { key: :callback, set: :callback_strike_through } if attr_value == 'line-through'
|
117
|
+
|
118
|
+
return { key: :styles, set: :append_styles }
|
119
|
+
end
|
120
|
+
rule
|
121
|
+
end
|
122
|
+
|
123
|
+
def apply_rule!(merged_styles:, rule:, value:, options:)
|
113
124
|
return unless rule
|
114
125
|
|
115
|
-
if rule[:set] == :
|
116
|
-
(
|
126
|
+
if rule[:set] == :append_styles
|
127
|
+
(merged_styles[rule[:key]] ||= []) << Utils.normalize_style(value)
|
117
128
|
else
|
118
|
-
|
129
|
+
opts = rule[:options] ? options[rule[:options]] : nil
|
130
|
+
merged_styles[rule[:key]] = Utils.send(rule[:set], value, options: opts)
|
119
131
|
end
|
120
132
|
end
|
121
133
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrawnHtml
|
4
|
+
module Callbacks
|
5
|
+
class Background
|
6
|
+
DEF_HIGHLIGHT = 'ffff00'
|
7
|
+
|
8
|
+
def initialize(pdf, color = nil)
|
9
|
+
@pdf = pdf
|
10
|
+
@color = color || DEF_HIGHLIGHT
|
11
|
+
end
|
12
|
+
|
13
|
+
def render_behind(fragment)
|
14
|
+
top, left = fragment.top_left
|
15
|
+
@pdf.draw_rectangle(x: left, y: top, width: fragment.width, height: fragment.height, color: @color)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -8,10 +8,10 @@ module PrawnHtml
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def render_in_front(fragment)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
x1 = fragment.left
|
12
|
+
x2 = fragment.right
|
13
|
+
y = (fragment.top + fragment.bottom) / 2
|
14
|
+
@pdf.underline(x1: x1, x2: x2, y: y)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/lib/prawn_html/context.rb
CHANGED
@@ -2,15 +2,17 @@
|
|
2
2
|
|
3
3
|
module PrawnHtml
|
4
4
|
class Context < Array
|
5
|
-
DEF_FONT_SIZE =
|
5
|
+
DEF_FONT_SIZE = 16 * PX
|
6
6
|
|
7
|
-
|
7
|
+
attr_reader :previous_tag
|
8
|
+
attr_accessor :last_text_node
|
8
9
|
|
9
10
|
# Init the Context
|
10
11
|
def initialize(*_args)
|
11
12
|
super
|
12
|
-
@last_margin = 0
|
13
13
|
@last_text_node = false
|
14
|
+
@merged_styles = nil
|
15
|
+
@previous_tag = nil
|
14
16
|
end
|
15
17
|
|
16
18
|
# Add an element to the context
|
@@ -25,6 +27,7 @@ module PrawnHtml
|
|
25
27
|
element.parent = last
|
26
28
|
push(element)
|
27
29
|
element.on_context_add(self) if element.respond_to?(:on_context_add)
|
30
|
+
@merged_styles = nil
|
28
31
|
self
|
29
32
|
end
|
30
33
|
|
@@ -32,9 +35,7 @@ module PrawnHtml
|
|
32
35
|
#
|
33
36
|
# @return [String] before content string
|
34
37
|
def before_content
|
35
|
-
|
36
|
-
|
37
|
-
last.tag_styles[:before_content].to_s
|
38
|
+
(last.respond_to?(:before_content) && last.before_content) || ''
|
38
39
|
end
|
39
40
|
|
40
41
|
# Merges the context block styles
|
@@ -51,11 +52,21 @@ module PrawnHtml
|
|
51
52
|
# Merge the context styles for text nodes
|
52
53
|
#
|
53
54
|
# @return [Hash] the hash of merged styles
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
def merged_styles
|
56
|
+
@merged_styles ||=
|
57
|
+
each_with_object(base_styles) do |element, res|
|
58
|
+
evaluate_element_styles(element, res)
|
59
|
+
element.update_styles(res) if element.respond_to?(:update_styles)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Remove the last element from the context
|
64
|
+
def remove_last
|
65
|
+
last.on_context_remove(self) if last.respond_to?(:on_context_remove)
|
66
|
+
@merged_styles = nil
|
67
|
+
@last_text_node = false
|
68
|
+
@previous_tag = last.tag
|
69
|
+
pop
|
59
70
|
end
|
60
71
|
|
61
72
|
private
|
@@ -7,47 +7,37 @@ module PrawnHtml
|
|
7
7
|
|
8
8
|
# Init the DocumentRenderer
|
9
9
|
#
|
10
|
-
# @param pdf [
|
10
|
+
# @param pdf [PdfWrapper] target PDF wrapper
|
11
11
|
def initialize(pdf)
|
12
12
|
@buffer = []
|
13
13
|
@context = Context.new
|
14
|
-
@
|
14
|
+
@last_margin = 0
|
15
15
|
@pdf = pdf
|
16
16
|
end
|
17
17
|
|
18
|
-
# Evaluate the document styles and store the internally
|
19
|
-
#
|
20
|
-
# @param styles [Hash] styles hash with CSS selectors as keys and rules as values
|
21
|
-
def assign_document_styles(styles)
|
22
|
-
@document_styles.merge!(
|
23
|
-
styles.transform_values do |style_rules|
|
24
|
-
Attributes.new(style: style_rules).styles
|
25
|
-
end
|
26
|
-
)
|
27
|
-
end
|
28
|
-
|
29
18
|
# On tag close callback
|
30
19
|
#
|
31
20
|
# @param element [Tag] closing element wrapper
|
32
21
|
def on_tag_close(element)
|
33
22
|
render_if_needed(element)
|
34
23
|
apply_tag_close_styles(element)
|
35
|
-
context.
|
36
|
-
context.pop
|
24
|
+
context.remove_last
|
37
25
|
end
|
38
26
|
|
39
27
|
# On tag open callback
|
40
28
|
#
|
41
29
|
# @param tag_name [String] the tag name of the opening element
|
42
30
|
# @param attributes [Hash] an hash of the element attributes
|
31
|
+
# @param element_styles [String] document styles to apply to the element
|
43
32
|
#
|
44
33
|
# @return [Tag] the opening element wrapper
|
45
|
-
def on_tag_open(tag_name, attributes)
|
34
|
+
def on_tag_open(tag_name, attributes:, element_styles: '')
|
46
35
|
tag_class = Tag.class_for(tag_name)
|
47
36
|
return unless tag_class
|
48
37
|
|
49
|
-
|
50
|
-
|
38
|
+
options = { width: pdf.page_width, height: pdf.page_height }
|
39
|
+
tag_class.new(tag_name, attributes: attributes, options: options).tap do |element|
|
40
|
+
setup_element(element, element_styles: element_styles)
|
51
41
|
end
|
52
42
|
end
|
53
43
|
|
@@ -59,9 +49,7 @@ module PrawnHtml
|
|
59
49
|
def on_text_node(content)
|
60
50
|
return if content.match?(/\A\s*\Z/)
|
61
51
|
|
62
|
-
|
63
|
-
text += content.gsub(/\A\s*\n\s*|\s*\n\s*\Z/, '').delete("\n").squeeze(' ')
|
64
|
-
buffer << context.text_node_styles.merge(text: text)
|
52
|
+
buffer << context.merged_styles.merge(text: prepare_text(content))
|
65
53
|
context.last_text_node = true
|
66
54
|
nil
|
67
55
|
end
|
@@ -72,19 +60,20 @@ module PrawnHtml
|
|
72
60
|
|
73
61
|
output_content(buffer.dup, context.block_styles)
|
74
62
|
buffer.clear
|
75
|
-
|
63
|
+
@last_margin = 0
|
76
64
|
end
|
77
65
|
|
78
66
|
alias_method :flush, :render
|
79
67
|
|
80
68
|
private
|
81
69
|
|
82
|
-
attr_reader :buffer, :context, :
|
70
|
+
attr_reader :buffer, :context, :last_margin, :pdf
|
83
71
|
|
84
|
-
def setup_element(element)
|
72
|
+
def setup_element(element, element_styles:)
|
85
73
|
add_space_if_needed unless render_if_needed(element)
|
86
|
-
apply_tag_open_styles(element)
|
87
74
|
context.add(element)
|
75
|
+
element.process_styles(element_styles: element_styles)
|
76
|
+
apply_tag_open_styles(element)
|
88
77
|
element.custom_render(pdf, context) if element.respond_to?(:custom_render)
|
89
78
|
end
|
90
79
|
|
@@ -102,41 +91,63 @@ module PrawnHtml
|
|
102
91
|
|
103
92
|
def apply_tag_close_styles(element)
|
104
93
|
tag_styles = element.tag_close_styles
|
105
|
-
|
106
|
-
|
107
|
-
pdf.
|
94
|
+
@last_margin = tag_styles[:margin_bottom].to_f
|
95
|
+
pdf.advance_cursor(last_margin + tag_styles[:padding_bottom].to_f)
|
96
|
+
pdf.start_new_page if tag_styles[:break_after]
|
108
97
|
end
|
109
98
|
|
110
99
|
def apply_tag_open_styles(element)
|
111
100
|
tag_styles = element.tag_open_styles
|
112
|
-
move_down = (tag_styles[:margin_top].to_f -
|
113
|
-
pdf.
|
101
|
+
move_down = (tag_styles[:margin_top].to_f - last_margin) + tag_styles[:padding_top].to_f
|
102
|
+
pdf.advance_cursor(move_down) if move_down > 0
|
103
|
+
pdf.start_new_page if tag_styles[:break_before]
|
104
|
+
end
|
105
|
+
|
106
|
+
def prepare_text(content)
|
107
|
+
white_space_pre = context.last && context.last.styles[:white_space] == :pre
|
108
|
+
text = ::Oga::HTML::Entities.decode(context.before_content)
|
109
|
+
text += white_space_pre ? content : content.gsub(/\A\s*\n\s*|\s*\n\s*\Z/, '').delete("\n").squeeze(' ')
|
110
|
+
text
|
114
111
|
end
|
115
112
|
|
116
113
|
def output_content(buffer, block_styles)
|
117
|
-
buffer
|
114
|
+
apply_callbacks(buffer)
|
118
115
|
left_indent = block_styles[:margin_left].to_f + block_styles[:padding_left].to_f
|
119
|
-
options = block_styles.slice(:align, :leading, :mode, :padding_left)
|
120
|
-
options[:
|
121
|
-
|
116
|
+
options = block_styles.slice(:align, :indent_paragraphs, :leading, :mode, :padding_left)
|
117
|
+
options[:leading] = adjust_leading(buffer, options[:leading])
|
118
|
+
pdf.puts(buffer, options, bounding_box: bounds(buffer, options, block_styles), left_indent: left_indent)
|
122
119
|
end
|
123
120
|
|
124
|
-
def
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
pdf.formatted_text(buffer, options)
|
121
|
+
def apply_callbacks(buffer)
|
122
|
+
buffer.select { |item| item[:callback] }.each do |item|
|
123
|
+
callback, arg = item[:callback]
|
124
|
+
callback_class = Tag::CALLBACKS[callback]
|
125
|
+
item[:callback] = callback_class.new(pdf, arg)
|
130
126
|
end
|
131
|
-
pdf.move_cursor_to(current_y)
|
132
127
|
end
|
133
128
|
|
134
|
-
def
|
129
|
+
def adjust_leading(buffer, leading)
|
130
|
+
return leading if leading
|
131
|
+
|
132
|
+
(buffer.map { |item| item[:size] || Context::DEF_FONT_SIZE }.max * 0.055).round(4)
|
133
|
+
end
|
134
|
+
|
135
|
+
def bounds(buffer, options, block_styles)
|
135
136
|
return unless block_styles[:position] == :absolute
|
136
137
|
|
137
|
-
|
138
|
-
|
139
|
-
|
138
|
+
x = if block_styles.include?(:right)
|
139
|
+
x1 = pdf.calc_buffer_width(buffer) + block_styles[:right]
|
140
|
+
x1 < pdf.page_width ? (pdf.page_width - x1) : 0
|
141
|
+
else
|
142
|
+
block_styles[:left] || 0
|
143
|
+
end
|
144
|
+
y = if block_styles.include?(:bottom)
|
145
|
+
pdf.calc_buffer_height(buffer, options) + block_styles[:bottom]
|
146
|
+
else
|
147
|
+
pdf.page_height - (block_styles[:top] || 0)
|
148
|
+
end
|
149
|
+
|
150
|
+
[[x, y], { width: pdf.page_width - x }]
|
140
151
|
end
|
141
152
|
end
|
142
153
|
end
|