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.
Files changed (144) hide show
  1. data/README +6 -10
  2. data/Rakefile +4 -13
  3. data/data/encodings/win_ansi.txt +29 -0
  4. data/data/images/fractal.jpg +0 -0
  5. data/data/images/letterhead.jpg +0 -0
  6. data/examples/bounding_box/bounding_boxes.rb +44 -0
  7. data/examples/bounding_box/lazy_bounding_boxes.rb +28 -0
  8. data/examples/bounding_box/padded_box.rb +24 -0
  9. data/examples/{russian_boxes.rb → bounding_box/russian_boxes.rb} +9 -6
  10. data/examples/general/background.rb +20 -0
  11. data/examples/{canvas.rb → general/canvas.rb} +6 -2
  12. data/examples/general/measurement_units.rb +52 -0
  13. data/examples/{multi_page_layout.rb → general/multi_page_layout.rb} +6 -3
  14. data/examples/{page_geometry.rb → general/page_geometry.rb} +6 -2
  15. data/examples/{image.rb → graphics/basic_images.rb} +8 -4
  16. data/examples/graphics/cmyk.rb +13 -0
  17. data/examples/graphics/curves.rb +12 -0
  18. data/examples/{hexagon.rb → graphics/hexagon.rb} +5 -5
  19. data/examples/graphics/image_fit.rb +16 -0
  20. data/examples/graphics/image_flow.rb +38 -0
  21. data/examples/graphics/image_position.rb +18 -0
  22. data/examples/{line.rb → graphics/line.rb} +4 -2
  23. data/examples/{png_types.rb → graphics/png_types.rb} +4 -4
  24. data/examples/{polygons.rb → graphics/polygons.rb} +5 -4
  25. data/examples/graphics/remote_images.rb +12 -0
  26. data/examples/{ruport_helpers.rb → graphics/ruport_style_helpers.rb} +8 -5
  27. data/examples/graphics/stroke_bounds.rb +23 -0
  28. data/examples/{chinese_text_wrapping.rb → m17n/chinese_text_wrapping.rb} +7 -4
  29. data/examples/m17n/euro.rb +16 -0
  30. data/examples/m17n/sjis.rb +29 -0
  31. data/examples/m17n/utf8.rb +14 -0
  32. data/examples/m17n/win_ansi_charset.rb +55 -0
  33. data/examples/{addressbook.csv → table/addressbook.csv} +0 -0
  34. data/examples/{cell.rb → table/cell.rb} +8 -6
  35. data/examples/{currency.csv → table/currency.csv} +0 -0
  36. data/examples/{fancy_table.rb → table/fancy_table.rb} +9 -6
  37. data/examples/{ruport_formatter.rb → table/ruport_formatter.rb} +6 -3
  38. data/examples/{table.rb → table/table.rb} +6 -2
  39. data/examples/table/table_alignment.rb +18 -0
  40. data/examples/table/table_border_color.rb +17 -0
  41. data/examples/table/table_colspan.rb +19 -0
  42. data/examples/table/table_header_color.rb +19 -0
  43. data/examples/table/table_header_underline.rb +15 -0
  44. data/examples/{alignment.rb → text/alignment.rb} +5 -2
  45. data/examples/text/family_based_styling.rb +25 -0
  46. data/examples/{flowing_text_with_header_and_footer.rb → text/flowing_text_with_header_and_footer.rb} +19 -8
  47. data/examples/text/font_calculations.rb +91 -0
  48. data/examples/text/font_size.rb +34 -0
  49. data/examples/{kerning.rb → text/kerning.rb} +5 -1
  50. data/examples/text/simple_text.rb +18 -0
  51. data/examples/text/simple_text_ttf.rb +18 -0
  52. data/examples/{span.rb → text/span.rb} +5 -2
  53. data/examples/text/text_box.rb +26 -0
  54. data/examples/{text_flow.rb → text/text_flow.rb} +5 -2
  55. data/lib/prawn.rb +26 -20
  56. data/lib/prawn/compatibility.rb +5 -8
  57. data/lib/prawn/document.rb +29 -13
  58. data/lib/prawn/document/annotations.rb +63 -0
  59. data/lib/prawn/document/bounding_box.rb +18 -3
  60. data/lib/prawn/document/destinations.rb +81 -0
  61. data/lib/prawn/document/internals.rb +16 -2
  62. data/lib/prawn/document/page_geometry.rb +58 -57
  63. data/lib/prawn/document/span.rb +8 -0
  64. data/lib/prawn/document/table.rb +81 -31
  65. data/lib/prawn/document/text.rb +66 -21
  66. data/lib/prawn/document/text/box.rb +77 -0
  67. data/lib/prawn/encoding.rb +121 -0
  68. data/lib/prawn/errors.rb +4 -0
  69. data/lib/prawn/font.rb +70 -42
  70. data/lib/prawn/font/metrics.rb +64 -119
  71. data/lib/prawn/graphics.rb +105 -87
  72. data/lib/prawn/graphics/cell.rb +55 -28
  73. data/lib/prawn/graphics/color.rb +8 -0
  74. data/lib/prawn/images.rb +55 -12
  75. data/lib/prawn/images/jpg.rb +2 -1
  76. data/lib/prawn/images/png.rb +2 -1
  77. data/lib/prawn/literal_string.rb +14 -0
  78. data/lib/prawn/measurement_extensions.rb +46 -0
  79. data/lib/prawn/measurements.rb +71 -0
  80. data/lib/prawn/name_tree.rb +165 -0
  81. data/lib/prawn/pdf_object.rb +8 -1
  82. data/spec/annotations_spec.rb +90 -0
  83. data/spec/destinations_spec.rb +15 -0
  84. data/spec/document_spec.rb +39 -2
  85. data/spec/font_spec.rb +22 -0
  86. data/spec/graphics_spec.rb +99 -87
  87. data/spec/images_spec.rb +29 -1
  88. data/spec/measurement_units_spec.rb +23 -0
  89. data/spec/metrics_spec.rb +3 -2
  90. data/spec/name_tree_spec.rb +103 -0
  91. data/spec/pdf_object_spec.rb +15 -5
  92. data/spec/png_spec.rb +14 -14
  93. data/spec/spec_helper.rb +8 -6
  94. data/spec/table_spec.rb +40 -0
  95. data/spec/text_spec.rb +6 -4
  96. data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
  97. data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
  98. data/vendor/ttfunk/example.rb +5 -0
  99. data/vendor/ttfunk/lib/ttfunk.rb +48 -0
  100. data/vendor/ttfunk/lib/ttfunk/table.rb +27 -0
  101. data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +94 -0
  102. data/vendor/ttfunk/lib/ttfunk/table/directory.rb +25 -0
  103. data/vendor/ttfunk/lib/ttfunk/table/head.rb +25 -0
  104. data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +27 -0
  105. data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +20 -0
  106. data/vendor/ttfunk/lib/ttfunk/table/kern.rb +48 -0
  107. data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +17 -0
  108. data/vendor/ttfunk/lib/ttfunk/table/name.rb +52 -0
  109. metadata +93 -62
  110. data/examples/bounding_boxes.rb +0 -30
  111. data/examples/curves.rb +0 -10
  112. data/examples/family_based_styling.rb +0 -21
  113. data/examples/font_size.rb +0 -19
  114. data/examples/image2.rb +0 -13
  115. data/examples/image_flow.rb +0 -29
  116. data/examples/lazy_bounding_boxes.rb +0 -19
  117. data/examples/remote_images.rb +0 -7
  118. data/examples/simple_text.rb +0 -15
  119. data/examples/simple_text_ttf.rb +0 -16
  120. data/examples/sjis.rb +0 -21
  121. data/examples/utf8.rb +0 -12
  122. data/vendor/font_ttf/ttf.rb +0 -20
  123. data/vendor/font_ttf/ttf/datatypes.rb +0 -189
  124. data/vendor/font_ttf/ttf/encodings.rb +0 -140
  125. data/vendor/font_ttf/ttf/exceptions.rb +0 -28
  126. data/vendor/font_ttf/ttf/file.rb +0 -290
  127. data/vendor/font_ttf/ttf/fontchunk.rb +0 -77
  128. data/vendor/font_ttf/ttf/table/cmap.rb +0 -408
  129. data/vendor/font_ttf/ttf/table/cvt.rb +0 -49
  130. data/vendor/font_ttf/ttf/table/fpgm.rb +0 -48
  131. data/vendor/font_ttf/ttf/table/gasp.rb +0 -88
  132. data/vendor/font_ttf/ttf/table/glyf.rb +0 -452
  133. data/vendor/font_ttf/ttf/table/head.rb +0 -86
  134. data/vendor/font_ttf/ttf/table/hhea.rb +0 -96
  135. data/vendor/font_ttf/ttf/table/hmtx.rb +0 -98
  136. data/vendor/font_ttf/ttf/table/kern.rb +0 -186
  137. data/vendor/font_ttf/ttf/table/loca.rb +0 -75
  138. data/vendor/font_ttf/ttf/table/maxp.rb +0 -81
  139. data/vendor/font_ttf/ttf/table/name.rb +0 -222
  140. data/vendor/font_ttf/ttf/table/os2.rb +0 -172
  141. data/vendor/font_ttf/ttf/table/post.rb +0 -120
  142. data/vendor/font_ttf/ttf/table/prep.rb +0 -27
  143. data/vendor/font_ttf/ttf/table/vhea.rb +0 -45
  144. data/vendor/font_ttf/ttf/table/vmtx.rb +0 -36
@@ -1,28 +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
-
21
- class MalformedFont < Exception
22
- end
23
-
24
- class TableMissing < Exception
25
- end
26
-
27
- end
28
- end
@@ -1,290 +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
- require 'ttf/datatypes'
19
- require 'ttf/exceptions'
20
- require 'ttf/fontchunk'
21
- require 'ttf/encodings'
22
-
23
- require 'ttf/table/cmap'
24
- require 'ttf/table/cvt'
25
- require 'ttf/table/fpgm'
26
- require 'ttf/table/gasp'
27
- require 'ttf/table/glyf'
28
- require 'ttf/table/head'
29
- require 'ttf/table/hhea'
30
- require 'ttf/table/hmtx'
31
- require 'ttf/table/kern'
32
- require 'ttf/table/loca'
33
- require 'ttf/table/maxp'
34
- require 'ttf/table/name'
35
- require 'ttf/table/os2'
36
- require 'ttf/table/post'
37
- require 'ttf/table/prep'
38
- require 'ttf/table/vhea'
39
- require 'ttf/table/vmtx'
40
-
41
- module Font
42
- module TTF
43
- # TTF/Ruby is a library to read and write TrueType fonts in Ruby.
44
- #
45
- # Author:: Mathieu Blondel
46
- # Copyright:: Copyright (c) 2006 Mathieu Blondel
47
- # License:: GPL
48
- #
49
- # This Font::TTF::File class is TTF/Ruby's main class and is a subclass
50
- # of Ruby's File class. Here is some sample code:
51
- #
52
- # require 'ttf'
53
- #
54
- # font = Font::TTF::File.new("copy.ttf")
55
- #
56
- # cmap_tbl = font.get_table(:cmap)
57
- # enc_tbl4 = cmap_tbl.encoding_tables.find { |t| t.format == 4 }
58
- # m_unicode = "m".unpack("U")[0]
59
- # glyph_id = enc_tbl4.charmaps[m_unicode]
60
- #
61
- # loca_tbl = font.get_table(:loca)
62
- # glyph_offset = loca_tbl.glyph_offsets[glyph_id]
63
- #
64
- # glyf_tbl = font.get_table(:glyf)
65
- # glyph = glyf_tbl.get_glyph_at_offset(glyph_offset)
66
- # unless glyph.composite?
67
- # glyph.abs_coordinates.each { |x, y| puts x, y }
68
- # end
69
- #
70
- # Here are the tables and their associated Symbol:
71
- #
72
- # * :cmap => Font::TTF::Table::Cmap
73
- # * :cvt => Font::TTF::Table::Cvt
74
- # * :fpgm => Font::TTF::Table::Fpgm
75
- # * :gasp => Font::TTF::Table::Gasp
76
- # * :glyf => Font::TTF::Table::Glyf
77
- # * :head => Font::TTF::Table::Head
78
- # * :hhea => Font::TTF::Table::Hhea
79
- # * :hmtx => Font::TTF::Table::Hmtx
80
- # * :kern => Font::TTF::Table::Kern
81
- # * :loca => Font::TTF::Table::Loca
82
- # * :maxp => Font::TTF::Table::Maxp
83
- # * :name => Font::TTF::Table::Name
84
- # * :"OS/2" => Font::TTF::Table::OS2
85
- # * :post => Font::TTF::Table::Post
86
- # * :prep => Font::TTF::Table::Prep
87
- # * :vhea => Font::TTF::Table::Vhea
88
- # * :vmtx => Font::TTF::Table::Vmtx
89
- #
90
- # Of course, you may modify attributes and generate a new font file.
91
- #
92
- # require "ttf"
93
- #
94
- # font = Font::TTF::File.new("file.ttf", "w")
95
- # name_tbl = font.get_table(:name)
96
- # nr = name_tbl.name_records[0]
97
- # nr.utf8_str = "blablabla"
98
- # font.write(font.dump)
99
- #
100
- class File < File
101
-
102
- TABLES = {:cmap => Font::TTF::Table::Cmap,
103
- :cvt => Font::TTF::Table::Cvt,
104
- :fpgm => Font::TTF::Table::Fpgm,
105
- :gasp => Font::TTF::Table::Gasp,
106
- :glyf => Font::TTF::Table::Glyf,
107
- :head => Font::TTF::Table::Head,
108
- :hhea => Font::TTF::Table::Hhea,
109
- :hmtx => Font::TTF::Table::Hmtx,
110
- :kern => Font::TTF::Table::Kern,
111
- :loca => Font::TTF::Table::Loca,
112
- :maxp => Font::TTF::Table::Maxp,
113
- :name => Font::TTF::Table::Name,
114
- :"OS/2" => Font::TTF::Table::OS2,
115
- :post => Font::TTF::Table::Post,
116
- :prep => Font::TTF::Table::Prep,
117
- :vhea => Font::TTF::Table::Vhea,
118
- :vmtx => Font::TTF::Table::Vmtx}
119
-
120
- DIR_ENTRY_SIZE = 4 * IO::SIZEOF_ULONG
121
-
122
- attr_reader :filename, :version, :search_range,
123
- :entry_selector, :range_shift, :table_list, :tables_infos
124
-
125
- attr_writer :version, :search_range, :entry_selector, :range_shift
126
-
127
- # Font::TTF::File being a subclass of Ruby's File class, you may
128
- # create new objects with the same parameters as Ruby's File class.
129
- #
130
- # But you may also create new objects without parameters in case you want
131
- # to create a font from scratch and you don't need to write it to a file.
132
- def initialize(*args)
133
- if args.length == 0
134
- @filename = nil
135
- @version = 0x00010000 # 1.0
136
- else
137
- super(*args)
138
- @filename = args[0]
139
- end
140
-
141
- @table_list = [] # ordered list
142
- @tables = {} # Tables are kept in this arr so we don't
143
- # have to create new objects everytime
144
- @tables_infos = {} # infos about tables present in file
145
-
146
- if not @filename.nil? and FileTest.exists? @filename
147
- begin
148
- at_offset(0) do
149
- @version = read_fixed
150
- table_num = read_ushort
151
- @search_range = read_ushort
152
- @entry_selector = read_ushort
153
- @range_shift = read_ushort
154
-
155
- table_num.times do
156
- tag = read_ulong_as_text.strip.to_sym
157
- @table_list << tag
158
- @tables_infos[tag] = {:checksum => read_ulong,
159
- :offset => read_ulong,
160
- :len => read_ulong}
161
- end
162
- end
163
- rescue
164
- raise MalformedFont
165
- end
166
- end
167
- end
168
-
169
- # Returns table associated with tag tbl_tag. It may return one of
170
- # Font::TTF::Table::* object or a Font::TTF::FontChunk object if the
171
- # table is not implemented yet by ttf-ruby.
172
- #
173
- # The table returned is kept internally so that every future call to
174
- # get_table with the same tbl_tag will return the same object.
175
- def get_table(tbl_tag)
176
- tbli = @tables_infos[tbl_tag]
177
-
178
- if @tables.include? tbl_tag
179
- @tables[tbl_tag]
180
- elsif tbli.nil?
181
- raise TableMissing, "Table #{tbl_tag.to_s} neither exists " + \
182
- "in file nor was defined by user!"
183
-
184
- elsif TABLES.include? tbl_tag
185
- @tables[tbl_tag] = \
186
- TABLES[tbl_tag].new(self, tbli[:offset], tbli[:len])
187
- else
188
- Font::TTF::FontChunk.new(self, tbli[:offset], tbli[:len])
189
- end
190
- end
191
-
192
- # Returns whether table with tag tbl_tag is already in font or not.
193
- def tables_include?(tbl_tag)
194
- @table_list.include? tbl_tag
195
- end
196
-
197
- # Gets a new empty table that then may be set with set_table.
198
- # tbl_tag is a Symbol.
199
- def get_new_table(tbl_tag)
200
- if TABLES.include? tbl_tag
201
- TABLES[tbl_tag].new(self)
202
- else
203
- Font::TTF::FontChunk.new(self)
204
- end
205
- end
206
-
207
- # Updates some member variables that change everytime a table is added
208
- # to the font.
209
- def table_list_update!
210
- @table_list.sort!
211
-
212
- res = 1
213
- power = 0
214
- while res <= @table_list.length
215
- res *= 2
216
- power += 1
217
- end
218
- @search_range = res * 16
219
- @entry_selector = power - 1
220
- @range_shift = @table_list.length * 16 - @search_range
221
- end
222
- private :table_list_update!
223
-
224
- # Adds tbl to font. tbl is a table object
225
- # (e.g. an instance of Font::TTF::Table::Loca).
226
- def set_table(tbl)
227
- tbl_tag = tbl.tag
228
-
229
- unless tables_include? tbl_tag
230
- @table_list << tbl_tag
231
- table_list_update!
232
- end
233
- @tables[tbl_tag] = tbl
234
- end
235
-
236
- # Removes tbl from font. tbl may be a Symbol (e.g. :loca for the loca table)
237
- # or a table object (e.g. an instance of Font::TTF::Table::Loca).
238
- def unset_table(tbl)
239
- if tbl.kind_of? Symbol
240
- tbl_tag = tbl
241
- else
242
- tbl_tag = tbl.tag
243
- end
244
-
245
- @table_list.delete(tbl_tag)
246
- @tables.delete(tbl_tag)
247
- table_list_update!
248
- end
249
-
250
- # Dumps the whole font in binary raw format as found in a font file.
251
- def dump
252
- raw = ""
253
- raw += (@version || 0).to_fixed
254
- raw += (@table_list || []).length.to_ushort
255
- raw += (@search_range || 0).to_ushort
256
- raw += (@entry_selector || 0).to_ushort
257
- raw += (@range_shift || 0).to_ushort
258
-
259
-
260
- offs = IO::SIZEOF_FIXED + 4 * IO::SIZEOF_USHORT + \
261
- @table_list.length * DIR_ENTRY_SIZE
262
-
263
- dumps = []
264
- @table_list.each do |tbl_tag|
265
- tbl = get_table(tbl_tag)
266
- tag = tbl_tag.to_s
267
- tag.four_chars!
268
- raw += tag
269
- # FIXME: FontChunk#checksum method is buggy
270
- # For now, I set it to 0
271
- raw += 0.to_ulong
272
- raw += offs.to_ulong
273
- dump = tbl.dump
274
- dumps << dump
275
- len = dump.length
276
- raw += len.to_ulong
277
- offs += len
278
- end
279
-
280
- dumps.each do |dump|
281
- raw += dump
282
- end
283
-
284
- raw
285
- end
286
-
287
- end
288
-
289
- end
290
- end
@@ -1,77 +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
-
21
- # A FontChunk is a portion of font. It starts at an offset and has a given
22
- # length. It is useful to handle tables that have not been implemented
23
- # or to quickly get a dump for a table that has not been modified.
24
- class FontChunk
25
-
26
- attr_reader :font
27
- attr_accessor :offset, :len
28
-
29
- def initialize(font, offset=nil, len=nil)
30
- @font = font
31
- # When a FontChunk is modified by user,
32
- # offset and len are not true anymore
33
- @offset = offset
34
- @len = len
35
- end
36
-
37
- # Returns the end of the class name as a Symbol.
38
- # Will be useful for tables, which are subclasses of FontChunk.
39
- # For example, calling tag on Font::TTF:Table::Loca object will return
40
- # :loca.
41
- def tag
42
- t = self.class.name.split("::").last.downcase.to_sym
43
- t = :"OS/2" if t == :os2
44
- t
45
- end
46
-
47
- # Basically each table is a FontChunk and tables may be created by hand
48
- # (i.e. not exist in file yet). This method returns whether the FontChunk
49
- # already exists in file or not.
50
- def exists_in_file?
51
- not @offset.nil?
52
- end
53
-
54
- # Returns raw binary data of the FontChunk.
55
- def dump
56
- @font.at_offset(@offset) do
57
- @font.read(@len)
58
- end
59
- end
60
-
61
- # Returns a checksum of dump.
62
- def self.checksum(dump)
63
- # FIXME: this methods seems to be buggy
64
- len = ((raw.length + 3) & ~3) / IO::SIZEOF_ULONG
65
- sum = 0
66
- (len - 1).times do |i|
67
- ulong_str = raw.slice(i * IO::SIZEOF_ULONG, IO::SIZEOF_ULONG)
68
- ulong = ulong_str.unpack("N")[0]
69
- sum += ulong
70
- end
71
- sum
72
- end
73
-
74
- end
75
-
76
- end
77
- end
@@ -1,408 +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
- # Cmap is the character to glyph index mapping table.
23
- class Cmap < Font::TTF::FontChunk
24
-
25
- # Base class for encoding table classes. It provides attributes which are
26
- # common to those classes such as platform_id and encoding_id.
27
- class EncodingTable < Font::TTF::FontChunk
28
-
29
- attr_accessor :table, :platform_id, :encoding_id, :offset_from_table
30
-
31
- def initialize(table, offset=nil, len=nil, platform_id=nil,
32
- encoding_id=nil)
33
- @table = table
34
- @font = table.font
35
-
36
- if not offset.nil?
37
- @offset_from_table = offset
38
- @platform_id = platform_id
39
- @encoding_id = encoding_id
40
- super(@table.font, @table.offset + offset, len)
41
- else
42
- super(@table.font)
43
- end
44
- end
45
-
46
- def unicode?
47
- @platform_id == Font::TTF::Encodings::Platform::UNICODE or \
48
- (@platform_id == Font::TTF::Encodings::Platform::MICROSOFT and \
49
- @encoding_id == Font::TTF::Encodings::MicrosoftEncoding::UNICODE)
50
- end
51
-
52
- # Returns the format (a Fixnum) of the encoding table.
53
- def format
54
- if self.class.superclass == EncodingTable
55
- self.class.name.split(//).last.to_i
56
- else
57
- nil # Not implemented table format
58
- end
59
- end
60
-
61
- end
62
-
63
- # Encoding table in format 0, the Apple standard character to glyph
64
- # mapping table.
65
- class EncodingTable0 < EncodingTable
66
-
67
- attr_accessor :version
68
- # An array of 256 elements with simple one to one mapping of
69
- # character codes to glyph indices.
70
- #
71
- # Char 0 => Index glyph_id_array[0]
72
- # Char 1 => Index glyph_id_array[1]
73
- # ...
74
- attr_accessor :glyph_id_array
75
-
76
- def initialize(*args)
77
- super(*args)
78
- if exists_in_file?
79
- # 2 * IO::SIZEOF_USHORT corresponds to format and len
80
- # that we want to skip
81
- @table.font.at_offset(@offset + 2 * IO::SIZEOF_USHORT) do
82
- @version = @font.read_ushort
83
- @glyph_id_array = @font.read_bytes(256)
84
- end
85
- else
86
- # This is to ensure that it will be an array
87
- @glyph_id_array = []
88
- end
89
- end
90
-
91
- # Dumps the table in binary raw format as may be found in a font
92
- # file.
93
- def dump
94
- raw = (format || 0).to_ushort
95
- len = 3 * IO::SIZEOF_USHORT + 256
96
- raw += len.to_ushort
97
- raw += (@version || 0).to_ushort
98
- raw += @glyph_id_array.to_bytes
99
- end
100
- end
101
-
102
- # Encoding table in format 2. Not implemented.
103
- class EncodingTable2 < EncodingTable
104
- end
105
-
106
- # Encoding table in format 4. This format is well-suited to map
107
- # several contiguous ranges, possibly with holes of characters.
108
- class EncodingTable4 < EncodingTable
109
-
110
- attr_accessor :version
111
-
112
- attr_reader :search_range, :entry_selector, :range_shift,
113
- :end_count_array, :reserved_pad, :start_count_array,
114
- :id_delta_array, :id_range_offset_array,
115
- :glyph_index_array, :segments
116
-
117
- def initialize(*args)
118
- super(*args)
119
-
120
- if exists_in_file?
121
- # 2 * IO::SIZEOF_USHORT corresponds to format and len
122
- # that we want to skip
123
- @table.font.at_offset(@offset + 2 * IO::SIZEOF_USHORT) do
124
- @version = @font.read_ushort
125
- @seg_count_x2 = @font.read_ushort
126
- @seg_count = @seg_count_x2 / 2
127
- @search_range = @font.read_ushort
128
- @entry_selector = @font.read_ushort
129
- @range_shift = @font.read_ushort
130
- @end_count_array = @font.read_ushorts(@seg_count)
131
- @reserved_pad = @font.read_ushort
132
- @start_count_array = @font.read_ushorts(@seg_count)
133
- @id_delta_array = @font.read_ushorts(@seg_count)
134
- @id_range_offset_array = @font.read_ushorts(@seg_count)
135
-
136
- @nb_glyph_indices = len - 8 * IO::SIZEOF_USHORT \
137
- - 4 * @seg_count * IO::SIZEOF_USHORT
138
- @nb_glyph_indices /= IO::SIZEOF_USHORT;
139
-
140
- if @nb_glyph_indices > 0
141
- @glyph_index_array = \
142
- @font.read_ushorts(@nb_glyph_indices)
143
- else
144
- @glyph_index_array = []
145
- end
146
-
147
- # Keep them in memory so we don't need to
148
- # recalculate them every time
149
- @segments = get_segments
150
- end # end at_offset
151
- else
152
- @segments = []
153
- @glyph_index_array = []
154
- end
155
- end # end initialize
156
-
157
- def get_segments
158
- segments = []
159
-
160
- # For each segment...
161
- @start_count_array.each_with_index do |start, curr_seg|
162
- endd = @end_count_array[curr_seg]
163
- delta = @id_delta_array[curr_seg]
164
- range = @id_range_offset_array[curr_seg]
165
-
166
- segments[curr_seg] = {}
167
-
168
- start.upto(endd) do |curr_char|
169
- if range == 0
170
- index = (curr_char + delta)
171
- else
172
- gindex = range / 2 + (curr_char - start) - \
173
- (@seg_count - curr_seg)
174
- index = @glyph_index_array[gindex]
175
- index = 0 if index.nil?
176
- index += delta if index != 0
177
- end
178
- index = index % 65536
179
- # charcode => glyph index
180
- segments[curr_seg][curr_char] = index
181
- end
182
- end
183
- segments
184
- end
185
- private :get_segments
186
-
187
- # Returns a Hash. Its keys are characters codes and associated values
188
- # are glyph indices.
189
- def charmaps
190
- hsh = {}
191
- segments.each do |seg|
192
- seg.each do |char_code, glyph_index|
193
- hsh[char_code] = glyph_index
194
- end
195
- end
196
- hsh
197
- end
198
-
199
- # Sets the charmaps. cmps is a Hash in the same fashion as the one
200
- # returned by charmaps.
201
- def charmaps=(cmps)
202
- # TODO: we would need fewer segments if we ensured that
203
- # glyphs with id in ascending order were associated
204
- # with char codes in ascending order
205
- raise "Charmaps is an empty array" if cmps.length == 0
206
-
207
- # Order is important since we will rebuild segments
208
- char_codes = cmps.keys.sort
209
-
210
- @start_count_array = []
211
- @end_count_array = []
212
- @id_delta_array = []
213
- curr_seg = 0
214
- i = 0
215
-
216
- @start_count_array[0] = char_codes.first
217
- @id_delta_array[0] = cmps[char_codes.first] - char_codes.first
218
-
219
- last_char = 0
220
- char_codes.each do |char_code|
221
- glyph_id = cmps[char_code]
222
- curr_delta = glyph_id - char_code
223
- if i > 0 and curr_delta != @id_delta_array.last
224
- # Need to create a new segment
225
- @end_count_array[curr_seg] = last_char
226
- curr_seg += 1
227
- @start_count_array[curr_seg] = char_code
228
- @id_delta_array[curr_seg] = curr_delta
229
- end
230
- last_char = char_code
231
- i += 1
232
- end
233
- seg_count = @start_count_array.length
234
- @end_count_array[seg_count - 1] = last_char
235
- @id_range_offset_array = [0] * seg_count # Range offsets not used
236
- @segments = get_segments # Recalculate segments
237
-
238
- # Values below are calculated
239
- # to allow faster computation by font rasterizers
240
- res = 1
241
- power = 0
242
- while res <= seg_count
243
- res *= 2
244
- power += 1
245
- end
246
- @search_range = res
247
- @entry_selector = power - 1
248
- @range_shift = 2 * seg_count - @search_range
249
- end
250
-
251
- # Returns index/id of glyph associated with unicode.
252
- def get_glyph_id_for_unicode(unicode)
253
- id = 0
254
- @segments.length.times do |i|
255
- if @start_count_array[i] <= unicode and \
256
- unicode <= @end_count_array[i]
257
- @segments[i].each do |char_code, glyph_id|
258
- if char_code == unicode
259
- id = glyph_id
260
- break
261
- end
262
- end
263
- end
264
- end
265
- id
266
- end
267
-
268
- # Returns the Font::TTF::Table::Glyf::SimpleGlyph or
269
- # Font::TTF::Table::Glyf::CompositeGlyph associated with unicode.
270
- def get_glyph_for_unicode(unicode)
271
- id = get_glyph_id_for_unicode(unicode)
272
- offs = @font.get_table(:loca).glyph_offsets[id]
273
- @font.get_table(:glyf).get_glyph_at_offset(offs)
274
- end
275
-
276
- # Returns the unicode of glyph with index id.
277
- def get_unicode_for_glyph_id(id)
278
- # TODO: this method could be rewritten much more efficiently
279
- # by using @start_count_array and @end_count_array
280
- unicode = 0
281
- charmaps.each do |char_code, glyph_index|
282
- if glyph_index == id
283
- unicode = char_code
284
- break
285
- end
286
- end
287
- unicode
288
- end
289
-
290
- # Dumps the table in binary raw format as may be found in a font
291
- # file.
292
- def dump
293
- raw = (format || 0).to_ushort
294
- seg_count = @segments.length || 0
295
- len = 8 * IO::SIZEOF_USHORT + 4 * seg_count * IO::SIZEOF_USHORT + \
296
- @glyph_index_array.length * IO::SIZEOF_USHORT
297
- raw += len.to_ushort
298
- raw += (@version || 0).to_ushort
299
- raw += (seg_count * 2).to_ushort
300
- raw += (@search_range || 0).to_ushort
301
- raw += (@entry_selector || 0).to_ushort
302
- raw += (@range_shift || 0).to_ushort
303
- raw += (@end_count_array || []).to_ushorts
304
- raw += (@reserved_pad || 0).to_ushort
305
- raw += (@start_count_array || []).to_ushorts
306
- raw += (@id_delta_array || []).to_ushorts
307
- raw += (@id_range_offset_array || []).to_ushorts
308
- raw += (@glyph_index_array || []).to_ushorts
309
- end
310
- end
311
-
312
- # Encoding table in format 6. Not implemented.
313
- class EncodingTable6 < EncodingTable
314
- end
315
-
316
- # Encoding table in format 8. Not implemented.
317
- class EncodingTable8 < EncodingTable
318
- end
319
-
320
- # Encoding table in format 10. Not implemented.
321
- class EncodingTable10 < EncodingTable
322
- end
323
-
324
- # Encoding table in format 12. Not implemented.
325
- class EncodingTable12 < EncodingTable
326
- end
327
-
328
- attr_accessor :version
329
- # An Array of encoding_tables. You may add or remove encoding tables
330
- # from this array.
331
- attr_accessor :encoding_tables
332
-
333
- def initialize(*args)
334
- super(*args)
335
-
336
- if exists_in_file?
337
- @font.at_offset(@offset) do
338
- @version = @font.read_ushort
339
- @encoding_table_num = @font.read_ushort
340
- @encoding_tables = []
341
- @encoding_table_num.times do
342
- platform_id = @font.read_ushort
343
- encoding_id = @font.read_ushort
344
- offset = @font.read_ulong
345
-
346
- @font.at_offset(@offset + offset) do
347
- format = @font.read_ushort
348
- len = @font.read_ushort
349
-
350
- if [0, 2, 4, 6, 8, 10, 12].include? format
351
- klass = eval("EncodingTable%d" % format)
352
- else
353
- klass = EncodingTable
354
- end
355
-
356
- @encoding_tables << klass.new(self,
357
- offset,
358
- len,
359
- platform_id,
360
- encoding_id)
361
- end
362
- end
363
-
364
- end
365
- else
366
- @encoding_tables = []
367
- end
368
- end
369
-
370
- # Returns a new empty EncodingTable0 object that you may add to the
371
- # encoding_tables array.
372
- def get_new_encoding_table0
373
- EncodingTable0.new(self)
374
- end
375
-
376
- # Returns a new empty EncodingTable4 object that you may add to the
377
- # encoding_tables array.
378
- def get_new_encoding_table4
379
- EncodingTable4.new(self)
380
- end
381
-
382
- # Dumps the cmap table in binary raw format as may be found in a font
383
- # file.
384
- def dump
385
- raw = (@version || 0).to_ushort
386
- raw += (@encoding_tables.length || 0).to_ushort
387
- dumps = []
388
- offs = 2 * IO::SIZEOF_USHORT + @encoding_tables.length * \
389
- (2 * IO::SIZEOF_USHORT + IO::SIZEOF_ULONG)
390
- @encoding_tables.each do |enc_tbl|
391
- raw += (enc_tbl.platform_id || 3).to_ushort
392
- raw += (enc_tbl.encoding_id || 1).to_ushort
393
- dump = enc_tbl.dump
394
- dumps << dump
395
- raw += offs.to_ulong
396
- offs += dump.length
397
- end
398
- dumps.each do |dump|
399
- raw += dump
400
- end
401
- raw
402
- end
403
-
404
- end
405
-
406
- end
407
- end
408
- end