class TTFunk::TTFEncoder
Encodes a TrueType font subset to its binary representation.
Constants
- OPTIMAL_TABLE_ORDER
Optimal table order according to TrueType specification.
Attributes
options[R]
Encoding options. @return [Hash]
original[R]
Original font. @return [TTFunk::File]
subset[R]
Subset
to encode. @return [TTFunk::Subset]
Public Class Methods
new(original, subset, options = {})
click to toggle source
@param original [TTFunk::File] @param subset [TTFunk::Subset] @param options [Hash] @option options :kerning [Boolean] whether to encode Kerning (‘kern`)
table.
# File lib/ttfunk/ttf_encoder.rb, line 30 def initialize(original, subset, options = {}) @original = original @subset = subset @options = options end
Public Instance Methods
encode()
click to toggle source
Encode the font subset.
@return [String]
# File lib/ttfunk/ttf_encoder.rb, line 39 def encode # https://www.microsoft.com/typography/otspec/otff.htm#offsetTable search_range = (2**Math.log2(tables.length).floor) * 16 entry_selector = Integer(Math.log2(2**Math.log2(tables.length).floor)) range_shift = (tables.length * 16) - search_range range_shift = 0 if range_shift.negative? newfont = EncodedString.new newfont << [ original.directory.scaler_type, tables.length, search_range, entry_selector, range_shift, ].pack('Nn*') # Tables are supposed to be listed in ascending order whereas there is a # known optimal order for table data. tables.keys.sort.each do |tag| newfont << [tag, checksum(tables[tag])].pack('A4N') newfont << Placeholder.new(tag, length: 4) newfont << [tables[tag].length].pack('N') end optimal_table_order.each do |optimal_tag| next unless tables.include?(optimal_tag) newfont.resolve_placeholder(optimal_tag, [newfont.length].pack('N')) newfont << tables[optimal_tag] newfont.align!(4) end sum = checksum(newfont) adjustment = 0xB1B0AFBA - sum newfont.resolve_placeholder(:checksum, [adjustment].pack('N')) newfont.string end
Private Instance Methods
align(data, width)
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 210 def align(data, width) if (data.length % width).positive? data + ("\0" * (width - (data.length % width))) else data end end
checksum(data)
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 202 def checksum(data) align(raw(data), 4).unpack('N*').sum & 0xFFFF_FFFF end
cmap_table()
click to toggle source
“mandatory” tables. Every font should (“should”) have these
# File lib/ttfunk/ttf_encoder.rb, line 89 def cmap_table @cmap_table ||= subset.new_cmap_table end
cvt_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 133 def cvt_table @cvt_table ||= TTFunk::Table::Simple.new(original, 'cvt ').raw end
dsig_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 164 def dsig_table @dsig_table ||= TTFunk::Table::Dsig.encode(original.digital_signature) end
fpgm_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 137 def fpgm_table @fpgm_table ||= TTFunk::Table::Simple.new(original, 'fpgm').raw end
gasp_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 145 def gasp_table @gasp_table ||= TTFunk::Table::Simple.new(original, 'gasp').raw end
glyf_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 93 def glyf_table @glyf_table ||= TTFunk::Table::Glyf.encode(glyphs, new_to_old_glyph, old_to_new_glyph) end
glyphs()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 190 def glyphs subset.glyphs end
head_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 121 def head_table @head_table ||= TTFunk::Table::Head.encode(original.header, loca_table, new_to_old_glyph) end
hhea_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 105 def hhea_table @hhea_table = TTFunk::Table::Hhea.encode(original.horizontal_header, hmtx_table, original, new_to_old_glyph) end
hmtx_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 101 def hmtx_table @hmtx_table ||= TTFunk::Table::Hmtx.encode(original.horizontal_metrics, new_to_old_glyph) end
kern_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 149 def kern_table # for PDFs, the kerning info is all included in the PDF as the text is # drawn. Thus, the PDF readers do not actually use the kerning info in # embedded fonts. If the library is used for something else, the # generated subfont may need a kerning table... in that case, you need # to opt into it. if options[:kerning] @kern_table ||= TTFunk::Table::Kern.encode(original.kerning, old_to_new_glyph) end end
loca_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 97 def loca_table @loca_table ||= TTFunk::Table::Loca.encode(glyf_table[:offsets]) end
maxp_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 109 def maxp_table @maxp_table ||= TTFunk::Table::Maxp.encode(original.maximum_profile, old_to_new_glyph) end
name_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 117 def name_table @name_table ||= TTFunk::Table::Name.encode(original.name, glyf_table.fetch(:table, '')) end
new_to_old_glyph()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 194 def new_to_old_glyph subset.new_to_old_glyph end
old_to_new_glyph()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 198 def old_to_new_glyph subset.old_to_new_glyph end
optimal_table_order()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 81 def optimal_table_order OPTIMAL_TABLE_ORDER + (tables.keys - ['DSIG'] - OPTIMAL_TABLE_ORDER) + ['DSIG'] end
os2_table()
click to toggle source
“optional” tables. Fonts may omit these if they do not need them. Because they apply globally, we can simply copy them over, without modification, if they exist.
# File lib/ttfunk/ttf_encoder.rb, line 129 def os2_table @os2_table ||= TTFunk::Table::OS2.encode(original.os2, subset) end
post_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 113 def post_table @post_table ||= TTFunk::Table::Post.encode(original.postscript, new_to_old_glyph) end
prep_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 141 def prep_table @prep_table ||= TTFunk::Table::Simple.new(original, 'prep').raw end
raw(data)
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 206 def raw(data) data.respond_to?(:unresolved_string) ? data.unresolved_string : data end
tables()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 168 def tables @tables ||= { 'cmap' => cmap_table[:table], 'glyf' => glyf_table[:table], 'loca' => loca_table[:table], 'kern' => kern_table, 'hmtx' => hmtx_table[:table], 'hhea' => hhea_table, 'maxp' => maxp_table, 'OS/2' => os2_table, 'post' => post_table, 'name' => name_table, 'head' => head_table, 'prep' => prep_table, 'fpgm' => fpgm_table, 'cvt ' => cvt_table, 'VORG' => vorg_table, 'DSIG' => dsig_table, 'gasp' => gasp_table, }.compact end
vorg_table()
click to toggle source
# File lib/ttfunk/ttf_encoder.rb, line 160 def vorg_table @vorg_table ||= TTFunk::Table::Vorg.encode(original.vertical_origins) end