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
@@ -1,49 +0,0 @@
|
|
1
|
-
# TTF/Ruby, a library to read and write TrueType fonts in Ruby.
|
2
|
-
# Copyright (C) 2006 Mathieu Blondel
|
3
|
-
#
|
4
|
-
# This program is free software; you can redistribute it and/or modify
|
5
|
-
# it under the terms of the GNU General Public License as published by
|
6
|
-
# the Free Software Foundation; either version 2 of the License, or
|
7
|
-
# (at your option) any later version.
|
8
|
-
#
|
9
|
-
# This program is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
# GNU General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU General Public License
|
15
|
-
# along with this program; if not, write to the Free Software
|
16
|
-
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
17
|
-
|
18
|
-
module Font
|
19
|
-
module TTF
|
20
|
-
module Table
|
21
|
-
|
22
|
-
# Cvt is the Control Value table. It references values that can be
|
23
|
-
# referenced by instructions (used for hinting, aka grid-fitting).
|
24
|
-
class Cvt < Font::TTF::FontChunk
|
25
|
-
|
26
|
-
attr_accessor :instructions
|
27
|
-
|
28
|
-
def initialize(*args)
|
29
|
-
super(*args)
|
30
|
-
|
31
|
-
if exists_in_file?
|
32
|
-
@font.at_offset(@offset) do
|
33
|
-
n = @len / IO::SIZEOF_FWORD
|
34
|
-
@instructions = @font.read_fwords(n)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# Dumps the cvt table in binary raw format as may be found in a font
|
40
|
-
# file.
|
41
|
-
def dump
|
42
|
-
(@instructions || []).to_fwords
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
# TTF/Ruby, a library to read and write TrueType fonts in Ruby.
|
2
|
-
# Copyright (C) 2006 Mathieu Blondel
|
3
|
-
#
|
4
|
-
# This program is free software; you can redistribute it and/or modify
|
5
|
-
# it under the terms of the GNU General Public License as published by
|
6
|
-
# the Free Software Foundation; either version 2 of the License, or
|
7
|
-
# (at your option) any later version.
|
8
|
-
#
|
9
|
-
# This program is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
# GNU General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU General Public License
|
15
|
-
# along with this program; if not, write to the Free Software
|
16
|
-
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
17
|
-
|
18
|
-
module Font
|
19
|
-
module TTF
|
20
|
-
module Table
|
21
|
-
|
22
|
-
# Fpgm is the Font Program table. It is similar to the Cvt table except
|
23
|
-
# it is only run once, when the font is first used.
|
24
|
-
class Fpgm < Font::TTF::FontChunk
|
25
|
-
|
26
|
-
attr_accessor :instructions
|
27
|
-
|
28
|
-
def initialize(*args)
|
29
|
-
super(*args)
|
30
|
-
|
31
|
-
if exists_in_file?
|
32
|
-
@font.at_offset(@offset) do
|
33
|
-
@instructions = @font.read_bytes(@len)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Dumps the fpgm table in binary raw format as may be found in a font
|
39
|
-
# file.
|
40
|
-
def dump
|
41
|
-
(@instructions || []).to_bytes
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,88 +0,0 @@
|
|
1
|
-
# TTF/Ruby, a library to read and write TrueType fonts in Ruby.
|
2
|
-
# Copyright (C) 2006 Mathieu Blondel
|
3
|
-
#
|
4
|
-
# This program is free software; you can redistribute it and/or modify
|
5
|
-
# it under the terms of the GNU General Public License as published by
|
6
|
-
# the Free Software Foundation; either version 2 of the License, or
|
7
|
-
# (at your option) any later version.
|
8
|
-
#
|
9
|
-
# This program is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
# GNU General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU General Public License
|
15
|
-
# along with this program; if not, write to the Free Software
|
16
|
-
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
17
|
-
|
18
|
-
module Font
|
19
|
-
module TTF
|
20
|
-
module Table
|
21
|
-
|
22
|
-
# Gasp is the Grid-fitting and scan conversion procedure table.
|
23
|
-
class Gasp < Font::TTF::FontChunk
|
24
|
-
|
25
|
-
class GaspRange < Font::TTF::FontChunk
|
26
|
-
|
27
|
-
SIZEOF_GASP_RANGE = 2 * IO::SIZEOF_USHORT
|
28
|
-
|
29
|
-
attr_accessor :range_max_ppem, :range_gasp_behavior
|
30
|
-
|
31
|
-
def initialize(table, n=nil)
|
32
|
-
if n.nil?
|
33
|
-
# when object is created by hand
|
34
|
-
super(table.font)
|
35
|
-
else
|
36
|
-
offs = table.offset + 2 * IO::SIZEOF_USHORT + \
|
37
|
-
n * SIZEOF_GASP_RANGE
|
38
|
-
super(table.font, offs, SIZEOF_GASP_RANGE)
|
39
|
-
|
40
|
-
table.font.at_offset(@offset) do
|
41
|
-
@range_max_ppem = table.font.read_ushort
|
42
|
-
@range_gasp_behavior = table.font.read_ushort
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def dump
|
48
|
-
raw = (@range_max_ppem || 0).to_ushort
|
49
|
-
raw += (@range_gasp_behavior || 0).to_ushort
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
attr_accessor :version
|
55
|
-
# An Array of GaspRange objects.
|
56
|
-
attr_accessor :gasp_ranges
|
57
|
-
|
58
|
-
def initialize(*args)
|
59
|
-
super(*args)
|
60
|
-
|
61
|
-
if exists_in_file?
|
62
|
-
@font.at_offset(@offset) do
|
63
|
-
@version = @font.read_ushort
|
64
|
-
@num_ranges = @font.read_ushort
|
65
|
-
@gasp_ranges = []
|
66
|
-
@num_ranges.times do |i|
|
67
|
-
@gasp_ranges << GaspRange.new(self, i)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# Dumps the gasp table in binary raw format as may be found in a font
|
74
|
-
# file.
|
75
|
-
def dump
|
76
|
-
raw = (@version || 0).to_ushort
|
77
|
-
raw += (@gasp_ranges || []).length.to_ushort
|
78
|
-
@gasp_ranges.each do |gr|
|
79
|
-
raw += gr.dump
|
80
|
-
end
|
81
|
-
raw
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
@@ -1,452 +0,0 @@
|
|
1
|
-
# TTF/Ruby, a library to read and write TrueType fonts in Ruby.
|
2
|
-
# Copyright (C) 2006 Mathieu Blondel
|
3
|
-
#
|
4
|
-
# This program is free software; you can redistribute it and/or modify
|
5
|
-
# it under the terms of the GNU General Public License as published by
|
6
|
-
# the Free Software Foundation; either version 2 of the License, or
|
7
|
-
# (at your option) any later version.
|
8
|
-
#
|
9
|
-
# This program is distributed in the hope that it will be useful,
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
# GNU General Public License for more details.
|
13
|
-
#
|
14
|
-
# You should have received a copy of the GNU General Public License
|
15
|
-
# along with this program; if not, write to the Free Software
|
16
|
-
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
17
|
-
|
18
|
-
module Font
|
19
|
-
module TTF
|
20
|
-
module Table
|
21
|
-
|
22
|
-
# Glyf is the Glyph data table.
|
23
|
-
class Glyf < Font::TTF::FontChunk
|
24
|
-
|
25
|
-
# Base class for SimpleGlyph and CompositeGlyph.
|
26
|
-
class Glyph < Font::TTF::FontChunk
|
27
|
-
|
28
|
-
attr_accessor :num_contours, :x_min, :y_min, :x_max, :y_max
|
29
|
-
|
30
|
-
def initialize(table, offset=nil)
|
31
|
-
@table = table
|
32
|
-
@offset_from_table = offset
|
33
|
-
super(@table.font, @table.offset + @offset_from_table)
|
34
|
-
|
35
|
-
if exists_in_file?
|
36
|
-
@font.at_offset(@offset) do
|
37
|
-
@num_contours = @font.read_short
|
38
|
-
@x_min = @font.read_fword
|
39
|
-
@y_min = @font.read_fword
|
40
|
-
@x_max = @font.read_fword
|
41
|
-
@y_max = @font.read_fword
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def dump
|
47
|
-
raw = (@num_contours || 0).to_short
|
48
|
-
raw += (@x_min || 0).to_fword
|
49
|
-
raw += (@y_min || 0).to_fword
|
50
|
-
raw += (@x_max || 0).to_fword
|
51
|
-
raw += (@y_max || 0).to_fword
|
52
|
-
end
|
53
|
-
|
54
|
-
# Returns whether the glyph is composite or not.
|
55
|
-
def composite?
|
56
|
-
self.class == CompositeGlyph
|
57
|
-
end
|
58
|
-
|
59
|
-
# Returns whether is simple (i.e. not composite) or not.
|
60
|
-
def simple?
|
61
|
-
self.class == SimpleGlyph
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
# SimpleGlyph class.
|
67
|
-
class SimpleGlyph < Glyph
|
68
|
-
|
69
|
-
Point = Struct.new(:rel_x, :abs_x, :rel_y, :abs_y,
|
70
|
-
:end_of_contour, :on_curve)
|
71
|
-
|
72
|
-
# Point is helper class which gives information on a point
|
73
|
-
# such as it absolute (abs_x, abs_y) and relative (rel_x, rel_y)
|
74
|
-
# coordinates
|
75
|
-
class Point
|
76
|
-
# Whether the point is end of contour or not.
|
77
|
-
alias :end_of_contour? :end_of_contour
|
78
|
-
# Whether the point is on curve or not.
|
79
|
-
alias :on_curve? :on_curve
|
80
|
-
|
81
|
-
# Whether the point is off curve or not.
|
82
|
-
def off_curve?
|
83
|
-
not on_curve?
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
FLAG_ON_CURVE = 0b1
|
88
|
-
FLAG_X_SHORT_VECTOR = 0b10
|
89
|
-
FLAG_Y_SHORT_VECTOR = 0b100
|
90
|
-
FLAG_REPEAT = 0b1000
|
91
|
-
FLAG_X_IS_SAME = 0b10000
|
92
|
-
FLAG_Y_IS_SAME = 0b100000
|
93
|
-
|
94
|
-
attr_accessor :end_pts_of_contours, :instructions, :flags,
|
95
|
-
:x_coordinates, :y_coordinates
|
96
|
-
|
97
|
-
def initialize(*args)
|
98
|
-
super(*args)
|
99
|
-
|
100
|
-
if exists_in_file?
|
101
|
-
offs = @offset + IO::SIZEOF_SHORT + 4 * IO::SIZEOF_FWORD
|
102
|
-
@font.at_offset(offs) do
|
103
|
-
@end_pts_of_contours = @font.read_ushorts(@num_contours)
|
104
|
-
instruction_len = @font.read_ushort
|
105
|
-
@instructions = @font.read_bytes(instruction_len)
|
106
|
-
unless @end_pts_of_contours.empty?
|
107
|
-
num_points = @end_pts_of_contours.last + 1
|
108
|
-
else
|
109
|
-
num_points = 0
|
110
|
-
end
|
111
|
-
@flags = []
|
112
|
-
while @flags.length < num_points
|
113
|
-
flag = @font.read_byte
|
114
|
-
@flags << flag
|
115
|
-
if flag & FLAG_REPEAT != 0
|
116
|
-
@font.read_byte.times do
|
117
|
-
@flags << flag
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
@x_coordinates = []
|
122
|
-
@y_coordinates = []
|
123
|
-
[[@x_coordinates, FLAG_X_SHORT_VECTOR, FLAG_X_IS_SAME],
|
124
|
-
[@y_coordinates, FLAG_Y_SHORT_VECTOR, FLAG_Y_IS_SAME]
|
125
|
-
].each do |coordinates, short, same|
|
126
|
-
num_points.times do |i|
|
127
|
-
flag = @flags[i]
|
128
|
-
if flag & short != 0
|
129
|
-
# if the coordinate is a BYTE
|
130
|
-
if flag & same != 0
|
131
|
-
coordinates << @font.read_byte
|
132
|
-
else
|
133
|
-
coordinates << -@font.read_byte
|
134
|
-
end
|
135
|
-
else
|
136
|
-
# the coordinate is a SHORT
|
137
|
-
if flag & same != 0
|
138
|
-
# same so 0 (relative coordinates)
|
139
|
-
coordinates << 0
|
140
|
-
else
|
141
|
-
coordinates << @font.read_short
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
@len = @font.pos - @offset
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
# Returns an Array of [x,y] pairs of relative coordinates.
|
153
|
-
def rel_coordinates
|
154
|
-
coords = []
|
155
|
-
@x_coordinates.length.times do |i|
|
156
|
-
coords << [@x_coordinates[i], @y_coordinates[i]]
|
157
|
-
end
|
158
|
-
coords
|
159
|
-
end
|
160
|
-
|
161
|
-
# Returns an Array of [x,y] pairs of absolute coordinates.
|
162
|
-
def abs_coordinates
|
163
|
-
abs_x = 0
|
164
|
-
abs_y = 0
|
165
|
-
coords = []
|
166
|
-
rel_coordinates.each do |rel_x, rel_y|
|
167
|
-
abs_x += rel_x
|
168
|
-
abs_y += rel_y
|
169
|
-
coords << [abs_x, abs_y]
|
170
|
-
end
|
171
|
-
coords
|
172
|
-
end
|
173
|
-
|
174
|
-
# Returns an Array of Point objects.
|
175
|
-
def points
|
176
|
-
x_abs = 0
|
177
|
-
y_abs = 0
|
178
|
-
pnts = []
|
179
|
-
@x_coordinates.length.times do |i|
|
180
|
-
pnt = Point.new
|
181
|
-
pnt.rel_x = @x_coordinates[i]
|
182
|
-
pnt.rel_y = @y_coordinates[i]
|
183
|
-
x_abs += pnt.rel_x
|
184
|
-
y_abs += pnt.rel_y
|
185
|
-
pnt.abs_x = x_abs
|
186
|
-
pnt.abs_y = y_abs
|
187
|
-
pnt.end_of_contour = @end_pts_of_contours.include? i
|
188
|
-
pnt.on_curve = (@flags[i] & FLAG_ON_CURVE != 0)
|
189
|
-
pnts << pnt
|
190
|
-
end
|
191
|
-
pnts
|
192
|
-
end
|
193
|
-
|
194
|
-
def dump
|
195
|
-
raw = super
|
196
|
-
raw += @end_pts_of_contours.to_ushorts
|
197
|
-
raw += @instructions.length.to_ushort
|
198
|
-
raw += @instructions.to_bytes
|
199
|
-
|
200
|
-
tmp = ""
|
201
|
-
[[@x_coordinates, FLAG_X_SHORT_VECTOR, FLAG_X_IS_SAME],
|
202
|
-
[@y_coordinates, FLAG_Y_SHORT_VECTOR, FLAG_Y_IS_SAME]
|
203
|
-
].each do |coordinates, short, same|
|
204
|
-
coordinates.each_with_index do |coord, i|
|
205
|
-
if 0 <= coord and coord <= 255
|
206
|
-
@flags[i] = (@flags[i] | short) | same
|
207
|
-
tmp += coord.to_byte
|
208
|
-
elsif -255 <= coord and coord < 0
|
209
|
-
@flags[i] = (@flags[i] | short) & ~same
|
210
|
-
tmp += (-coord).to_byte
|
211
|
-
elsif coord == 0
|
212
|
-
@flags[i] = (@flags[i] & ~short) | same
|
213
|
-
else
|
214
|
-
@flags[i] = (@flags[i] & ~short) & ~same
|
215
|
-
tmp += coord.to_short
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
# We write all flags rather than using the flag_repeat trick
|
221
|
-
# So we unset the "repeat" bit for all flags
|
222
|
-
# TODO: implement the repeat feature (this saves space)
|
223
|
-
raw += @flags.collect { |f| f & ~FLAG_REPEAT }.to_bytes
|
224
|
-
|
225
|
-
raw += tmp
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
# CompositeGlyph class.
|
230
|
-
class CompositeGlyph < Glyph
|
231
|
-
|
232
|
-
GlyphComponent = Struct.new(:flags, :index, :args, :scale,
|
233
|
-
:xscale, :yscale, :scale01, :scale10)
|
234
|
-
|
235
|
-
ARG_1_AND_2_ARE_WORDS = 0b1
|
236
|
-
ARGS_ARE_XY_VALUES = 0b10
|
237
|
-
ROUND_XY_TO_GRID = 0b100
|
238
|
-
WE_HAVE_A_SCALE = 0b1000
|
239
|
-
RESERVED = 0b10000
|
240
|
-
MORE_COMPONENTS = 0b100000
|
241
|
-
WE_HAVE_AN_X_AND_Y_SCALE = 0b1000000
|
242
|
-
WE_HAVE_A_TWO_BY_TWO = 0b10000000
|
243
|
-
WE_HAVE_INSTRUCTIONS = 0b100000000
|
244
|
-
USE_MY_METRICS = 0b1000000000
|
245
|
-
|
246
|
-
# An Array of GlyphComponent objects
|
247
|
-
attr_accessor :components
|
248
|
-
# An Array of instructions (Fixnums)
|
249
|
-
attr_accessor :instructions
|
250
|
-
|
251
|
-
def initialize(*args)
|
252
|
-
super(*args)
|
253
|
-
|
254
|
-
if exists_in_file?
|
255
|
-
offs = @offset + IO::SIZEOF_SHORT + 4 * IO::SIZEOF_FWORD
|
256
|
-
@font.at_offset(offs) do
|
257
|
-
@components = []
|
258
|
-
continue = true
|
259
|
-
while continue
|
260
|
-
gc = GlyphComponent.new
|
261
|
-
gc.flags = @font.read_ushort
|
262
|
-
gc.index = @font.read_ushort
|
263
|
-
|
264
|
-
gc.args = []
|
265
|
-
if gc.flags & ARG_1_AND_2_ARE_WORDS != 0
|
266
|
-
gc.args[0] = @font.read_short
|
267
|
-
gc.args[1] = @font.read_short
|
268
|
-
else
|
269
|
-
gc.args[0] = @font.read_ushort
|
270
|
-
end
|
271
|
-
|
272
|
-
if gc.flags & WE_HAVE_A_SCALE != 0
|
273
|
-
gc.scale = @font.read_f2dot14
|
274
|
-
elsif gc.flags & WE_HAVE_AN_X_AND_Y_SCALE != 0
|
275
|
-
gc.xscale = @font.read_f2dot14
|
276
|
-
gc.yscale = @font.read_f2dot14
|
277
|
-
elsif gc.flags & WE_HAVE_A_TWO_BY_TWO != 0
|
278
|
-
gc.xscale = @font.read_f2dot14
|
279
|
-
gc.scale01 = @font.read_f2dot14
|
280
|
-
gc.scale10 = @font.read_f2dot14
|
281
|
-
gc.yscale = @font.read_f2dot14
|
282
|
-
end
|
283
|
-
@components << gc
|
284
|
-
continue = (gc.flags & MORE_COMPONENTS != 0)
|
285
|
-
end
|
286
|
-
|
287
|
-
if @components.last.flags & \
|
288
|
-
WE_HAVE_INSTRUCTIONS != 0
|
289
|
-
inst_len = @font.read_ushort
|
290
|
-
@instructions = @font.read_bytes(inst_len)
|
291
|
-
else
|
292
|
-
@instructions = []
|
293
|
-
end
|
294
|
-
|
295
|
-
@len = @font.pos - @offset
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
def dump
|
301
|
-
raw = super
|
302
|
-
components_len = @components.length
|
303
|
-
@components.each_with_index do |gc, i|
|
304
|
-
flags = gc.flags
|
305
|
-
tmp = ""
|
306
|
-
if not gc.args.nil? and gc.args.length == 2
|
307
|
-
flags |= ARG_1_AND_2_ARE_WORDS
|
308
|
-
tmp += gc.args[0].to_short
|
309
|
-
tmp += gc.args[1].to_short
|
310
|
-
else
|
311
|
-
flags &= ~ARG_1_AND_2_ARE_WORDS
|
312
|
-
tmp += gc.args[0].to_ushort
|
313
|
-
end
|
314
|
-
if not gc.scale.nil?
|
315
|
-
flags |= WE_HAVE_A_SCALE
|
316
|
-
tmp += gc.scale.to_f2dot14
|
317
|
-
elsif not gc.scale01.nil?
|
318
|
-
flags |= WE_HAVE_A_TWO_BY_TWO
|
319
|
-
tmp += gc.xscale.to_f2dot14
|
320
|
-
tmp += gc.scale01.to_f2dot14
|
321
|
-
tmp += gc.scale10.to_f2dot14
|
322
|
-
tmp += gc.yscale.to_f2dot14
|
323
|
-
elsif not gc.xscale.nil?
|
324
|
-
flags |= WE_HAVE_AN_X_AND_Y_SCALE
|
325
|
-
tmp += gc.xscale.to_f2dot14
|
326
|
-
tmp += gc.yscale.to_f2dot14
|
327
|
-
end
|
328
|
-
|
329
|
-
if i < components_len - 1
|
330
|
-
flags |= MORE_COMPONENTS
|
331
|
-
else
|
332
|
-
flags &= ~MORE_COMPONENTS
|
333
|
-
if @instructions.length > 0
|
334
|
-
flags |= WE_HAVE_INSTRUCTIONS
|
335
|
-
else
|
336
|
-
flags &= ~WE_HAVE_INSTRUCTIONS
|
337
|
-
end
|
338
|
-
end
|
339
|
-
raw += flags.to_ushort
|
340
|
-
raw += gc.index.to_ushort
|
341
|
-
raw += tmp
|
342
|
-
end
|
343
|
-
unless @instructions.empty?
|
344
|
-
raw += @instructions.length.to_ushort
|
345
|
-
raw += @instructions.to_bytes
|
346
|
-
end
|
347
|
-
raw
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
attr_accessor :glyphs
|
352
|
-
|
353
|
-
def initialize(*args)
|
354
|
-
super(*args)
|
355
|
-
end
|
356
|
-
|
357
|
-
# Returns the kind of glyph at offset, i.e. either SimpleGlyph
|
358
|
-
# or CompositeGlyph.
|
359
|
-
def kind_of_glyph_at_offset(offs_from_table)
|
360
|
-
@font.at_offset(@offset + offs_from_table) do
|
361
|
-
num_contours = @font.read_short
|
362
|
-
if num_contours >= 0
|
363
|
-
SimpleGlyph
|
364
|
-
else
|
365
|
-
CompositeGlyph
|
366
|
-
end
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
def get_glyph_at_offset(offs_from_table)
|
371
|
-
klass = kind_of_glyph_at_offset(offs_from_table)
|
372
|
-
klass.new(self, offs_from_table)
|
373
|
-
end
|
374
|
-
|
375
|
-
def get_glyphs
|
376
|
-
loca = @font.get_table(:loca)
|
377
|
-
glyphs = []
|
378
|
-
loca.glyph_offsets[0...-1].each do |off|
|
379
|
-
glyphs << get_glyph_at_offset(off)
|
380
|
-
end
|
381
|
-
glyphs
|
382
|
-
end
|
383
|
-
private :get_glyphs
|
384
|
-
|
385
|
-
# Returns all Glyph (SimpleGlyph or CompositeGlyph) in an Array.
|
386
|
-
# This method may be real overkill if you just need to access a few glyphs.
|
387
|
-
# In this case, you should use the loca table (Font::TTF::Table::Loca)
|
388
|
-
# to get offsets and get_glyph_at_offset to get glyph associated with them.
|
389
|
-
def glyphs
|
390
|
-
@glyphs ||= get_glyphs
|
391
|
-
end
|
392
|
-
|
393
|
-
# Sets glyphs. new_glyphs is an Array of Glyph objects.
|
394
|
-
def glyphs=(new_glyphs)
|
395
|
-
@glyphs = new_glyphs
|
396
|
-
@font.get_table(:maxp).num_glyphs = @glyphs.length
|
397
|
-
@font.get_table(:post).num_glyphs = @glyphs.length
|
398
|
-
end
|
399
|
-
|
400
|
-
# Iterates over each glyph.
|
401
|
-
# It does not load all glyphs like glyphs.each would do.
|
402
|
-
def each_glyph
|
403
|
-
loca = @font.get_table(:loca)
|
404
|
-
glyphs = []
|
405
|
-
loca.glyph_offsets[0...-1].each do |off|
|
406
|
-
glyph = get_glyph_at_offset(off)
|
407
|
-
yield glyph
|
408
|
-
end
|
409
|
-
end
|
410
|
-
|
411
|
-
# Dumps the glyf table in binary raw format as may be found in a font
|
412
|
-
# file.
|
413
|
-
def dump
|
414
|
-
raw = ""
|
415
|
-
offs = 0
|
416
|
-
glyph_offsets = []
|
417
|
-
glyphs.each do |glyph|
|
418
|
-
glyph_offsets << offs
|
419
|
-
dump = glyph.dump
|
420
|
-
len = dump.length
|
421
|
-
raw += dump
|
422
|
-
# offsets should be multiples of SIZEOF_ULONG
|
423
|
-
diff = len % IO::SIZEOF_ULONG
|
424
|
-
raw += " " * diff
|
425
|
-
offs += len + diff
|
426
|
-
end
|
427
|
-
# An additional offset is added so that the length of the last
|
428
|
-
# glyph can be calculated:
|
429
|
-
# len of last glyph = additional offs - last glyph offs
|
430
|
-
glyph_offsets << offs
|
431
|
-
|
432
|
-
# 2 ** 16 * 2 = 131072 is the maximum size supported
|
433
|
-
# if the short format is used in the loca table
|
434
|
-
# Using shorts saves two bytes per glyph!
|
435
|
-
if offs < 131072
|
436
|
-
@font.get_table(:head).index_to_loc_format = \
|
437
|
-
Font::TTF::Table::Head::SHORT_FORMAT
|
438
|
-
else
|
439
|
-
@font.get_table(:head).index_to_loc_format = \
|
440
|
-
Font::TTF::Table::Head::LONG_FORMAT
|
441
|
-
end
|
442
|
-
|
443
|
-
@font.get_table(:loca).glyph_offsets = glyph_offsets
|
444
|
-
|
445
|
-
raw
|
446
|
-
end
|
447
|
-
|
448
|
-
end
|
449
|
-
|
450
|
-
end
|
451
|
-
end
|
452
|
-
end
|