prawn 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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"
|