ttfunk 1.7.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +74 -0
  4. data/README.md +17 -15
  5. data/lib/ttfunk/aggregate.rb +5 -0
  6. data/lib/ttfunk/bin_utils.rb +27 -8
  7. data/lib/ttfunk/bit_field.rb +25 -2
  8. data/lib/ttfunk/collection.rb +27 -3
  9. data/lib/ttfunk/directory.rb +7 -1
  10. data/lib/ttfunk/encoded_string.rb +58 -4
  11. data/lib/ttfunk/max.rb +14 -0
  12. data/lib/ttfunk/min.rb +14 -0
  13. data/lib/ttfunk/one_based_array.rb +20 -0
  14. data/lib/ttfunk/otf_encoder.rb +5 -14
  15. data/lib/ttfunk/placeholder.rb +15 -1
  16. data/lib/ttfunk/reader.rb +6 -4
  17. data/lib/ttfunk/resource_file.rb +29 -5
  18. data/lib/ttfunk/sci_form.rb +20 -3
  19. data/lib/ttfunk/sub_table.rb +29 -4
  20. data/lib/ttfunk/subset/base.rb +48 -0
  21. data/lib/ttfunk/subset/code_page.rb +49 -2
  22. data/lib/ttfunk/subset/mac_roman.rb +2 -0
  23. data/lib/ttfunk/subset/unicode.rb +32 -0
  24. data/lib/ttfunk/subset/unicode_8bit.rb +32 -0
  25. data/lib/ttfunk/subset/windows_1252.rb +2 -0
  26. data/lib/ttfunk/subset.rb +8 -0
  27. data/lib/ttfunk/subset_collection.rb +39 -14
  28. data/lib/ttfunk/sum.rb +13 -0
  29. data/lib/ttfunk/table/cff/charset.rb +96 -18
  30. data/lib/ttfunk/table/cff/charsets/expert.rb +3 -2
  31. data/lib/ttfunk/table/cff/charsets/expert_subset.rb +3 -2
  32. data/lib/ttfunk/table/cff/charsets/iso_adobe.rb +3 -2
  33. data/lib/ttfunk/table/cff/charsets/standard_strings.rb +3 -2
  34. data/lib/ttfunk/table/cff/charsets.rb +1 -0
  35. data/lib/ttfunk/table/cff/charstring.rb +33 -12
  36. data/lib/ttfunk/table/cff/charstrings_index.rb +17 -11
  37. data/lib/ttfunk/table/cff/dict.rb +53 -23
  38. data/lib/ttfunk/table/cff/encoding.rb +82 -24
  39. data/lib/ttfunk/table/cff/encodings/expert.rb +3 -2
  40. data/lib/ttfunk/table/cff/encodings/standard.rb +3 -2
  41. data/lib/ttfunk/table/cff/encodings.rb +1 -0
  42. data/lib/ttfunk/table/cff/fd_selector.rb +61 -21
  43. data/lib/ttfunk/table/cff/font_dict.rb +30 -18
  44. data/lib/ttfunk/table/cff/font_index.rb +22 -10
  45. data/lib/ttfunk/table/cff/header.rb +16 -3
  46. data/lib/ttfunk/table/cff/index.rb +97 -65
  47. data/lib/ttfunk/table/cff/one_based_index.rb +11 -1
  48. data/lib/ttfunk/table/cff/path.rb +43 -4
  49. data/lib/ttfunk/table/cff/private_dict.rb +31 -11
  50. data/lib/ttfunk/table/cff/subr_index.rb +7 -2
  51. data/lib/ttfunk/table/cff/top_dict.rb +82 -59
  52. data/lib/ttfunk/table/cff/top_index.rb +10 -6
  53. data/lib/ttfunk/table/cff.rb +41 -21
  54. data/lib/ttfunk/table/cmap/format00.rb +27 -6
  55. data/lib/ttfunk/table/cmap/format04.rb +34 -14
  56. data/lib/ttfunk/table/cmap/format06.rb +28 -1
  57. data/lib/ttfunk/table/cmap/format10.rb +29 -2
  58. data/lib/ttfunk/table/cmap/format12.rb +29 -2
  59. data/lib/ttfunk/table/cmap/subtable.rb +50 -6
  60. data/lib/ttfunk/table/cmap.rb +21 -0
  61. data/lib/ttfunk/table/dsig.rb +47 -6
  62. data/lib/ttfunk/table/glyf/compound.rb +73 -6
  63. data/lib/ttfunk/table/glyf/path_based.rb +40 -3
  64. data/lib/ttfunk/table/glyf/simple.rb +50 -5
  65. data/lib/ttfunk/table/glyf.rb +15 -7
  66. data/lib/ttfunk/table/head.rb +84 -6
  67. data/lib/ttfunk/table/hhea.rb +71 -10
  68. data/lib/ttfunk/table/hmtx.rb +32 -5
  69. data/lib/ttfunk/table/kern/format0.rb +25 -7
  70. data/lib/ttfunk/table/kern.rb +16 -4
  71. data/lib/ttfunk/table/loca.rb +21 -8
  72. data/lib/ttfunk/table/maxp.rb +195 -10
  73. data/lib/ttfunk/table/name.rb +126 -9
  74. data/lib/ttfunk/table/os2.rb +150 -26
  75. data/lib/ttfunk/table/post/format10.rb +7 -0
  76. data/lib/ttfunk/table/post/format20.rb +9 -0
  77. data/lib/ttfunk/table/post/format30.rb +6 -0
  78. data/lib/ttfunk/table/post/format40.rb +5 -0
  79. data/lib/ttfunk/table/post.rb +63 -7
  80. data/lib/ttfunk/table/sbix.rb +50 -14
  81. data/lib/ttfunk/table/simple.rb +5 -0
  82. data/lib/ttfunk/table/vorg.rb +31 -3
  83. data/lib/ttfunk/table.rb +20 -1
  84. data/lib/ttfunk/ttf_encoder.rb +39 -41
  85. data/lib/ttfunk.rb +154 -1
  86. data.tar.gz.sig +0 -0
  87. metadata +50 -28
  88. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8c6a1d61ab884e88dd7424c80680f5dac53de5d891645f5b3fb5699ebbcffce3
4
- data.tar.gz: 7031ece12dacbf351ea1e98fceccca054bca245ddd7437a62ca746e1d85b40e9
3
+ metadata.gz: eb1a969a808f290fe7ac4dda94e2fff26dbfc69ba183b6e409062c18b28cfc7b
4
+ data.tar.gz: 89534c924740d79858f0fe8a9e8bd1830ad7fa89473d170365870eb15d9345c2
5
5
  SHA512:
6
- metadata.gz: f2481488976f0015fb0abf49c8fa510cf6b8ee6120d17eebd04a01d4fcda5c96397c8bcf729bf42efae8f08238ebe3cba914f082bac2966d92f867f62e87b92b
7
- data.tar.gz: fc4561d7ff2892a7a8f1c752c473a4b6e0a1e7b17042e60c175c98ef83bea9cbbdf6893ddab92c841f9ec9759af9fa41617445d304903c585a6f20d111e59e6e
6
+ metadata.gz: b5282d51944572615cb694dc810e55e45961cb9a122fa31481542fd2417e5465bae2585b2e06867221b93fb2f2cbf885bca9b9bd7fb34bd1ea21cde560f83e9b
7
+ data.tar.gz: ae54beef0f1f1cbc9b7e02929d73a1da5264239611802f57c2d9f5ce7cba7db4ca9cee25847a2d07ed2cccfdcce6cfd04e6e53cffc694fe94996a8a581336cea
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -7,6 +7,80 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Fixed
11
+
12
+ * Corrupted CFF index data
13
+
14
+ there was a subtle bug in cff index implementation that resulted in
15
+ a data corruption. in certain circumstances some items didn't get
16
+ properly encoded. this happened when items were not previously accessed.
17
+
18
+ this resulted, for instance, in missing glyphs. but only sometimes
19
+ because indexes might've still contain data that shouldn't've been
20
+ there. in combination with incorrect encoding (see further) this
21
+ resulted in some glyphs still being rendered, sometimes even correctly.
22
+
23
+ along with the fix a rather large api change landed. this resulted in
24
+ quite a big diff.
25
+
26
+ Alexander Mankuta
27
+
28
+ * Incorrect CFF encoding in subsets
29
+
30
+ TTFunk used to reuse encoding from the original font. This mapping was
31
+ incorrect for subset fonts which used not just a subset of glyphs but
32
+ also a different encoding.
33
+
34
+ A separate issue was that some fonts have empty CFF encoding. This
35
+ incorrect mapping resulted in encoding that mapped all codes to glyph 0.
36
+
37
+ This had impact on Prawn in particular. PDF spec explicitly says that
38
+ CFF encoding is not to be used in OpenType fonts. `cmap` table should
39
+ directly index charstrings in the CFF table. Despite this PDF renderers
40
+ still use CFF encoding to retrieve glyphs. So TTFunk has to discard the
41
+ original CFF encoding and supply its own.
42
+
43
+ Alexander Mankuta
44
+
45
+ * `maxp` table
46
+
47
+ The table is now correctly parsed and encoded for both TrueType and CFF-based
48
+ OpenType fonts.
49
+
50
+ Cameron Dutro, Alexander Mankuta
51
+
52
+ * Files are closed sooner
53
+
54
+ Files were garbage collected but could stay open for longer than necessary.
55
+
56
+ Jon Burgess
57
+
58
+ * Long date time in the `head` table
59
+
60
+ The `created` and `modified` fields we parsed and encoded with incorrect
61
+ endiannes. Additionally helper methods were added to convert these fields to
62
+ and from Ruby `Time`.
63
+
64
+ Jens Kutilek, Peter Goldstein
65
+
66
+ * Removed execution permissions on non-executable files
67
+
68
+ Keenan Brock
69
+
70
+ ### Changes
71
+
72
+ * Minimum Ruby is 2.7
73
+
74
+ Alexander Mankuta
75
+
76
+ * Performance improvement in subsets construction
77
+
78
+ Thomas Leitner
79
+
80
+ * CI improvememnts
81
+
82
+ Peter Goldstein
83
+
10
84
  ## 1.7.0
11
85
 
12
86
  ### Changes
data/README.md CHANGED
@@ -3,24 +3,29 @@
3
3
  ![Maintained: yes](https://img.shields.io/badge/maintained-yes-brightgreen.svg)
4
4
  ![CI status](https://github.com/prawnpdf/ttfunk/workflows/CI/badge.svg)
5
5
 
6
- TTFunk is a TrueType font parser written in pure ruby.
6
+ TTFunk is a TrueType and OpenType font library written in pure ruby. It supports
7
+ both parsing and encoding of fonts. Also provides limited font subsetting.
7
8
 
8
9
  ## Installation
9
10
 
10
11
  The recommended installation method is via Rubygems.
11
12
 
12
- gem install ttfunk
13
+ ```shell
14
+ gem install ttfunk
15
+ ```
13
16
 
14
17
  ## Usage
15
18
 
16
19
  Basic usage:
17
20
 
18
- require 'ttfunk'
21
+ ```ruby
22
+ require 'ttfunk'
19
23
 
20
- file = TTFunk::File.open("some/path/myfont.ttf")
21
- puts "name : #{file.name.font_name.join(', ')}"
22
- puts "ascent : #{file.ascent}"
23
- puts "descent : #{file.descent}"
24
+ file = TTFunk::File.open("some/path/myfont.ttf")
25
+ puts "name : #{file.name.font_name.join(', ')}"
26
+ puts "ascent : #{file.ascent}"
27
+ puts "descent : #{file.descent}"
28
+ ```
24
29
 
25
30
  For more detailed examples, explore the examples directory.
26
31
 
@@ -32,15 +37,12 @@ Matz's terms for Ruby, GPLv2, or GPLv3. See LICENSE for details.
32
37
 
33
38
  This project is maintained by the same folks who run the Prawn PDF project.
34
39
 
35
- You can find the full list of Github users who have at least one patch accepted
36
- to ttfunk at:
40
+ Here's the [full list](https://github.com/prawnpdf/ttfunk/contributors) of
41
+ Github users who have at least one patch accepted to TTFunk.
37
42
 
38
- https://github.com/prawnpdf/ttfunk/contributors
39
-
40
- ## Mailing List
43
+ ## Community support
41
44
 
42
45
  TTFunk is maintained as a dependency of Prawn, the ruby PDF generation library.
43
46
 
44
- Any questions or feedback should be sent to the Prawn google group.
45
-
46
- https://groups.google.com/group/prawn-ruby
47
+ Any questions or feedback should be sent to the [Prawn
48
+ Diccussions](https://github.com/orgs/prawnpdf/discussions) group.
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTFunk
4
+ # Base class for different aggregate values and accumulators.
5
+ #
6
+ # @see TTFunk::Min
7
+ # @see TTFunk::Max
8
+ # @see TTFunk::Sum
4
9
  class Aggregate
5
10
  private
6
11
 
@@ -1,27 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module TTFunk
3
+ module TTFunk # rubocop: disable Style/Documentation # false positive
4
+ # Bit crunching utility methods.
4
5
  module BinUtils
5
- # assumes big-endian
6
+ # Turn a bunch of small integers into one big integer. Assumes big-endian.
7
+ #
8
+ # @param arr [Array<Integer>]
9
+ # @param bit_width [Integer] bit width of the elements
10
+ # @return [Integer]
6
11
  def stitch_int(arr, bit_width:)
7
12
  value = 0
8
13
 
9
14
  arr.each_with_index do |element, index|
10
- value |= element << bit_width * index
15
+ value |= element << (bit_width * index)
11
16
  end
12
17
 
13
18
  value
14
19
  end
15
20
 
16
- # assumes big-endian
21
+ # Slice a big integer into a bunch of small integers. Assumes big-endian.
22
+ #
23
+ # @param value [Integer]
24
+ # @param bit_width [Integer] bit width of the elements
25
+ # @param slice_count [Integer] number of elements to slice into. This is
26
+ # needed for cases where top bits are zero.
27
+ # @return [Array<Integer>]
17
28
  def slice_int(value, bit_width:, slice_count:)
18
- mask = 2**bit_width - 1
29
+ mask = (2**bit_width) - 1
19
30
 
20
31
  Array.new(slice_count) do |i|
21
- (value >> bit_width * i) & mask
32
+ (value >> (bit_width * i)) & mask
22
33
  end
23
34
  end
24
35
 
36
+ # Two's compliment to an integer.
37
+ #
38
+ # @param num [Integer]
39
+ # @param bit_width [Integer] number width
40
+ # @return [Integer]
25
41
  def twos_comp_to_int(num, bit_width:)
26
42
  if num >> (bit_width - 1) == 1
27
43
  # we want all ones
@@ -34,8 +50,11 @@ module TTFunk
34
50
  end
35
51
  end
36
52
 
37
- # turns a (sorted) sequence of values into a series of two-element arrays
38
- # where the first element is the start and the second is the length
53
+ # Turns a (sorted) sequence of values into a series of two-element arrays
54
+ # where the first element is the start and the second is the length.
55
+ #
56
+ # @param values [Array<Integer>]
57
+ # @return [Array<Array(Integer, Integer)>]
39
58
  def rangify(values)
40
59
  values
41
60
  .slice_when { |a, b| b - a > 1 }
@@ -1,29 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTFunk
4
+ # Bitfield represents a series of bits that can individually be toggled.
4
5
  class BitField
6
+ # Serialized value.
7
+ # @return [Integer]
5
8
  attr_reader :value
6
9
 
10
+ # @param value [Integer] initial value
7
11
  def initialize(value = 0)
8
12
  @value = value
9
13
  end
10
14
 
15
+ # Set bit on.
16
+ #
17
+ # @param pos [Integer] bit position
18
+ # @return [void]
11
19
  def on(pos)
12
20
  @value |= 2**pos
13
21
  end
14
22
 
23
+ # If bit on?
24
+ #
25
+ # @param pos [Integer]
26
+ # @return [Boolean]
15
27
  def on?(pos)
16
- (value & 2**pos).positive?
28
+ (value & (2**pos)).positive?
17
29
  end
18
30
 
31
+ # Set bit off.
32
+ #
33
+ # @param pos [Integer]
34
+ # @return [void]
19
35
  def off(pos)
20
- @value &= 2**Math.log2(value).ceil - 2**pos - 1
36
+ @value &= (2**Math.log2(value).ceil) - (2**pos) - 1
21
37
  end
22
38
 
39
+ # Is bit off?
40
+ #
41
+ # @param pos [Integer]
42
+ # @return [Boolean]
23
43
  def off?(pos)
24
44
  !on?(pos)
25
45
  end
26
46
 
47
+ # Get a duplicate of this bit field.
48
+ #
49
+ # @return [BitField]
27
50
  def dup
28
51
  self.class.new(value)
29
52
  end
@@ -1,21 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTFunk
4
+ # TrueType font collection. Usually a file with `.ttc` extension.
4
5
  class Collection
5
6
  include Enumerable
6
7
 
8
+ # Load a TrueType collection.
9
+ #
10
+ # @overload open(io)
11
+ # @param io [IO] IO to read the collection from.
12
+ # @yieldparam collection [TTFunk::Collection]
13
+ # @return [any] whatever the block returns
14
+ # @overload open(file_path)
15
+ # @param file_path [String, Pathname] Path to the font collection file.
16
+ # @yieldparam collection [TTFunk::Collection]
17
+ # @return [any] whatever the block returns
7
18
  def self.open(path)
8
19
  if path.respond_to?(:read)
9
- result = yield new(path)
20
+ result = yield(new(path))
10
21
  path.rewind
11
22
  result
12
23
  else
13
24
  ::File.open(path, 'rb') do |io|
14
- yield new(io)
25
+ yield(new(io))
15
26
  end
16
27
  end
17
28
  end
18
29
 
30
+ # @param io [IO(#read & #rewind)]
31
+ # @raise [ArgumentError] if `io` doesn't start with a ttc tag
19
32
  def initialize(io)
20
33
  tag = io.read(4)
21
34
  raise ArgumentError, 'not a TTC file' unless tag == 'ttcf'
@@ -29,17 +42,28 @@ module TTFunk
29
42
  @cache = []
30
43
  end
31
44
 
45
+ # Number of fonts in this collection.
46
+ #
47
+ # @return [Integer]
32
48
  def count
33
49
  @offsets.length
34
50
  end
35
51
 
52
+ # Iterate over fonts in the collection.
53
+ #
54
+ # @yieldparam font [TTFunk::File]
55
+ # @return [self]
36
56
  def each
37
57
  count.times do |index|
38
- yield self[index]
58
+ yield(self[index])
39
59
  end
40
60
  self
41
61
  end
42
62
 
63
+ # Get font by index.
64
+ #
65
+ # @param index [Integer]
66
+ # @return [TTFunk::File]
43
67
  def [](index)
44
68
  @cache[index] ||= TTFunk::File.new(@contents, @offsets[index])
45
69
  end
@@ -1,8 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTFunk
4
+ # SFNT table directory.
4
5
  class Directory
6
+ # Table descriptors
7
+ # @return [Hash{String => Hash}]
5
8
  attr_reader :tables
9
+
10
+ # Scaler type
11
+ # @return [Integer]
6
12
  attr_reader :scaler_type
7
13
 
8
14
  def initialize(io, offset = 0)
@@ -20,7 +26,7 @@ module TTFunk
20
26
  tag: tag,
21
27
  checksum: checksum,
22
28
  offset: offset,
23
- length: length
29
+ length: length,
24
30
  }
25
31
  end
26
32
  end
@@ -1,50 +1,88 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'stringio'
4
+ require_relative 'placeholder'
4
5
 
5
6
  module TTFunk
7
+ # Risen when the final encoded string was requested but there were some
8
+ # unresolved placeholders in it.
6
9
  class UnresolvedPlaceholderError < StandardError
7
10
  end
8
11
 
12
+ # Risen when a placeholder is added to an Encoded String but it already
13
+ # contains a placeholder with the same name.
9
14
  class DuplicatePlaceholderError < StandardError
10
15
  end
11
16
 
17
+ # Encoded string takes care of placeholders in binary strings. Placeholders
18
+ # are used when bytes need to be placed in the stream before their value is
19
+ # known.
20
+ #
21
+ # @api private
12
22
  class EncodedString
23
+ # @yieldparam [self]
13
24
  def initialize
14
- yield self if block_given?
25
+ yield(self) if block_given?
15
26
  end
16
27
 
28
+ # Append to string.
29
+ #
30
+ # @param obj [String, Placeholder, EncodedString]
31
+ # @return [self]
17
32
  def <<(obj)
18
33
  case obj
19
34
  when String
20
35
  io << obj
21
36
  when Placeholder
22
37
  add_placeholder(obj)
23
- io << "\0" * obj.length
38
+ io << ("\0" * obj.length)
24
39
  when self.class
25
40
  # adjust placeholders to be relative to the entire encoded string
26
41
  obj.placeholders.each_pair do |_, placeholder|
27
42
  add_placeholder(placeholder.dup, placeholder.position + io.length)
28
43
  end
29
44
 
30
- self << obj.unresolved_string
45
+ io << obj.unresolved_string
31
46
  end
32
47
 
33
48
  self
34
49
  end
35
50
 
51
+ # Append multiple objects.
52
+ #
53
+ # @param objs [Array<String, Placeholder, EncodedString>]
54
+ # @return [self]
55
+ def concat(*objs)
56
+ objs.each do |obj|
57
+ self << obj
58
+ end
59
+ self
60
+ end
61
+
62
+ # Append padding to align string to the specified word width.
63
+ #
64
+ # @param width [Integer]
65
+ # @return [self]
36
66
  def align!(width = 4)
37
67
  if (length % width).positive?
38
- self << "\0" * (width - length % width)
68
+ self << ("\0" * (width - (length % width)))
39
69
  end
40
70
 
41
71
  self
42
72
  end
43
73
 
74
+ # Length of this string.
75
+ #
76
+ # @return [Integer]
44
77
  def length
45
78
  io.length
46
79
  end
47
80
 
81
+ # Raw string.
82
+ #
83
+ # @return [String]
84
+ # @raise [UnresolvedPlaceholderError] if there are any unresolved
85
+ # placeholders left.
48
86
  def string
49
87
  unless placeholders.empty?
50
88
  raise UnresolvedPlaceholderError,
@@ -54,14 +92,27 @@ module TTFunk
54
92
  io.string
55
93
  end
56
94
 
95
+ # Raw bytes.
96
+ #
97
+ # @return [Array<Integer>]
98
+ # @raise [UnresolvedPlaceholderError] if there are any unresolved
99
+ # placeholders left.
57
100
  def bytes
58
101
  string.bytes
59
102
  end
60
103
 
104
+ # Unresolved raw string.
105
+ #
106
+ # @return [String]
61
107
  def unresolved_string
62
108
  io.string
63
109
  end
64
110
 
111
+ # Resolve placeholder.
112
+ #
113
+ # @param name [Symbol]
114
+ # @param value [String]
115
+ # @return [void]
65
116
  def resolve_placeholder(name, value)
66
117
  last_pos = io.pos
67
118
 
@@ -74,6 +125,9 @@ module TTFunk
74
125
  io.seek(last_pos)
75
126
  end
76
127
 
128
+ # Plaholders
129
+ #
130
+ # @return [Hash{Symbol => Plaholder}]
77
131
  def placeholders
78
132
  @placeholders ||= {}
79
133
  end
data/lib/ttfunk/max.rb CHANGED
@@ -1,14 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTFunk
4
+ # Maximum aggregate. Its value can only become greater.
4
5
  class Max < Aggregate
6
+ # Value
7
+ #
8
+ # @return [Comparable, nil]
5
9
  attr_reader :value
6
10
 
11
+ # @param init_value [Comparable] initial value
7
12
  def initialize(init_value = nil)
8
13
  super()
9
14
  @value = init_value
10
15
  end
11
16
 
17
+ # Push a value. It will become the new value if it's greater than the
18
+ # current value (or if there was no value).
19
+ #
20
+ # @param new_value [Comparable]
21
+ # @return [void]
12
22
  def <<(new_value)
13
23
  new_value = coerce(new_value)
14
24
 
@@ -17,6 +27,10 @@ module TTFunk
17
27
  end
18
28
  end
19
29
 
30
+ # Get the stored value or default.
31
+ #
32
+ # @param default [any]
33
+ # @return [any]
20
34
  def value_or(default)
21
35
  return default if value.nil?
22
36
 
data/lib/ttfunk/min.rb CHANGED
@@ -1,14 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTFunk
4
+ # Minimum aggregate. Its value can only become lower.
4
5
  class Min < Aggregate
6
+ # Value
7
+ #
8
+ # @return [Comparable, nil]
5
9
  attr_reader :value
6
10
 
11
+ # @param init_value [Comparable] initial value
7
12
  def initialize(init_value = nil)
8
13
  super()
9
14
  @value = init_value
10
15
  end
11
16
 
17
+ # Push a value. It will become the new value if it's lower than the current
18
+ # value (or if there was no value).
19
+ #
20
+ # @param new_value [Comparable]
21
+ # @return [void]
12
22
  def <<(new_value)
13
23
  new_value = coerce(new_value)
14
24
 
@@ -17,6 +27,10 @@ module TTFunk
17
27
  end
18
28
  end
19
29
 
30
+ # Get the stored value or default.
31
+ #
32
+ # @param default [any]
33
+ # @return [any]
20
34
  def value_or(default)
21
35
  return default if value.nil?
22
36
 
@@ -1,13 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTFunk
4
+ # Array with indexing starting at 1.
4
5
  class OneBasedArray
5
6
  include Enumerable
6
7
 
8
+ # @overload initialize(size)
9
+ # @param size [Integer] number of entries in this array
10
+ # @overload initialize(entries)
11
+ # @param entries [Array] an array to take entries from
7
12
  def initialize(size = 0)
8
13
  @entries = Array.new(size)
9
14
  end
10
15
 
16
+ # Get element by index.
17
+ #
18
+ # @param idx [Integer]
19
+ # @return [any, nil]
20
+ # @raise IndexError if index is 0
11
21
  def [](idx)
12
22
  if idx.zero?
13
23
  raise IndexError,
@@ -17,14 +27,24 @@ module TTFunk
17
27
  entries[idx - 1]
18
28
  end
19
29
 
30
+ # Number of elements in this array.
31
+ #
32
+ # @return [Integer]
20
33
  def size
21
34
  entries.size
22
35
  end
23
36
 
37
+ # Convert to native array.
38
+ #
39
+ # @return [Array]
24
40
  def to_ary
25
41
  entries
26
42
  end
27
43
 
44
+ # Iterate over elements.
45
+ #
46
+ # @yieldparam element [any]
47
+ # @return [void]
28
48
  def each(&block)
29
49
  entries.each(&block)
30
50
  end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TTFunk
4
+ # Encodes a CFF-based OpenType font subset to its binary representation.
4
5
  class OTFEncoder < TTFEncoder
5
- OPTIMAL_TABLE_ORDER = [
6
- 'head', 'hhea', 'maxp', 'OS/2', 'name', 'cmap', 'post', 'CFF '
7
- ].freeze
6
+ # Optimal table order according to OpenType specification.
7
+ OPTIMAL_TABLE_ORDER = ['head', 'hhea', 'maxp', 'OS/2', 'name', 'cmap', 'post', 'CFF '].freeze
8
8
 
9
9
  private
10
10
 
@@ -27,7 +27,7 @@ module TTFunk
27
27
  end
28
28
 
29
29
  def cff_table
30
- @cff_table ||= original.cff.encode(new_to_old_glyph, old_to_new_glyph)
30
+ @cff_table ||= original.cff.encode(subset)
31
31
  end
32
32
 
33
33
  def vorg_table
@@ -38,7 +38,7 @@ module TTFunk
38
38
  @tables ||= super.merge(
39
39
  'BASE' => base_table,
40
40
  'VORG' => vorg_table,
41
- 'CFF ' => cff_table
41
+ 'CFF ' => cff_table,
42
42
  ).compact
43
43
  end
44
44
 
@@ -48,14 +48,5 @@ module TTFunk
48
48
  (tables.keys - ['DSIG'] - OPTIMAL_TABLE_ORDER) +
49
49
  ['DSIG']
50
50
  end
51
-
52
- def collect_glyphs(glyph_ids)
53
- # CFF top indexes are supposed to contain only one font, although they're
54
- # capable of supporting many (no idea why this is true, maybe for CFF
55
- # v2??). Anyway it's cool to do top_index[0], don't worry about it.
56
- glyph_ids.each_with_object({}) do |id, h|
57
- h[id] = original.cff.top_index[0].charstrings_index[id]
58
- end
59
- end
60
51
  end
61
52
  end