prawn 0.4.1 → 0.5.0.1
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/lib/prawn.rb +2 -72
- metadata +33 -224
- data/COPYING +0 -340
- data/LICENSE +0 -56
- data/README +0 -40
- data/Rakefile +0 -79
- data/data/encodings/win_ansi.txt +0 -29
- data/data/fonts/Action Man.dfont +0 -0
- data/data/fonts/Activa.ttf +0 -0
- data/data/fonts/Chalkboard.ttf +0 -0
- data/data/fonts/Courier-Bold.afm +0 -342
- data/data/fonts/Courier-BoldOblique.afm +0 -342
- data/data/fonts/Courier-Oblique.afm +0 -342
- data/data/fonts/Courier.afm +0 -342
- data/data/fonts/DejaVuSans.ttf +0 -0
- data/data/fonts/Dustismo_Roman.ttf +0 -0
- data/data/fonts/Helvetica-Bold.afm +0 -2827
- data/data/fonts/Helvetica-BoldOblique.afm +0 -2827
- data/data/fonts/Helvetica-Oblique.afm +0 -3051
- data/data/fonts/Helvetica.afm +0 -3051
- data/data/fonts/MustRead.html +0 -19
- data/data/fonts/Symbol.afm +0 -213
- data/data/fonts/Times-Bold.afm +0 -2588
- data/data/fonts/Times-BoldItalic.afm +0 -2384
- data/data/fonts/Times-Italic.afm +0 -2667
- data/data/fonts/Times-Roman.afm +0 -2419
- data/data/fonts/ZapfDingbats.afm +0 -225
- data/data/fonts/comicsans.ttf +0 -0
- data/data/fonts/gkai00mp.ttf +0 -0
- data/data/images/arrow.png +0 -0
- data/data/images/arrow2.png +0 -0
- data/data/images/barcode_issue.png +0 -0
- data/data/images/dice.alpha +0 -0
- data/data/images/dice.dat +0 -0
- data/data/images/dice.png +0 -0
- data/data/images/fractal.jpg +0 -0
- data/data/images/letterhead.jpg +0 -0
- data/data/images/page_white_text.alpha +0 -0
- data/data/images/page_white_text.dat +0 -0
- data/data/images/page_white_text.png +0 -0
- data/data/images/pigs.jpg +0 -0
- data/data/images/rails.dat +0 -0
- data/data/images/rails.png +0 -0
- data/data/images/ruport.png +0 -0
- data/data/images/ruport_data.dat +0 -0
- data/data/images/ruport_transparent.png +0 -0
- data/data/images/ruport_type0.png +0 -0
- data/data/images/stef.jpg +0 -0
- data/data/images/web-links.dat +0 -1
- data/data/images/web-links.png +0 -0
- data/data/shift_jis_text.txt +0 -1
- data/examples/bounding_box/bounding_boxes.rb +0 -44
- data/examples/bounding_box/lazy_bounding_boxes.rb +0 -28
- data/examples/bounding_box/padded_box.rb +0 -24
- data/examples/bounding_box/russian_boxes.rb +0 -37
- data/examples/general/background.rb +0 -20
- data/examples/general/canvas.rb +0 -16
- data/examples/general/measurement_units.rb +0 -52
- data/examples/general/multi_page_layout.rb +0 -17
- data/examples/general/page_geometry.rb +0 -32
- data/examples/graphics/basic_images.rb +0 -27
- data/examples/graphics/cmyk.rb +0 -13
- data/examples/graphics/curves.rb +0 -12
- data/examples/graphics/hexagon.rb +0 -14
- data/examples/graphics/image_fit.rb +0 -16
- data/examples/graphics/image_flow.rb +0 -38
- data/examples/graphics/image_position.rb +0 -18
- data/examples/graphics/line.rb +0 -33
- data/examples/graphics/png_types.rb +0 -23
- data/examples/graphics/polygons.rb +0 -17
- data/examples/graphics/remote_images.rb +0 -12
- data/examples/graphics/ruport_style_helpers.rb +0 -20
- data/examples/graphics/stroke_bounds.rb +0 -23
- data/examples/m17n/chinese_text_wrapping.rb +0 -20
- data/examples/m17n/euro.rb +0 -16
- data/examples/m17n/sjis.rb +0 -29
- data/examples/m17n/utf8.rb +0 -14
- data/examples/m17n/win_ansi_charset.rb +0 -55
- data/examples/text/alignment.rb +0 -19
- data/examples/text/dfont.rb +0 -49
- data/examples/text/family_based_styling.rb +0 -25
- data/examples/text/flowing_text_with_header_and_footer.rb +0 -37
- data/examples/text/font_calculations.rb +0 -92
- data/examples/text/font_size.rb +0 -34
- data/examples/text/kerning.rb +0 -31
- data/examples/text/simple_text.rb +0 -18
- data/examples/text/simple_text_ttf.rb +0 -18
- data/examples/text/span.rb +0 -30
- data/examples/text/text_box.rb +0 -26
- data/examples/text/text_flow.rb +0 -68
- data/lib/prawn/compatibility.rb +0 -38
- data/lib/prawn/document.rb +0 -309
- data/lib/prawn/document/annotations.rb +0 -63
- data/lib/prawn/document/bounding_box.rb +0 -368
- data/lib/prawn/document/destinations.rb +0 -81
- data/lib/prawn/document/internals.rb +0 -126
- data/lib/prawn/document/page_geometry.rb +0 -79
- data/lib/prawn/document/span.rb +0 -55
- data/lib/prawn/document/text.rb +0 -185
- data/lib/prawn/document/text/box.rb +0 -76
- data/lib/prawn/document/text/wrapping.rb +0 -59
- data/lib/prawn/encoding.rb +0 -121
- data/lib/prawn/errors.rb +0 -40
- data/lib/prawn/font.rb +0 -277
- data/lib/prawn/font/afm.rb +0 -202
- data/lib/prawn/font/dfont.rb +0 -31
- data/lib/prawn/font/ttf.rb +0 -326
- data/lib/prawn/graphics.rb +0 -257
- data/lib/prawn/graphics/color.rb +0 -140
- data/lib/prawn/images.rb +0 -339
- data/lib/prawn/images/jpg.rb +0 -45
- data/lib/prawn/images/png.rb +0 -199
- data/lib/prawn/literal_string.rb +0 -14
- data/lib/prawn/measurement_extensions.rb +0 -46
- data/lib/prawn/measurements.rb +0 -71
- data/lib/prawn/name_tree.rb +0 -165
- data/lib/prawn/pdf_object.rb +0 -73
- data/lib/prawn/reference.rb +0 -59
- data/spec/annotations_spec.rb +0 -90
- data/spec/bounding_box_spec.rb +0 -141
- data/spec/destinations_spec.rb +0 -15
- data/spec/document_spec.rb +0 -193
- data/spec/font_spec.rb +0 -234
- data/spec/graphics_spec.rb +0 -209
- data/spec/images_spec.rb +0 -68
- data/spec/jpg_spec.rb +0 -25
- data/spec/measurement_units_spec.rb +0 -23
- data/spec/name_tree_spec.rb +0 -103
- data/spec/pdf_object_spec.rb +0 -112
- data/spec/png_spec.rb +0 -196
- data/spec/reference_spec.rb +0 -42
- data/spec/spec_helper.rb +0 -23
- data/spec/text_spec.rb +0 -178
- data/vendor/pdf-inspector/README +0 -18
- data/vendor/pdf-inspector/lib/pdf/inspector.rb +0 -25
- data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +0 -80
- data/vendor/pdf-inspector/lib/pdf/inspector/page.rb +0 -16
- data/vendor/pdf-inspector/lib/pdf/inspector/text.rb +0 -31
- data/vendor/pdf-inspector/lib/pdf/inspector/xobject.rb +0 -19
- data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
- data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
- data/vendor/ttfunk/example.rb +0 -45
- data/vendor/ttfunk/lib/ttfunk.rb +0 -102
- data/vendor/ttfunk/lib/ttfunk/directory.rb +0 -17
- data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +0 -88
- data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +0 -69
- data/vendor/ttfunk/lib/ttfunk/reader.rb +0 -44
- data/vendor/ttfunk/lib/ttfunk/resource_file.rb +0 -78
- data/vendor/ttfunk/lib/ttfunk/subset.rb +0 -18
- data/vendor/ttfunk/lib/ttfunk/subset/base.rb +0 -141
- data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +0 -46
- data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +0 -48
- data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +0 -63
- data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +0 -51
- data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +0 -72
- data/vendor/ttfunk/lib/ttfunk/table.rb +0 -46
- data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +0 -34
- data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +0 -54
- data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +0 -126
- data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +0 -79
- data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +0 -64
- data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +0 -81
- data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +0 -37
- data/vendor/ttfunk/lib/ttfunk/table/head.rb +0 -44
- data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +0 -41
- data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +0 -47
- data/vendor/ttfunk/lib/ttfunk/table/kern.rb +0 -79
- data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +0 -62
- data/vendor/ttfunk/lib/ttfunk/table/loca.rb +0 -43
- data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +0 -40
- data/vendor/ttfunk/lib/ttfunk/table/name.rb +0 -119
- data/vendor/ttfunk/lib/ttfunk/table/os2.rb +0 -78
- data/vendor/ttfunk/lib/ttfunk/table/post.rb +0 -91
- data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +0 -43
- data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +0 -35
- data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +0 -23
- data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +0 -17
- data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +0 -17
- data/vendor/ttfunk/lib/ttfunk/table/simple.rb +0 -14
data/lib/prawn/font/dfont.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'prawn/font/ttf'
|
2
|
-
|
3
|
-
module Prawn
|
4
|
-
class Font
|
5
|
-
class DFont < TTF
|
6
|
-
# Returns a list of the names of all named fonts in the given dfont file.
|
7
|
-
# Note that fonts are not required to be named in a dfont file, so the
|
8
|
-
# list may be empty even if the file does contain fonts. Also, note that
|
9
|
-
# the list is returned in no particular order, so the first font in the
|
10
|
-
# list is not necessarily the font at index 0 in the file.
|
11
|
-
def self.named_fonts(file)
|
12
|
-
TTFunk::ResourceFile.open(file) do |file|
|
13
|
-
return file.resources_for("sfnt")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
# Returns the number of fonts contained in the dfont file.
|
18
|
-
def self.font_count(file)
|
19
|
-
TTFunk::ResourceFile.open(file) do |file|
|
20
|
-
return file.map["sfnt"][:list].length
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def read_ttf_file
|
27
|
-
TTFunk::File.from_dfont(@name, @options[:font] || 0)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/lib/prawn/font/ttf.rb
DELETED
@@ -1,326 +0,0 @@
|
|
1
|
-
require 'ttfunk'
|
2
|
-
require 'ttfunk/subset_collection'
|
3
|
-
|
4
|
-
module Prawn
|
5
|
-
class Font
|
6
|
-
class TTF < Font
|
7
|
-
attr_reader :ttf, :subsets
|
8
|
-
|
9
|
-
def initialize(document, name, options={})
|
10
|
-
super
|
11
|
-
|
12
|
-
@ttf = read_ttf_file
|
13
|
-
@subsets = TTFunk::SubsetCollection.new(@ttf)
|
14
|
-
|
15
|
-
@attributes = {}
|
16
|
-
@bounding_boxes = {}
|
17
|
-
@char_widths = {}
|
18
|
-
@has_kerning_data = @ttf.kerning.exists? && @ttf.kerning.tables.any?
|
19
|
-
|
20
|
-
@ascender = Integer(@ttf.ascent * scale_factor)
|
21
|
-
@descender = Integer(@ttf.descent * scale_factor)
|
22
|
-
@line_gap = Integer(@ttf.line_gap * scale_factor)
|
23
|
-
end
|
24
|
-
|
25
|
-
# +string+ must be UTF8-encoded.
|
26
|
-
def width_of(string, options={})
|
27
|
-
scale = (options[:size] || size) / 1000.0
|
28
|
-
if options[:kerning]
|
29
|
-
kern(string).inject(0) do |s,r|
|
30
|
-
if r.is_a?(Numeric)
|
31
|
-
s - r
|
32
|
-
else
|
33
|
-
r.inject(s) { |s2, u| s2 + character_width_by_code(u) }
|
34
|
-
end
|
35
|
-
end * scale
|
36
|
-
else
|
37
|
-
string.unpack("U*").inject(0) do |s,r|
|
38
|
-
s + character_width_by_code(r)
|
39
|
-
end * scale
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def bbox
|
44
|
-
@bbox ||= @ttf.bbox.map { |i| Integer(i * scale_factor) }
|
45
|
-
end
|
46
|
-
|
47
|
-
def has_kerning_data?
|
48
|
-
@has_kerning_data
|
49
|
-
end
|
50
|
-
|
51
|
-
# Perform any changes to the string that need to happen
|
52
|
-
# before it is rendered to the canvas. Returns an array of
|
53
|
-
# subset "chunks", where the even-numbered indices are the
|
54
|
-
# font subset number, and the following entry element is
|
55
|
-
# either a string or an array (for kerned text).
|
56
|
-
#
|
57
|
-
# The +text+ parameter must be UTF8-encoded.
|
58
|
-
def encode_text(text,options={})
|
59
|
-
text = text.chomp
|
60
|
-
|
61
|
-
if options[:kerning]
|
62
|
-
last_subset = nil
|
63
|
-
kern(text).inject([]) do |result, element|
|
64
|
-
if element.is_a?(Numeric)
|
65
|
-
result.last[1] = [result.last[1]] unless result.last[1].is_a?(Array)
|
66
|
-
result.last[1] << element
|
67
|
-
result
|
68
|
-
else
|
69
|
-
encoded = @subsets.encode(element)
|
70
|
-
|
71
|
-
if encoded.first[0] == last_subset
|
72
|
-
result.last[1] << encoded.first[1]
|
73
|
-
encoded.shift
|
74
|
-
end
|
75
|
-
|
76
|
-
if encoded.any?
|
77
|
-
last_subset = encoded.last[0]
|
78
|
-
result + encoded
|
79
|
-
else
|
80
|
-
result
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
else
|
85
|
-
@subsets.encode(text.unpack("U*"))
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def basename
|
90
|
-
@basename ||= @ttf.name.postscript_name
|
91
|
-
end
|
92
|
-
|
93
|
-
# not sure how to compute this for true-type fonts...
|
94
|
-
def stemV
|
95
|
-
0
|
96
|
-
end
|
97
|
-
|
98
|
-
def italic_angle
|
99
|
-
@italic_angle ||= if @ttf.postscript.exists?
|
100
|
-
raw = @ttf.postscript.italic_angle
|
101
|
-
hi, low = raw >> 16, raw & 0xFF
|
102
|
-
hi = -((hi ^ 0xFFFF) + 1) if hi & 0x8000 != 0
|
103
|
-
"#{hi}.#{low}".to_f
|
104
|
-
else
|
105
|
-
0
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def cap_height
|
110
|
-
@cap_height ||= begin
|
111
|
-
height = @ttf.os2.exists? && @ttf.os2.cap_height || 0
|
112
|
-
height == 0 ? ascender : height
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def x_height
|
117
|
-
# FIXME: seems like if os2 table doesn't exist, we could
|
118
|
-
# just find the height of the lower-case 'x' glyph?
|
119
|
-
@ttf.os2.exists? && @ttf.os2.x_height || 0
|
120
|
-
end
|
121
|
-
|
122
|
-
def family_class
|
123
|
-
@family_class ||= (@ttf.os2.exists? && @ttf.os2.family_class || 0) >> 8
|
124
|
-
end
|
125
|
-
|
126
|
-
def serif?
|
127
|
-
@serif ||= [1,2,3,4,5,7].include?(family_class)
|
128
|
-
end
|
129
|
-
|
130
|
-
def script?
|
131
|
-
@script ||= family_class == 10
|
132
|
-
end
|
133
|
-
|
134
|
-
def pdf_flags
|
135
|
-
@flags ||= begin
|
136
|
-
flags = 0
|
137
|
-
flags |= 0x0001 if @ttf.postscript.fixed_pitch?
|
138
|
-
flags |= 0x0002 if serif?
|
139
|
-
flags |= 0x0008 if script?
|
140
|
-
flags |= 0x0040 if italic_angle != 0
|
141
|
-
flags |= 0x0004 # assume the font contains at least some non-latin characters
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def normalize_encoding(text)
|
146
|
-
if text.respond_to?(:encode!)
|
147
|
-
# if we're running under a M17n aware VM, ensure the string provided is
|
148
|
-
# UTF-8 (by converting it if necessary)
|
149
|
-
begin
|
150
|
-
text.encode!("UTF-8")
|
151
|
-
rescue
|
152
|
-
raise Prawn::Errors::IncompatibleStringEncoding, "Encoding " +
|
153
|
-
"#{text.encoding} can not be transparently converted to UTF-8. " +
|
154
|
-
"Please ensure the encoding of the string you are attempting " +
|
155
|
-
"to use is set correctly"
|
156
|
-
end
|
157
|
-
else
|
158
|
-
# on a non M17N aware VM, use unpack as a hackish way to verify the
|
159
|
-
# string is valid utf-8. I thought it was better than loading iconv
|
160
|
-
# though.
|
161
|
-
begin
|
162
|
-
text.unpack("U*")
|
163
|
-
rescue
|
164
|
-
raise Prawn::Errors::IncompatibleStringEncoding, "The string you " +
|
165
|
-
"are attempting to render is not encoded in valid UTF-8."
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
private
|
171
|
-
|
172
|
-
def cmap
|
173
|
-
@cmap ||= @ttf.cmap.unicode.first or raise("no unicode cmap for font")
|
174
|
-
end
|
175
|
-
|
176
|
-
# +string+ must be UTF8-encoded.
|
177
|
-
#
|
178
|
-
# Returns an array. If an element is a numeric, it represents the
|
179
|
-
# kern amount to inject at that position. Otherwise, the element
|
180
|
-
# is an array of UTF-16 characters.
|
181
|
-
def kern(string)
|
182
|
-
a = []
|
183
|
-
|
184
|
-
string.unpack("U*").each do |r|
|
185
|
-
if a.empty?
|
186
|
-
a << [r]
|
187
|
-
elsif (kern = kern_pairs_table[[cmap[a.last.last], cmap[r]]])
|
188
|
-
kern *= scale_factor
|
189
|
-
a << -kern << [r]
|
190
|
-
else
|
191
|
-
a.last << r
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
a
|
196
|
-
end
|
197
|
-
|
198
|
-
def kern_pairs_table
|
199
|
-
@kerning_data ||= has_kerning_data? ? @ttf.kerning.tables.first.pairs : {}
|
200
|
-
end
|
201
|
-
|
202
|
-
def cid_to_gid_map
|
203
|
-
max = cmap.code_map.keys.max
|
204
|
-
(0..max).map { |cid| cmap[cid] }.pack("n*")
|
205
|
-
end
|
206
|
-
|
207
|
-
def hmtx
|
208
|
-
@hmtx ||= @ttf.horizontal_metrics
|
209
|
-
end
|
210
|
-
|
211
|
-
def character_width_by_code(code)
|
212
|
-
return 0 unless cmap[code]
|
213
|
-
@char_widths[code] ||= Integer(hmtx.widths[cmap[code]] * scale_factor)
|
214
|
-
end
|
215
|
-
|
216
|
-
def scale_factor
|
217
|
-
@scale ||= 1000.0 / @ttf.header.units_per_em
|
218
|
-
end
|
219
|
-
|
220
|
-
def register(subset)
|
221
|
-
temp_name = @ttf.name.postscript_name
|
222
|
-
@document.ref(:Type => :Font, :BaseFont => temp_name) { |ref| embed(ref, subset) }
|
223
|
-
end
|
224
|
-
|
225
|
-
def embed(reference, subset)
|
226
|
-
font_content = @subsets[subset].encode
|
227
|
-
|
228
|
-
# FIXME: we need postscript_name and glyph widths from the font
|
229
|
-
# subset. Perhaps this could be done by querying the subset,
|
230
|
-
# rather than by parsing the font that the subset produces?
|
231
|
-
font = TTFunk::File.new(font_content)
|
232
|
-
|
233
|
-
# empirically, it looks like Adobe Reader will not display fonts
|
234
|
-
# if their font name is more than 33 bytes long. Strange. But true.
|
235
|
-
basename = font.name.postscript_name[0, 33]
|
236
|
-
|
237
|
-
raise "Can't detect a postscript name for #{file}" if basename.nil?
|
238
|
-
|
239
|
-
compressed_font = Zlib::Deflate.deflate(font_content)
|
240
|
-
|
241
|
-
fontfile = @document.ref(:Length => compressed_font.size,
|
242
|
-
:Length1 => font_content.size,
|
243
|
-
:Filter => :FlateDecode )
|
244
|
-
fontfile << compressed_font
|
245
|
-
|
246
|
-
descriptor = @document.ref(:Type => :FontDescriptor,
|
247
|
-
:FontName => basename,
|
248
|
-
:FontFile2 => fontfile,
|
249
|
-
:FontBBox => bbox,
|
250
|
-
:Flags => pdf_flags,
|
251
|
-
:StemV => stemV,
|
252
|
-
:ItalicAngle => italic_angle,
|
253
|
-
:Ascent => ascender,
|
254
|
-
:Descent => descender,
|
255
|
-
:CapHeight => cap_height,
|
256
|
-
:XHeight => x_height)
|
257
|
-
|
258
|
-
hmtx = font.horizontal_metrics
|
259
|
-
widths = font.cmap.tables.first.code_map.map { |gid|
|
260
|
-
Integer(hmtx.widths[gid] * scale_factor) }[32..-1]
|
261
|
-
|
262
|
-
# It would be nice to have Encoding set for the macroman subsets,
|
263
|
-
# and only do a ToUnicode cmap for non-encoded unicode subsets.
|
264
|
-
# However, apparently Adobe Reader won't render MacRoman encoded
|
265
|
-
# subsets if original font contains unicode characters. (It has to
|
266
|
-
# be some flag or something that ttfunk is simply copying over...
|
267
|
-
# but I can't figure out which flag that is.)
|
268
|
-
#
|
269
|
-
# For now, it's simplest to just create a unicode cmap for every font.
|
270
|
-
# It offends my inner purist, but it'll do.
|
271
|
-
|
272
|
-
map = @subsets[subset].to_unicode_map
|
273
|
-
|
274
|
-
ranges = [[]]
|
275
|
-
lines = map.keys.sort.inject("") do |s, code|
|
276
|
-
ranges << [] if ranges.last.length >= 100
|
277
|
-
unicode = map[code]
|
278
|
-
ranges.last << "<%02x><%04x>" % [code, unicode]
|
279
|
-
end
|
280
|
-
|
281
|
-
range_blocks = ranges.inject("") do |s, list|
|
282
|
-
s << "%d beginbfchar\n%s\nendbfchar\n" % [list.length, list.join("\n")]
|
283
|
-
end
|
284
|
-
|
285
|
-
to_unicode_cmap = UNICODE_CMAP_TEMPLATE % range_blocks.strip
|
286
|
-
|
287
|
-
cmap = @document.ref({})
|
288
|
-
cmap << to_unicode_cmap
|
289
|
-
cmap.compress_stream
|
290
|
-
|
291
|
-
reference.data.update(:Subtype => :TrueType,
|
292
|
-
:BaseFont => basename,
|
293
|
-
:FontDescriptor => descriptor,
|
294
|
-
:FirstChar => 32,
|
295
|
-
:LastChar => 255,
|
296
|
-
:Widths => @document.ref(widths),
|
297
|
-
:ToUnicode => cmap)
|
298
|
-
end
|
299
|
-
|
300
|
-
UNICODE_CMAP_TEMPLATE = <<-STR.strip.gsub(/^\s*/, "")
|
301
|
-
/CIDInit /ProcSet findresource begin
|
302
|
-
12 dict begin
|
303
|
-
begincmap
|
304
|
-
/CIDSystemInfo <<
|
305
|
-
/Registry (Adobe)
|
306
|
-
/Ordering (UCS)
|
307
|
-
/Supplement 0
|
308
|
-
>> def
|
309
|
-
/CMapName /Adobe-Identity-UCS def
|
310
|
-
/CMapType 2 def
|
311
|
-
1 begincodespacerange
|
312
|
-
<00><ff>
|
313
|
-
endcodespacerange
|
314
|
-
%s
|
315
|
-
endcmap
|
316
|
-
CMapName currentdict /CMap defineresource pop
|
317
|
-
end
|
318
|
-
end
|
319
|
-
STR
|
320
|
-
|
321
|
-
def read_ttf_file
|
322
|
-
TTFunk::File.open(@name)
|
323
|
-
end
|
324
|
-
end
|
325
|
-
end
|
326
|
-
end
|
data/lib/prawn/graphics.rb
DELETED
@@ -1,257 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
# graphics.rb : Implements PDF drawing primitives
|
4
|
-
#
|
5
|
-
# Copyright April 2008, Gregory Brown. All Rights Reserved.
|
6
|
-
#
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
8
|
-
|
9
|
-
require "enumerator"
|
10
|
-
require "prawn/graphics/color"
|
11
|
-
|
12
|
-
module Prawn
|
13
|
-
|
14
|
-
# Implements the drawing facilities for Prawn::Document.
|
15
|
-
# Use this to draw the most beautiful imaginable things.
|
16
|
-
#
|
17
|
-
# This file lifts and modifies several of PDF::Writer's graphics functions
|
18
|
-
# ruby-pdf.rubyforge.org
|
19
|
-
#
|
20
|
-
module Graphics
|
21
|
-
|
22
|
-
include Color
|
23
|
-
|
24
|
-
#######################################################################
|
25
|
-
# Low level drawing operations must translate to absolute coords! #
|
26
|
-
#######################################################################
|
27
|
-
|
28
|
-
# Moves the drawing position to a given point. The point can be
|
29
|
-
# specified as a tuple or a flattened argument list
|
30
|
-
#
|
31
|
-
# pdf.move_to [100,50]
|
32
|
-
# pdf.move_to(100,50)
|
33
|
-
#
|
34
|
-
def move_to(*point)
|
35
|
-
x,y = translate(point)
|
36
|
-
add_content("%.3f %.3f m" % [ x, y ])
|
37
|
-
end
|
38
|
-
|
39
|
-
# Draws a line from the current drawing position to the specified point.
|
40
|
-
# The destination may be described as a tuple or a flattened list:
|
41
|
-
#
|
42
|
-
# pdf.line_to [50,50]
|
43
|
-
# pdf.line_to(50,50)
|
44
|
-
#
|
45
|
-
def line_to(*point)
|
46
|
-
x,y = translate(point)
|
47
|
-
add_content("%.3f %.3f l" % [ x, y ])
|
48
|
-
end
|
49
|
-
|
50
|
-
# Draws a Bezier curve from the current drawing position to the
|
51
|
-
# specified point, bounded by two additional points.
|
52
|
-
#
|
53
|
-
# pdf.curve_to [100,100], :bounds => [[90,90],[75,75]]
|
54
|
-
#
|
55
|
-
def curve_to(dest,options={})
|
56
|
-
options[:bounds] or raise Prawn::Errors::InvalidGraphicsPath,
|
57
|
-
"Bounding points for bezier curve must be specified "+
|
58
|
-
"as :bounds => [[x1,y1],[x2,y2]]"
|
59
|
-
|
60
|
-
curve_points = (options[:bounds] << dest).map { |e| translate(e) }
|
61
|
-
add_content("%.3f %.3f %.3f %.3f %.3f %.3f c" %
|
62
|
-
curve_points.flatten )
|
63
|
-
end
|
64
|
-
|
65
|
-
# Draws a rectangle given <tt>point</tt>, <tt>width</tt> and
|
66
|
-
# <tt>height</tt>. The rectangle is bounded by its upper-left corner.
|
67
|
-
#
|
68
|
-
# pdf.rectangle [300,300], 100, 200
|
69
|
-
#
|
70
|
-
def rectangle(point,width,height)
|
71
|
-
x,y = translate(point)
|
72
|
-
add_content("%.3f %.3f %.3f %.3f re" % [ x, y - height, width, height ])
|
73
|
-
end
|
74
|
-
|
75
|
-
###########################################################
|
76
|
-
# Higher level functions: May use relative coords #
|
77
|
-
###########################################################
|
78
|
-
|
79
|
-
# Sets line thickness to the <tt>width</tt> specified.
|
80
|
-
#
|
81
|
-
def line_width=(width)
|
82
|
-
@line_width = width
|
83
|
-
add_content("#{width} w")
|
84
|
-
end
|
85
|
-
|
86
|
-
# When called without an argument, returns the current line thickness.
|
87
|
-
# When called with an argument, sets the line thickness to the specified
|
88
|
-
# value (in PDF points)
|
89
|
-
#
|
90
|
-
# pdf.line_width #=> 1
|
91
|
-
# pdf.line_width(5)
|
92
|
-
# pdf.line_width #=> 5
|
93
|
-
#
|
94
|
-
def line_width(width=nil)
|
95
|
-
if width
|
96
|
-
self.line_width = width
|
97
|
-
else
|
98
|
-
@line_width || 1
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# Draws a line from one point to another. Points may be specified as
|
103
|
-
# tuples or flattened argument list:
|
104
|
-
#
|
105
|
-
# pdf.line [100,100], [200,250]
|
106
|
-
# pdf.line(100,100,200,250)
|
107
|
-
#
|
108
|
-
def line(*points)
|
109
|
-
x0,y0,x1,y1 = points.flatten
|
110
|
-
move_to(x0, y0)
|
111
|
-
line_to(x1, y1)
|
112
|
-
end
|
113
|
-
|
114
|
-
# Draws a horizontal line from <tt>x1</tt> to <tt>x2</tt> at the
|
115
|
-
# current <tt>y</tt> position, or the position specified by the :at option.
|
116
|
-
#
|
117
|
-
# # draw a line from [25, 75] to [100, 75]
|
118
|
-
# horizontal_line 25, 100, :at => 75
|
119
|
-
#
|
120
|
-
def horizontal_line(x1,x2,options={})
|
121
|
-
if options[:at]
|
122
|
-
y1 = options[:at]
|
123
|
-
else
|
124
|
-
y1 = y - bounds.absolute_bottom
|
125
|
-
end
|
126
|
-
|
127
|
-
line(x1,y1,x2,y1)
|
128
|
-
end
|
129
|
-
|
130
|
-
# Draws a horizontal line from the left border to the right border of the
|
131
|
-
# bounding box at the current <tt>y</tt> position.
|
132
|
-
#
|
133
|
-
def horizontal_rule
|
134
|
-
horizontal_line(bounds.left, bounds.right)
|
135
|
-
end
|
136
|
-
|
137
|
-
# Draws a vertical line at the x cooordinate given by :at from y1 to y2.
|
138
|
-
#
|
139
|
-
# # draw a line from [25, 100] to [25, 300]
|
140
|
-
# vertical_line 100, 300, :at => 25
|
141
|
-
#
|
142
|
-
def vertical_line(y1,y2,params)
|
143
|
-
line(params[:at],y1,params[:at],y2)
|
144
|
-
end
|
145
|
-
|
146
|
-
# Draws a Bezier curve between two points, bounded by two additional
|
147
|
-
# points
|
148
|
-
#
|
149
|
-
# pdf.curve [50,100], [100,100], :bounds => [[90,90],[75,75]]
|
150
|
-
#
|
151
|
-
def curve(origin,dest, options={})
|
152
|
-
move_to(*origin)
|
153
|
-
curve_to(dest,options)
|
154
|
-
end
|
155
|
-
|
156
|
-
# This constant is used to approximate a symmetrical arc using a cubic
|
157
|
-
# Bezier curve.
|
158
|
-
#
|
159
|
-
KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0)
|
160
|
-
|
161
|
-
# Draws a circle of radius <tt>:radius</tt> with the centre-point at <tt>point</tt>
|
162
|
-
# as a complete subpath. The drawing point will be moved to the
|
163
|
-
# centre-point upon completion of the drawing the circle.
|
164
|
-
#
|
165
|
-
# pdf.circle_at [100,100], :radius => 25
|
166
|
-
#
|
167
|
-
def circle_at(point, options)
|
168
|
-
x,y = point
|
169
|
-
ellipse_at [x, y], options[:radius]
|
170
|
-
end
|
171
|
-
|
172
|
-
# Draws an ellipse of +x+ radius <tt>r1</tt> and +y+ radius <tt>r2</tt>
|
173
|
-
# with the centre-point at <tt>point</tt> as a complete subpath. The
|
174
|
-
# drawing point will be moved to the centre-point upon completion of the
|
175
|
-
# drawing the ellipse.
|
176
|
-
#
|
177
|
-
# # draws an ellipse with x-radius 25 and y-radius 50
|
178
|
-
# pdf.ellipse_at [100,100], 25, 50
|
179
|
-
#
|
180
|
-
def ellipse_at(point, r1, r2 = r1)
|
181
|
-
x, y = point
|
182
|
-
l1 = r1 * KAPPA
|
183
|
-
l2 = r2 * KAPPA
|
184
|
-
|
185
|
-
move_to(x + r1, y)
|
186
|
-
|
187
|
-
# Upper right hand corner
|
188
|
-
curve_to [x, y + r2],
|
189
|
-
:bounds => [[x + r1, y + l1], [x + l2, y + r2]]
|
190
|
-
|
191
|
-
# Upper left hand corner
|
192
|
-
curve_to [x - r1, y],
|
193
|
-
:bounds => [[x - l2, y + r2], [x - r1, y + l1]]
|
194
|
-
|
195
|
-
# Lower left hand corner
|
196
|
-
curve_to [x, y - r2],
|
197
|
-
:bounds => [[x - r1, y - l1], [x - l2, y - r2]]
|
198
|
-
|
199
|
-
# Lower right hand corner
|
200
|
-
curve_to [x + r1, y],
|
201
|
-
:bounds => [[x + l2, y - r2], [x + r1, y - l1]]
|
202
|
-
|
203
|
-
move_to(x, y)
|
204
|
-
end
|
205
|
-
|
206
|
-
# Draws a polygon from the specified points.
|
207
|
-
#
|
208
|
-
# # draws a snazzy triangle
|
209
|
-
# pdf.polygon [100,100], [100,200], [200,200]
|
210
|
-
#
|
211
|
-
def polygon(*points)
|
212
|
-
move_to points[0]
|
213
|
-
(points << points[0]).each_cons(2) do |p1,p2|
|
214
|
-
line_to(*p2)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
# Strokes and closes the current path. See Graphic::Color for color details
|
219
|
-
#
|
220
|
-
def stroke
|
221
|
-
yield if block_given?
|
222
|
-
add_content "S"
|
223
|
-
end
|
224
|
-
|
225
|
-
# Draws and strokes a rectangle represented by the current bounding box
|
226
|
-
#
|
227
|
-
def stroke_bounds
|
228
|
-
stroke_rectangle bounds.top_left, bounds.width, bounds.height
|
229
|
-
end
|
230
|
-
|
231
|
-
# Fills and closes the current path. See Graphic::Color for color details
|
232
|
-
#
|
233
|
-
def fill
|
234
|
-
yield if block_given?
|
235
|
-
add_content "f"
|
236
|
-
end
|
237
|
-
|
238
|
-
# Fills, strokes, and closes the current path. See Graphic::Color for color details
|
239
|
-
#
|
240
|
-
def fill_and_stroke
|
241
|
-
yield if block_given?
|
242
|
-
add_content "b"
|
243
|
-
end
|
244
|
-
|
245
|
-
private
|
246
|
-
|
247
|
-
def translate(*point)
|
248
|
-
x,y = point.flatten
|
249
|
-
[@bounding_box.absolute_left + x, @bounding_box.absolute_bottom + y]
|
250
|
-
end
|
251
|
-
|
252
|
-
def translate!(point)
|
253
|
-
point.replace(translate(point))
|
254
|
-
end
|
255
|
-
|
256
|
-
end
|
257
|
-
end
|