Module: TTFunk::Table::Cmap::Format04
- Defined in:
- lib/ttfunk/table/cmap/format04.rb
Overview
Format 4: Segment mapping to delta values.
This module conditionally extends Subtable.
Instance Attribute Summary collapse
-
#code_map ⇒ Hash{Integer => Integer}
readonly
Code map.
-
#language ⇒ Integer
readonly
Language.
Class Method Summary collapse
-
.encode(charmap) ⇒ Hash
Encode the encoding record to format 4.
Instance Method Summary collapse
-
#[](code) ⇒ Integer
Get glyph ID for character code.
-
#supported? ⇒ true
Is this encoding record format supported?.
Instance Attribute Details
#code_map ⇒ Hash{Integer => Integer} (readonly)
Code map.
Source Code
lib/ttfunk/table/cmap/format04.rb, line 16
16 | def code_map |
17 | @code_map
|
18 | end
|
#language ⇒ Integer (readonly)
Language.
Source Code
lib/ttfunk/table/cmap/format04.rb, line 12
12 | def language |
13 | @language
|
14 | end
|
Class Method Details
.encode(charmap) ⇒ Hash
Encode the encoding record to format 4.
Source Code
lib/ttfunk/table/cmap/format04.rb, line 30
30 | def self.encode(charmap) |
31 | end_codes = [] |
32 | start_codes = [] |
33 | next_id = 0 |
34 | last = difference = nil |
35 | |
36 | glyph_map = { 0 => 0 } |
37 | new_map = |
38 | charmap.keys.sort.each_with_object({}) do |code, map| |
39 | old = charmap[code] |
40 | glyph_map[old] ||= next_id += 1 |
41 | map[code] = { old: old, new: glyph_map[old] } |
42 | |
43 | delta = glyph_map[old] - code |
44 | if last.nil? || delta != difference |
45 | end_codes << last if last |
46 | start_codes << code |
47 | difference = delta |
48 | end
|
49 | last = code |
50 | |
51 | map
|
52 | end
|
53 | |
54 | end_codes << last if last |
55 | end_codes << 0xFFFF |
56 | start_codes << 0xFFFF |
57 | segcount = start_codes.length |
58 | |
59 | # build the conversion tables
|
60 | deltas = [] |
61 | range_offsets = [] |
62 | glyph_indices = [] |
63 | offset = 0 |
64 | |
65 | start_codes.zip(end_codes).each_with_index do |(a, b), segment| |
66 | if a == 0xFFFF |
67 | # We want the final 0xFFFF code to map to glyph 0.
|
68 | # The glyph index is calculated as glyph = charcode + delta,
|
69 | # which means that delta must be -0xFFFF to map character code
|
70 | # 0xFFFF to glyph 0.
|
71 | deltas << -0xFFFF |
72 | range_offsets << 0 |
73 | break
|
74 | end
|
75 | |
76 | start_glyph_id = new_map[a][:new] |
77 | |
78 | if a - start_glyph_id >= 0x8000 |
79 | deltas << 0 |
80 | range_offsets << (2 * (glyph_indices.length + segcount - segment)) |
81 | a.upto(b) { |code| glyph_indices << new_map[code][:new] } |
82 | else
|
83 | deltas << (-a + start_glyph_id) |
84 | range_offsets << 0 |
85 | end
|
86 | |
87 | offset += 2 |
88 | end
|
89 | |
90 | # format, length, language
|
91 | subtable = [ |
92 | 4, 16 + (8 * segcount) + (2 * glyph_indices.length), 0, |
93 | ].pack('nnn') |
94 | |
95 | search_range = 2 * (2**Integer(Math.log(segcount) / Math.log(2))) |
96 | entry_selector = Integer(Math.log(search_range / 2) / Math.log(2)) |
97 | range_shift = (2 * segcount) - search_range |
98 | subtable << [ |
99 | segcount * 2, search_range, entry_selector, range_shift, |
100 | ].pack('nnnn') |
101 | |
102 | subtable << end_codes.pack('n*') << "\0\0" << start_codes.pack('n*') |
103 | subtable << deltas.pack('n*') << range_offsets.pack('n*') |
104 | subtable << glyph_indices.pack('n*') |
105 | |
106 | { charmap: new_map, subtable: subtable, max_glyph_id: next_id + 1 } |
107 | end
|
Instance Method Details
#[](code) ⇒ Integer
Get glyph ID for character code.
Source Code
lib/ttfunk/table/cmap/format04.rb, line 113
113 | def [](code) |
114 | @code_map[code] || 0 |
115 | end
|
#supported? ⇒ true
Is this encoding record format supported?
Source Code
lib/ttfunk/table/cmap/format04.rb, line 120
120 | def supported? |
121 | true
|
122 | end
|