class TTFunk::Table::Cff::Encoding
CFF Encoding.
def [](glyph_id)
-
(Integer, nil)
-
Parameters:
-
glyph_id
(Integer
) --
def [](glyph_id) return 0 if glyph_id.zero? return code_for(glyph_id) if offset self.class.codes_for_encoding_id(offset_or_id)[glyph_id] end
def code_for(glyph_id)
def code_for(glyph_id) return 0 if glyph_id.zero? # rather than validating the glyph as part of one of the predefined # encodings, just pass it through return glyph_id unless offset case format_sym when :array_format, :supplemental @entries[glyph_id] when :range_format remaining = glyph_id @entries.each do |range| if range.size >= remaining return (range.first + remaining) - 1 end remaining -= range.size end 0 end end
def codes_for_encoding_id(encoding_id)
-
(TTFunk::OneBasedArray
-)
Parameters:
-
encoding_id
(Integer
) --
def codes_for_encoding_id(encoding_id) case encoding_id when STANDARD_ENCODING_ID Encodings::STANDARD when EXPERT_ENCODING_ID Encodings::EXPERT end end
def each
-
(Enumerator)
- -
(void)
-
Overloads:
-
each()
-
each()
Other tags:
- Yieldparam: code -
def each return to_enum(__method__) unless block_given? # +1 adjusts for the implicit .notdef glyph (items_count + 1).times { |i| yield(self[i]) } end
def element_format(fmt = format_sym)
def element_format(fmt = format_sym) { array_format: 'C', range_format: 'CC', supplemental: 'Cn', }[fmt] end
def element_width(fmt = format_sym)
def element_width(fmt = format_sym) case fmt when :array_format then 1 when :range_format then 2 when :supplemental then 3 else raise Error, "'#{fmt}' is an unsupported encoding format" end end
def encode(charmap)
-
(String)
-
Parameters:
-
charmap
(Hash{Integer => Hash}
) -- keys are the charac codes,
def encode(charmap) # Any subset encoding is all but guaranteed to be different from the # standard encoding so we don't even attempt to see if it matches. We # assume it's different and just encode it anew. return encode_supplemental(charmap) if supplemental? codes = charmap .reject { |_code, mapping| mapping[:new].zero? } .sort_by { |_code, mapping| mapping[:new] } .map { |(code, _m)| code } ranges = TTFunk::BinUtils.rangify(codes) # calculate whether storing the charset as a series of ranges is # more efficient (i.e. takes up less space) vs storing it as an # array of SID values total_range_size = (2 * ranges.size) + (element_width(:range_format) * ranges.size) total_array_size = codes.size * element_width(:array_format) if total_array_size <= total_range_size ([format_int(:array_format), codes.size] + codes).pack('C*') else element_fmt = element_format(:range_format) result = [format_int(:range_format), ranges.size].pack('CC') ranges.each { |range| result << range.pack(element_fmt) } result end end
def encode_supplemental(charmap)
def encode_supplemental(charmap) new_entries = charmap .reject { |_code, mapping| mapping[:new].zero? } .transform_values { |mapping| mapping[:new] } result = [format_int(:supplemental), new_entries.size].pack('CC') fmt = element_format(:supplemental) new_entries.each do |code, new_gid| result << [code, new_gid].pack(fmt) end result end
def format_int(sym = format_sym)
def format_int(sym = format_sym) case sym when :array_format then 0 when :range_format then 1 when :supplemental then 129 else raise Error, "unsupported charset format '#{sym}'" end end
def format_sym
def format_sym return :supplemental if supplemental? case @format when 0 then :array_format when 1 then :range_format else raise Error, "unsupported charset format '#{fmt}'" end end
def initialize(top_dict, file, offset_or_id = nil, length = nil)
-
encoding_id
(Integer
) -- 0, 1, or 2 -
file
(TTFunk::File
) -- -
top_dict
(TTFunk::Table:Cff::TopDict
) -- -
length
(Integer
) -- -
offset
(Integer
) -- -
file
(TTFunk::File
) -- -
top_dict
(TTFunk::Table:Cff::TopDict
) --
Overloads:
-
initialize(top_dict, file, charset_id)
-
initialize(top_dict, file, offset = nil, length = nil)
def initialize(top_dict, file, offset_or_id = nil, length = nil) @top_dict = top_dict @offset_or_id = offset_or_id || DEFAULT_ENCODING_ID if offset super(file, offset, length) @supplemental = format >> 7 == 1 else @items_count = self.class.codes_for_encoding_id(offset_or_id).size @supplemental = false end end
def offset
-
(Integer, nil)
-
def offset # Numbers from 0..1 mean encoding IDs instead of offsets. IDs are # pre-defined, generic encodings that define the characters present # in the font. # # In the case of an offset, add the CFF table's offset since the # charset offset is relative to the start of the CFF table. Otherwise # return nil (no offset). if offset_or_id > 1 offset_or_id + top_dict.cff_offset end end
def parse!
def parse! @format, entry_count = read(2, 'C*') @length = entry_count * element_width case format_sym when :array_format @items_count = entry_count @entries = OneBasedArray.new(read(length, 'C*')) when :range_format @entries = [] @items_count = 0 entry_count.times do code, num_left = read(element_width, element_format) @entries << (code..(code + num_left)) @items_count += num_left + 1 end when :supplemental @entries = {} @items_count = entry_count entry_count.times do code, glyph = read(element_width, element_format) @entries[code] = glyph end end end
def supplemental?
-
(Boolean)
-
def supplemental? # high-order bit set to 1 indicates supplemental encoding @supplemental end