Class: TTFunk::SubsetCollection

Inherits:
Object
  • Object
show all
Defined in:
lib/ttfunk/subset_collection.rb

Overview

Subset collection.

For many use cases a font subset can be efficiently encoded using MacRoman encoding. However, for full font coverage and characters that are not in MacRoman encoding an additional Unicode subset is used. There can be as many as needed Unicode subsets to fully cover glyphs provided by the original font. Ther resulting set of subsets all use 8-bit encoding helping to efficiently encode text in Prawn.

Instance Method Summary collapse

Constructor Details

#initialize(original) ⇒ SubsetCollection

Returns a new instance of SubsetCollection.

Parameters:



16
17
18
19
# File 'lib/ttfunk/subset_collection.rb', line 16

def initialize(original)
  @original = original
  @subsets = [Subset.for(@original, :mac_roman)]
end

Instance Method Details

#[](subset) ⇒ TTFunk::Subset::Unicode, ...

Get subset by index.



26
27
28
# File 'lib/ttfunk/subset_collection.rb', line 26

def [](subset)
  @subsets[subset]
end

#encode(characters) ⇒ Array<Array(Integer, String)>

Encode characters into subset-character pairs.

Parameters:

  • characters (Array<Integer>)

    should be an array of UTF-16 code points

Returns:

  • (Array<Array(Integer, String)>)

    subset chunks, where each chunk is another array of two elements. The first element is the subset number, and the second element is the string of characters to render with that font subset. The strings will be encoded for their subset font, and so may not look (in the raw) like what was passed in, but they will render correctly with the corresponding subset font.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/ttfunk/subset_collection.rb', line 67

def encode(characters)
  return [] if characters.empty?

  # TODO: probably would be more optimal to nix the #use method,
  # and merge it into this one, so it can be done in a single
  # pass instead of two passes.
  use(characters)

  parts = []
  current_subset = 0
  current_char = 0
  char = characters[current_char]

  loop do
    while @subsets[current_subset].includes?(char)
      char = @subsets[current_subset].from_unicode(char)

      if parts.empty? || parts.last[0] != current_subset
        encoded_char = char.chr
        if encoded_char.respond_to?(:force_encoding)
          encoded_char.force_encoding('ASCII-8BIT')
        end
        parts << [current_subset, encoded_char]
      else
        parts.last[1] << char
      end

      current_char += 1
      return parts if current_char >= characters.length

      char = characters[current_char]
    end

    current_subset = (current_subset + 1) % @subsets.length
  end
end

#use(characters) ⇒ void

This method returns an undefined value.

Add chracters to appropiate subsets.

Parameters:

  • characters (Array<Integer>)

    should be an array of UTF-16 code points



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/ttfunk/subset_collection.rb', line 35

def use(characters)
  characters.each do |char|
    covered = false
    i = 0
    length = @subsets.length
    while i < length
      subset = @subsets[i]
      if subset.covers?(char)
        subset.use(char)
        covered = true
        break
      end
      i += 1
    end

    unless covered
      @subsets << Subset.for(@original, :unicode_8bit)
      @subsets.last.use(char)
    end
  end
end