Skip to content

Commit ed86a97

Browse files
committed
refactor text_box (WIP)
1 parent 438efd8 commit ed86a97

1 file changed

Lines changed: 60 additions & 105 deletions

File tree

  • lib/thinreports/generator/pdf/document/graphics

lib/thinreports/generator/pdf/document/graphics/text.rb

Lines changed: 60 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,53 @@ module Graphics
2525
def text_box(content, x, y, w, h, attrs = {})
2626
w, h = s2f(w, h)
2727

28-
box_attrs = text_box_attrs(
29-
x, y, w, h,
30-
single: attrs.delete(:single),
31-
overflow: attrs[:overflow]
32-
)
33-
34-
# Do not break by word unless :word_wrap is :break_word
35-
content = text_without_line_wrap(content) if attrs[:word_wrap] == :none
36-
37-
with_text_styles(attrs) do |built_attrs, font_styles|
38-
pdf.formatted_text_box(
39-
[{ text: content, styles: font_styles }],
40-
built_attrs.merge(box_attrs)
41-
)
28+
return if attrs[:color] == 'none'
29+
30+
# Building parameters for box
31+
box_params = {}.tap do |params|
32+
params[:at] = pos(x, y)
33+
params[:width] = w
34+
35+
[
36+
:align,
37+
:valign,
38+
:overflow
39+
].each { |param_key| params[param_key] = attrs[param_key] }
40+
41+
if attrs[:single]
42+
params[:single_line] = attrs[:overflow] != :expand
43+
else
44+
params[:height] = h
45+
end
46+
47+
if attrs[:line_height]
48+
params[:leading] = text_line_leading(attrs[:line_height], name: attrs[:font], size: attrs[:size])
49+
end
50+
51+
if attrs[:letter_spacing]
52+
params[:character_spacing] = attrs[:letter_spacing]
53+
end
4254
end
55+
56+
# Building parameters for text
57+
text_params = {}.tap do |params|
58+
params[:text] = attrs[:word_wrap] == :none ? text_without_line_wrap(content) : content
59+
params[:styles] = attrs[:styles] || []
60+
params[:size] = attrs[:size]
61+
params[:font] = attrs[:font]
62+
params[:color] = parse_color(attrs[:color])
63+
end
64+
65+
if need_bold_style_emulation?(text_params[:font], text_params[:styles])
66+
box_params[:mode] = :fill_stroke
67+
68+
emulate_bold_style(text_params[:color], text_params[:size]) do
69+
pdf.formatted_text_box([text_params], box_params)
70+
end
71+
else
72+
pdf.formatted_text_box([text_params], box_params)
73+
end
74+
4375
rescue Prawn::Errors::CannotFit
4476
# Nothing to do.
4577
#
@@ -56,64 +88,6 @@ def text(content, x, y, w, h, attrs = {})
5688

5789
private
5890

59-
# @param x (see #text_box)
60-
# @param y (see #text_box)
61-
# @param w (see #text_box)
62-
# @param h (see #text_box)
63-
# @param [Hash] states
64-
# @option states [Boolean] :single
65-
# @option states [Symbold] :overflow
66-
# @return [Hash]
67-
def text_box_attrs(x, y, w, h, states = {})
68-
attrs = {
69-
at: pos(x, y),
70-
width: s2f(w)
71-
}
72-
if states[:single]
73-
states[:overflow] != :expand ? attrs.merge(single_line: true) : attrs
74-
else
75-
attrs.merge(height: s2f(h))
76-
end
77-
end
78-
79-
# @param attrs (see #text)
80-
# @yield [built_attrs, font_styles]
81-
# @yieldparam [Hash] built_attrs The finalized attributes.
82-
# @yieldparam [Array] font_styles The finalized styles.
83-
def with_text_styles(attrs, &block)
84-
# When no color is given, do not draw.
85-
return unless attrs.key?(:color) && attrs[:color] != 'none'
86-
87-
save_graphics_state
88-
89-
fontinfo = {
90-
name: attrs.delete(:font).to_s,
91-
color: parse_color(attrs.delete(:color)),
92-
size: s2f(attrs.delete(:size))
93-
}
94-
95-
# Add the specified value to :leading option.
96-
line_height = attrs.delete(:line_height)
97-
if line_height
98-
attrs[:leading] = text_line_leading(
99-
s2f(line_height),
100-
name: fontinfo[:name],
101-
size: fontinfo[:size]
102-
)
103-
end
104-
105-
# Set the :character_spacing option.
106-
spacing = attrs.delete(:letter_spacing)
107-
attrs[:character_spacing] = s2f(spacing) if spacing
108-
109-
# Or... with_font_styles(attrs, fontinfo, &block)
110-
with_font_styles(attrs, fontinfo) do |modified_attrs, styles|
111-
block.call(modified_attrs, styles)
112-
end
113-
114-
restore_graphics_state
115-
end
116-
11791
# @param [Numeric] line_height
11892
# @param [Hash] font
11993
# @option font [String] :name Name of font.
@@ -129,43 +103,24 @@ def text_without_line_wrap(content)
129103
content.gsub(/ /, Prawn::Text::NBSP)
130104
end
131105

132-
# @param [Hash] attrs
133-
# @param [Hash] font
134-
# @option font [String] :color
135-
# @option font [Numeric] :size
136-
# @option font [String] :name
137-
# @yield [attributes, styles]
138-
# @yieldparam [Hash] modified_attrs
139-
# @yieldparam [Array] styles
140-
def with_font_styles(attrs, font, &block)
141-
# Building font styles.
142-
styles = attrs.delete(:styles)
143-
144-
if styles
145-
manual, styles = styles.partition do |style|
146-
%i[bold italic].include?(style) && !font_has_style?(font[:name], style)
147-
end
148-
end
106+
# @param [String] font_family
107+
# @param [Array<Symbol>] font_styles
108+
# @return [Boolean]
109+
def need_bold_style_emulation?(font_family, font_styles)
110+
font_styles.include?(:bold) && !font_has_style?(font_family, :bold)
111+
end
149112

150-
# Emulate bold style.
151-
if manual && manual.include?(:bold)
152-
pdf.stroke_color(font[:color])
153-
pdf.line_width(font[:size] * 0.025)
113+
# @param [String] font_color
114+
# @param [Integer, Float] font_size
115+
def emulate_bold_style(font_color, font_size, &block)
116+
save_graphics_state
154117

155-
# Change rendering mode to :fill_stroke.
156-
attrs[:mode] = :fill_stroke
157-
end
118+
pdf.stroke_color(font_color)
119+
pdf.line_width(font_size * 0.025)
158120

159-
# Emulate italic style.
160-
if manual && manual.include?(:italic)
161-
# FIXME
162-
# pdf.transformation_matrix(1, 0, 0.26, 1, 0, 0)
163-
end
121+
yield
164122

165-
pdf.font(font[:name], size: font[:size]) do
166-
pdf.fill_color(font[:color])
167-
block.call(attrs, styles || [])
168-
end
123+
restore_graphics_state
169124
end
170125
end
171126
end

0 commit comments

Comments
 (0)