prawn 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +6 -10
- data/Rakefile +4 -13
- data/data/encodings/win_ansi.txt +29 -0
- data/data/images/fractal.jpg +0 -0
- data/data/images/letterhead.jpg +0 -0
- data/examples/bounding_box/bounding_boxes.rb +44 -0
- data/examples/bounding_box/lazy_bounding_boxes.rb +28 -0
- data/examples/bounding_box/padded_box.rb +24 -0
- data/examples/{russian_boxes.rb → bounding_box/russian_boxes.rb} +9 -6
- data/examples/general/background.rb +20 -0
- data/examples/{canvas.rb → general/canvas.rb} +6 -2
- data/examples/general/measurement_units.rb +52 -0
- data/examples/{multi_page_layout.rb → general/multi_page_layout.rb} +6 -3
- data/examples/{page_geometry.rb → general/page_geometry.rb} +6 -2
- data/examples/{image.rb → graphics/basic_images.rb} +8 -4
- data/examples/graphics/cmyk.rb +13 -0
- data/examples/graphics/curves.rb +12 -0
- data/examples/{hexagon.rb → graphics/hexagon.rb} +5 -5
- data/examples/graphics/image_fit.rb +16 -0
- data/examples/graphics/image_flow.rb +38 -0
- data/examples/graphics/image_position.rb +18 -0
- data/examples/{line.rb → graphics/line.rb} +4 -2
- data/examples/{png_types.rb → graphics/png_types.rb} +4 -4
- data/examples/{polygons.rb → graphics/polygons.rb} +5 -4
- data/examples/graphics/remote_images.rb +12 -0
- data/examples/{ruport_helpers.rb → graphics/ruport_style_helpers.rb} +8 -5
- data/examples/graphics/stroke_bounds.rb +23 -0
- data/examples/{chinese_text_wrapping.rb → m17n/chinese_text_wrapping.rb} +7 -4
- data/examples/m17n/euro.rb +16 -0
- data/examples/m17n/sjis.rb +29 -0
- data/examples/m17n/utf8.rb +14 -0
- data/examples/m17n/win_ansi_charset.rb +55 -0
- data/examples/{addressbook.csv → table/addressbook.csv} +0 -0
- data/examples/{cell.rb → table/cell.rb} +8 -6
- data/examples/{currency.csv → table/currency.csv} +0 -0
- data/examples/{fancy_table.rb → table/fancy_table.rb} +9 -6
- data/examples/{ruport_formatter.rb → table/ruport_formatter.rb} +6 -3
- data/examples/{table.rb → table/table.rb} +6 -2
- data/examples/table/table_alignment.rb +18 -0
- data/examples/table/table_border_color.rb +17 -0
- data/examples/table/table_colspan.rb +19 -0
- data/examples/table/table_header_color.rb +19 -0
- data/examples/table/table_header_underline.rb +15 -0
- data/examples/{alignment.rb → text/alignment.rb} +5 -2
- data/examples/text/family_based_styling.rb +25 -0
- data/examples/{flowing_text_with_header_and_footer.rb → text/flowing_text_with_header_and_footer.rb} +19 -8
- data/examples/text/font_calculations.rb +91 -0
- data/examples/text/font_size.rb +34 -0
- data/examples/{kerning.rb → text/kerning.rb} +5 -1
- data/examples/text/simple_text.rb +18 -0
- data/examples/text/simple_text_ttf.rb +18 -0
- data/examples/{span.rb → text/span.rb} +5 -2
- data/examples/text/text_box.rb +26 -0
- data/examples/{text_flow.rb → text/text_flow.rb} +5 -2
- data/lib/prawn.rb +26 -20
- data/lib/prawn/compatibility.rb +5 -8
- data/lib/prawn/document.rb +29 -13
- data/lib/prawn/document/annotations.rb +63 -0
- data/lib/prawn/document/bounding_box.rb +18 -3
- data/lib/prawn/document/destinations.rb +81 -0
- data/lib/prawn/document/internals.rb +16 -2
- data/lib/prawn/document/page_geometry.rb +58 -57
- data/lib/prawn/document/span.rb +8 -0
- data/lib/prawn/document/table.rb +81 -31
- data/lib/prawn/document/text.rb +66 -21
- data/lib/prawn/document/text/box.rb +77 -0
- data/lib/prawn/encoding.rb +121 -0
- data/lib/prawn/errors.rb +4 -0
- data/lib/prawn/font.rb +70 -42
- data/lib/prawn/font/metrics.rb +64 -119
- data/lib/prawn/graphics.rb +105 -87
- data/lib/prawn/graphics/cell.rb +55 -28
- data/lib/prawn/graphics/color.rb +8 -0
- data/lib/prawn/images.rb +55 -12
- data/lib/prawn/images/jpg.rb +2 -1
- data/lib/prawn/images/png.rb +2 -1
- data/lib/prawn/literal_string.rb +14 -0
- data/lib/prawn/measurement_extensions.rb +46 -0
- data/lib/prawn/measurements.rb +71 -0
- data/lib/prawn/name_tree.rb +165 -0
- data/lib/prawn/pdf_object.rb +8 -1
- data/spec/annotations_spec.rb +90 -0
- data/spec/destinations_spec.rb +15 -0
- data/spec/document_spec.rb +39 -2
- data/spec/font_spec.rb +22 -0
- data/spec/graphics_spec.rb +99 -87
- data/spec/images_spec.rb +29 -1
- data/spec/measurement_units_spec.rb +23 -0
- data/spec/metrics_spec.rb +3 -2
- data/spec/name_tree_spec.rb +103 -0
- data/spec/pdf_object_spec.rb +15 -5
- data/spec/png_spec.rb +14 -14
- data/spec/spec_helper.rb +8 -6
- data/spec/table_spec.rb +40 -0
- data/spec/text_spec.rb +6 -4
- data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
- data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
- data/vendor/ttfunk/example.rb +5 -0
- data/vendor/ttfunk/lib/ttfunk.rb +48 -0
- data/vendor/ttfunk/lib/ttfunk/table.rb +27 -0
- data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +94 -0
- data/vendor/ttfunk/lib/ttfunk/table/directory.rb +25 -0
- data/vendor/ttfunk/lib/ttfunk/table/head.rb +25 -0
- data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +27 -0
- data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +20 -0
- data/vendor/ttfunk/lib/ttfunk/table/kern.rb +48 -0
- data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +17 -0
- data/vendor/ttfunk/lib/ttfunk/table/name.rb +52 -0
- metadata +93 -62
- data/examples/bounding_boxes.rb +0 -30
- data/examples/curves.rb +0 -10
- data/examples/family_based_styling.rb +0 -21
- data/examples/font_size.rb +0 -19
- data/examples/image2.rb +0 -13
- data/examples/image_flow.rb +0 -29
- data/examples/lazy_bounding_boxes.rb +0 -19
- data/examples/remote_images.rb +0 -7
- data/examples/simple_text.rb +0 -15
- data/examples/simple_text_ttf.rb +0 -16
- data/examples/sjis.rb +0 -21
- data/examples/utf8.rb +0 -12
- data/vendor/font_ttf/ttf.rb +0 -20
- data/vendor/font_ttf/ttf/datatypes.rb +0 -189
- data/vendor/font_ttf/ttf/encodings.rb +0 -140
- data/vendor/font_ttf/ttf/exceptions.rb +0 -28
- data/vendor/font_ttf/ttf/file.rb +0 -290
- data/vendor/font_ttf/ttf/fontchunk.rb +0 -77
- data/vendor/font_ttf/ttf/table/cmap.rb +0 -408
- data/vendor/font_ttf/ttf/table/cvt.rb +0 -49
- data/vendor/font_ttf/ttf/table/fpgm.rb +0 -48
- data/vendor/font_ttf/ttf/table/gasp.rb +0 -88
- data/vendor/font_ttf/ttf/table/glyf.rb +0 -452
- data/vendor/font_ttf/ttf/table/head.rb +0 -86
- data/vendor/font_ttf/ttf/table/hhea.rb +0 -96
- data/vendor/font_ttf/ttf/table/hmtx.rb +0 -98
- data/vendor/font_ttf/ttf/table/kern.rb +0 -186
- data/vendor/font_ttf/ttf/table/loca.rb +0 -75
- data/vendor/font_ttf/ttf/table/maxp.rb +0 -81
- data/vendor/font_ttf/ttf/table/name.rb +0 -222
- data/vendor/font_ttf/ttf/table/os2.rb +0 -172
- data/vendor/font_ttf/ttf/table/post.rb +0 -120
- data/vendor/font_ttf/ttf/table/prep.rb +0 -27
- data/vendor/font_ttf/ttf/table/vhea.rb +0 -45
- data/vendor/font_ttf/ttf/table/vmtx.rb +0 -36
data/lib/prawn/document/text.rb
CHANGED
@@ -6,10 +6,12 @@
|
|
6
6
|
#
|
7
7
|
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
8
|
require "zlib"
|
9
|
+
require "prawn/document/text/box"
|
9
10
|
|
10
11
|
module Prawn
|
11
12
|
class Document
|
12
13
|
module Text
|
14
|
+
|
13
15
|
# Draws text on the page. If a point is specified via the +:at+
|
14
16
|
# option the text will begin exactly at that point, and the string is
|
15
17
|
# assumed to be pre-formatted to properly fit the page.
|
@@ -37,15 +39,45 @@ module Prawn
|
|
37
39
|
# text will be kerned by default. You can disable this feature by passing
|
38
40
|
# <tt>:kerning => false</tt>.
|
39
41
|
#
|
40
|
-
# ===
|
42
|
+
# === Text Positioning Details:
|
43
|
+
#
|
44
|
+
# When using the :at parameter, Prawn will position your text by its
|
45
|
+
# baseline, and flow along a single line.
|
46
|
+
#
|
47
|
+
# When using automatic text flow, Prawn currently does a bunch of nasty
|
48
|
+
# hacks to get things to position nicely in bounding boxes, table cells,
|
49
|
+
# etc.
|
50
|
+
#
|
51
|
+
# For AFM fonts, the first line of text is positioned font.height below
|
52
|
+
# the baseline.
|
53
|
+
#
|
54
|
+
# For TTF fonts, the first line is possitioned font.ascender below the
|
55
|
+
# baseline.
|
56
|
+
#
|
57
|
+
# The issue here is that there are complex issues with determining the
|
58
|
+
# size of the glyphs above and below the baseline in TTF that we haven't
|
59
|
+
# figured out yet, and that AFM and TTF appear to handle things very
|
60
|
+
# differently.
|
61
|
+
#
|
62
|
+
# The moral of the story is that if you want reliable font positioning
|
63
|
+
# for your advanced needs, use :at, otherwise, just let Prawn do its
|
64
|
+
# positioning magic for you, or investigate and help us get rid of this
|
65
|
+
# ugly issue.
|
66
|
+
#
|
67
|
+
# == Rotation
|
68
|
+
#
|
69
|
+
# Text can be rotated before it is placed on the canvas by specifying the
|
70
|
+
# :rotate option. Rotation occurs counter-clockwise.
|
71
|
+
#
|
72
|
+
# == Encoding
|
41
73
|
#
|
42
74
|
# Note that strings passed to this function should be encoded as UTF-8.
|
43
75
|
# If you get unexpected characters appearing in your rendered document,
|
44
76
|
# check this.
|
45
77
|
#
|
46
78
|
# If the current font is a built-in one, although the string must be
|
47
|
-
# encoded as UTF-8, only characters that are available in
|
48
|
-
# are allowed
|
79
|
+
# encoded as UTF-8, only characters that are available in WinAnsi
|
80
|
+
# are allowed.
|
49
81
|
#
|
50
82
|
# If an empty box is rendered to your PDF instead of the character you
|
51
83
|
# wanted it usually means the current font doesn't include that character.
|
@@ -67,6 +99,9 @@ module Prawn
|
|
67
99
|
x,y = translate(options[:at])
|
68
100
|
font.size(options[:size]) { add_text_content(text,x,y,options) }
|
69
101
|
else
|
102
|
+
if options[:rotate]
|
103
|
+
raise ArgumentError, "Rotated text may only be used with :at"
|
104
|
+
end
|
70
105
|
wrapped_text(text,options)
|
71
106
|
end
|
72
107
|
|
@@ -86,7 +121,7 @@ module Prawn
|
|
86
121
|
|
87
122
|
def process_text_options(options)
|
88
123
|
Prawn.verify_options [:style, :kerning, :size, :at, :wrap,
|
89
|
-
:spacing, :align ], options
|
124
|
+
:spacing, :align, :rotate ], options
|
90
125
|
|
91
126
|
if options[:style]
|
92
127
|
raise "Bad font family" unless font.family
|
@@ -115,10 +150,14 @@ module Prawn
|
|
115
150
|
text = font.metrics.naive_wrap(text, bounds.right, font.size,
|
116
151
|
:kerning => options[:kerning], :mode => options[:wrap])
|
117
152
|
|
118
|
-
lines = text.lines
|
153
|
+
lines = text.lines.to_a
|
119
154
|
|
120
|
-
lines.
|
121
|
-
|
155
|
+
lines.each_with_index do |e,i|
|
156
|
+
if font.metrics.type0?
|
157
|
+
move_text_position(font.ascender)
|
158
|
+
else
|
159
|
+
move_text_position(font.height)
|
160
|
+
end
|
122
161
|
|
123
162
|
line_width = font.width_of(e)
|
124
163
|
case(options[:align])
|
@@ -132,27 +171,33 @@ module Prawn
|
|
132
171
|
end
|
133
172
|
|
134
173
|
add_text_content(e,x,y,options)
|
135
|
-
|
174
|
+
|
175
|
+
if font.metrics.type0? && i < lines.length - 1
|
176
|
+
move_text_position(font.height - font.ascender)
|
177
|
+
end
|
178
|
+
|
179
|
+
move_text_position(options[:spacing]) if options[:spacing]
|
136
180
|
end
|
137
181
|
end
|
138
182
|
end
|
139
|
-
|
183
|
+
|
140
184
|
def add_text_content(text, x, y, options)
|
141
185
|
text = font.metrics.convert_text(text,options)
|
142
186
|
|
143
|
-
add_content
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
187
|
+
add_content "\nBT"
|
188
|
+
add_content "/#{font.identifier} #{font.size} Tf"
|
189
|
+
if options[:rotate]
|
190
|
+
rad = options[:rotate].to_i * Math::PI / 180
|
191
|
+
arr = [ Math.cos(rad), Math.sin(rad), -Math.sin(rad), Math.cos(rad), x, y ]
|
192
|
+
add_content "%.3f %.3f %.3f %.3f %.3f %.3f Tm" % arr
|
193
|
+
else
|
194
|
+
add_content "#{x} #{y} Td"
|
195
|
+
end
|
196
|
+
rad = 1.570796
|
149
197
|
add_content Prawn::PdfObject(text, true) <<
|
150
|
-
" #{options[:kerning] ? 'TJ' : 'Tj'}
|
151
|
-
|
152
|
-
|
153
|
-
ET
|
154
|
-
}
|
155
|
-
end
|
198
|
+
" #{options[:kerning] ? 'TJ' : 'Tj'}"
|
199
|
+
add_content "ET\n"
|
200
|
+
end
|
156
201
|
end
|
157
202
|
end
|
158
203
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# text/box.rb : Implements simple text boxes
|
4
|
+
#
|
5
|
+
# Copyright September 2008, Gregory Brown. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
+
|
9
|
+
module Prawn
|
10
|
+
class Document
|
11
|
+
|
12
|
+
# Defines an invisible rectangle which you can flow text in. When the
|
13
|
+
# text overflows the box, you can either display :ellipses, :truncate
|
14
|
+
# the text, or allow it to :overflow the bottom boundary.
|
15
|
+
#
|
16
|
+
# text_box "Oh hai text box. " * 200,
|
17
|
+
# :width => 300, :height => font.height * 5,
|
18
|
+
# :overflow => :ellipses,
|
19
|
+
# :at => [100,bounds.top]
|
20
|
+
#
|
21
|
+
def text_box(text,options)
|
22
|
+
Text::Box.new(text, options.merge(:for => self)).render
|
23
|
+
end
|
24
|
+
|
25
|
+
module Text
|
26
|
+
class Box #:nodoc:
|
27
|
+
def initialize(text,options={})
|
28
|
+
@document = options[:for]
|
29
|
+
@text = text
|
30
|
+
@at = options[:at] || [0, @document.y - @document.bounds.absolute_bottom]
|
31
|
+
@width = options[:width] || @document.bounds.width
|
32
|
+
@height = options[:height]
|
33
|
+
@overflow = options[:overflow] || :truncate
|
34
|
+
end
|
35
|
+
|
36
|
+
def render
|
37
|
+
x,y = @at
|
38
|
+
|
39
|
+
unless @overflow == :expand
|
40
|
+
original_y = @document.y
|
41
|
+
fit_text_to_box
|
42
|
+
end
|
43
|
+
|
44
|
+
@document.bounding_box([x,@document.bounds.top],
|
45
|
+
:width => @width, :height => @document.bounds.height) do
|
46
|
+
@document.y = @document.bounds.absolute_bottom + y
|
47
|
+
@document.text @text
|
48
|
+
end
|
49
|
+
|
50
|
+
unless @overflow == :expand
|
51
|
+
@document.y = y + @document.bounds.absolute_bottom - @height
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def fit_text_to_box
|
58
|
+
text = @document.font.metrics.naive_wrap(@text,
|
59
|
+
@width, @document.font.size)
|
60
|
+
|
61
|
+
max_lines = (@height / @document.font.height).floor
|
62
|
+
|
63
|
+
lines = text.lines.to_a
|
64
|
+
|
65
|
+
unless lines.length < max_lines
|
66
|
+
@text = lines[0...max_lines].join
|
67
|
+
case(@overflow)
|
68
|
+
when :ellipses
|
69
|
+
@text[-3..-1] = "..."
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# Copyright September 2008, Gregory Brown, James Healy All Rights Reserved.
|
4
|
+
#
|
5
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
6
|
+
#
|
7
|
+
module Prawn
|
8
|
+
module Encoding
|
9
|
+
# Map between unicode and WinAnsiEnoding
|
10
|
+
#
|
11
|
+
class WinAnsi #:nodoc:
|
12
|
+
CHARACTERS = %w[
|
13
|
+
.notdef .notdef .notdef .notdef
|
14
|
+
.notdef .notdef .notdef .notdef
|
15
|
+
.notdef .notdef .notdef .notdef
|
16
|
+
.notdef .notdef .notdef .notdef
|
17
|
+
.notdef .notdef .notdef .notdef
|
18
|
+
.notdef .notdef .notdef .notdef
|
19
|
+
.notdef .notdef .notdef .notdef
|
20
|
+
.notdef .notdef .notdef .notdef
|
21
|
+
|
22
|
+
space exclam quotedbl numbersign
|
23
|
+
dollar percent ampersand quotesingle
|
24
|
+
parenleft parenright asterisk plus
|
25
|
+
comma hyphen period slash
|
26
|
+
zero one two three
|
27
|
+
four five six seven
|
28
|
+
eight nine colon semicolon
|
29
|
+
less equal greater question
|
30
|
+
|
31
|
+
at A B C
|
32
|
+
D E F G
|
33
|
+
H I J K
|
34
|
+
L M N O
|
35
|
+
P Q R S
|
36
|
+
T U V W
|
37
|
+
X Y Z bracketleft
|
38
|
+
backslash bracketright asciicircum underscore
|
39
|
+
|
40
|
+
grave a b c
|
41
|
+
d e f g
|
42
|
+
h i j k
|
43
|
+
l m n o
|
44
|
+
p q r s
|
45
|
+
t u v w
|
46
|
+
x y z braceleft
|
47
|
+
bar braceright asciitilde .notdef
|
48
|
+
|
49
|
+
Euro .notdef quotesinglbase florin
|
50
|
+
quotedblbase ellipsis dagger daggerdbl
|
51
|
+
circumflex perthousand Scaron guilsinglleft
|
52
|
+
OE .notdef Zcaron .notdef
|
53
|
+
.notdef quoteleft quoteright quotedblleft
|
54
|
+
quotedblright bullet endash emdash
|
55
|
+
tilde trademark scaron guilsinglright
|
56
|
+
oe .notdef zcaron ydieresis
|
57
|
+
|
58
|
+
space exclamdown cent sterling
|
59
|
+
currency yen brokenbar section
|
60
|
+
dieresis copyright ordfeminine guillemotleft
|
61
|
+
logicalnot hyphen registered macron
|
62
|
+
degree plusminus twosuperior threesuperior
|
63
|
+
acute mu paragraph periodcentered
|
64
|
+
cedilla onesuperior ordmasculine guillemotright
|
65
|
+
onequarter onehalf threequarters questiondown
|
66
|
+
|
67
|
+
Agrave Aacute Acircumflex Atilde
|
68
|
+
Adieresis Aring AE Ccedilla
|
69
|
+
Egrave Eacute Ecircumflex Edieresis
|
70
|
+
Igrave Iacute Icircumflex Idieresis
|
71
|
+
Eth Ntilde Ograve Oacute
|
72
|
+
Ocircumflex Otilde Odieresis multiply
|
73
|
+
Oslash Ugrave Uacute Ucircumflex
|
74
|
+
Udieresis Yacute Thorn germandbls
|
75
|
+
|
76
|
+
agrave aacute acircumflex atilde
|
77
|
+
adieresis aring ae ccedilla
|
78
|
+
egrave eacute ecircumflex edieresis
|
79
|
+
igrave iacute icircumflex idieresis
|
80
|
+
eth ntilde ograve oacute
|
81
|
+
ocircumflex otilde odieresis divide
|
82
|
+
oslash ugrave uacute ucircumflex
|
83
|
+
udieresis yacute thorn ydieresis
|
84
|
+
]
|
85
|
+
|
86
|
+
def initialize
|
87
|
+
@mapping_file = "#{Prawn::BASEDIR}/data/encodings/win_ansi.txt"
|
88
|
+
load_mapping if self.class.mapping.empty?
|
89
|
+
end
|
90
|
+
|
91
|
+
# Converts a Unicode codepoint into a valid WinAnsi single byte character.
|
92
|
+
#
|
93
|
+
# If there is no WinAnsi equivlant for a character, a _ will be substituted.
|
94
|
+
#
|
95
|
+
def [](codepoint)
|
96
|
+
# unicode codepoints < 255 map directly to the single byte value in WinAnsi
|
97
|
+
return codepoint if codepoint <= 255
|
98
|
+
|
99
|
+
# There are a handful of codepoints > 255 that have equivilants in WinAnsi.
|
100
|
+
# Replace anything else with an underscore
|
101
|
+
self.class.mapping[codepoint] || 95
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.mapping
|
105
|
+
@mapping ||= {}
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def load_mapping
|
111
|
+
RUBY_VERSION >= "1.9" ? mode = "r:BINARY" : mode = "r"
|
112
|
+
File.open(@mapping_file, mode) do |f|
|
113
|
+
f.each do |l|
|
114
|
+
m, single_byte, unicode = *l.match(/([0-9A-Za-z]+);([0-9A-F]{4})/)
|
115
|
+
self.class.mapping["0x#{unicode}".hex] = "0x#{single_byte}".hex if single_byte
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/lib/prawn/errors.rb
CHANGED
data/lib/prawn/font.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
2
|
+
#
|
3
|
+
# font.rb : The Prawn font class
|
4
|
+
#
|
5
|
+
# Copyright May 2008, Gregory Brown / James Healy. All Rights Reserved.
|
6
|
+
#
|
7
|
+
# This is free software. Please see the LICENSE and COPYING files for details.
|
3
8
|
require "prawn/font/wrapping"
|
4
9
|
require "prawn/font/metrics"
|
5
10
|
require "prawn/font/cmap"
|
@@ -7,7 +12,8 @@ require "prawn/font/cmap"
|
|
7
12
|
module Prawn
|
8
13
|
|
9
14
|
class Document
|
10
|
-
#
|
15
|
+
# Without arguments, this returns the currently selected font. Otherwise,
|
16
|
+
# it sets the current font.
|
11
17
|
#
|
12
18
|
# The single parameter must be a string. It can be one of the 14 built-in
|
13
19
|
# fonts supported by PDF, or the location of a TTF file. The BUILT_INS
|
@@ -22,19 +28,36 @@ module Prawn
|
|
22
28
|
# more portable.
|
23
29
|
#
|
24
30
|
def font(name=nil, options={})
|
25
|
-
if name
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
return @font || font("Helvetica") if name.nil?
|
32
|
+
|
33
|
+
if block_given?
|
34
|
+
original_name = font.name
|
35
|
+
original_size = font.size
|
36
|
+
end
|
37
|
+
|
38
|
+
@font = find_font(name, options)
|
39
|
+
@font.add_to_current_page
|
40
|
+
|
41
|
+
@font.size = options[:size] if options[:size]
|
42
|
+
|
43
|
+
if block_given?
|
44
|
+
yield
|
45
|
+
font(original_name, :size => original_size)
|
46
|
+
else
|
47
|
+
@font
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Looks up the given font name. Once a font has been found by that name,
|
52
|
+
# it will be cached to subsequent lookups for that font will return the
|
53
|
+
# same object.
|
54
|
+
#
|
55
|
+
def find_font(name, options={}) #:nodoc:
|
56
|
+
if font_families.key?(name)
|
57
|
+
family, name = name, font_families[name][options[:style] || :normal]
|
58
|
+
end
|
59
|
+
|
60
|
+
font_registry[name] ||= Font.new(name, options.merge(:for => self, :family => family))
|
38
61
|
end
|
39
62
|
|
40
63
|
# Hash of Font objects keyed by names
|
@@ -94,10 +117,6 @@ module Prawn
|
|
94
117
|
|
95
118
|
DEFAULT_SIZE = 12
|
96
119
|
|
97
|
-
def self.register(name,options={}) #:nodoc:
|
98
|
-
options[:for].font_registry[name] = Font.new(name,options)
|
99
|
-
end
|
100
|
-
|
101
120
|
# The font metrics object
|
102
121
|
attr_reader :metrics
|
103
122
|
|
@@ -125,16 +144,13 @@ module Prawn
|
|
125
144
|
@document.proc_set :PDF, :Text
|
126
145
|
@size = DEFAULT_SIZE
|
127
146
|
@identifier = :"F#{@document.font_registry.size + 1}"
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
add_to_current_page
|
137
|
-
end
|
147
|
+
|
148
|
+
@reference = nil
|
149
|
+
end
|
150
|
+
|
151
|
+
def inspect
|
152
|
+
"Prawn::Font< #{name}: #{size} >"
|
153
|
+
end
|
138
154
|
|
139
155
|
# Sets the default font size for use within a block. Individual overrides
|
140
156
|
# can be used as desired. The previous font size will be restored after the
|
@@ -166,6 +182,9 @@ module Prawn
|
|
166
182
|
|
167
183
|
# Gets width of string in PDF points at current font size
|
168
184
|
#
|
185
|
+
# If using an AFM, string *must* be encoded as WinAnsi
|
186
|
+
# (Use normalize_encoding to convert)
|
187
|
+
#
|
169
188
|
def width_of(string)
|
170
189
|
@metrics.string_width(string,@size)
|
171
190
|
end
|
@@ -173,6 +192,9 @@ module Prawn
|
|
173
192
|
# Gets height of text in PDF points at current font size.
|
174
193
|
# Text +:line_width+ must be specified in PDF points.
|
175
194
|
#
|
195
|
+
# If using an AFM, string *must* be encoded as WinAnsi
|
196
|
+
# (Use normalize_encoding to convert)
|
197
|
+
#
|
176
198
|
def height_of(text,options={})
|
177
199
|
@metrics.string_height( text, :font_size => @size,
|
178
200
|
:line_width => options[:line_width] )
|
@@ -195,6 +217,10 @@ module Prawn
|
|
195
217
|
def descender
|
196
218
|
@metrics.descender / 1000.0 * @size
|
197
219
|
end
|
220
|
+
|
221
|
+
def line_gap
|
222
|
+
@metrics.line_gap / 1000.0 * @size
|
223
|
+
end
|
198
224
|
|
199
225
|
def normalize_encoding(text) # :nodoc:
|
200
226
|
# check the string is encoded sanely
|
@@ -208,23 +234,25 @@ module Prawn
|
|
208
234
|
end
|
209
235
|
|
210
236
|
def add_to_current_page #:nodoc:
|
237
|
+
embed! unless @reference
|
211
238
|
@document.page_fonts.merge!(@identifier => @reference)
|
212
239
|
end
|
213
240
|
|
214
241
|
private
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
242
|
+
|
243
|
+
def embed!
|
244
|
+
case(name)
|
245
|
+
when /\.ttf$/i
|
246
|
+
embed_ttf(name)
|
220
247
|
else
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
248
|
+
register_builtin(name)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# built-in fonts only work with winansi encoding, so translate the string
|
253
|
+
def normalize_builtin_encoding(text)
|
254
|
+
enc = Prawn::Encoding::WinAnsi.new
|
255
|
+
text.replace text.unpack("U*").collect { |i| enc[i] }.pack("C*")
|
228
256
|
end
|
229
257
|
|
230
258
|
def normalize_ttf_encoding(text)
|
@@ -275,7 +303,7 @@ module Prawn
|
|
275
303
|
|
276
304
|
raise "Can't detect a postscript name for #{file}" if basename.nil?
|
277
305
|
|
278
|
-
@encodings = @metrics.
|
306
|
+
@encodings = @metrics.cmap
|
279
307
|
|
280
308
|
if @encodings.nil?
|
281
309
|
raise "#{file} missing the required encoding table"
|