File: subset_collection.rb

package info (click to toggle)
ruby-ttfunk 1.0.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 916 kB
  • sloc: ruby: 1,719; makefile: 16
file content (72 lines) | stat: -rw-r--r-- 2,079 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
require 'ttfunk/subset'

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

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

    # +characters+ should be an array of UTF-16 characters
    def use(characters)
      characters.each do |char|
        covered = false
        @subsets.each_with_index do |subset, i|
          if subset.covers?(char)
            subset.use(char)
            covered = true
            break
          end
        end

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

    # +characters+ should be an array of UTF-16 characters. Returns
    # an array of 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 indicated subset font.
    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
            parts << [current_subset, char.chr]
          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
  end
end