Class: TTFunk::Table::Cff::Charset

Inherits:
SubTable
  • Object
show all
Includes:
Enumerable
Defined in:
lib/ttfunk/table/cff/charset.rb

Overview

CFF Charset

Constant Summary collapse

FIRST_GLYPH_STRING =

First glyph string. This is an implicit glyph present in all charsets.

'.notdef'
ARRAY_FORMAT =

Format 0.

0
RANGE_FORMAT_8 =

Format 1.

1
RANGE_FORMAT_16 =

Format 2.

2
ISO_ADOBE_CHARSET_ID =

Predefined ISOAdobe charset ID.

0
EXPERT_CHARSET_ID =

Predefined Expert charset ID.

1
EXPERT_SUBSET_CHARSET_ID =

Predefined Expert Subset charset ID.

2
DEFAULT_CHARSET_ID =

Default charset ID.

ISO_ADOBE_CHARSET_ID

Instance Attribute Summary collapse

Attributes inherited from SubTable

#file, #table_offset

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from SubTable

#eot?, #read

Constructor Details

#initialize(top_dict, file, offset = nil, length = nil) ⇒ Charset #initialize(top_dict, file, charset_id) ⇒ Charset

Returns a new instance of Charset.

Overloads:

  • #initialize(top_dict, file, offset = nil, length = nil) ⇒ Charset

    Parameters:

    • top_dict (TTFunk::Table:Cff::TopDict)
    • file (TTFunk::File)
    • offset (Integer) (defaults to: nil)
    • length (Integer) (defaults to: nil)
  • #initialize(top_dict, file, charset_id) ⇒ Charset

    Parameters:

    • top_dict (TTFunk::Table:Cff::TopDict)
    • file (TTFunk::File)
    • charset_id (Integer)

      0, 1, or 2



92
93
94
95
96
97
98
99
100
101
# File 'lib/ttfunk/table/cff/charset.rb', line 92

def initialize(top_dict, file, offset_or_id = nil, length = nil)
  @top_dict = top_dict
  @offset_or_id = offset_or_id || DEFAULT_CHARSET_ID

  if offset
    super(file, offset, length)
  else
    @items_count = self.class.strings_for_charset_id(offset_or_id).size
  end
end

Instance Attribute Details

#entriesTTFunk::OneBasedArray<Integer>, Array<Range<Integer>> (readonly)

Encoded entries.

Returns:



61
62
63
# File 'lib/ttfunk/table/cff/charset.rb', line 61

def entries
  @entries
end

#formatInteger (readonly)

Encodign format.

Returns:

  • (Integer)


73
74
75
# File 'lib/ttfunk/table/cff/charset.rb', line 73

def format
  @format
end

#items_countInteger (readonly)

Number of encoded items.

Returns:

  • (Integer)


77
78
79
# File 'lib/ttfunk/table/cff/charset.rb', line 77

def items_count
  @items_count
end

#lengthInteger (readonly)

Length of encoded charset subtable.

Returns:

  • (Integer)


65
66
67
# File 'lib/ttfunk/table/cff/charset.rb', line 65

def length
  @length
end

#offset_or_idInteger (readonly)

Offset or charset ID.

Returns:

  • (Integer)


81
82
83
# File 'lib/ttfunk/table/cff/charset.rb', line 81

def offset_or_id
  @offset_or_id
end

#top_dictTTFunk::Table::Cff::TopDict (readonly)

Top dict.



69
70
71
# File 'lib/ttfunk/table/cff/charset.rb', line 69

def top_dict
  @top_dict
end

Class Method Details

.standard_stringsTTFunk::OneBasedArray<String>

Standard strings defined in the spec that do not need to be defined in the CFF.

Returns:



39
40
41
# File 'lib/ttfunk/table/cff/charset.rb', line 39

def standard_strings
  Charsets::STANDARD_STRINGS
end

.strings_for_charset_id(charset_id) ⇒ TTFunk::OneBasedArray<String>

Strings for charset ID.

Parameters:

  • charset_id (Integer)

Returns:



47
48
49
50
51
52
53
54
55
56
# File 'lib/ttfunk/table/cff/charset.rb', line 47

def strings_for_charset_id(charset_id)
  case charset_id
  when ISO_ADOBE_CHARSET_ID
    Charsets::ISO_ADOBE
  when EXPERT_CHARSET_ID
    Charsets::EXPERT
  when EXPERT_SUBSET_CHARSET_ID
    Charsets::EXPERT_SUBSET
  end
end

Instance Method Details

#[](glyph_id) ⇒ String?

Get character name for glyph index.

Parameters:

  • glyph_id (Integer)

Returns:

  • (String, nil)


121
122
123
124
125
# File 'lib/ttfunk/table/cff/charset.rb', line 121

def [](glyph_id)
  return FIRST_GLYPH_STRING if glyph_id.zero?

  find_string(sid_for(glyph_id))
end

#each {|name| ... } ⇒ void #eachEnumerator

Iterate over character names.

Overloads:

  • #each {|name| ... } ⇒ void

    This method returns an undefined value.

    Yield Parameters:

    • name (String)
  • #eachEnumerator

    Returns:

    • (Enumerator)


110
111
112
113
114
115
# File 'lib/ttfunk/table/cff/charset.rb', line 110

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

#encode(charmap) ⇒ String

Encode charset.

Parameters:

  • charmap (Hash{Integer => Hash})

    keys are the charac codes, values are hashes:

    • ‘:old` (Integer) - glyph ID in the original font.

    • ‘:new` (Integer) - glyph ID in the subset font.

Returns:

  • (String)


149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/ttfunk/table/cff/charset.rb', line 149

def encode(charmap)
  # no offset means no charset was specified (i.e. we're supposed to
  # use a predefined charset) so there's nothing to encode
  return '' unless offset

  sids =
    charmap
      .values
      .reject { |mapping| mapping[:new].zero? }
      .sort_by { |mapping| mapping[:new] }
      .map { |mapping| sid_for(mapping[:old]) }

  ranges = TTFunk::BinUtils.rangify(sids)
  range_max = ranges.map(&:last).max

  range_bytes =
    if range_max.positive?
      (Math.log2(range_max) / 8).floor + 1
    else
      # for cases when there are no sequences at all
      Float::INFINITY
    end

  # 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) + (range_bytes * ranges.size)
  total_array_size = sids.size * element_width(:array_format)

  if total_array_size <= total_range_size
    ([format_int(:array_format)] + sids).pack('Cn*')
  else
    fmt = range_bytes == 1 ? :range_format8 : :range_format16
    element_fmt = element_format(fmt)
    result = [format_int(fmt)].pack('C')
    ranges.each { |range| result << range.pack(element_fmt) }
    result
  end
end

#offsetInteger?

Charset offset in the file.

Returns:

  • (Integer, nil)


130
131
132
133
134
135
136
137
138
139
140
# File 'lib/ttfunk/table/cff/charset.rb', line 130

def offset
  # Numbers from 0..2 mean charset IDs instead of offsets. IDs are
  # basically pre-defined sets of characters.
  #
  # 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 > 2
    offset_or_id + top_dict.cff_offset
  end
end