class TTFunk::Table::Cff::Encoding
CFF Encoding
.
Constants
Attributes
Encodign format. @return [Integer]
Number of encoded items. @return [Integer]
Offset or encoding ID. @return [Integer]
Top dict. @return [TTFunk::Table::Cff::TopDict]
Public Class Methods
Source
# File lib/ttfunk/table/cff/encoding.rb, line 24 def codes_for_encoding_id(encoding_id) case encoding_id when STANDARD_ENCODING_ID Encodings::STANDARD when EXPERT_ENCODING_ID Encodings::EXPERT end end
Get predefined encoding by ID.
@param encoding_id [Integer] @return [TTFunk::OneBasedArray<Integer>]
Source
# File lib/ttfunk/table/cff/encoding.rb, line 59 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
@overload initialize(top_dict
, file, offset = nil, length = nil)
@param top_dict [TTFunk::Table:Cff::TopDict] @param file [TTFunk::File] @param offset [Integer] @param length [Integer]
@overload initialize(top_dict
, file, charset_id)
@param top_dict [TTFunk::Table:Cff::TopDict] @param file [TTFunk::File] @param encoding_id [Integer] 0, 1, or 2
TTFunk::SubTable::new
Public Instance Methods
Source
# File lib/ttfunk/table/cff/encoding.rb, line 90 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
Get character code for glyph index.
@param glyph_id [Integer] @return [Integer, nil]
Source
# File lib/ttfunk/table/cff/encoding.rb, line 79 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
Iterate over character codes.
@overload each()
@yieldparam code [Integer] @return [void]
@overload each()
@return [Enumerator]
Source
# File lib/ttfunk/table/cff/encoding.rb, line 120 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
Encode encoding.
@param charmap [Hash{Integer => Hash}] keys are the charac codes,
values are hashes: * `:old` (<tt>Integer</tt>) - glyph ID in the original font. * `:new` (<tt>Integer</tt>) - glyph ID in the subset font.
@return [String]
Source
# File lib/ttfunk/table/cff/encoding.rb, line 100 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
Encoding
offset in the file.
@return [Integer, nil]
Source
# File lib/ttfunk/table/cff/encoding.rb, line 156 def supplemental? # high-order bit set to 1 indicates supplemental encoding @supplemental end
Is this a supplemental encoding?
@return [Boolean]
Private Instance Methods
Source
# File lib/ttfunk/table/cff/encoding.rb, line 179 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
Source
# File lib/ttfunk/table/cff/encoding.rb, line 235 def element_format(fmt = format_sym) { array_format: 'C', range_format: 'CC', supplemental: 'Cn', }[fmt] end
Source
# File lib/ttfunk/table/cff/encoding.rb, line 244 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
@TODO: handle supplemental encoding (necessary?)
Source
# File lib/ttfunk/table/cff/encoding.rb, line 163 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
Source
# File lib/ttfunk/table/cff/encoding.rb, line 265 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
Source
# File lib/ttfunk/table/cff/encoding.rb, line 254 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
Source
# File lib/ttfunk/table/cff/encoding.rb, line 205 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