davebenvenuti-prawn 0.11.1.pre
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/COPYING +340 -0
- data/HACKING +50 -0
- data/LICENSE +56 -0
- data/README +141 -0
- data/Rakefile +52 -0
- data/data/encodings/win_ansi.txt +29 -0
- 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 +342 -0
- data/data/fonts/Courier-BoldOblique.afm +342 -0
- data/data/fonts/Courier-Oblique.afm +342 -0
- data/data/fonts/Courier.afm +342 -0
- data/data/fonts/DejaVuSans.ttf +0 -0
- data/data/fonts/Dustismo_Roman.ttf +0 -0
- data/data/fonts/Helvetica-Bold.afm +2827 -0
- data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
- data/data/fonts/Helvetica-Oblique.afm +3051 -0
- data/data/fonts/Helvetica.afm +3051 -0
- data/data/fonts/MustRead.html +19 -0
- data/data/fonts/Symbol.afm +213 -0
- data/data/fonts/Times-Bold.afm +2588 -0
- data/data/fonts/Times-BoldItalic.afm +2384 -0
- data/data/fonts/Times-Italic.afm +2667 -0
- data/data/fonts/Times-Roman.afm +2419 -0
- data/data/fonts/ZapfDingbats.afm +225 -0
- data/data/fonts/comicsans.ttf +0 -0
- data/data/fonts/gkai00mp.ttf +0 -0
- data/data/images/16bit.alpha +0 -0
- data/data/images/16bit.dat +0 -0
- data/data/images/16bit.png +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/dice_interlaced.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/tru256.bmp +0 -0
- data/data/images/web-links.dat +1 -0
- data/data/images/web-links.png +0 -0
- data/data/pdfs/complex_template.pdf +0 -0
- data/data/pdfs/contains_ttf_font.pdf +0 -0
- data/data/pdfs/encrypted.pdf +0 -0
- data/data/pdfs/hexagon.pdf +61 -0
- data/data/pdfs/indirect_reference.pdf +86 -0
- data/data/pdfs/nested_pages.pdf +118 -0
- data/data/pdfs/page_without_mediabox.pdf +193 -0
- data/data/pdfs/resources_as_indirect_object.pdf +83 -0
- data/data/pdfs/two_hexagons.pdf +90 -0
- data/data/pdfs/version_1_6.pdf +61 -0
- data/data/shift_jis_text.txt +1 -0
- data/examples/bounding_box/bounding_boxes.rb +44 -0
- data/examples/bounding_box/indentation.rb +35 -0
- data/examples/bounding_box/russian_boxes.rb +37 -0
- data/examples/bounding_box/stretched_nesting.rb +68 -0
- data/examples/example_helper.rb +8 -0
- data/examples/general/background.rb +24 -0
- data/examples/general/canvas.rb +16 -0
- data/examples/general/context_sensitive_headers.rb +38 -0
- data/examples/general/float.rb +12 -0
- data/examples/general/margin.rb +37 -0
- data/examples/general/measurement_units.rb +52 -0
- data/examples/general/metadata-info.rb +17 -0
- data/examples/general/multi_page_layout.rb +19 -0
- data/examples/general/outlines.rb +67 -0
- data/examples/general/page_geometry.rb +32 -0
- data/examples/general/page_numbering.rb +16 -0
- data/examples/general/repeaters.rb +48 -0
- data/examples/general/stamp.rb +42 -0
- data/examples/general/templates.rb +14 -0
- data/examples/graphics/basic_images.rb +24 -0
- data/examples/graphics/cmyk.rb +13 -0
- data/examples/graphics/curves.rb +12 -0
- data/examples/graphics/hexagon.rb +14 -0
- 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/graphics/line.rb +33 -0
- data/examples/graphics/png_types.rb +23 -0
- data/examples/graphics/polygons.rb +17 -0
- data/examples/graphics/remote_images.rb +13 -0
- data/examples/graphics/rounded_polygons.rb +20 -0
- data/examples/graphics/rounded_rectangle.rb +21 -0
- data/examples/graphics/ruport_style_helpers.rb +20 -0
- data/examples/graphics/stroke_bounds.rb +21 -0
- data/examples/graphics/stroke_cap_and_join.rb +46 -0
- data/examples/graphics/stroke_dash.rb +43 -0
- data/examples/graphics/transformations.rb +53 -0
- data/examples/graphics/transparency.rb +27 -0
- data/examples/grid/bounding_boxes.rb +22 -0
- data/examples/grid/column_gutter_grid.rb +21 -0
- data/examples/grid/multi_boxes.rb +52 -0
- data/examples/grid/show_grid.rb +14 -0
- data/examples/grid/simple_grid.rb +21 -0
- data/examples/m17n/chinese_text_wrapping.rb +18 -0
- 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/security/hello_foo.rb +9 -0
- data/examples/table/bill.rb +54 -0
- data/examples/table/cell.rb +13 -0
- data/examples/table/checkerboard.rb +23 -0
- data/examples/table/header.rb +15 -0
- data/examples/table/inline_format_table.rb +13 -0
- data/examples/table/multi_page_table.rb +10 -0
- data/examples/table/simple_table.rb +25 -0
- data/examples/table/subtable.rb +13 -0
- data/examples/table/widths.rb +21 -0
- data/examples/text/alignment.rb +19 -0
- data/examples/text/character_spacing.rb +13 -0
- data/examples/text/dfont.rb +49 -0
- data/examples/text/family_based_styling.rb +25 -0
- data/examples/text/font_calculations.rb +92 -0
- data/examples/text/font_size.rb +34 -0
- data/examples/text/hyphenation.rb +46 -0
- data/examples/text/indent_paragraphs.rb +23 -0
- data/examples/text/inline_format.rb +104 -0
- data/examples/text/kerning.rb +31 -0
- data/examples/text/rotated.rb +99 -0
- data/examples/text/shaped_text_box.rb +32 -0
- data/examples/text/simple_text.rb +18 -0
- data/examples/text/simple_text_ttf.rb +18 -0
- data/examples/text/span.rb +30 -0
- data/examples/text/text_box.rb +89 -0
- data/examples/text/text_box_returning_excess.rb +52 -0
- data/examples/text/text_flow.rb +68 -0
- data/lib/prawn.rb +26 -0
- data/lib/prawn/compatibility.rb +51 -0
- data/lib/prawn/core.rb +85 -0
- data/lib/prawn/core/annotations.rb +61 -0
- data/lib/prawn/core/byte_string.rb +9 -0
- data/lib/prawn/core/destinations.rb +90 -0
- data/lib/prawn/core/document_state.rb +78 -0
- data/lib/prawn/core/literal_string.rb +16 -0
- data/lib/prawn/core/name_tree.rb +165 -0
- data/lib/prawn/core/object_store.rb +236 -0
- data/lib/prawn/core/page.rb +199 -0
- data/lib/prawn/core/pdf_object.rb +108 -0
- data/lib/prawn/core/reference.rb +112 -0
- data/lib/prawn/core/text.rb +140 -0
- data/lib/prawn/core/text/formatted/arranger.rb +266 -0
- data/lib/prawn/core/text/formatted/line_wrap.rb +127 -0
- data/lib/prawn/core/text/formatted/wrap.rb +112 -0
- data/lib/prawn/core/text/line_wrap.rb +211 -0
- data/lib/prawn/core/text/wrap.rb +82 -0
- data/lib/prawn/document.rb +575 -0
- data/lib/prawn/document/bounding_box.rb +428 -0
- data/lib/prawn/document/graphics_state.rb +48 -0
- data/lib/prawn/document/internals.rb +170 -0
- data/lib/prawn/document/page_geometry.rb +136 -0
- data/lib/prawn/document/snapshot.rb +87 -0
- data/lib/prawn/document/span.rb +55 -0
- data/lib/prawn/encoding.rb +121 -0
- data/lib/prawn/errors.rb +86 -0
- data/lib/prawn/font.rb +368 -0
- data/lib/prawn/font/afm.rb +225 -0
- data/lib/prawn/font/dfont.rb +42 -0
- data/lib/prawn/font/ttf.rb +350 -0
- data/lib/prawn/graphics.rb +325 -0
- data/lib/prawn/graphics/cap_style.rb +38 -0
- data/lib/prawn/graphics/color.rb +205 -0
- data/lib/prawn/graphics/dash.rb +71 -0
- data/lib/prawn/graphics/join_style.rb +38 -0
- data/lib/prawn/graphics/transformation.rb +156 -0
- data/lib/prawn/graphics/transparency.rb +99 -0
- data/lib/prawn/images.rb +217 -0
- data/lib/prawn/images/jpg.rb +85 -0
- data/lib/prawn/images/png.rb +356 -0
- data/lib/prawn/layout.rb +20 -0
- data/lib/prawn/layout/grid.rb +259 -0
- data/lib/prawn/measurement_extensions.rb +46 -0
- data/lib/prawn/measurements.rb +71 -0
- data/lib/prawn/outline.rb +326 -0
- data/lib/prawn/repeater.rb +129 -0
- data/lib/prawn/security.rb +262 -0
- data/lib/prawn/security/arcfour.rb +51 -0
- data/lib/prawn/stamp.rb +126 -0
- data/lib/prawn/table.rb +451 -0
- data/lib/prawn/table/cell.rb +395 -0
- data/lib/prawn/table/cell/in_table.rb +27 -0
- data/lib/prawn/table/cell/subtable.rb +65 -0
- data/lib/prawn/table/cell/text.rb +135 -0
- data/lib/prawn/table/cells.rb +206 -0
- data/lib/prawn/text.rb +449 -0
- data/lib/prawn/text/box.rb +397 -0
- data/lib/prawn/text/formatted.rb +4 -0
- data/lib/prawn/text/formatted/box.rb +222 -0
- data/lib/prawn/text/formatted/fragment.rb +181 -0
- data/lib/prawn/text/formatted/parser.rb +213 -0
- data/prawn.gemspec +28 -0
- data/spec/annotations_spec.rb +90 -0
- data/spec/bounding_box_spec.rb +190 -0
- data/spec/cell_spec.rb +430 -0
- data/spec/destinations_spec.rb +15 -0
- data/spec/document_spec.rb +476 -0
- data/spec/extensions/mocha.rb +32 -0
- data/spec/font_spec.rb +324 -0
- data/spec/formatted_text_arranger_spec.rb +426 -0
- data/spec/formatted_text_box_spec.rb +756 -0
- data/spec/formatted_text_fragment_spec.rb +211 -0
- data/spec/graphics_spec.rb +446 -0
- data/spec/grid_spec.rb +85 -0
- data/spec/images_spec.rb +119 -0
- data/spec/inline_formatted_text_parser_spec.rb +502 -0
- data/spec/jpg_spec.rb +25 -0
- data/spec/line_wrap_spec.rb +341 -0
- data/spec/measurement_units_spec.rb +23 -0
- data/spec/name_tree_spec.rb +112 -0
- data/spec/object_store_spec.rb +160 -0
- data/spec/outline_spec.rb +404 -0
- data/spec/pdf_object_spec.rb +170 -0
- data/spec/png_spec.rb +237 -0
- data/spec/reference_spec.rb +82 -0
- data/spec/repeater_spec.rb +96 -0
- data/spec/security_spec.rb +120 -0
- data/spec/snapshot_spec.rb +154 -0
- data/spec/span_spec.rb +49 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/stamp_spec.rb +108 -0
- data/spec/stroke_styles_spec.rb +163 -0
- data/spec/table_spec.rb +687 -0
- data/spec/template_spec.rb +165 -0
- data/spec/text_at_spec.rb +125 -0
- data/spec/text_box_spec.rb +777 -0
- data/spec/text_spacing_spec.rb +75 -0
- data/spec/text_spec.rb +349 -0
- data/spec/text_with_inline_formatting_spec.rb +193 -0
- data/spec/transparency_spec.rb +89 -0
- data/vendor/pdf-inspector/README +18 -0
- data/vendor/pdf-inspector/lib/pdf/inspector.rb +26 -0
- data/vendor/pdf-inspector/lib/pdf/inspector/extgstate.rb +18 -0
- data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +131 -0
- data/vendor/pdf-inspector/lib/pdf/inspector/page.rb +25 -0
- data/vendor/pdf-inspector/lib/pdf/inspector/text.rb +46 -0
- data/vendor/pdf-inspector/lib/pdf/inspector/xobject.rb +19 -0
- data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
- data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
- data/vendor/ttfunk/example.rb +45 -0
- data/vendor/ttfunk/lib/ttfunk.rb +102 -0
- data/vendor/ttfunk/lib/ttfunk/directory.rb +17 -0
- data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +88 -0
- data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +69 -0
- data/vendor/ttfunk/lib/ttfunk/reader.rb +44 -0
- data/vendor/ttfunk/lib/ttfunk/resource_file.rb +78 -0
- data/vendor/ttfunk/lib/ttfunk/subset.rb +18 -0
- data/vendor/ttfunk/lib/ttfunk/subset/base.rb +141 -0
- data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +50 -0
- data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +48 -0
- data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +63 -0
- data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +55 -0
- data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +72 -0
- data/vendor/ttfunk/lib/ttfunk/table.rb +46 -0
- data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +34 -0
- data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +54 -0
- data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +126 -0
- data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +79 -0
- data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +64 -0
- data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +81 -0
- data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +37 -0
- data/vendor/ttfunk/lib/ttfunk/table/head.rb +44 -0
- data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +41 -0
- data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +47 -0
- data/vendor/ttfunk/lib/ttfunk/table/kern.rb +79 -0
- data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +62 -0
- data/vendor/ttfunk/lib/ttfunk/table/loca.rb +43 -0
- data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +40 -0
- data/vendor/ttfunk/lib/ttfunk/table/name.rb +125 -0
- data/vendor/ttfunk/lib/ttfunk/table/os2.rb +78 -0
- data/vendor/ttfunk/lib/ttfunk/table/post.rb +91 -0
- data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +43 -0
- data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +35 -0
- data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +23 -0
- data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +17 -0
- data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +17 -0
- data/vendor/ttfunk/lib/ttfunk/table/simple.rb +14 -0
- metadata +379 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'ttfunk/reader'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Cmap
|
6
|
+
class Subtable
|
7
|
+
include Reader
|
8
|
+
|
9
|
+
attr_reader :platform_id
|
10
|
+
attr_reader :encoding_id
|
11
|
+
attr_reader :format
|
12
|
+
|
13
|
+
ENCODING_MAPPINGS = {
|
14
|
+
:mac_roman => { :platform_id => 1, :encoding_id => 0 },
|
15
|
+
# use microsoft unicode, instead of generic unicode, for optimal windows support
|
16
|
+
:unicode => { :platform_id => 3, :encoding_id => 1 }
|
17
|
+
}
|
18
|
+
|
19
|
+
def self.encode(charmap, encoding)
|
20
|
+
case encoding
|
21
|
+
when :mac_roman
|
22
|
+
result = Format00.encode(charmap)
|
23
|
+
when :unicode
|
24
|
+
result = Format04.encode(charmap)
|
25
|
+
else
|
26
|
+
raise NotImplementedError, "encoding #{encoding.inspect} is not supported"
|
27
|
+
end
|
28
|
+
|
29
|
+
mapping = ENCODING_MAPPINGS[encoding]
|
30
|
+
|
31
|
+
# platform-id, encoding-id, offset
|
32
|
+
result[:subtable] = [mapping[:platform_id], mapping[:encoding_id],
|
33
|
+
12, result[:subtable]].pack("nnNA*")
|
34
|
+
|
35
|
+
return result
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(file, table_start)
|
39
|
+
@file = file
|
40
|
+
@platform_id, @encoding_id, @offset = read(8, "nnN")
|
41
|
+
@offset += table_start
|
42
|
+
|
43
|
+
parse_from(@offset) do
|
44
|
+
@format = read(2, "n").first
|
45
|
+
|
46
|
+
case @format
|
47
|
+
when 0 then extend(TTFunk::Table::Cmap::Format00)
|
48
|
+
when 4 then extend(TTFunk::Table::Cmap::Format04)
|
49
|
+
end
|
50
|
+
|
51
|
+
parse_cmap!
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def unicode?
|
56
|
+
platform_id == 3 && encoding_id == 1 && format == 4 ||
|
57
|
+
platform_id == 0 && format == 4
|
58
|
+
end
|
59
|
+
|
60
|
+
def supported?
|
61
|
+
false
|
62
|
+
end
|
63
|
+
|
64
|
+
def [](code)
|
65
|
+
raise NotImplementedError, "cmap format #{@format} is not supported"
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def parse_cmap!
|
71
|
+
# do nothing...
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
require 'ttfunk/table/cmap/format00'
|
79
|
+
require 'ttfunk/table/cmap/format04'
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'ttfunk/table'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Glyf < Table
|
6
|
+
# Accepts a hash mapping (old) glyph-ids to glyph objects, and a hash
|
7
|
+
# mapping old glyph-ids to new glyph-ids.
|
8
|
+
#
|
9
|
+
# Returns a hash containing:
|
10
|
+
#
|
11
|
+
# * :table - a string representing the encoded 'glyf' table containing
|
12
|
+
# the given glyphs.
|
13
|
+
# * :offsets - an array of offsets for each glyph
|
14
|
+
def self.encode(glyphs, new2old, old2new)
|
15
|
+
result = { :table => "", :offsets => [] }
|
16
|
+
|
17
|
+
new2old.keys.sort.each do |new_id|
|
18
|
+
glyph = glyphs[new2old[new_id]]
|
19
|
+
result[:offsets] << result[:table].length
|
20
|
+
result[:table] << glyph.recode(old2new) if glyph
|
21
|
+
end
|
22
|
+
|
23
|
+
# include an offset at the end of the table, for use in computing the
|
24
|
+
# size of the last glyph
|
25
|
+
result[:offsets] << result[:table].length
|
26
|
+
return result
|
27
|
+
end
|
28
|
+
|
29
|
+
def for(glyph_id)
|
30
|
+
return @cache[glyph_id] if @cache.key?(glyph_id)
|
31
|
+
|
32
|
+
index = file.glyph_locations.index_of(glyph_id)
|
33
|
+
size = file.glyph_locations.size_of(glyph_id)
|
34
|
+
|
35
|
+
if size.zero? # blank glyph, e.g. space character
|
36
|
+
@cache[glyph_id] = nil
|
37
|
+
return nil
|
38
|
+
end
|
39
|
+
|
40
|
+
parse_from(offset + index) do
|
41
|
+
raw = io.read(size)
|
42
|
+
number_of_contours, x_min, y_min, x_max, y_max = raw.unpack("n5").map { |i| to_signed(i) }
|
43
|
+
|
44
|
+
@cache[glyph_id] = if number_of_contours == -1
|
45
|
+
Compound.new(raw, x_min, y_min, x_max, y_max)
|
46
|
+
else
|
47
|
+
Simple.new(raw, number_of_contours, x_min, y_min, x_max, y_max)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def parse!
|
55
|
+
# because the glyf table is rather complex to parse, we defer
|
56
|
+
# the parse until we need a specific glyf, and then cache it.
|
57
|
+
@cache = {}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
require 'ttfunk/table/glyf/compound'
|
64
|
+
require 'ttfunk/table/glyf/simple'
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'ttfunk/reader'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Glyf
|
6
|
+
class Compound
|
7
|
+
include Reader
|
8
|
+
|
9
|
+
ARG_1_AND_2_ARE_WORDS = 0x0001
|
10
|
+
WE_HAVE_A_SCALE = 0x0008
|
11
|
+
MORE_COMPONENTS = 0x0020
|
12
|
+
WE_HAVE_AN_X_AND_Y_SCALE = 0x0040
|
13
|
+
WE_HAVE_A_TWO_BY_TWO = 0x0080
|
14
|
+
WE_HAVE_INSTRUCTIONS = 0x0100
|
15
|
+
|
16
|
+
attr_reader :raw
|
17
|
+
attr_reader :x_min, :y_min, :x_max, :y_max
|
18
|
+
attr_reader :glyph_ids
|
19
|
+
|
20
|
+
Component = Struct.new(:flags, :glyph_index, :arg1, :arg2, :transform)
|
21
|
+
|
22
|
+
def initialize(raw, x_min, y_min, x_max, y_max)
|
23
|
+
@raw = raw
|
24
|
+
@x_min, @y_min, @x_max, @y_max = x_min, y_min, x_max, y_max
|
25
|
+
|
26
|
+
# Because TTFunk only cares about glyphs insofar as they (1) provide
|
27
|
+
# a bounding box for each glyph, and (2) can be rewritten into a
|
28
|
+
# font subset, we don't really care about the rest of the glyph data
|
29
|
+
# except as a whole. Thus, we don't actually decompose the glyph
|
30
|
+
# into it's parts--all we really care about are the locations within
|
31
|
+
# the raw string where the component glyph ids are stored, so that
|
32
|
+
# when we rewrite this glyph into a subset we can rewrite the
|
33
|
+
# component glyph-ids so they are correct for the subset.
|
34
|
+
|
35
|
+
@glyph_ids = []
|
36
|
+
@glyph_id_offsets = []
|
37
|
+
offset = 10 # 2 bytes for each of num-contours, min x/y, max x/y
|
38
|
+
|
39
|
+
loop do
|
40
|
+
flags, glyph_id = @raw[offset, 4].unpack("n*")
|
41
|
+
@glyph_ids << glyph_id
|
42
|
+
@glyph_id_offsets << offset + 2
|
43
|
+
|
44
|
+
break unless flags & MORE_COMPONENTS != 0
|
45
|
+
offset += 4
|
46
|
+
|
47
|
+
if flags & ARG_1_AND_2_ARE_WORDS != 0
|
48
|
+
offset += 4
|
49
|
+
else
|
50
|
+
offset += 2
|
51
|
+
end
|
52
|
+
|
53
|
+
if flags & WE_HAVE_A_TWO_BY_TWO != 0
|
54
|
+
offset += 8
|
55
|
+
elsif flags & WE_HAVE_AN_X_AND_Y_SCALE != 0
|
56
|
+
offset += 4
|
57
|
+
elsif flags & WE_HAVE_A_SCALE != 0
|
58
|
+
offset += 2
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def compound?
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def recode(mapping)
|
68
|
+
result = @raw.dup
|
69
|
+
new_ids = glyph_ids.map { |id| mapping[id] }
|
70
|
+
|
71
|
+
new_ids.zip(@glyph_id_offsets).each do |new_id, offset|
|
72
|
+
result[offset, 2] = [new_id].pack("n")
|
73
|
+
end
|
74
|
+
|
75
|
+
return result
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'ttfunk/reader'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Glyf
|
6
|
+
class Simple
|
7
|
+
attr_reader :raw
|
8
|
+
attr_reader :number_of_contours
|
9
|
+
attr_reader :x_min, :y_min, :x_max, :y_max
|
10
|
+
|
11
|
+
def initialize(raw, number_of_contours, x_min, y_min, x_max, y_max)
|
12
|
+
@raw = raw
|
13
|
+
@number_of_contours = number_of_contours
|
14
|
+
@x_min, @y_min = x_min, y_min
|
15
|
+
@x_max, @y_max = x_max, y_max
|
16
|
+
|
17
|
+
# Because TTFunk is, at this time, a library for simply pulling
|
18
|
+
# metrics out of font files, or for writing font subsets, we don't
|
19
|
+
# really care what the contours are for simple glyphs. We just
|
20
|
+
# care that we've got an entire glyph's definition. Also, a
|
21
|
+
# bounding box could be nice to know. Since we've got all that
|
22
|
+
# at this point, we don't need to worry about parsing the full
|
23
|
+
# contents of the glyph.
|
24
|
+
end
|
25
|
+
|
26
|
+
def compound?
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
def recode(mapping)
|
31
|
+
raw
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'ttfunk/table'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Head < TTFunk::Table
|
6
|
+
attr_reader :version
|
7
|
+
attr_reader :font_revision
|
8
|
+
attr_reader :checksum_adjustment
|
9
|
+
attr_reader :magic_number
|
10
|
+
attr_reader :flags
|
11
|
+
attr_reader :units_per_em
|
12
|
+
attr_reader :created
|
13
|
+
attr_reader :modified
|
14
|
+
attr_reader :x_min
|
15
|
+
attr_reader :y_min
|
16
|
+
attr_reader :x_max
|
17
|
+
attr_reader :y_max
|
18
|
+
attr_reader :mac_style
|
19
|
+
attr_reader :lowest_rec_ppem
|
20
|
+
attr_reader :font_direction_hint
|
21
|
+
attr_reader :index_to_loc_format
|
22
|
+
attr_reader :glyph_data_format
|
23
|
+
|
24
|
+
def self.encode(head, loca)
|
25
|
+
table = head.raw
|
26
|
+
table[8,4] = "\0\0\0\0" # set checksum adjustment to 0 initially
|
27
|
+
table[-4,2] = [loca[:type]].pack("n") # set index_to_loc_format
|
28
|
+
return table
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def parse!
|
34
|
+
@version, @font_revision, @check_sum_adjustment, @magic_number,
|
35
|
+
@flags, @units_per_em, @created, @modified = read(36, "N4n2q2")
|
36
|
+
|
37
|
+
@x_min, @y_min, @x_max, @y_max = read_signed(4)
|
38
|
+
|
39
|
+
@mac_style, @lowest_rec_ppem, @font_direction_hint,
|
40
|
+
@index_to_loc_format, @glyph_data_format = read(10, "n*")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'ttfunk/table'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Hhea < Table
|
6
|
+
attr_reader :version
|
7
|
+
attr_reader :ascent
|
8
|
+
attr_reader :descent
|
9
|
+
attr_reader :line_gap
|
10
|
+
attr_reader :advance_width_max
|
11
|
+
attr_reader :min_left_side_bearing
|
12
|
+
attr_reader :min_right_side_bearing
|
13
|
+
attr_reader :x_max_extent
|
14
|
+
attr_reader :carot_slope_rise
|
15
|
+
attr_reader :carot_slope_run
|
16
|
+
attr_reader :metric_data_format
|
17
|
+
attr_reader :number_of_metrics
|
18
|
+
|
19
|
+
def self.encode(hhea, hmtx)
|
20
|
+
raw = hhea.raw
|
21
|
+
raw[-2,2] = [hmtx[:number_of_metrics]].pack("n")
|
22
|
+
return raw
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def parse!
|
28
|
+
@version = read(4, "N").first
|
29
|
+
@ascent, @descent, @line_gap = read_signed(3)
|
30
|
+
@advance_width_max = read(2, "n").first
|
31
|
+
|
32
|
+
@min_left_side_bearing, @min_right_side_bearing, @x_max_extent,
|
33
|
+
@carot_slope_rise, @carot_slope_run, @caret_offset,
|
34
|
+
reserved, reserved, reserved, reserved,
|
35
|
+
@metric_data_format = read_signed(11)
|
36
|
+
|
37
|
+
@number_of_metrics = read(2, "n").first
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'ttfunk/table'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Hmtx < Table
|
6
|
+
attr_reader :metrics
|
7
|
+
attr_reader :left_side_bearings
|
8
|
+
attr_reader :widths
|
9
|
+
|
10
|
+
def self.encode(hmtx, mapping)
|
11
|
+
metrics = mapping.keys.sort.map do |new_id|
|
12
|
+
metric = hmtx.for(mapping[new_id])
|
13
|
+
[metric.advance_width, metric.left_side_bearing]
|
14
|
+
end
|
15
|
+
|
16
|
+
{ :number_of_metrics => metrics.length,
|
17
|
+
:table => metrics.flatten.pack("n*") }
|
18
|
+
end
|
19
|
+
|
20
|
+
HorizontalMetric = Struct.new(:advance_width, :left_side_bearing)
|
21
|
+
|
22
|
+
def for(glyph_id)
|
23
|
+
@metrics[glyph_id] ||
|
24
|
+
HorizontalMetric.new(@metrics.last.advance_width,
|
25
|
+
@left_side_bearings[glyph_id - @metrics.length])
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def parse!
|
31
|
+
@metrics = []
|
32
|
+
|
33
|
+
file.horizontal_header.number_of_metrics.times do
|
34
|
+
advance = read(2, "n").first
|
35
|
+
lsb = read_signed(1).first
|
36
|
+
@metrics.push HorizontalMetric.new(advance, lsb)
|
37
|
+
end
|
38
|
+
|
39
|
+
lsb_count = file.maximum_profile.num_glyphs - file.horizontal_header.number_of_metrics
|
40
|
+
@left_side_bearings = read_signed(lsb_count)
|
41
|
+
|
42
|
+
@widths = @metrics.map { |metric| metric.advance_width }
|
43
|
+
@widths += [@widths.last] * @left_side_bearings.length
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'ttfunk/table'
|
2
|
+
|
3
|
+
module TTFunk
|
4
|
+
class Table
|
5
|
+
class Kern < Table
|
6
|
+
attr_reader :version
|
7
|
+
attr_reader :tables
|
8
|
+
|
9
|
+
def self.encode(kerning, mapping)
|
10
|
+
return nil unless kerning.exists? && kerning.tables.any?
|
11
|
+
tables = kerning.tables.map { |table| table.recode(mapping) }.compact
|
12
|
+
return nil if tables.empty?
|
13
|
+
|
14
|
+
[0, tables.length, tables.join].pack("nnA*")
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def parse!
|
20
|
+
@version, num_tables = read(4, "n*")
|
21
|
+
@tables = []
|
22
|
+
|
23
|
+
if @version == 1 # Mac OS X fonts
|
24
|
+
@version = (@version << 16) + num_tables
|
25
|
+
num_tables = read(4, "N").first
|
26
|
+
parse_version_1_tables(num_tables)
|
27
|
+
else
|
28
|
+
parse_version_0_tables(num_tables)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_version_0_tables(num_tables)
|
33
|
+
# It looks like some MS fonts report their kerning subtable lengths
|
34
|
+
# wrong. In one case, the length was reported to be some 19366, and yet
|
35
|
+
# the table also claimed to hold 14148 pairs (each pair consisting of 6 bytes).
|
36
|
+
# You do the math!
|
37
|
+
#
|
38
|
+
# We're going to assume that the microsoft fonts hold only a single kerning
|
39
|
+
# subtable, which occupies the entire length of the kerning table. Worst
|
40
|
+
# case, we lose any other subtables that the font contains, but it's better
|
41
|
+
# than reading a truncated kerning table.
|
42
|
+
#
|
43
|
+
# And what's more, it appears to work. So.
|
44
|
+
version, length, coverage = read(6, "n*")
|
45
|
+
format = coverage >> 8
|
46
|
+
|
47
|
+
add_table format, :version => version, :length => length,
|
48
|
+
:coverage => coverage, :data => raw[10..-1],
|
49
|
+
:vertical => (coverage & 0x1 == 0),
|
50
|
+
:minimum => (coverage & 0x2 != 0),
|
51
|
+
:cross => (coverage & 0x4 != 0),
|
52
|
+
:override => (coverage & 0x8 != 0)
|
53
|
+
end
|
54
|
+
|
55
|
+
def parse_version_1_tables(num_tables)
|
56
|
+
num_tables.times do
|
57
|
+
length, coverage, tuple_index = read(8, "Nnn")
|
58
|
+
format = coverage & 0x0FF
|
59
|
+
|
60
|
+
add_table format, :length => length, :coverage => coverage,
|
61
|
+
:tuple_index => tuple_index, :data => io.read(length-8),
|
62
|
+
:vertical => (coverage & 0x8000 != 0),
|
63
|
+
:cross => (coverage & 0x4000 != 0),
|
64
|
+
:variation => (coverage & 0x2000 != 0)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_table(format, attributes={})
|
69
|
+
if format == 0
|
70
|
+
@tables << Kern::Format0.new(attributes)
|
71
|
+
else
|
72
|
+
# silently ignore unsupported kerning tables
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
require 'ttfunk/table/kern/format0'
|