@@ -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