Module: TTFunk::Table::Cmap::Format04

Defined in:
lib/ttfunk/table/cmap/format04.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#code_mapObject (readonly)

Returns the value of attribute code_map.



7
8
9
# File 'lib/ttfunk/table/cmap/format04.rb', line 7

def code_map
  @code_map
end

#languageObject (readonly)

Returns the value of attribute language.



6
7
8
# File 'lib/ttfunk/table/cmap/format04.rb', line 6

def language
  @language
end

Class Method Details

.encode(charmap) ⇒ Object

Expects a hash mapping character codes to glyph ids (where the glyph ids are from the original font). Returns a hash including a new map (:charmap) that maps the characters in charmap to a another hash containing both the old (:old) and new (:new) glyph ids. The returned hash also includes a :subtable key, which contains the encoded subtable for the given charmap.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/ttfunk/table/cmap/format04.rb', line 15

def self.encode(charmap)
  end_codes = []
  start_codes = []
  next_id = 0
  last = difference = nil

  glyph_map = { 0 => 0 }
  new_map = charmap.keys.sort.inject({}) do |map, code|
    old = charmap[code]
    glyph_map[old] ||= next_id += 1
    map[code] = { :old => old, :new => glyph_map[old] }

    delta = glyph_map[old] - code
    if last.nil? || delta != difference
      end_codes << last if last
      start_codes << code
      difference = delta
    end
    last = code

    map
  end

  end_codes << last if last
  end_codes << 0xFFFF
  start_codes << 0xFFFF
  segcount = start_codes.length

  # build the conversion tables
  deltas = []
  range_offsets = []
  glyph_indices = []

  offset = 0
  start_codes.zip(end_codes).each_with_index do |(a, b), segment|
    if a == 0xFFFF
      deltas << 0
      range_offsets << 0
      break
    end

    start_glyph_id = new_map[a][:new]
    if a - start_glyph_id >= 0x8000
      deltas << 0
      range_offsets << 2 * (glyph_indices.length + segcount - segment)
      a.upto(b) { |code| glyph_indices << new_map[code][:new] }
    else
      deltas << -a + start_glyph_id
      range_offsets << 0
    end
    offset += 2
  end

  # format, length, language
  subtable = [4, 16 + 8 * segcount + 2 * glyph_indices.length, 0].pack("nnn")

  search_range = 2 * 2 ** (Math.log(segcount) / Math.log(2)).to_i
  entry_selector = (Math.log(search_range / 2) / Math.log(2)).to_i
  range_shift = (2 * segcount) - search_range
  subtable << [segcount * 2, search_range, entry_selector, range_shift].pack("nnnn")

  subtable << end_codes.pack("n*") << "\0\0" << start_codes.pack("n*")
  subtable << deltas.pack("n*") << range_offsets.pack("n*") << glyph_indices.pack("n*")

  { :charmap => new_map, :subtable => subtable, :max_glyph_id => next_id+1 }
end

Instance Method Details

#[](code) ⇒ Object



82
83
84
# File 'lib/ttfunk/table/cmap/format04.rb', line 82

def [](code)
  @code_map[code] || 0
end

#supported?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/ttfunk/table/cmap/format04.rb', line 86

def supported?
  true
end