forked from prawnpdf/prawn
/
text.rb
177 lines (151 loc) · 5.27 KB
/
text.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# encoding: utf-8
# prawn/core/text.rb : Implements low level text helpers for Prawn
#
# Copyright January 2010, Daniel Nelson. All Rights Reserved.
#
# This is free software. Please see the LICENSE and COPYING files for details.
ruby_18 { $KCODE="U" }
module Prawn
module Core
module Text #:nodoc:
# These should be used as a base. Extensions may build on this list
#
VALID_OPTIONS = [:kerning, :size, :style]
attr_reader :skip_encoding
# Low level text placement method. All font and size alterations
# should already be set
#
def draw_text!(text, options)
x,y = map_to_absolute(options[:at])
add_text_content(text,x,y,options)
end
# Low level call to set the current font style and extract text options from
# an options hash. Should be called from within a save_font block
#
def process_text_options(options)
if options[:style]
raise "Bad font family" unless font.family
font(font.family, :style => options[:style])
end
# must compare against false to keep kerning on as default
unless options[:kerning] == false
options[:kerning] = font.has_kerning_data?
end
options[:size] ||= font_size
end
# Document wide setting of whether or not to use kerning with text
# Defaults to true
# Can be overridden using the :kerning text option
#
def default_kerning?
return true if @default_kerning.nil?
@default_kerning
end
def default_kerning(boolean)
@default_kerning = boolean
end
alias_method :default_kerning=, :default_kerning
# Document wide setting of leading
# Defaults to 0
# Can be overridden using the :leading text option
#
def default_leading?
return 0 if @default_leading.nil?
@default_leading
end
def default_leading(number)
@default_leading = number
end
alias_method :default_leading=, :default_leading
# Call with no argument to retrieve the current text rendering mode.
#
# Call with an integer and block to temporarily change the current
# text rendering mode.
#
# pdf.text_rendering_mode(1) do
# pdf.text("Outlined Text")
# end
#
# Valid modes are:
#
# * 0 - fill text (default)
# * 1 - stroke text
# * 2 - fill, then stroke text
# * 3 - invisible text
# * 4 - fill text then add to path for clipping
# * 5 - stroke text then add to path for clipping
# * 6 - fill then stroke text, then add to path for clipping
# * 7 - add text to path for clipping
#
def text_rendering_mode(mode=nil)
return @text_rendering_mode || 0 if mode.nil?
if mode.to_i < 0 || mode.to_i > 7
raise ArgumentError, "mode must be between 0 and 7"
end
original_mode = text_rendering_mode
if original_mode == mode
yield
else
@text_rendering_mode = mode
add_content "\n#{mode} Tr"
yield
add_content "\n#{original_mode} Tr"
@text_rendering_mode = original_mode
end
end
# Increases or decreases the space between characters.
# For horizontal text, a positive value will increase the space.
# For veritical text, a positive value will decrease the space.
#
def character_spacing(amount=nil)
return @character_spacing || 0 if amount.nil?
original_character_spacing = character_spacing
if original_character_spacing == amount
yield
else
@character_spacing = amount
add_content "\n%.3f Tc" % amount
yield
add_content "\n%.3f Tc" % original_character_spacing
@character_spacing = original_character_spacing
end
end
# Increases or decreases the space between words.
# For horizontal text, a positive value will increase the space.
# For veritical text, a positive value will decrease the space.
#
def word_spacing(amount=nil)
return @word_spacing || 0 if amount.nil?
original_word_spacing = word_spacing
if original_word_spacing == amount
yield
else
@word_spacing = amount
add_content "\n%.3f Tw" % amount
yield
add_content "\n%.3f Tw" % original_word_spacing
@word_spacing = original_word_spacing
end
end
private
def add_text_content(text, x, y, options)
chunks = font.encode_text(text,options)
add_content "\nBT"
if options[:rotate]
rad = options[:rotate].to_f * Math::PI / 180
arr = [ Math.cos(rad), Math.sin(rad), -Math.sin(rad), Math.cos(rad), x, y ]
add_content "%.3f %.3f %.3f %.3f %.3f %.3f Tm" % arr
else
add_content "#{x} #{y} Td"
end
chunks.each do |(subset, string)|
font.add_to_current_page(subset)
add_content "/#{font.identifier_for(subset)} #{font_size} Tf"
operation = options[:kerning] && string.is_a?(Array) ? "TJ" : "Tj"
add_content Prawn::Core::PdfObject(string, true) << " " << operation
end
add_content "ET\n"
end
end
end
end