class TTFunk::Table::Cff::FdSelector
Constants
- ARRAY_ENTRY_SIZE
- ARRAY_FORMAT
- RANGE_ENTRY_SIZE
- RANGE_FORMAT
Attributes
count[R]
entries[R]
n_glyphs[R]
top_dict[R]
Public Class Methods
new(top_dict, file, offset, length = nil)
click to toggle source
Calls superclass method
TTFunk::SubTable::new
# File lib/ttfunk/table/cff/fd_selector.rb, line 17 def initialize(top_dict, file, offset, length = nil) @top_dict = top_dict super(file, offset, length) end
Public Instance Methods
[](glyph_id)
click to toggle source
# File lib/ttfunk/table/cff/fd_selector.rb, line 22 def [](glyph_id) case format_sym when :array_format entries[glyph_id] when :range_format if (entry = range_cache[glyph_id]) return entry end range, entry = entries.bsearch do |rng, _| if rng.cover?(glyph_id) 0 elsif glyph_id < rng.first -1 else 1 end end range.each { |i| range_cache[i] = entry } entry end end
each() { |self| ... }
click to toggle source
# File lib/ttfunk/table/cff/fd_selector.rb, line 48 def each return to_enum(__method__) unless block_given? count.times { |i| yield self[i] } end
encode(mapping)
click to toggle source
mapping is new -> old glyph ids
# File lib/ttfunk/table/cff/fd_selector.rb, line 55 def encode(mapping) # get list of [new_gid, fd_index] pairs new_indices = mapping.keys.sort.map do |new_gid| [new_gid, self[mapping[new_gid]]] end ranges = rangify_gids(new_indices) total_range_size = ranges.size * RANGE_ENTRY_SIZE total_array_size = new_indices.size * ARRAY_ENTRY_SIZE ''.b.tap do |result| if total_array_size <= total_range_size result << [ARRAY_FORMAT].pack('C') result << new_indices.map(&:last).pack('C*') else result << [RANGE_FORMAT, ranges.size].pack('Cn') ranges.each { |range| result << range.pack('nC') } # "A sentinel GID follows the last range element and serves to # delimit the last range in the array. (The sentinel GID is set # equal to the number of glyphs in the font. That is, its value # is 1 greater than the last GID in the font)." result << [new_indices.size].pack('n') end end end
Private Instance Methods
format_sym()
click to toggle source
# File lib/ttfunk/table/cff/fd_selector.rb, line 142 def format_sym case @format when ARRAY_FORMAT then :array_format when RANGE_FORMAT then :range_format else raise Error, "unsupported fd select format '#{@format}'" end end
parse!()
click to toggle source
# File lib/ttfunk/table/cff/fd_selector.rb, line 105 def parse! @format = read(1, 'C').first @length = 1 case format_sym when :array_format @n_glyphs = top_dict.charstrings_index.count data = io.read(n_glyphs) @length += data.bytesize @count = data.bytesize @entries = data.bytes when :range_format # +2 for sentinel GID, +2 for num_ranges num_ranges = read(2, 'n').first @length += (num_ranges * RANGE_ENTRY_SIZE) + 4 ranges = Array.new(num_ranges) { read(RANGE_ENTRY_SIZE, 'nC') } @entries = ranges.each_cons(2).map do |first, second| first_gid, fd_index = first second_gid, = second [(first_gid...second_gid), fd_index] end # read the sentinel GID, otherwise known as the number of glyphs # in the font @n_glyphs = read(2, 'n').first last_start_gid, last_fd_index = ranges.last @entries << [(last_start_gid...(n_glyphs + 1)), last_fd_index] @count = entries.reduce(0) { |sum, entry| sum + entry.first.size } end end
range_cache()
click to toggle source
# File lib/ttfunk/table/cff/fd_selector.rb, line 85 def range_cache @range_cache ||= {} end
rangify_gids(values)
click to toggle source
values is an array of [new_gid, fd_index] pairs
# File lib/ttfunk/table/cff/fd_selector.rb, line 90 def rangify_gids(values) start_gid = 0 [].tap do |ranges| values.each_cons(2) do |(_, first_idx), (sec_gid, sec_idx)| if first_idx != sec_idx ranges << [start_gid, first_idx] start_gid = sec_gid end end ranges << [start_gid, values.last[1]] end end