Class: TTFunk::TTFEncoder

Inherits:
Object
  • Object
show all
Defined in:
lib/ttfunk/ttf_encoder.rb

Overview

Encodes a TrueType font subset to its binary representation.

Direct Known Subclasses

OTFEncoder

Constant Summary collapse

OPTIMAL_TABLE_ORDER =

Optimal table order according to TrueType specification.

[
  'head', 'hhea', 'maxp', 'OS/2', 'hmtx', 'LTSH', 'VDMX',
  'hdmx', 'cmap', 'fpgm', 'prep', 'cvt ', 'loca', 'glyf',
  'kern', 'name', 'post', 'gasp', 'PCLT',
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(original, subset, options = {}) ⇒ TTFEncoder

Returns a new instance of TTFEncoder.

Parameters:

Options Hash (options):

  • :kerning (Boolean)

    whether to encode Kerning (kern) table.

Source Code
lib/ttfunk/ttf_encoder.rb, line 30
30
def initialize(original, subset, options = {})
31
  @original = original
32
  @subset = subset
33
  @options = options
34
end

Instance Attribute Details

#optionsHash (readonly)

Encoding options.

Returns:

  • (Hash)
Source Code
lib/ttfunk/ttf_encoder.rb, line 23
23
def options
24
  @options
25
end

#originalTTFunk::File (readonly)

Original font.

Returns:

Source Code
lib/ttfunk/ttf_encoder.rb, line 15
15
def original
16
  @original
17
end

#subsetTTFunk::Subset (readonly)

Subset to encode.

Returns:

Source Code
lib/ttfunk/ttf_encoder.rb, line 19
19
def subset
20
  @subset
21
end

Instance Method Details

#encodeString

Encode the font subset.

Returns:

  • (String)
Source Code
lib/ttfunk/ttf_encoder.rb, line 39
39
def encode
40
  # https://www.microsoft.com/typography/otspec/otff.htm#offsetTable
41
  search_range = (2**Math.log2(tables.length).floor) * 16
42
  entry_selector = Integer(Math.log2(2**Math.log2(tables.length).floor))
43
  range_shift = (tables.length * 16) - search_range
44
  range_shift = 0 if range_shift.negative?
45
46
  newfont = EncodedString.new
47
48
  newfont << [
49
    original.directory.scaler_type,
50
    tables.length,
51
    search_range,
52
    entry_selector,
53
    range_shift,
54
  ].pack('Nn*')
55
56
  # Tables are supposed to be listed in ascending order whereas there is a
57
  # known optimal order for table data.
58
  tables.keys.sort.each do |tag|
59
    newfont << [tag, checksum(tables[tag])].pack('A4N')
60
    newfont << Placeholder.new(tag, length: 4)
61
    newfont << [tables[tag].length].pack('N')
62
  end
63
64
  optimal_table_order.each do |optimal_tag|
65
    next unless tables.include?(optimal_tag)
66
67
    newfont.resolve_placeholder(optimal_tag, [newfont.length].pack('N'))
68
    newfont << tables[optimal_tag]
69
    newfont.align!(4)
70
  end
71
72
  sum = checksum(newfont)
73
  adjustment = 0xB1B0AFBA - sum
74
  newfont.resolve_placeholder(:checksum, [adjustment].pack('N'))
75
76
  newfont.string
77
end