diff --git a/.rubocop.yml b/.rubocop.yml index 2b8fb300..45b62ddc 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -9,6 +9,19 @@ RSpec/MultipleMemoizedHelpers: Exclude: - spec/ttfunk/table/os2_spec.rb +RSpec/SpecFilePathFormat: + CustomTransform: + TTFunk: ttfunk + Exclude: + - spec/ttfunk/table/cff/charstrings_index_spec.rb + - spec/ttfunk/table/cff/name_index_spec.rb + Style/FormatStringToken: Exclude: - examples/metrics.rb + + +Style/Documentation: + Exclude: + - examples/**/*.rb + - spec/**/*.rb diff --git a/examples/metrics.rb b/examples/metrics.rb index 4ce9a162..321a9c2c 100644 --- a/examples/metrics.rb +++ b/examples/metrics.rb @@ -3,21 +3,21 @@ require_relative '../lib/ttfunk' def character_lookup(file, character) - puts "character : #{character}" + puts("character : #{character}") character_code = character.unpack1('U*') - puts "character code: #{character_code}" + puts("character code: #{character_code}") glyph_id = file.cmap.unicode.first[character_code] - puts "glyph id : #{glyph_id}" + puts("glyph id : #{glyph_id}") glyph = file.glyph_outlines.for(glyph_id) - puts format('glyph type : %s', glyph.class.name.split(/::/).last.downcase) - puts format('glyph size : %db', glyph.raw.length) - puts format('glyph bbox : (%d,%d)-(%d,%d)', glyph.x_min, glyph.y_min, glyph.x_max, glyph.y_max) + puts(format('glyph type : %s', glyph.class.name.split('::').last.downcase)) + puts(format('glyph size : %db', glyph.raw.length)) + puts(format('glyph bbox : (%d,%d)-(%d,%d)', glyph.x_min, glyph.y_min, glyph.x_max, glyph.y_max)) if glyph.compound? - puts format('components : %d %s', glyph.glyph_ids.length, glyph.glyph_ids.inspect) + puts(format('components : %d %s', glyph.glyph_ids.length, glyph.glyph_ids.inspect)) end end diff --git a/examples/string_width.rb b/examples/string_width.rb index b08e0fa1..09f014ba 100644 --- a/examples/string_width.rb +++ b/examples/string_width.rb @@ -16,12 +16,12 @@ def initialize(path_to_file) end def width_of(string) - string.split('').sum { |char| character_width(char) } + string.chars.sum { |char| character_width(char) } end def character_width(character) width_in_units = horizontal_metrics.for(glyph_id(character)).advance_width - width_in_units.to_f / units_per_em + Float(width_in_units) / units_per_em end def units_per_em diff --git a/lib/ttfunk/bin_utils.rb b/lib/ttfunk/bin_utils.rb index 1599aaf9..2552c47f 100644 --- a/lib/ttfunk/bin_utils.rb +++ b/lib/ttfunk/bin_utils.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module TTFunk +module TTFunk # rubocop: disable Style/Documentation # false positive # Bit crunching utility methods. module BinUtils # Turn a bunch of small integers into one big integer. Assumes big-endian. @@ -12,7 +12,7 @@ def stitch_int(arr, bit_width:) value = 0 arr.each_with_index do |element, index| - value |= element << bit_width * index + value |= element << (bit_width * index) end value @@ -26,10 +26,10 @@ def stitch_int(arr, bit_width:) # needed for cases where top bits are zero. # @return [Array] def slice_int(value, bit_width:, slice_count:) - mask = 2**bit_width - 1 + mask = (2**bit_width) - 1 Array.new(slice_count) do |i| - (value >> bit_width * i) & mask + (value >> (bit_width * i)) & mask end end diff --git a/lib/ttfunk/bit_field.rb b/lib/ttfunk/bit_field.rb index 7a8d4f48..af201684 100644 --- a/lib/ttfunk/bit_field.rb +++ b/lib/ttfunk/bit_field.rb @@ -25,7 +25,7 @@ def on(pos) # @param pos [Integer] # @return [Boolean] def on?(pos) - (value & 2**pos).positive? + (value & (2**pos)).positive? end # Set bit off. @@ -33,7 +33,7 @@ def on?(pos) # @param pos [Integer] # @return [void] def off(pos) - @value &= 2**Math.log2(value).ceil - 2**pos - 1 + @value &= (2**Math.log2(value).ceil) - (2**pos) - 1 end # Is bit off? diff --git a/lib/ttfunk/collection.rb b/lib/ttfunk/collection.rb index d67fbe83..65007332 100644 --- a/lib/ttfunk/collection.rb +++ b/lib/ttfunk/collection.rb @@ -17,12 +17,12 @@ class Collection # @return [any] whatever the block returns def self.open(path) if path.respond_to?(:read) - result = yield new(path) + result = yield(new(path)) path.rewind result else ::File.open(path, 'rb') do |io| - yield new(io) + yield(new(io)) end end end @@ -55,7 +55,7 @@ def count # @return [self] def each count.times do |index| - yield self[index] + yield(self[index]) end self end diff --git a/lib/ttfunk/directory.rb b/lib/ttfunk/directory.rb index fb4fe6cc..742952db 100644 --- a/lib/ttfunk/directory.rb +++ b/lib/ttfunk/directory.rb @@ -26,7 +26,7 @@ def initialize(io, offset = 0) tag: tag, checksum: checksum, offset: offset, - length: length + length: length, } end end diff --git a/lib/ttfunk/encoded_string.rb b/lib/ttfunk/encoded_string.rb index 0ede2244..693d6579 100644 --- a/lib/ttfunk/encoded_string.rb +++ b/lib/ttfunk/encoded_string.rb @@ -22,7 +22,7 @@ class DuplicatePlaceholderError < StandardError class EncodedString # @yieldparam [self] def initialize - yield self if block_given? + yield(self) if block_given? end # Append to string. @@ -35,7 +35,7 @@ def <<(obj) io << obj when Placeholder add_placeholder(obj) - io << "\0" * obj.length + io << ("\0" * obj.length) when self.class # adjust placeholders to be relative to the entire encoded string obj.placeholders.each_pair do |_, placeholder| @@ -65,7 +65,7 @@ def concat(*objs) # @return [self] def align!(width = 4) if (length % width).positive? - self << "\0" * (width - length % width) + self << ("\0" * (width - (length % width))) end self diff --git a/lib/ttfunk/otf_encoder.rb b/lib/ttfunk/otf_encoder.rb index fb6affe6..2d7f8c15 100644 --- a/lib/ttfunk/otf_encoder.rb +++ b/lib/ttfunk/otf_encoder.rb @@ -4,9 +4,7 @@ module TTFunk # Encodes a CFF-based OpenType font subset to its binary representation. class OTFEncoder < TTFEncoder # Optimal table order according to OpenType specification. - OPTIMAL_TABLE_ORDER = [ - 'head', 'hhea', 'maxp', 'OS/2', 'name', 'cmap', 'post', 'CFF ' - ].freeze + OPTIMAL_TABLE_ORDER = ['head', 'hhea', 'maxp', 'OS/2', 'name', 'cmap', 'post', 'CFF '].freeze private @@ -40,7 +38,7 @@ def tables @tables ||= super.merge( 'BASE' => base_table, 'VORG' => vorg_table, - 'CFF ' => cff_table + 'CFF ' => cff_table, ).compact end diff --git a/lib/ttfunk/reader.rb b/lib/ttfunk/reader.rb index bfed3001..6ec321dd 100644 --- a/lib/ttfunk/reader.rb +++ b/lib/ttfunk/reader.rb @@ -25,7 +25,7 @@ def to_signed(number) def parse_from(position) saved = io.pos io.pos = position - result = yield position + result = yield(position) io.pos = saved result end @@ -38,12 +38,12 @@ def hexdump(string) if ((i + 1) % 16).zero? puts elsif ((i + 1) % 8).zero? - print ' ' + print(' ') else - print ' ' + print(' ') end end - puts unless (bytes.length % 16).zero? + puts if (bytes.length % 16) != 0 end end end diff --git a/lib/ttfunk/resource_file.rb b/lib/ttfunk/resource_file.rb index 466bb9d2..38e7b555 100644 --- a/lib/ttfunk/resource_file.rb +++ b/lib/ttfunk/resource_file.rb @@ -14,10 +14,10 @@ class ResourceFile # @yieldparam resource_file [TTFunk::ResourceFile] # @return [any] result of the block def self.open(path) - ::File.open(path, 'rb') do |io| + ::File.open(path, 'rb') { |io| file = new(io) - yield file - end + yield(file) + } end # @param io [IO] @@ -51,7 +51,7 @@ def initialize(io) id: id, attributes: attr, offset: data_ofs, - handle: handle + handle: handle, } if name_list_offset + name_ofs < map_offset + map_length @@ -95,7 +95,7 @@ def [](type, index = 0) # @param type [String] # @return [Array] def resources_for(type) - (@map[type] && @map[type][:named] || {}).keys + ((@map[type] && @map[type][:named]) || {}).keys end private diff --git a/lib/ttfunk/sci_form.rb b/lib/ttfunk/sci_form.rb index 0d407c95..05096728 100644 --- a/lib/ttfunk/sci_form.rb +++ b/lib/ttfunk/sci_form.rb @@ -3,7 +3,6 @@ module TTFunk # Scientific number representation class SciForm - alias eql? == # Significand # @return [Float, Integer] attr_reader :significand @@ -23,7 +22,7 @@ def initialize(significand, exponent = 0) # # @return [Float] def to_f - significand * 10**exponent + significand * (10**exponent) end # Check equality to another number. @@ -41,5 +40,7 @@ def ==(other) false end end + + alias eql? == end end diff --git a/lib/ttfunk/sub_table.rb b/lib/ttfunk/sub_table.rb index a781f656..9d1539cb 100644 --- a/lib/ttfunk/sub_table.rb +++ b/lib/ttfunk/sub_table.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative './reader' +require_relative 'reader' module TTFunk # SFNT sub-table diff --git a/lib/ttfunk/subset/code_page.rb b/lib/ttfunk/subset/code_page.rb index 1caf9f1c..66e2822f 100644 --- a/lib/ttfunk/subset/code_page.rb +++ b/lib/ttfunk/subset/code_page.rb @@ -113,7 +113,6 @@ def new_cmap_table end end - # Get the list of Glyph IDs from the original font that are in this # subset. # diff --git a/lib/ttfunk/table.rb b/lib/ttfunk/table.rb index aba96bc2..ac43629a 100644 --- a/lib/ttfunk/table.rb +++ b/lib/ttfunk/table.rb @@ -55,7 +55,7 @@ def raw # # @return [String] def tag - self.class.name.split(/::/).last.downcase + self.class.name.split('::').last.downcase end private diff --git a/lib/ttfunk/table/cff.rb b/lib/ttfunk/table/cff.rb index ca5eef22..61c7ce2e 100644 --- a/lib/ttfunk/table/cff.rb +++ b/lib/ttfunk/table/cff.rb @@ -67,7 +67,7 @@ def encode(subset) name_index.encode, top_index.encode, string_index.encode, - global_subr_index.encode + global_subr_index.encode, ) charmap = subset.new_cmap_table[:charmap] @@ -80,18 +80,9 @@ def encode(subset) def parse! @header = Header.new(file, offset) @name_index = Index.new(file, @header.table_offset + @header.length) - - @top_index = TopIndex.new( - file, @name_index.table_offset + @name_index.length - ) - - @string_index = OneBasedIndex.new( - file, @top_index.table_offset + @top_index.length - ) - - @global_subr_index = SubrIndex.new( - file, @string_index.table_offset + @string_index.length - ) + @top_index = TopIndex.new(file, @name_index.table_offset + @name_index.length) + @string_index = OneBasedIndex.new(file, @top_index.table_offset + @top_index.length) + @global_subr_index = SubrIndex.new(file, @string_index.table_offset + @string_index.length) end end end diff --git a/lib/ttfunk/table/cff/charset.rb b/lib/ttfunk/table/cff/charset.rb index 1c0385b5..c4a87ee5 100644 --- a/lib/ttfunk/table/cff/charset.rb +++ b/lib/ttfunk/table/cff/charset.rb @@ -111,7 +111,7 @@ def each return to_enum(__method__) unless block_given? # +1 adjusts for the implicit .notdef glyph - (items_count + 1).times { |i| yield self[i] } + (items_count + 1).times { |i| yield(self[i]) } end # Get character name for glyph index. @@ -256,7 +256,7 @@ def element_width(fmt = format_sym) { array_format: 2, # SID range_format8: 3, # SID + Card8 - range_format16: 4 # SID + Card16 + range_format16: 4, # SID + Card16 }[fmt] end @@ -264,7 +264,7 @@ def element_format(fmt = format_sym) { array_format: 'n', range_format8: 'nC', - range_format16: 'nn' + range_format16: 'nn', }[fmt] end @@ -282,7 +282,7 @@ def format_int(sym = format_sym) { array_format: ARRAY_FORMAT, range_format8: RANGE_FORMAT_8, - range_format16: RANGE_FORMAT_16 + range_format16: RANGE_FORMAT_16, }[sym] end end diff --git a/lib/ttfunk/table/cff/charsets/expert.rb b/lib/ttfunk/table/cff/charsets/expert.rb index 07621ac9..adeb23f2 100644 --- a/lib/ttfunk/table/cff/charsets/expert.rb +++ b/lib/ttfunk/table/cff/charsets/expert.rb @@ -181,8 +181,8 @@ module Charsets 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', - 'Thornsmall' - ] + 'Thornsmall', + ], ).freeze end end diff --git a/lib/ttfunk/table/cff/charsets/expert_subset.rb b/lib/ttfunk/table/cff/charsets/expert_subset.rb index a6488d28..85f03257 100644 --- a/lib/ttfunk/table/cff/charsets/expert_subset.rb +++ b/lib/ttfunk/table/cff/charsets/expert_subset.rb @@ -111,8 +111,8 @@ module Charsets 'nineinferior', 'centinferior', 'dollarinferior', - 'periodinferior' - ] + 'periodinferior', + ], ).freeze end end diff --git a/lib/ttfunk/table/cff/charsets/iso_adobe.rb b/lib/ttfunk/table/cff/charsets/iso_adobe.rb index 7a2ec4b9..c99ee209 100644 --- a/lib/ttfunk/table/cff/charsets/iso_adobe.rb +++ b/lib/ttfunk/table/cff/charsets/iso_adobe.rb @@ -233,8 +233,8 @@ module Charsets 'ugrave', 'yacute', 'ydieresis', - 'zcaron' - ] + 'zcaron', + ], ).freeze end end diff --git a/lib/ttfunk/table/cff/charsets/standard_strings.rb b/lib/ttfunk/table/cff/charsets/standard_strings.rb index bbb5614d..c1ec8621 100644 --- a/lib/ttfunk/table/cff/charsets/standard_strings.rb +++ b/lib/ttfunk/table/cff/charsets/standard_strings.rb @@ -396,8 +396,8 @@ module Charsets 'Medium', 'Regular', 'Roman', - 'Semibold' - ] + 'Semibold', + ], ).freeze end end diff --git a/lib/ttfunk/table/cff/charstring.rb b/lib/ttfunk/table/cff/charstring.rb index 22bb905b..fd3f947c 100644 --- a/lib/ttfunk/table/cff/charstring.rb +++ b/lib/ttfunk/table/cff/charstring.rb @@ -30,7 +30,7 @@ class Charstring 28 => :shortint, 29 => :callgsubr, 30 => :vhcurveto, - 31 => :hvcurveto + 31 => :hvcurveto, }.freeze # Type 2 Flex operators. @@ -38,7 +38,7 @@ class Charstring 35 => :flex, 34 => :hflex, 36 => :hflex1, - 37 => :flex1 + 37 => :flex1, }.freeze # Glyph ID. @@ -112,7 +112,7 @@ def render(x: 0, y: 0, font_size: 72) x: x, y: y, font_size: font_size, - units_per_em: @top_dict.file.header.units_per_em + units_per_em: @top_dict.file.header.units_per_em, ) end @@ -127,22 +127,22 @@ def parse! next if code == 11 if code >= 32 && code <= 246 - @stack << code - 139 + @stack << (code - 139) elsif (m = CODE_MAP[code]) __send__(m) elsif code >= 247 && code <= 250 b0 = code b1 = @data[@index] @index += 1 - @stack << (b0 - 247) * 256 + b1 + 108 + @stack << (((b0 - 247) * 256) + b1 + 108) elsif code >= 251 && code <= 254 b0 = code b1 = @data[@index] @index += 1 - @stack << -(b0 - 251) * 256 - b1 - 108 + @stack << ((-(b0 - 251) * 256) - b1 - 108) else b1, b2, b3, b4 = read_bytes(4) - @stack << ((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65_536 + @stack << (((b1 << 24) | (b2 << 16) | (b3 << 8) | b4) / 65_536) end end end diff --git a/lib/ttfunk/table/cff/charstrings_index.rb b/lib/ttfunk/table/cff/charstrings_index.rb index 0fc9173b..be8c3e47 100644 --- a/lib/ttfunk/table/cff/charstrings_index.rb +++ b/lib/ttfunk/table/cff/charstrings_index.rb @@ -22,9 +22,7 @@ def initialize(top_dict, *remaining_args) private def decode_item(index, _offset, _length) - TTFunk::Table::Cff::Charstring.new( - index, top_dict, font_dict_for(index), super - ) + TTFunk::Table::Cff::Charstring.new(index, top_dict, font_dict_for(index), super) end def encode_items(charmap) diff --git a/lib/ttfunk/table/cff/dict.rb b/lib/ttfunk/table/cff/dict.rb index 710118cf..7aeee255 100644 --- a/lib/ttfunk/table/cff/dict.rb +++ b/lib/ttfunk/table/cff/dict.rb @@ -68,10 +68,11 @@ def each(&block) # @return [String] def encode sort_by(&:first) - .map do |(operator, operands)| - operands.map { |operand| encode_operand(operand) }.join + - encode_operator(operator) - end.join + .map { |(operator, operands)| + operands.map { |operand| encode_operand(operand) }.join + + encode_operator(operator) + } + .join end private @@ -80,7 +81,7 @@ def encode_operator(operator) if operator >= WIDE_OPERATOR_ADJUSTMENT [ WIDE_OPERATOR_BZERO, - operator - WIDE_OPERATOR_ADJUSTMENT + operator - WIDE_OPERATOR_ADJUSTMENT, ].pack('C*') else [operator].pack('C') @@ -143,7 +144,7 @@ def encode_significand(sig) sig.to_s.each_char.with_object([]) do |char, ret| case char when '0'..'9' - ret << char.to_i + ret << Integer(char) when '.' ret << 0xA when '-' @@ -160,7 +161,7 @@ def pack_decimal_nibbles(nibbles) nibbles.each_slice(2).each do |(high_nb, low_nb)| # low_nb can be nil if nibbles contains an odd number of elements low_nb ||= 0xF - bytes << (high_nb << 4 | low_nb) + bytes << ((high_nb << 4) | low_nb) end bytes << 0xFF if nibbles.size.even? @@ -186,8 +187,7 @@ def parse! if operands.size > MAX_OPERANDS raise TooManyOperandsError, - 'found one too many operands at '\ - "position #{io.pos} in dict at position #{table_offset}" + "found one too many operands at position #{io.pos} in dict at position #{table_offset}" end else raise Error, "dict byte value #{b_zero} is reserved" @@ -248,9 +248,9 @@ def decode_sci def validate_sci!(significand, exponent) unless valid_significand?(significand) && valid_exponent?(exponent) raise InvalidOperandError, - 'invalid scientific notation operand with significand '\ - "'#{significand}' and exponent '#{exponent}' ending at "\ - "position #{io.pos} in dict at position #{table_offset}" + 'invalid scientific notation operand with significand ' \ + "'#{significand}' and exponent '#{exponent}' ending at " \ + "position #{io.pos} in dict at position #{table_offset}" end end @@ -274,24 +274,22 @@ def decode_integer(b_zero) when 247..250 # 2 bytes b_one = read(1, 'C').first - (b_zero - 247) * 256 + b_one + 108 + ((b_zero - 247) * 256) + b_one + 108 when 251..254 # 2 bytes b_one = read(1, 'C').first - -(b_zero - 251) * 256 - b_one - 108 + (-(b_zero - 251) * 256) - b_one - 108 when 28 # 2 bytes in number (3 total) b_one, b_two = read(2, 'C*') - BinUtils.twos_comp_to_int(b_one << 8 | b_two, bit_width: 16) + BinUtils.twos_comp_to_int((b_one << 8) | b_two, bit_width: 16) when 29 # 4 bytes in number (5 total) b_one, b_two, b_three, b_four = read(4, 'C*') - BinUtils.twos_comp_to_int( - b_one << 24 | b_two << 16 | b_three << 8 | b_four, bit_width: 32 - ) + BinUtils.twos_comp_to_int((b_one << 24) | (b_two << 16) | (b_three << 8) | b_four, bit_width: 32) end end end diff --git a/lib/ttfunk/table/cff/encoding.rb b/lib/ttfunk/table/cff/encoding.rb index e2e59cc6..efa04e34 100644 --- a/lib/ttfunk/table/cff/encoding.rb +++ b/lib/ttfunk/table/cff/encoding.rb @@ -13,7 +13,6 @@ class Encoding < TTFunk::SubTable # Predefined Expert Encoding ID. EXPERT_ENCODING_ID = 1 - # Default encoding ID. DEFAULT_ENCODING_ID = STANDARD_ENCODING_ID @@ -81,7 +80,7 @@ def each return to_enum(__method__) unless block_given? # +1 adjusts for the implicit .notdef glyph - (items_count + 1).times { |i| yield self[i] } + (items_count + 1).times { |i| yield(self[i]) } end # Get character code for glyph index. @@ -237,7 +236,7 @@ def element_format(fmt = format_sym) { array_format: 'C', range_format: 'CC', - supplemental: 'Cn' + supplemental: 'Cn', }[fmt] end diff --git a/lib/ttfunk/table/cff/encodings/expert.rb b/lib/ttfunk/table/cff/encodings/expert.rb index 681274a1..5c2b7f89 100644 --- a/lib/ttfunk/table/cff/encodings/expert.rb +++ b/lib/ttfunk/table/cff/encodings/expert.rb @@ -198,8 +198,8 @@ module Encodings 375, 376, 377, - 378 - ] + 378, + ], ).freeze end end diff --git a/lib/ttfunk/table/cff/encodings/standard.rb b/lib/ttfunk/table/cff/encodings/standard.rb index e83109a3..3f0afaa0 100644 --- a/lib/ttfunk/table/cff/encodings/standard.rb +++ b/lib/ttfunk/table/cff/encodings/standard.rb @@ -173,8 +173,8 @@ module Encodings 147, 148, 149, - *[0] * 4 - ] + *[0] * 4, + ], ).freeze end end diff --git a/lib/ttfunk/table/cff/fd_selector.rb b/lib/ttfunk/table/cff/fd_selector.rb index 3a640fea..b2f01a82 100644 --- a/lib/ttfunk/table/cff/fd_selector.rb +++ b/lib/ttfunk/table/cff/fd_selector.rb @@ -59,15 +59,15 @@ def [](glyph_id) end range, entry = - entries.bsearch do |rng, _| - if rng.cover?(glyph_id) - 0 - elsif glyph_id < rng.first - -1 - else - 1 - end - end + entries.bsearch { |rng, _| + if rng.cover?(glyph_id) + 0 + elsif glyph_id < rng.first + -1 + else + 1 + end + } range.each { |i| range_cache[i] = entry } entry @@ -81,7 +81,7 @@ def [](glyph_id) def each return to_enum(__method__) unless block_given? - items_count.times { |i| yield self[i] } + items_count.times { |i| yield(self[i]) } end # Encode Font dict selector. @@ -162,11 +162,11 @@ def parse! ranges = Array.new(num_ranges) { read(RANGE_ENTRY_SIZE, 'nC') } @entries = - ranges.each_cons(2).map do |first, second| + ranges.each_cons(2).map { |first, second| first_gid, fd_index = first second_gid, = second [(first_gid...second_gid), fd_index] - end + } # read the sentinel GID, otherwise known as the number of glyphs # in the font diff --git a/lib/ttfunk/table/cff/font_dict.rb b/lib/ttfunk/table/cff/font_dict.rb index b1885f50..be979b71 100644 --- a/lib/ttfunk/table/cff/font_dict.rb +++ b/lib/ttfunk/table/cff/font_dict.rb @@ -54,13 +54,8 @@ def finalize(new_cff_data) encoded_offset = encode_integer32(new_cff_data.length) encoded_length = encode_integer32(encoded_private_dict.length) - new_cff_data.resolve_placeholder( - :"private_length_#{@table_offset}", encoded_length - ) - - new_cff_data.resolve_placeholder( - :"private_offset_#{@table_offset}", encoded_offset - ) + new_cff_data.resolve_placeholder(:"private_length_#{@table_offset}", encoded_length) + new_cff_data.resolve_placeholder(:"private_offset_#{@table_offset}", encoded_offset) private_dict.finalize(encoded_private_dict) new_cff_data << encoded_private_dict @@ -77,7 +72,7 @@ def private_dict PrivateDict.new( file, top_dict.cff_offset + private_dict_offset, - private_dict_length + private_dict_length, ) end end @@ -86,13 +81,8 @@ def private_dict def encode_private EncodedString.new do |result| - result << Placeholder.new( - :"private_length_#{@table_offset}", length: PLACEHOLDER_LENGTH - ) - - result << Placeholder.new( - :"private_offset_#{@table_offset}", length: PLACEHOLDER_LENGTH - ) + result << Placeholder.new(:"private_length_#{@table_offset}", length: PLACEHOLDER_LENGTH) + result << Placeholder.new(:"private_offset_#{@table_offset}", length: PLACEHOLDER_LENGTH) end end end diff --git a/lib/ttfunk/table/cff/font_index.rb b/lib/ttfunk/table/cff/font_index.rb index 9cb34703..d458ecac 100644 --- a/lib/ttfunk/table/cff/font_index.rb +++ b/lib/ttfunk/table/cff/font_index.rb @@ -29,9 +29,7 @@ def finalize(new_cff_data) private def decode_item(_index, offset, length) - TTFunk::Table::Cff::FontDict.new( - top_dict, file, offset, length - ) + TTFunk::Table::Cff::FontDict.new(top_dict, file, offset, length) end def encode_items(*) diff --git a/lib/ttfunk/table/cff/index.rb b/lib/ttfunk/table/cff/index.rb index 18ac407e..10aaaacb 100644 --- a/lib/ttfunk/table/cff/index.rb +++ b/lib/ttfunk/table/cff/index.rb @@ -18,7 +18,7 @@ def [](index) decode_item( index, data_reference_offset + offsets[index], - offsets[index + 1] - offsets[index] + offsets[index + 1] - offsets[index], ) end @@ -33,7 +33,7 @@ def each(&block) return to_enum(__method__) unless block items_count.times do |i| - yield self[i] + yield(self[i]) end end @@ -61,9 +61,9 @@ def encode(*args) offsets_array = new_items - .each_with_object([1]) do |item, offsets| - offsets << offsets.last + item.length - end + .each_with_object([1]) { |item, offsets| + offsets << (offsets.last + item.length) + } offset_size = (offsets_array.last.bit_length / 8.0).ceil @@ -72,13 +72,15 @@ def encode(*args) EncodedString.new.concat( [new_items.length, offset_size].pack('nC'), *offsets_array, - *new_items + *new_items, ) end private - attr_reader :items, :offsets, :data_reference_offset + attr_reader :items + attr_reader :offsets + attr_reader :data_reference_offset def entry_cache @entry_cache ||= {} @@ -128,22 +130,22 @@ def parse! offset_size = read(1, 'C').first @offsets = - Array.new(num_entries + 1) do + Array.new(num_entries + 1) { unpack_offset(io.read(offset_size), offset_size) - end + } - @data_reference_offset = table_offset + 3 + offsets.length * offset_size - 1 + @data_reference_offset = table_offset + 3 + (offsets.length * offset_size) - 1 @length = 2 + # num entries 1 + # offset size - offsets.length * offset_size + # offsets + (offsets.length * offset_size) + # offsets offsets.last - 1 # items @items = - offsets.each_cons(2).map do |offset, next_offset| + offsets.each_cons(2).map { |offset, next_offset| io.read(next_offset - offset) - end + } end def unpack_offset(offset_data, offset_size) diff --git a/lib/ttfunk/table/cff/path.rb b/lib/ttfunk/table/cff/path.rb index 1fc3eff5..4e2f9040 100644 --- a/lib/ttfunk/table/cff/path.rb +++ b/lib/ttfunk/table/cff/path.rb @@ -50,7 +50,7 @@ def line_to(x, y) # @param x [Integer, Float] # @param y [Integer, Float] # @return [void] - def curve_to(x1, y1, x2, y2, x, y) # rubocop: disable Metrics/ParameterLists,Style/CommentedKeyword + def curve_to(x1, y1, x2, y2, x, y) # rubocop: disable Metrics/ParameterLists @commands << [:curve, x1, y1, x2, y2, x, y] end @@ -86,7 +86,7 @@ def render(x: 0, y: 0, font_size: 72, units_per_em: 1000) x + (cmd[3] * scale), y + (-cmd[4] * scale), x + (cmd[5] * scale), - y + (-cmd[6] * scale) + y + (-cmd[6] * scale), ) when :close new_path.close_path diff --git a/lib/ttfunk/table/cff/private_dict.rb b/lib/ttfunk/table/cff/private_dict.rb index 74f6e091..1b542665 100644 --- a/lib/ttfunk/table/cff/private_dict.rb +++ b/lib/ttfunk/table/cff/private_dict.rb @@ -18,7 +18,7 @@ class PrivateDict < TTFunk::Table::Cff::Dict OPERATORS = { subrs: 19, default_width_x: 20, - nominal_width_x: 21 + nominal_width_x: 21, }.freeze # Inverse operator mapping. @@ -54,9 +54,7 @@ def finalize(private_dict_data) encoded_subr_index = subr_index.encode encoded_offset = encode_integer32(private_dict_data.length) - private_dict_data.resolve_placeholder( - :"subrs_#{@table_offset}", encoded_offset - ) + private_dict_data.resolve_placeholder(:"subrs_#{@table_offset}", encoded_offset) private_dict_data << encoded_subr_index end @@ -97,9 +95,7 @@ def nominal_width_x def encode_subrs EncodedString.new do |result| - result << Placeholder.new( - :"subrs_#{@table_offset}", length: PLACEHOLDER_LENGTH - ) + result << Placeholder.new(:"subrs_#{@table_offset}", length: PLACEHOLDER_LENGTH) end end end diff --git a/lib/ttfunk/table/cff/top_dict.rb b/lib/ttfunk/table/cff/top_dict.rb index 0431e72a..576fb0c8 100644 --- a/lib/ttfunk/table/cff/top_dict.rb +++ b/lib/ttfunk/table/cff/top_dict.rb @@ -22,14 +22,14 @@ class TopDict < TTFunk::Table::Cff::Dict charstrings_index: 17, private: 18, font_index: 1236, - font_dict_selector: 1237 + font_dict_selector: 1237, }.freeze # All the operators we currently care about. OPERATORS = { **POINTER_OPERATORS, ros: 1230, - charstring_type: 1206 + charstring_type: 1206, }.freeze # Inverse operator mapping. @@ -46,7 +46,7 @@ def encode(*) elsif pointer_operator?(operator) result << Placeholder.new( OPERATOR_CODES[operator], - length: POINTER_PLACEHOLDER_LENGTH + length: POINTER_PLACEHOLDER_LENGTH, ) else operands.each { |operand| result << encode_operand(operand) } @@ -67,41 +67,25 @@ def encode(*) # @return [void] def finalize(new_cff_data, charmap) if charset - finalize_subtable( - new_cff_data, :charset, charset.encode(charmap) - ) + finalize_subtable(new_cff_data, :charset, charset.encode(charmap)) end if encoding - finalize_subtable( - new_cff_data, :encoding, encoding.encode(charmap) - ) + finalize_subtable(new_cff_data, :encoding, encoding.encode(charmap)) end if charstrings_index - finalize_subtable( - new_cff_data, - :charstrings_index, - charstrings_index.encode(charmap) - ) + finalize_subtable(new_cff_data, :charstrings_index, charstrings_index.encode(charmap)) end if font_index - finalize_subtable( - new_cff_data, - :font_index, - font_index.encode - ) + finalize_subtable(new_cff_data, :font_index, font_index.encode) font_index.finalize(new_cff_data) end if font_dict_selector - finalize_subtable( - new_cff_data, - :font_dict_selector, - font_dict_selector.encode(charmap) - ) + finalize_subtable(new_cff_data, :font_dict_selector, font_dict_selector.encode(charmap)) end if private_dict @@ -109,13 +93,8 @@ def finalize(new_cff_data, charmap) encoded_offset = encode_integer32(new_cff_data.length) encoded_length = encode_integer32(encoded_private_dict.length) - new_cff_data.resolve_placeholder( - :"private_length_#{@table_offset}", encoded_length - ) - - new_cff_data.resolve_placeholder( - :"private_offset_#{@table_offset}", encoded_offset - ) + new_cff_data.resolve_placeholder(:"private_length_#{@table_offset}", encoded_length) + new_cff_data.resolve_placeholder(:"private_offset_#{@table_offset}", encoded_offset) private_dict.finalize(encoded_private_dict) new_cff_data << encoded_private_dict @@ -178,9 +157,7 @@ def encoding def charstrings_index @charstrings_index ||= if (charstrings_offset = self[OPERATORS[:charstrings_index]]) - CharstringsIndex.new( - self, file, cff_offset + charstrings_offset.first - ) + CharstringsIndex.new(self, file, cff_offset + charstrings_offset.first) end end @@ -220,9 +197,7 @@ def private_dict if (info = self[OPERATORS[:private]]) private_dict_length, private_dict_offset = info - PrivateDict.new( - file, cff_offset + private_dict_offset, private_dict_length - ) + PrivateDict.new(file, cff_offset + private_dict_offset, private_dict_length) end end @@ -246,12 +221,12 @@ def encode_private EncodedString.new do |result| result << Placeholder.new( :"private_length_#{@table_offset}", - length: PLACEHOLDER_LENGTH + length: PLACEHOLDER_LENGTH, ) result << Placeholder.new( :"private_offset_#{@table_offset}", - length: PLACEHOLDER_LENGTH + length: PLACEHOLDER_LENGTH, ) end end diff --git a/lib/ttfunk/table/cmap/format04.rb b/lib/ttfunk/table/cmap/format04.rb index 0f62bee5..ab9001e4 100644 --- a/lib/ttfunk/table/cmap/format04.rb +++ b/lib/ttfunk/table/cmap/format04.rb @@ -77,10 +77,10 @@ def self.encode(charmap) if a - start_glyph_id >= 0x8000 deltas << 0 - range_offsets << 2 * (glyph_indices.length + segcount - segment) + range_offsets << (2 * (glyph_indices.length + segcount - segment)) a.upto(b) { |code| glyph_indices << new_map[code][:new] } else - deltas << -a + start_glyph_id + deltas << (-a + start_glyph_id) range_offsets << 0 end @@ -89,14 +89,14 @@ def self.encode(charmap) # format, length, language subtable = [ - 4, 16 + 8 * segcount + 2 * glyph_indices.length, 0 + 4, 16 + (8 * segcount) + (2 * glyph_indices.length), 0, ].pack('nnn') - search_range = 2 * 2**(Math.log(segcount) / Math.log(2)).to_i - entry_selector = (Math.log(search_range / 2) / Math.log(2)).to_i + search_range = 2 * (2**Integer(Math.log(segcount) / Math.log(2))) + entry_selector = Integer(Math.log(search_range / 2) / Math.log(2)) range_shift = (2 * segcount) - search_range subtable << [ - segcount * 2, search_range, entry_selector, range_shift + segcount * 2, search_range, entry_selector, range_shift, ].pack('nnnn') subtable << end_codes.pack('n*') << "\0\0" << start_codes.pack('n*') @@ -144,8 +144,7 @@ def parse_cmap! if (id_range_offset[i]).zero? glyph_id = code + id_delta[i] else - index = id_range_offset[i] / 2 + - (code - start_code[i]) - (segcount - i) + index = (id_range_offset[i] / 2) + (code - start_code[i]) - (segcount - i) # Because some TTF fonts are broken glyph_id = glyph_ids[index] || 0 glyph_id += id_delta[i] if glyph_id != 0 diff --git a/lib/ttfunk/table/cmap/format06.rb b/lib/ttfunk/table/cmap/format06.rb index 403cac1f..3e6a68cd 100644 --- a/lib/ttfunk/table/cmap/format06.rb +++ b/lib/ttfunk/table/cmap/format06.rb @@ -45,7 +45,7 @@ def self.encode(charmap) end subtable = [ - 6, 10 + entry_count * 2, 0, low_char, entry_count, *glyph_indexes + 6, 10 + (entry_count * 2), 0, low_char, entry_count, *glyph_indexes, ].pack('n*') { charmap: new_map, subtable: subtable, max_glyph_id: next_id + 1 } diff --git a/lib/ttfunk/table/cmap/format10.rb b/lib/ttfunk/table/cmap/format10.rb index b8008c2e..b6ed1ff8 100644 --- a/lib/ttfunk/table/cmap/format10.rb +++ b/lib/ttfunk/table/cmap/format10.rb @@ -45,8 +45,8 @@ def self.encode(charmap) end subtable = [ - 10, 0, 20 + entry_count * 4, 0, low_char, entry_count, - *glyph_indexes + 10, 0, 20 + (entry_count * 4), 0, low_char, entry_count, + *glyph_indexes, ].pack('nnN*') { charmap: new_map, subtable: subtable, max_glyph_id: next_id + 1 } diff --git a/lib/ttfunk/table/cmap/format12.rb b/lib/ttfunk/table/cmap/format12.rb index 13ccd971..07c6dd34 100644 --- a/lib/ttfunk/table/cmap/format12.rb +++ b/lib/ttfunk/table/cmap/format12.rb @@ -52,13 +52,13 @@ def self.encode(charmap) end subtable = [ - 12, 0, 16 + 12 * range_lengths.size, 0, range_lengths.size + 12, 0, 16 + (12 * range_lengths.size), 0, range_lengths.size, ].pack('nnNNN') range_lengths.each_with_index do |length, i| firstglyph = range_firstglyphs[i] firstcode = range_firstcodes[i] subtable << [ - firstcode, firstcode + length - 1, firstglyph + firstcode, firstcode + length - 1, firstglyph, ].pack('NNN') end diff --git a/lib/ttfunk/table/cmap/subtable.rb b/lib/ttfunk/table/cmap/subtable.rb index 9d078a48..230cdb3b 100644 --- a/lib/ttfunk/table/cmap/subtable.rb +++ b/lib/ttfunk/table/cmap/subtable.rb @@ -34,7 +34,7 @@ class Subtable # Use microsoft unicode, instead of generic unicode, for optimal # Windows support unicode: { platform_id: 3, encoding_id: 1 }.freeze, - unicode_ucs4: { platform_id: 3, encoding_id: 10 }.freeze + unicode_ucs4: { platform_id: 3, encoding_id: 10 }.freeze, }.freeze # Encode encoding record. @@ -76,8 +76,8 @@ def self.encode(charmap, encoding) mapping[:platform_id], mapping[:encoding_id], 12, - result[:subtable] - ].pack('nnNA*') + result[:subtable], + ].pack('nnNA*'), ) end @@ -107,9 +107,8 @@ def initialize(file, table_start) # # @return [Boolean] def unicode? - platform_id == 3 && (encoding_id == 1 || encoding_id == 10) && - format != 0 || - platform_id.zero? && format != 0 + (platform_id == 3 && (encoding_id == 1 || encoding_id == 10) && format != 0) || + (platform_id.zero? && format != 0) end # Is this encoding record format supported? diff --git a/lib/ttfunk/table/dsig.rb b/lib/ttfunk/table/dsig.rb index 6aad3407..10fe836b 100644 --- a/lib/ttfunk/table/dsig.rb +++ b/lib/ttfunk/table/dsig.rb @@ -77,16 +77,16 @@ def parse! @version, num_signatures, @flags = read(8, 'Nnn') @signatures = - Array.new(num_signatures) do + Array.new(num_signatures) { format, length, sig_offset = read(12, 'N3') signature = - parse_from(offset + sig_offset) do + parse_from(offset + sig_offset) { _, _, sig_length = read(8, 'nnN') read(sig_length, 'C*') - end + } SignatureRecord.new(format, length, sig_offset, signature) - end + } end end end diff --git a/lib/ttfunk/table/glyf/compound.rb b/lib/ttfunk/table/glyf/compound.rb index 2cdcf53b..0f8fe157 100644 --- a/lib/ttfunk/table/glyf/compound.rb +++ b/lib/ttfunk/table/glyf/compound.rb @@ -58,7 +58,6 @@ class Compound # @return [Integer] attr_reader :y_max - # IDs of compound glyphs. attr_reader :glyph_ids @@ -89,9 +88,9 @@ def initialize(id, raw) io = StringIO.new(raw) @number_of_contours, @x_min, @y_min, @x_max, @y_max = - io.read(10).unpack('n*').map do |i| + io.read(10).unpack('n*').map { |i| BinUtils.twos_comp_to_int(i, bit_width: 16) - end + } # Because TTFunk only cares about glyphs insofar as they (1) provide # a bounding box for each glyph, and (2) can be rewritten into a @@ -109,9 +108,9 @@ def initialize(id, raw) loop do flags, glyph_id = @raw[offset, 4].unpack('n*') @glyph_ids << glyph_id - @glyph_id_offsets << offset + 2 + @glyph_id_offsets << (offset + 2) - break unless flags & MORE_COMPONENTS != 0 + break if (flags & MORE_COMPONENTS).zero? offset += 4 diff --git a/lib/ttfunk/table/glyf/simple.rb b/lib/ttfunk/table/glyf/simple.rb index 0280d92e..52db3c0b 100644 --- a/lib/ttfunk/table/glyf/simple.rb +++ b/lib/ttfunk/table/glyf/simple.rb @@ -55,9 +55,9 @@ def initialize(id, raw) io = StringIO.new(raw) @number_of_contours, @x_min, @y_min, @x_max, @y_max = - io.read(10).unpack('n*').map do |i| + io.read(10).unpack('n*').map { |i| BinUtils.twos_comp_to_int(i, bit_width: 16) - end + } @end_points_of_contours = io.read(number_of_contours * 2).unpack('n*') @instruction_length = io.read(2).unpack1('n') diff --git a/lib/ttfunk/table/head.rb b/lib/ttfunk/table/head.rb index 7f070a43..8b7cd42c 100644 --- a/lib/ttfunk/table/head.rb +++ b/lib/ttfunk/table/head.rb @@ -100,7 +100,7 @@ def encode(head, loca, mapping) head.created, head.modified, *min_max_values_for(head, mapping), head.mac_style, head.lowest_rec_ppem, head.font_direction_hint, - loca[:type] || 0, head.glyph_data_format + loca[:type] || 0, head.glyph_data_format, ].pack('Nn2q>2n*') end end @@ -116,7 +116,7 @@ def from_long_date_time(ldt) # @param time [Time] # @return [Integer] def to_long_date_time(time) - time.to_i - LONG_DATE_TIME_BASIS + Integer(time) - LONG_DATE_TIME_BASIS end private @@ -127,7 +127,7 @@ def min_max_values_for(head, mapping) y_min = Min.new y_max = Max.new - mapping.each do |_, old_glyph_id| + mapping.each_value do |old_glyph_id| glyph = head.file.find_glyph(old_glyph_id) next unless glyph @@ -139,7 +139,7 @@ def min_max_values_for(head, mapping) [ x_min.value_or(0), y_min.value_or(0), - x_max.value_or(0), y_max.value_or(0) + x_max.value_or(0), y_max.value_or(0), ] end end diff --git a/lib/ttfunk/table/hhea.rb b/lib/ttfunk/table/hhea.rb index 9e23db76..63109efe 100644 --- a/lib/ttfunk/table/hhea.rb +++ b/lib/ttfunk/table/hhea.rb @@ -89,7 +89,7 @@ def encode(hhea, hmtx, original, mapping) hhea.ascent, hhea.descent, hhea.line_gap, *min_max_values_for(original, mapping), hhea.caret_slope_rise, hhea.caret_slope_run, hhea.caret_offset, - 0, 0, 0, 0, hhea.metric_data_format, hmtx[:number_of_metrics] + 0, 0, 0, 0, hhea.metric_data_format, hmtx[:number_of_metrics], ].pack('n*') end end @@ -102,7 +102,7 @@ def min_max_values_for(original, mapping) max_aw = Max.new max_extent = Max.new - mapping.each do |_, old_glyph_id| + mapping.each_value do |old_glyph_id| horiz_metrics = original.horizontal_metrics.for(old_glyph_id) next unless horiz_metrics @@ -114,15 +114,14 @@ def min_max_values_for(original, mapping) x_delta = glyph.x_max - glyph.x_min - min_rsb << horiz_metrics.advance_width - - horiz_metrics.left_side_bearing - x_delta + min_rsb << (horiz_metrics.advance_width - horiz_metrics.left_side_bearing - x_delta) - max_extent << horiz_metrics.left_side_bearing + x_delta + max_extent << (horiz_metrics.left_side_bearing + x_delta) end [ max_aw.value_or(0), min_lsb.value_or(0), - min_rsb.value_or(0), max_extent.value_or(0) + min_rsb.value_or(0), max_extent.value_or(0), ] end end diff --git a/lib/ttfunk/table/hmtx.rb b/lib/ttfunk/table/hmtx.rb index 73319360..e3087871 100644 --- a/lib/ttfunk/table/hmtx.rb +++ b/lib/ttfunk/table/hmtx.rb @@ -28,14 +28,14 @@ class Hmtx < Table # * `:table` - encoded table. def self.encode(hmtx, mapping) metrics = - mapping.keys.sort.map do |new_id| + mapping.keys.sort.map { |new_id| metric = hmtx.for(mapping[new_id]) [metric.advance_width, metric.left_side_bearing] - end + } { number_of_metrics: metrics.length, - table: metrics.flatten.pack('n*') + table: metrics.flatten.pack('n*'), } end @@ -56,7 +56,7 @@ def for(glyph_id) metrics_cache[glyph_id] ||= HorizontalMetric.new( @metrics.last.advance_width, - @left_side_bearings[glyph_id - @metrics.length] + @left_side_bearings[glyph_id - @metrics.length], ) end @@ -72,7 +72,7 @@ def parse! file.horizontal_header.number_of_metrics.times do advance = read(2, 'n').first lsb = read_signed(1).first - @metrics.push HorizontalMetric.new(advance, lsb) + @metrics.push(HorizontalMetric.new(advance, lsb)) end lsb_count = file.maximum_profile.num_glyphs - diff --git a/lib/ttfunk/table/kern.rb b/lib/ttfunk/table/kern.rb index b47016de..676cdad2 100644 --- a/lib/ttfunk/table/kern.rb +++ b/lib/ttfunk/table/kern.rb @@ -23,7 +23,7 @@ class Kern < Table def self.encode(kerning, mapping) return unless kerning.exists? && kerning.tables.any? - tables = kerning.tables.map { |table| table.recode(mapping) }.compact + tables = kerning.tables.filter_map { |table| table.recode(mapping) } return if tables.empty? [0, tables.length, tables.join].pack('nnA*') @@ -68,7 +68,7 @@ def parse_version_0_tables(_num_tables) vertical: (coverage & 0x1).zero?, minimum: (coverage & 0x2 != 0), cross: (coverage & 0x4 != 0), - override: (coverage & 0x8 != 0) + override: (coverage & 0x8 != 0), ) end @@ -85,7 +85,7 @@ def parse_version_1_tables(num_tables) data: io.read(length - 8), vertical: (coverage & 0x8000 != 0), cross: (coverage & 0x4000 != 0), - variation: (coverage & 0x2000 != 0) + variation: (coverage & 0x2000 != 0), ) end end diff --git a/lib/ttfunk/table/kern/format0.rb b/lib/ttfunk/table/kern/format0.rb index 1c12af1b..591c020f 100644 --- a/lib/ttfunk/table/kern/format0.rb +++ b/lib/ttfunk/table/kern/format0.rb @@ -26,11 +26,11 @@ def initialize(attributes = {}) @pairs = {} num_pairs.times do |i| # sanity check, in case there's a bad length somewhere - break if i * 3 + 2 > pairs.length + break if (i * 3) + 2 > pairs.length left = pairs[i * 3] - right = pairs[i * 3 + 1] - value = to_signed(pairs[i * 3 + 2]) + right = pairs[(i * 3) + 1] + value = to_signed(pairs[(i * 3) + 2]) @pairs[[left, right]] = value end end @@ -69,19 +69,19 @@ def recode(mapping) return if subset.empty? num_pairs = subset.length - search_range = 2 * 2**(Math.log(num_pairs) / Math.log(2)).to_i - entry_selector = (Math.log(search_range / 2) / Math.log(2)).to_i + search_range = 2 * (2**Integer(Math.log(num_pairs) / Math.log(2))) + entry_selector = Integer(Math.log(search_range / 2) / Math.log(2)) range_shift = (2 * num_pairs) - search_range [ attributes[:version], - num_pairs * 6 + 14, + (num_pairs * 6) + 14, attributes[:coverage], num_pairs, search_range, entry_selector, range_shift, - subset + subset, ].flatten.pack('n*') end end diff --git a/lib/ttfunk/table/loca.rb b/lib/ttfunk/table/loca.rb index 4447c0e7..1e74cb5b 100644 --- a/lib/ttfunk/table/loca.rb +++ b/lib/ttfunk/table/loca.rb @@ -21,10 +21,10 @@ class Loca < Table # * `:table` - encoded bytes def self.encode(offsets) long_offsets = - offsets.any? do |offset| + offsets.any? { |offset| short_offset = offset / 2 short_offset * 2 != offset || short_offset > 0xffff - end + } if long_offsets { type: 1, table: offsets.pack('N*') } diff --git a/lib/ttfunk/table/maxp.rb b/lib/ttfunk/table/maxp.rb index 8cc7c129..f58e5d3f 100644 --- a/lib/ttfunk/table/maxp.rb +++ b/lib/ttfunk/table/maxp.rb @@ -89,9 +89,7 @@ def encode(maxp, new2old_glyph) table << [maxp.version, num_glyphs].pack('Nn') if maxp.version == 0x10000 - stats = stats_for( - maxp, glyphs_from_ids(maxp, new2old_glyph.values) - ) + stats = stats_for(maxp, glyphs_from_ids(maxp, new2old_glyph.values)) table << [ stats[:max_points], @@ -108,7 +106,7 @@ def encode(maxp, new2old_glyph) maxp.max_stack_elements, stats[:max_size_of_instructions], stats[:max_component_elements], - stats[:max_component_depth] + stats[:max_component_depth], ].pack('n*') end end @@ -150,7 +148,7 @@ def stats_for_simple(_maxp, glyphs) max_component_elements: max_component_elements, max_points: max_points, max_contours: max_contours, - max_size_of_instructions: max_size_of_instructions + max_size_of_instructions: max_size_of_instructions, } end @@ -171,7 +169,7 @@ def stats_for_compound(maxp, glyphs) { max_component_points: max_component_points, max_component_depth: max_component_depth, - max_component_contours: max_component_contours + max_component_contours: max_component_contours, } end @@ -182,9 +180,7 @@ def totals_for_compound(maxp, glyphs, depth) glyphs.each do |glyph| if glyph.compound? - stats = totals_for_compound( - maxp, glyphs_from_ids(maxp, glyph.glyph_ids), depth + 1 - ) + stats = totals_for_compound(maxp, glyphs_from_ids(maxp, glyph.glyph_ids), depth + 1) total_points << stats[:total_points] total_contours << stats[:total_contours] @@ -199,7 +195,7 @@ def totals_for_compound(maxp, glyphs, depth) { total_points: total_points, total_contours: total_contours, - max_depth: max_depth + max_depth: max_depth, } end end diff --git a/lib/ttfunk/table/name.rb b/lib/ttfunk/table/name.rb index 4740f6be..6f876d7d 100644 --- a/lib/ttfunk/table/name.rb +++ b/lib/ttfunk/table/name.rb @@ -7,7 +7,6 @@ module TTFunk class Table # Naming (`name`) table class Name < Table - # Name Record. class NameString < ::String # Platform ID. @@ -188,15 +187,13 @@ def strip_extended def self.encode(names, key = '') tag = Digest::SHA1.hexdigest(key)[0, 6] - postscript_name = NameString.new( - "#{tag}+#{names.postscript_name}", 1, 0, 0 - ) + postscript_name = NameString.new("#{tag}+#{names.postscript_name}", 1, 0, 0) strings = names.strings.dup strings[6] = [postscript_name] str_count = strings.reduce(0) { |sum, (_, list)| sum + list.length } - table = [0, str_count, 6 + 12 * str_count].pack('n*') + table = [0, str_count, 6 + (12 * str_count)].pack('n*') strtable = +'' items = [] @@ -206,13 +203,13 @@ def self.encode(names, key = '') end end items = - items.sort_by do |id, string| + items.sort_by { |id, string| [string.platform_id, string.encoding_id, string.language_id, id] - end + } items.each do |id, string| table << [ string.platform_id, string.encoding_id, string.language_id, id, - string.length, strtable.length + string.length, strtable.length, ].pack('n*') strtable << string end @@ -244,7 +241,7 @@ def parse! name_id: id, length: length, offset: offset + string_offset + start_offset, - text: nil + text: nil, } end @@ -257,7 +254,7 @@ def parse! @entries[i][:text] || '', @entries[i][:platform_id], @entries[i][:encoding_id], - @entries[i][:language_id] + @entries[i][:language_id], ) end diff --git a/lib/ttfunk/table/os2.rb b/lib/ttfunk/table/os2.rb index 38070937..1988eed0 100644 --- a/lib/ttfunk/table/os2.rb +++ b/lib/ttfunk/table/os2.rb @@ -178,7 +178,7 @@ class OS2 < Table 737 => 60, 708 => 61, 850 => 62, - 437 => 63 + 437 => 63, }.freeze # Unicode blocks. @@ -351,7 +351,7 @@ class OS2 < Table (0x10280..0x1029F) => 121, (0x10920..0x1093F) => 121, (0x1F030..0x1F09F) => 122, - (0x1F000..0x1F02F) => 122 + (0x1F000..0x1F02F) => 122, }.freeze # Indicates that font supports supplementary characters. @@ -371,10 +371,9 @@ class OS2 < Table # Space character code point. CODEPOINT_SPACE = 32 - SPACE_GLYPH_MISSING_ERROR = "Space glyph (0x#{CODEPOINT_SPACE.to_s(16)})"\ - ' must be included in the font' # Error message for missing space character. + SPACE_GLYPH_MISSING_ERROR = "Space glyph (0x#{CODEPOINT_SPACE.to_s(16)}) must be included in the font" # Used to calculate the xAvgCharWidth field. # From https://docs.microsoft.com/en-us/typography/opentype/spec/os2: @@ -393,7 +392,7 @@ class OS2 < Table # chracter weights for average character width calculation. WEIGHT_LOWERCASE = [ 64, 14, 27, 35, 100, 20, 14, 42, 63, 3, 6, 35, 20, - 56, 56, 17, 4, 49, 56, 71, 31, 10, 18, 3, 18, 2 + 56, 56, 17, 4, 49, 56, 71, 31, 10, 18, 3, 18, 2, ].freeze # Table tag. @@ -405,7 +404,7 @@ def tag class << self # Encode table. # - # @param head [TTFunk::Table::Head] + # @param os2 [TTFunk::Table::OS2] # @param subset [TTFunk::Subset::MacRoman, TTFunk::Subset::Windows1252, # TTFunk::Subset::Unicode, TTFunk::Subset::Unicode8Bit] # @return [String] @@ -418,7 +417,7 @@ def encode(os2, subset) os2.y_subscript_y_offset, os2.y_superscript_x_size, os2.y_superscript_y_size, os2.y_superscript_x_offset, os2.y_superscript_y_offset, os2.y_strikeout_size, - os2.y_strikeout_position, os2.family_class + os2.y_strikeout_position, os2.family_class, ].pack('n*') result << os2.panose @@ -428,7 +427,7 @@ def encode(os2, subset) .slice_int( new_char_range.value, bit_width: 32, - slice_count: 4 + slice_count: 4, ) .pack('N*') @@ -449,27 +448,27 @@ def encode(os2, subset) last_char_index = [code_points.last || 0, UNICODE_MAX].min result << [ - os2.selection, first_char_index, last_char_index + os2.selection, first_char_index, last_char_index, ].pack('n*') if os2.version.positive? result << [ os2.ascent, os2.descent, os2.line_gap, - os2.win_ascent, os2.win_descent + os2.win_ascent, os2.win_descent, ].pack('n*') result << BinUtils .slice_int( code_pages_for(subset).value, bit_width: 32, - slice_count: 2 + slice_count: 2, ) .pack('N*') if os2.version > 1 result << [ os2.x_height, os2.cap_height, os2.default_char, - os2.break_char, os2.max_context + os2.break_char, os2.max_context, ].pack('n*') end end @@ -534,7 +533,7 @@ def avg_ms_symbol_char_width_for(os2, subset) # use new -> old glyph mapping in order to include compound glyphs # in the calculation - subset.new_to_old_glyph.each do |_, old_gid| + subset.new_to_old_glyph.each_value do |old_gid| if (metric = os2.file.horizontal_metrics.for(old_gid)) total_width += metric.advance_width num_glyphs += 1 if metric.advance_width.positive? @@ -585,7 +584,7 @@ def avg_weighted_char_width_for(os2, subset) # use new -> old glyph mapping in order to include compound glyphs # in the calculation - subset.new_to_old_glyph.each do |_, old_gid| + subset.new_to_old_glyph.each_value do |old_gid| if (metric = os2.file.horizontal_metrics.for(old_gid)) total_width += metric.advance_width end @@ -610,9 +609,7 @@ def parse! @y_strikeout_position, @family_class = read_signed(12) @panose = io.read(10) - @char_range = BitField.new( - BinUtils.stitch_int(read(16, 'N*'), bit_width: 32) - ) + @char_range = BitField.new(BinUtils.stitch_int(read(16, 'N*'), bit_width: 32)) @vendor_id = io.read(4) @selection, @first_char_index, @last_char_index = read(6, 'n*') @@ -620,9 +617,7 @@ def parse! if @version.positive? @ascent, @descent, @line_gap = read_signed(3) @win_ascent, @win_descent = read(4, 'nn') - @code_page_range = BitField.new( - BinUtils.stitch_int(read(8, 'N*'), bit_width: 32) - ) + @code_page_range = BitField.new(BinUtils.stitch_int(read(8, 'N*'), bit_width: 32)) if @version > 1 @x_height, @cap_height = read_signed(2) diff --git a/lib/ttfunk/table/post.rb b/lib/ttfunk/table/post.rb index 32111244..950e790a 100644 --- a/lib/ttfunk/table/post.rb +++ b/lib/ttfunk/table/post.rb @@ -64,7 +64,7 @@ class Post < Table # are old glyph IDs # @return [String, nil] def self.encode(post, mapping) - return unless post.exists? + return if post.nil? post.recode(mapping) end @@ -106,7 +106,7 @@ def recode(mapping) if position index << position else - index << 257 + strings.length + index << (257 + strings.length) strings << post_glyph end end @@ -145,11 +145,7 @@ def parse! end def parse_format! - warn( - Kernel.format( - 'postscript table format 0x%08X is not supported', @format - ) - ) + warn(Kernel.format('postscript table format 0x%08X is not supported', @format)) end end end diff --git a/lib/ttfunk/table/sbix.rb b/lib/ttfunk/table/sbix.rb index d6f29ff2..952aa303 100644 --- a/lib/ttfunk/table/sbix.rb +++ b/lib/ttfunk/table/sbix.rb @@ -56,13 +56,11 @@ def bitmap_data_for(glyph_id, strike_index) if glyph_offset && next_glyph_offset bytes = next_glyph_offset - glyph_offset if bytes.positive? - parse_from(offset + strike[:offset] + glyph_offset) do + parse_from(offset + strike[:offset] + glyph_offset) { x, y, type = read(8, 's2A4') data = StringIO.new(io.read(bytes - 8)) - BitmapData.new( - x, y, type, data, strike[:ppem], strike[:resolution] - ) - end + BitmapData.new(x, y, type, data, strike[:ppem], strike[:resolution]) + } end end end @@ -72,9 +70,9 @@ def bitmap_data_for(glyph_id, strike_index) # @param glyph_id [Integer] # @return [Array] def all_bitmap_data_for(glyph_id) - strikes.each_index.map do |strike_index| + strikes.each_index.filter_map { |strike_index| bitmap_data_for(glyph_id, strike_index) - end.compact + } end private @@ -84,21 +82,21 @@ def parse! strike_offsets = Array.new(num_strikes) { read(4, 'N').first } @strikes = - strike_offsets.map do |strike_offset| - parse_from(offset + strike_offset) do + strike_offsets.map { |strike_offset| + parse_from(offset + strike_offset) { ppem, resolution = read(4, 'n2') data_offsets = - Array.new(file.maximum_profile.num_glyphs + 1) do + Array.new(file.maximum_profile.num_glyphs + 1) { read(4, 'N').first - end + } { ppem: ppem, resolution: resolution, offset: strike_offset, - glyph_data_offset: data_offsets + glyph_data_offset: data_offsets, } - end - end + } + } end end end diff --git a/lib/ttfunk/table/vorg.rb b/lib/ttfunk/table/vorg.rb index ab9b61be..808f5461 100644 --- a/lib/ttfunk/table/vorg.rb +++ b/lib/ttfunk/table/vorg.rb @@ -34,7 +34,7 @@ def self.encode(vorg) ''.b.tap do |table| table << [ vorg.major_version, vorg.minor_version, - vorg.default_vert_origin_y, vorg.count + vorg.default_vert_origin_y, vorg.count, ].pack('n*') vorg.origins.each_pair do |glyph_id, vert_origin_y| diff --git a/lib/ttfunk/ttf_encoder.rb b/lib/ttfunk/ttf_encoder.rb index 2fe4c223..6203a15b 100644 --- a/lib/ttfunk/ttf_encoder.rb +++ b/lib/ttfunk/ttf_encoder.rb @@ -7,7 +7,7 @@ class TTFEncoder OPTIMAL_TABLE_ORDER = [ 'head', 'hhea', 'maxp', 'OS/2', 'hmtx', 'LTSH', 'VDMX', 'hdmx', 'cmap', 'fpgm', 'prep', 'cvt ', 'loca', 'glyf', - 'kern', 'name', 'post', 'gasp', 'PCLT' + 'kern', 'name', 'post', 'gasp', 'PCLT', ].freeze # Original font. @@ -38,9 +38,9 @@ def initialize(original, subset, options = {}) # @return [String] def encode # https://www.microsoft.com/typography/otspec/otff.htm#offsetTable - search_range = 2**Math.log2(tables.length).floor * 16 - entry_selector = Math.log2(2**Math.log2(tables.length).floor).to_i - range_shift = tables.length * 16 - search_range + search_range = (2**Math.log2(tables.length).floor) * 16 + entry_selector = Integer(Math.log2(2**Math.log2(tables.length).floor)) + range_shift = (tables.length * 16) - search_range range_shift = 0 if range_shift.negative? newfont = EncodedString.new @@ -50,7 +50,7 @@ def encode tables.length, search_range, entry_selector, - range_shift + range_shift, ].pack('Nn*') # Tables are supposed to be listed in ascending order whereas there is a @@ -91,51 +91,35 @@ def cmap_table end def glyf_table - @glyf_table ||= TTFunk::Table::Glyf.encode( - glyphs, new_to_old_glyph, old_to_new_glyph - ) + @glyf_table ||= TTFunk::Table::Glyf.encode(glyphs, new_to_old_glyph, old_to_new_glyph) end def loca_table - @loca_table ||= TTFunk::Table::Loca.encode( - glyf_table[:offsets] - ) + @loca_table ||= TTFunk::Table::Loca.encode(glyf_table[:offsets]) end def hmtx_table - @hmtx_table ||= TTFunk::Table::Hmtx.encode( - original.horizontal_metrics, new_to_old_glyph - ) + @hmtx_table ||= TTFunk::Table::Hmtx.encode(original.horizontal_metrics, new_to_old_glyph) end def hhea_table - @hhea_table = TTFunk::Table::Hhea.encode( - original.horizontal_header, hmtx_table, original, new_to_old_glyph - ) + @hhea_table = TTFunk::Table::Hhea.encode(original.horizontal_header, hmtx_table, original, new_to_old_glyph) end def maxp_table - @maxp_table ||= TTFunk::Table::Maxp.encode( - original.maximum_profile, old_to_new_glyph - ) + @maxp_table ||= TTFunk::Table::Maxp.encode(original.maximum_profile, old_to_new_glyph) end def post_table - @post_table ||= TTFunk::Table::Post.encode( - original.postscript, new_to_old_glyph - ) + @post_table ||= TTFunk::Table::Post.encode(original.postscript, new_to_old_glyph) end def name_table - @name_table ||= TTFunk::Table::Name.encode( - original.name, glyf_table.fetch(:table, '') - ) + @name_table ||= TTFunk::Table::Name.encode(original.name, glyf_table.fetch(:table, '')) end def head_table - @head_table ||= TTFunk::Table::Head.encode( - original.header, loca_table, new_to_old_glyph - ) + @head_table ||= TTFunk::Table::Head.encode(original.header, loca_table, new_to_old_glyph) end # "optional" tables. Fonts may omit these if they do not need them. @@ -169,22 +153,16 @@ def kern_table # generated subfont may need a kerning table... in that case, you need # to opt into it. if options[:kerning] - @kern_table ||= TTFunk::Table::Kern.encode( - original.kerning, old_to_new_glyph - ) + @kern_table ||= TTFunk::Table::Kern.encode(original.kerning, old_to_new_glyph) end end def vorg_table - @vorg_table ||= TTFunk::Table::Vorg.encode( - original.vertical_origins - ) + @vorg_table ||= TTFunk::Table::Vorg.encode(original.vertical_origins) end def dsig_table - @dsig_table ||= TTFunk::Table::Dsig.encode( - original.digital_signature - ) + @dsig_table ||= TTFunk::Table::Dsig.encode(original.digital_signature) end def tables @@ -205,7 +183,7 @@ def tables 'cvt ' => cvt_table, 'VORG' => vorg_table, 'DSIG' => dsig_table, - 'gasp' => gasp_table + 'gasp' => gasp_table, }.compact end @@ -231,7 +209,7 @@ def raw(data) def align(data, width) if (data.length % width).positive? - data + "\0" * (width - data.length % width) + data + ("\0" * (width - (data.length % width))) else data end diff --git a/spec/integration/subset_spec.rb b/spec/integration/subset_spec.rb index 79a33d45..e4f223b0 100644 --- a/spec/integration/subset_spec.rb +++ b/spec/integration/subset_spec.rb @@ -4,159 +4,157 @@ require 'stringio' require 'ttfunk/subset' -describe TTFunk do - describe 'subsetting' do - let(:space_char) { TTFunk::Subset::Unicode::SPACE_CHAR } +describe 'subsetting' do # rubocop: disable RSpec/DescribeClass + let(:space_char) { TTFunk::Subset::Unicode::SPACE_CHAR } - it 'consistently names font for same subsets' do - font = TTFunk::File.open test_font('DejaVuSans') + it 'consistently names font for same subsets' do + font = TTFunk::File.open(test_font('DejaVuSans')) - subset1 = TTFunk::Subset.for(font, :unicode) - subset1.use(97) - name1 = TTFunk::File.new(subset1.encode).name.strings[6] + subset1 = TTFunk::Subset.for(font, :unicode) + subset1.use(97) + name1 = TTFunk::File.new(subset1.encode).name.strings[6] - subset2 = TTFunk::Subset.for(font, :unicode) - subset2.use(97) - name2 = TTFunk::File.new(subset2.encode).name.strings[6] + subset2 = TTFunk::Subset.for(font, :unicode) + subset2.use(97) + name2 = TTFunk::File.new(subset2.encode).name.strings[6] - expect(name1).to eq name2 - end - - it 'can reconstruct an entire font' do - font = TTFunk::File.open test_font('DejaVuSans') - subset = TTFunk::Subset.for(font, :unicode) + expect(name1).to eq name2 + end - font.cmap.unicode.first.code_map.each do |code_point, _gid| - subset.use(code_point) - end + it 'can reconstruct an entire font' do + font = TTFunk::File.open(test_font('DejaVuSans')) + subset = TTFunk::Subset.for(font, :unicode) - expect { subset.encode }.to_not raise_error + font.cmap.unicode.first.code_map.each_key do |code_point| + subset.use(code_point) end - it 'always includes the space glyph' do - font = TTFunk::File.open test_font('DejaVuSans') - subset = TTFunk::Subset.for(font, :unicode) - new_font = TTFunk::File.new(subset.encode) + expect { subset.encode }.to_not raise_error + end - # space should be GID 1 since it's the only glyph in the font - # (0 is always .notdef) - expect(new_font.cmap.unicode.first[space_char]).to eq(1) - end + it 'always includes the space glyph' do + font = TTFunk::File.open(test_font('DejaVuSans')) + subset = TTFunk::Subset.for(font, :unicode) + new_font = TTFunk::File.new(subset.encode) - it "explodes if the space glyph isn't included" do - font = TTFunk::File.open test_font('DejaVuSans') - subset = TTFunk::Subset.for(font, :unicode) - subset.instance_variable_get(:@subset).delete(space_char) - expect { subset.encode }.to raise_error(/Space glyph .* must be included/) - end + # space should be GID 1 since it's the only glyph in the font + # (0 is always .notdef) + expect(new_font.cmap.unicode.first[space_char]).to eq(1) + end - it 'changes font names for different subsets' do - font = TTFunk::File.open test_font('DejaVuSans') + it "explodes if the space glyph isn't included" do + font = TTFunk::File.open(test_font('DejaVuSans')) + subset = TTFunk::Subset.for(font, :unicode) + subset.instance_variable_get(:@subset).delete(space_char) + expect { subset.encode }.to raise_error(/Space glyph .* must be included/) + end - subset1 = TTFunk::Subset.for(font, :unicode) - subset1.use(97) - name1 = TTFunk::File.new(subset1.encode).name.strings[6] + it 'changes font names for different subsets' do + font = TTFunk::File.open(test_font('DejaVuSans')) - subset2 = TTFunk::Subset.for(font, :unicode) - subset2.use(97) - subset2.use(98) - name2 = TTFunk::File.new(subset2.encode).name.strings[6] + subset1 = TTFunk::Subset.for(font, :unicode) + subset1.use(97) + name1 = TTFunk::File.new(subset1.encode).name.strings[6] - expect(name1).to_not eq name2 - end + subset2 = TTFunk::Subset.for(font, :unicode) + subset2.use(97) + subset2.use(98) + name2 = TTFunk::File.new(subset2.encode).name.strings[6] - it 'calculates checksum correctly for empty table data' do - font = TTFunk::File.open test_font('Mplus1p') - subset1 = TTFunk::Subset.for(font, :unicode) - expect { subset1.encode }.to_not raise_error - end + expect(name1).to_not eq name2 + end - it 'generates font directory with tables in ascending order' do - font = TTFunk::File.open test_font('DejaVuSans') + it 'calculates checksum correctly for empty table data' do + font = TTFunk::File.open(test_font('Mplus1p')) + subset1 = TTFunk::Subset.for(font, :unicode) + expect { subset1.encode }.to_not raise_error + end - subset = TTFunk::Subset.for(font, :unicode) - subset.use(97) + it 'generates font directory with tables in ascending order' do + font = TTFunk::File.open(test_font('DejaVuSans')) - directory = TTFunk::File.new(subset.encode).directory - table_tags = directory.tables.keys + subset = TTFunk::Subset.for(font, :unicode) + subset.use(97) - expect(table_tags.sort).to eq(table_tags) - expect(table_tags.first).to be < table_tags.last - end + directory = TTFunk::File.new(subset.encode).directory + table_tags = directory.tables.keys + + expect(table_tags.sort).to eq(table_tags) + expect(table_tags.first).to be < table_tags.last + end - it 'calculates search_range, entry_selector & range_shift values' do - font = TTFunk::File.open test_font('DejaVuSans') + it 'calculates search_range, entry_selector & range_shift values' do + font = TTFunk::File.open(test_font('DejaVuSans')) + + subset = TTFunk::Subset.for(font, :unicode) + subset.use(97) + subset_io = StringIO.new(subset.encode) + + scaler_type, table_count = subset_io.read(6).unpack('Nn') + search_range, entry_selector, range_shift = + subset_io.read(6).unpack('nnn') + + # Subset fonts include 14 tables by default. + expected_table_count = 14 + # Smallest power of two less than number of tables, times 16. + expected_search_range = 8 * 16 + # Log2 of max power of two smaller than number of tables. + expected_entry_selector = 3 + # Range shift is defined as 16*table_count - search_range. + expected_range_shift = (16 * expected_table_count) - expected_search_range + + expect(scaler_type).to eq(font.directory.scaler_type) + expect(table_count).to eq(expected_table_count) + expect(search_range).to eq(expected_search_range) + expect(entry_selector).to eq(expected_entry_selector) + expect(range_shift).to eq(expected_range_shift) + end + + it 'knows which characters it includes' do + font = TTFunk::File.open(test_font('DejaVuSans')) + unicode = TTFunk::Subset.for(font, :unicode) + unicode_8bit = TTFunk::Subset.for(font, :unicode_8bit) + mac_roman = TTFunk::Subset.for(font, :mac_roman) + windows1252 = TTFunk::Subset.for(font, :windows_1252) # rubocop: disable Naming/VariableNumber - subset = TTFunk::Subset.for(font, :unicode) + [unicode, unicode_8bit, mac_roman, windows1252].each do |subset| + expect(subset).to_not be_includes(97) subset.use(97) - subset_io = StringIO.new(subset.encode) - - scaler_type, table_count = subset_io.read(6).unpack('Nn') - search_range, entry_selector, range_shift = - subset_io.read(6).unpack('nnn') - - # Subset fonts include 14 tables by default. - expected_table_count = 14 - # Smallest power of two less than number of tables, times 16. - expected_search_range = 8 * 16 - # Log2 of max power of two smaller than number of tables. - expected_entry_selector = 3 - # Range shift is defined as 16*table_count - search_range. - expected_range_shift = 16 * expected_table_count - expected_search_range - - expect(scaler_type).to eq(font.directory.scaler_type) - expect(table_count).to eq(expected_table_count) - expect(search_range).to eq(expected_search_range) - expect(entry_selector).to eq(expected_entry_selector) - expect(range_shift).to eq(expected_range_shift) + expect(subset).to be_includes(97) end + end - it 'knows which characters it includes' do - font = TTFunk::File.open test_font('DejaVuSans') - unicode = TTFunk::Subset.for(font, :unicode) - unicode_8bit = TTFunk::Subset.for(font, :unicode_8bit) - mac_roman = TTFunk::Subset.for(font, :mac_roman) - windows1252 = TTFunk::Subset.for(font, :windows_1252) # rubocop: disable Naming/VariableNumber - - [unicode, unicode_8bit, mac_roman, windows1252].each do |subset| - expect(subset).to_not be_includes(97) - subset.use(97) - expect(subset).to be_includes(97) - end - end + it 'maps final code 0xFFFF to glyph 0 in generated type 4 cmap' do + font = TTFunk::File.open(test_font('DejaVuSans')) - it 'maps final code 0xFFFF to glyph 0 in generated type 4 cmap' do - font = TTFunk::File.open test_font('DejaVuSans') + subset = TTFunk::Subset.for(font, :unicode) + subset.use(97) + cmap = TTFunk::File.new(subset.encode).cmap - subset = TTFunk::Subset.for(font, :unicode) - subset.use(97) - cmap = TTFunk::File.new(subset.encode).cmap + # Unicode subsets only contain a single format 4 cmap subtable. + expect(cmap.tables.size).to eq(1) + format04 = cmap.tables.first + expect(format04.format).to eq(4) + expect(format04.code_map[0xFFFF]).to eq(0) + end - # Unicode subsets only contain a single format 4 cmap subtable. - expect(cmap.tables.size).to eq(1) - format04 = cmap.tables.first - expect(format04.format).to eq(4) - expect(format04.code_map[0xFFFF]).to eq(0) + it 'sorts records in the name table correctly' do + font = TTFunk::File.open(test_font('DejaVuSans')) + + subset = TTFunk::Subset.for(font, :unicode) + subset.use(97) + name = TTFunk::File.new(subset.encode).name + + records = [] + name.entries.each do |entry| + records << [ + entry[:platform_id], + entry[:encoding_id], + entry[:language_id], + entry[:name_id], + ] end - it 'sorts records in the name table correctly' do - font = TTFunk::File.open test_font('DejaVuSans') - - subset = TTFunk::Subset.for(font, :unicode) - subset.use(97) - name = TTFunk::File.new(subset.encode).name - - records = [] - name.entries.each do |entry| - records << [ - entry[:platform_id], - entry[:encoding_id], - entry[:language_id], - entry[:name_id] - ] - end - - expect(records).to eq(records.sort) - end + expect(records).to eq(records.sort) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7e772f77..cb1a192c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,6 +8,5 @@ Dir[File.expand_path('support/**/*.rb', __dir__)].sort.each { |f| require f } RSpec.configure do |config| - config.include PathHelpers - config.include TextHelpers + config.include(PathHelpers) end diff --git a/spec/support/text_helpers.rb b/spec/support/text_helpers.rb deleted file mode 100644 index 49868c1b..00000000 --- a/spec/support/text_helpers.rb +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -module TextHelpers - def strip_leading_spaces(str) - # isolate leading spaces for all lines then choose the shortest, i.e. the - # number of leading spaces all the lines have in common - min_leader_len = str.scan(/^(\s+)/).flatten.min_by(&:length).length - - # remove the first min_leader_len leading spaces from each line - str.gsub(/^\s{#{min_leader_len}}/, '') - end -end diff --git a/spec/ttfunk/bin_utils_spec.rb b/spec/ttfunk/bin_utils_spec.rb index 03aa5204..365e57a3 100644 --- a/spec/ttfunk/bin_utils_spec.rb +++ b/spec/ttfunk/bin_utils_spec.rb @@ -8,9 +8,7 @@ describe '.stitch_int' do it 'composes an int from a series of bytes of a given width' do - result = described_class.stitch_int( - [0b01001100, 0b11010001], bit_width: bit_width - ) + result = described_class.stitch_int([0b01001100, 0b11010001], bit_width: bit_width) expect(result).to eq(0b1101000101001100) end @@ -18,9 +16,7 @@ describe '.slice_int' do it 'breaks down an int into a series of segments of the given bit width' do - result = described_class.slice_int( - 0b1101000101001100, bit_width: bit_width, slice_count: 2 - ) + result = described_class.slice_int(0b1101000101001100, bit_width: bit_width, slice_count: 2) expect(result).to eq([0b01001100, 0b11010001]) end @@ -28,15 +24,11 @@ describe '.twos_comp_to_int' do it "converts a two's complement number to an integer" do - expect(described_class.twos_comp_to_int(0b10101001, bit_width: 8)).to( - eq(-0b01010111) - ) + expect(described_class.twos_comp_to_int(0b10101001, bit_width: 8)).to eq(-0b01010111) end it "returns the original number if the number isn't negative" do - expect(described_class.twos_comp_to_int(0b01101001, bit_width: 8)).to( - eq(0b01101001) - ) + expect(described_class.twos_comp_to_int(0b01101001, bit_width: 8)).to eq(0b01101001) end end diff --git a/spec/ttfunk/bit_field_spec.rb b/spec/ttfunk/bit_field_spec.rb index fb7f3336..b7787cc4 100644 --- a/spec/ttfunk/bit_field_spec.rb +++ b/spec/ttfunk/bit_field_spec.rb @@ -10,45 +10,39 @@ describe '#on?' do it 'determines that the correct bits are on' do - expect(bit_field.on?(0)).to eq(false) - expect(bit_field.on?(1)).to eq(true) - expect(bit_field.on?(2)).to eq(true) - expect(bit_field.on?(3)).to eq(false) - expect(bit_field.on?(4)).to eq(false) - expect(bit_field.on?(5)).to eq(true) - expect(bit_field.on?(6)).to eq(false) - expect(bit_field.on?(7)).to eq(true) + expect(bit_field.on?(0)).to be false + expect(bit_field.on?(1)).to be true + expect(bit_field.on?(2)).to be true + expect(bit_field.on?(3)).to be false + expect(bit_field.on?(4)).to be false + expect(bit_field.on?(5)).to be true + expect(bit_field.on?(6)).to be false + expect(bit_field.on?(7)).to be true end end describe '#off?' do it 'determines that the correct bits are off' do - expect(bit_field.off?(0)).to eq(true) - expect(bit_field.off?(1)).to eq(false) - expect(bit_field.off?(2)).to eq(false) - expect(bit_field.off?(3)).to eq(true) - expect(bit_field.off?(4)).to eq(true) - expect(bit_field.off?(5)).to eq(false) - expect(bit_field.off?(6)).to eq(true) - expect(bit_field.off?(7)).to eq(false) + expect(bit_field.off?(0)).to be true + expect(bit_field.off?(1)).to be false + expect(bit_field.off?(2)).to be false + expect(bit_field.off?(3)).to be true + expect(bit_field.off?(4)).to be true + expect(bit_field.off?(5)).to be false + expect(bit_field.off?(6)).to be true + expect(bit_field.off?(7)).to be false end end describe '#on' do it 'turns the given bit on' do - expect { bit_field.on(3) }.to( - change { bit_field.on?(3) }.from(false).to(true) - ) + expect { bit_field.on(3) }.to change { bit_field.on?(3) }.from(false).to(true) end it 'updates the value' do - expect { bit_field.on(0) }.to( - change(bit_field, :value).from(0b10100110).to(0b10100111) - ) + expect { bit_field.on(0) }.to change(bit_field, :value).from(0b10100110).to(0b10100111) - expect { bit_field.on(3) }.to( - change(bit_field, :value).from(0b10100111).to(0b10101111) - ) + expect { bit_field.on(3) }.to change(bit_field, :value).from(0b10100111).to(0b10101111) end it 'does not update the value if no bits were flipped' do @@ -58,19 +52,13 @@ describe '#off' do it 'turns the given bit off' do - expect { bit_field.off(5) }.to( - change { bit_field.off?(5) }.from(false).to(true) - ) + expect { bit_field.off(5) }.to change { bit_field.off?(5) }.from(false).to(true) end it 'updates the value' do - expect { bit_field.off(1) }.to( - change(bit_field, :value).from(0b10100110).to(0b10100100) - ) + expect { bit_field.off(1) }.to change(bit_field, :value).from(0b10100110).to(0b10100100) - expect { bit_field.off(5) }.to( - change(bit_field, :value).from(0b10100100).to(0b10000100) - ) + expect { bit_field.off(5) }.to change(bit_field, :value).from(0b10100100).to(0b10000100) end it 'does not update the value if no bits were flipped' do diff --git a/spec/integration/collection_spec.rb b/spec/ttfunk/collection_spec.rb similarity index 79% rename from spec/integration/collection_spec.rb rename to spec/ttfunk/collection_spec.rb index f75f6dbd..edea2749 100644 --- a/spec/integration/collection_spec.rb +++ b/spec/ttfunk/collection_spec.rb @@ -4,12 +4,12 @@ describe TTFunk::Collection do describe '.open' do - it 'will not open non-TTC files' do - expect { described_class.open test_font('DejaVuSans') } + it 'does not open non-TTC files' do + expect { described_class.open(test_font('DejaVuSans')) } .to raise_error(ArgumentError) end - it 'will open TTC files' do + it 'opens TTC files' do success = false described_class.open(test_font('DejaVuSans', :ttc)) do |_ttc| @@ -19,7 +19,7 @@ expect(success).to be true end - it 'will open TTC files as IO' do + it 'opens TTC files as IO' do success = false io = StringIO.new(File.read(test_font('DejaVuSans', :ttc))) @@ -30,7 +30,7 @@ expect(success).to be true end - it 'will report fonts in TTC' do + it 'reports fonts in TTC' do described_class.open(test_font('DejaVuSans', :ttc)) do |ttc| expect(ttc.count).to eq 2 expect(ttc[0].name.font_name.first).to eq 'DejaVu Sans' diff --git a/spec/ttfunk/encoded_string_spec.rb b/spec/ttfunk/encoded_string_spec.rb index 8242b23a..99b4031a 100644 --- a/spec/ttfunk/encoded_string_spec.rb +++ b/spec/ttfunk/encoded_string_spec.rb @@ -37,9 +37,7 @@ it 'does not allow adding two placeholders with the same name' do encoded_string << TTFunk::Placeholder.new(:foo) - expect { encoded_string << TTFunk::Placeholder.new(:foo) }.to( - raise_error(TTFunk::DuplicatePlaceholderError) - ) + expect { encoded_string << TTFunk::Placeholder.new(:foo) }.to raise_error(TTFunk::DuplicatePlaceholderError) end it 'adds padding bytes when adding a placeholder' do @@ -83,9 +81,7 @@ it "raises an error if any placeholders haven't been resolved" do encoded_string << 'foo' encoded_string << TTFunk::Placeholder.new(:name) - expect { encoded_string.string }.to( - raise_error(TTFunk::UnresolvedPlaceholderError) - ) + expect { encoded_string.string }.to raise_error(TTFunk::UnresolvedPlaceholderError) end end @@ -98,9 +94,7 @@ it "raises an error if any placeholders haven't been resolved" do encoded_string << 'foo' encoded_string << TTFunk::Placeholder.new(:name) - expect { encoded_string.bytes }.to( - raise_error(TTFunk::UnresolvedPlaceholderError) - ) + expect { encoded_string.bytes }.to raise_error(TTFunk::UnresolvedPlaceholderError) end end diff --git a/spec/integration/file_spec.rb b/spec/ttfunk/file_spec.rb similarity index 95% rename from spec/integration/file_spec.rb rename to spec/ttfunk/file_spec.rb index 132f936f..8c560f98 100644 --- a/spec/integration/file_spec.rb +++ b/spec/ttfunk/file_spec.rb @@ -5,13 +5,13 @@ describe TTFunk::File do describe '.open' do it 'opens file paths' do - font = described_class.open test_font('DejaVuSans') + font = described_class.open(test_font('DejaVuSans')) expect(font.contents.read(4)).to eq("\x00\x00\x00\x01") end it 'opens IO Objects' do - File.open test_font('DejaVuSans') do |io| - font = described_class.open io + File.open(test_font('DejaVuSans')) do |io| + font = described_class.open(io) expect(font.contents.read(4)).to eq("\x00\x00\x00\x01") end end @@ -121,7 +121,7 @@ tag: 'head', checksum: 0xF95F2039, offset: 581_036, - length: 54 + length: 54, ) end @@ -131,7 +131,7 @@ tag: 'hmtx', checksum: 0xF7E35CB8, offset: 581_128, - length: 23_712 + length: 23_712, ) end @@ -141,7 +141,7 @@ tag: 'glyf', checksum: 0x77CAC4E8, offset: 51_644, - length: 529_392 + length: 529_392, ) end end @@ -155,7 +155,7 @@ tag: 'CFF ', checksum: 0xE3109AB9, offset: 260_480, - length: 14_170_569 + length: 14_170_569, ) end end diff --git a/spec/ttfunk/otf_encoder_spec.rb b/spec/ttfunk/otf_encoder_spec.rb index 560daa5b..6f30a6c3 100644 --- a/spec/ttfunk/otf_encoder_spec.rb +++ b/spec/ttfunk/otf_encoder_spec.rb @@ -34,9 +34,7 @@ new_font.directory.tables.keys tables.each_cons(2) do |first_table, second_table| - expect(new_font.directory.tables[first_table][:offset]).to( - be < new_font.directory.tables[second_table][:offset] - ) + expect(new_font.directory.tables[first_table][:offset]).to be < new_font.directory.tables[second_table][:offset] end end end diff --git a/spec/ttfunk/sci_form_spec.rb b/spec/ttfunk/sci_form_spec.rb index c5d007ac..502a8882 100644 --- a/spec/ttfunk/sci_form_spec.rb +++ b/spec/ttfunk/sci_form_spec.rb @@ -8,7 +8,7 @@ describe '#to_f' do it 'converts to a float' do - expect(sci.to_f).to eq(612_300) + expect(Float(sci)).to eq(612_300) end end end diff --git a/spec/ttfunk/table/cff/charset_spec.rb b/spec/ttfunk/table/cff/charset_spec.rb index 91c609e5..7879b941 100644 --- a/spec/ttfunk/table/cff/charset_spec.rb +++ b/spec/ttfunk/table/cff/charset_spec.rb @@ -15,9 +15,7 @@ end it 'includes all the entries from the expert charset' do - expect(charset.to_a).to eq( - ['.notdef'] + described_class.strings_for_charset_id(charset_id) - ) + expect(charset.to_a).to eq(['.notdef'] + described_class.strings_for_charset_id(charset_id)) end end @@ -28,25 +26,21 @@ # From the spec: There is one less element in the glyph name array than # nGlyphs (i.e. charstrings count) because the .notdef glyph name is # omitted. - expect(charset.items_count).to( - eq(font.cff.top_index[0].charstrings_index.items_count - 1) - ) + expect(charset.items_count).to eq(font.cff.top_index[0].charstrings_index.items_count - 1) end it 'parses the entries correctly' do strings = charset.to_a # these should come from the set of "standard" strings - expect(strings[0..6]).to eq( - %w[.notdef uni000D space exclam quotedbl numbersign dollar] - ) + expect(strings[0..6]).to eq %w[.notdef uni000D space exclam quotedbl numbersign dollar] # these should come from the strings index expect(strings[-6..]).to eq( %w[ endash.smcp emdash.smcp parenleft.alt parenright.alt parenleft.smcp parenright.smcp - ] + ], ) end end @@ -58,23 +52,17 @@ # From the spec: There is one less element in the glyph name array than # nGlyphs (i.e. charstrings count) because the .notdef glyph name is # omitted. - expect(charset.items_count).to( - eq(font.cff.top_index[0].charstrings_index.items_count - 1) - ) + expect(charset.items_count).to eq(font.cff.top_index[0].charstrings_index.items_count - 1) end it 'parses the entries correctly' do strings = charset.to_a # these should come from the set of "standard" strings - expect(strings[0..6]).to eq( - %w[.notdef .null CR space exclam quotedbl numbersign] - ) + expect(strings[0..6]).to eq %w[.notdef .null CR space exclam quotedbl numbersign] # these should come from the strings index - expect(strings[-6..]).to eq( - %w[r_r s_s t_t w_w_w zero_seven zero_zero] - ) + expect(strings[-6..]).to eq %w[r_r s_s t_t w_w_w zero_seven zero_zero] end end @@ -85,18 +73,14 @@ # From the spec: There is one less element in the glyph name array than # nGlyphs (i.e. charstrings count) because the .notdef glyph name is # omitted. - expect(charset.items_count).to( - eq(font.cff.top_index[0].charstrings_index.items_count - 1) - ) + expect(charset.items_count).to eq(font.cff.top_index[0].charstrings_index.items_count - 1) end it 'parses the entries correctly' do strings = charset.to_a # these should come from the set of "standard" strings - expect(strings[0..6]).to eq( - %w[.notdef space exclam quotedbl numbersign dollar percent] - ) + expect(strings[0..6]).to eq %w[.notdef space exclam quotedbl numbersign dollar percent] # These should come from the strings index. This particular font is # curious however in that most of the glyphs do not have a corresponding @@ -106,9 +90,7 @@ # font are Chinese characters which may not have useful descriptions. # For example, the Unicode/CLDR data for most Chinese characters simply # contains the description "CJK Ideograph." - expect(strings[-6..]).to eq( - [nil, nil, nil, nil, nil, nil] - ) + expect(strings[-6..]).to eq [nil, nil, nil, nil, nil, nil] end end end @@ -128,7 +110,7 @@ 0x29 => { old: 10, new: 10 }, 0x2d => { old: 14, new: 14 }, 0x2e => { old: 15, new: 15 }, - 0x34 => { old: 21, new: 21 } + 0x34 => { old: 21, new: 21 }, } end @@ -141,8 +123,8 @@ expect(encoded.bytes).to eq( [ 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x0A, - 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x15 - ] + 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x15, + ], ) end end @@ -151,7 +133,7 @@ let(:charmap) do # i.e. the first 20 characters, in order # (supposed to be new => old glyph IDs) - Hash[(1..20).map { |i| [0x20 + i, { old: i, new: i }] }] + (1..20).to_h { |i| [0x20 + i, { old: i, new: i }] } end it 'encodes using the 8-bit range-based format' do @@ -168,7 +150,7 @@ let(:charmap) do # we want to get a 2-byte range to demonstrate the 16-bit format # (supposed to be new => old glyph IDs) - Hash[(1..2**10).map { |i| [0x20 + i, { old: i, new: i }] }] + (1..(2**10)).to_h { |i| [0x20 + i, { old: i, new: i }] } end it 'encodes using the 16-bit range-based format' do diff --git a/spec/ttfunk/table/cff/charstrings_index_spec.rb b/spec/ttfunk/table/cff/charstrings_index_spec.rb index ff5ba29b..7dd35c81 100644 --- a/spec/ttfunk/table/cff/charstrings_index_spec.rb +++ b/spec/ttfunk/table/cff/charstrings_index_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require 'ttfunk/table/cff' -RSpec.describe TTFunk::Table::Cff do +RSpec.describe TTFunk::Table::Cff, 'Charstring Index' do # rubocop: disable RSpec/DescribeMethod let(:font_path) { test_font('NotoSansCJKsc-Thin', :otf) } let(:font) { TTFunk::File.open(font_path) } let(:charstrings_index) { font.cff.top_index[0].charstrings_index } @@ -44,8 +44,8 @@ [:curve, 869, 688, 916, 613, 938, 572], [:line, 967, 587], [:curve, 942, 629, 893, 704, 868, 737], - [:close] - ] + [:close], + ], ) end @@ -95,8 +95,8 @@ [:line, -332, 176], [:line, -127, 176], [:line, -127, 206], - [:close] - ] + [:close], + ], ) end @@ -170,8 +170,8 @@ [:curve, 933, 263, 941, 274, 949, 280], [:curve, 765, 326, 616, 387, 512, 527], [:curve, 518, 534, 522, 542, 527, 549], - [:close] - ] + [:close], + ], ) end end diff --git a/spec/ttfunk/table/cff/dict_spec.rb b/spec/ttfunk/table/cff/dict_spec.rb index 5d558549..a3ae1642 100644 --- a/spec/ttfunk/table/cff/dict_spec.rb +++ b/spec/ttfunk/table/cff/dict_spec.rb @@ -19,7 +19,7 @@ # negative 4-byte int, positive 4-byte int, operator 9 [0x1D, 0xBC, 0x92, 0x6A, 0xE8, 0x1D, 0x55, 0x4F, 0x3A, 0xD4, 0x09] => { - 9 => [-1_131_255_064, 1_431_255_764] + 9 => [-1_131_255_064, 1_431_255_764], }, # negative float with no exponent, operator 10 @@ -30,12 +30,12 @@ # positive float with negative exponent, operator 11 [0x1E, 0x0A, 0x14, 0x05, 0x41, 0xC3, 0xFF, 0x0B] => { - 11 => [TTFunk::SciForm.new(0.140541, -3)] + 11 => [TTFunk::SciForm.new(0.140541, -3)], }, # positive float with positive exponent, operator 11 [0x1E, 0x0A, 0x14, 0x05, 0x41, 0xB3, 0xFF, 0x0B] => { - 11 => [TTFunk::SciForm.new(0.140541, 3)] + 11 => [TTFunk::SciForm.new(0.140541, 3)], }, # Float with a missing exponent, operator 1 @@ -43,12 +43,10 @@ } test_cases.each_with_index do |(bytes, decoded_values), idx| - context "test case #{idx}" do + context "with example #{idx}" do subject(:dict) do io = StringIO.new(bytes.pack('C*')) - described_class.new( - TestFile.new(io), 0, bytes.length - ) + described_class.new(TestFile.new(io), 0, bytes.length) end it 'parses correctly' do @@ -68,9 +66,7 @@ data = [0x1E, 0x0A, 0xFF, 0x05] file = TestFile.new(StringIO.new(data.pack('C*'))) - expect { described_class.new(file, 0, data.length) }.to raise_error( - described_class::InvalidOperandError - ) + expect { described_class.new(file, 0, data.length) }.to raise_error(described_class::InvalidOperandError) end it 'raises an error if too many operands are supplied' do @@ -78,9 +74,7 @@ data << 0x05 # operator file = TestFile.new(StringIO.new(data.pack('C*'))) - expect { described_class.new(file, 0, data.length) }.to raise_error( - described_class::TooManyOperandsError - ) + expect { described_class.new(file, 0, data.length) }.to raise_error(described_class::TooManyOperandsError) end it 'allows addition of entries' do diff --git a/spec/ttfunk/table/cff/encoding_spec.rb b/spec/ttfunk/table/cff/encoding_spec.rb index 710a4cd5..d1addc81 100644 --- a/spec/ttfunk/table/cff/encoding_spec.rb +++ b/spec/ttfunk/table/cff/encoding_spec.rb @@ -13,9 +13,7 @@ let(:encoding_id) { described_class::STANDARD_ENCODING_ID } it 'includes all the entries from the standard encoding' do - expect(encoding.to_a).to eq( - [0] + described_class.codes_for_encoding_id(encoding_id) - ) + expect(encoding.to_a).to eq([0] + described_class.codes_for_encoding_id(encoding_id)) end end @@ -23,9 +21,7 @@ let(:font_path) { test_font('AlbertTextBold', :otf) } it 'parses the entries correctly' do - expect(encoding.to_a[0..8]).to eq( - [0, 26, 27, 28, 29, 30, 31, 32, 33] - ) + expect(encoding.to_a[0..8]).to eq [0, 26, 27, 28, 29, 30, 31, 32, 33] end end end @@ -45,7 +41,7 @@ 0x29 => { old: 10, new: 10 }, 0x2d => { old: 14, new: 14 }, 0x2e => { old: 15, new: 15 }, - 0x34 => { old: 21, new: 13 } + 0x34 => { old: 21, new: 13 }, } end @@ -74,15 +70,11 @@ # predefined encoding, but which is non-zero. Since, again, we're # testing in isolation, the parser needs to start at position 0. Long # story short: we need to zero out both values to run the test. - allow_any_instance_of(described_class).to( - receive(:offset).and_return(0) - ) + allow_any_instance_of(described_class).to receive(:offset).and_return(0) allow(font.cff.top_index[0]).to receive(:cff_offset).and_return(0) - new_encoding = described_class.new( - font.cff.top_index[0], file, fake_offset, encoded.length - ) + new_encoding = described_class.new(font.cff.top_index[0], file, fake_offset, encoded.length) expect(new_encoding.to_a).to eq([0, 0x20, 0x23, 0x29, 0x34, 0x2d, 0x2e]) end @@ -93,7 +85,7 @@ let(:charmap) do # i.e. the first 20 characters, in order # (supposed to be new => old glyph IDs) - Hash[(1..20).map { |i| [0x20 + i, { old: i, new: i }] }] + (1..20).to_h { |i| [0x20 + i, { old: i, new: i }] } end it 'encodes using the range-based format' do diff --git a/spec/ttfunk/table/cff/fd_selector_spec.rb b/spec/ttfunk/table/cff/fd_selector_spec.rb index e83bde77..63b45fa5 100644 --- a/spec/ttfunk/table/cff/fd_selector_spec.rb +++ b/spec/ttfunk/table/cff/fd_selector_spec.rb @@ -17,14 +17,14 @@ instance_double( TTFunk::Table::Cff::TopDict, :top_dict, - charstrings_index: charstrings_index + charstrings_index: charstrings_index, ) end let(:charstrings_index) do instance_double( TTFunk::Table::Cff::CharstringsIndex, :charstrings_index, - items_count: entry_count + items_count: entry_count, ) end let(:fd_selector) do @@ -32,9 +32,7 @@ end before do - allow(fd_selector).to( - receive(:charstrings_index).and_return(charstrings_index) - ) + allow(fd_selector).to receive(:charstrings_index).and_return(charstrings_index) end it 'includes entries for all the glyphs in the font' do @@ -49,7 +47,7 @@ charmap = { 0x20 => { old: 1, new: 1 }, 0x22 => { old: 3, new: 3 }, - 0x24 => { old: 5, new: 5 } + 0x24 => { old: 5, new: 5 }, } expect(fd_selector.encode(charmap)).to eq("\x00\x02\x04\x06") end @@ -60,33 +58,25 @@ it 'includes entries for all the glyphs in the font' do # the charstrings index doesn't contain an entry for the .notdef glyph - expect(fd_selector.items_count).to( - eq(font.cff.top_index[0].charstrings_index.items_count + 1) - ) + expect(fd_selector.items_count).to eq(font.cff.top_index[0].charstrings_index.items_count + 1) end it 'parses the entries correctly' do fd_indices = fd_selector.to_a - expect(fd_indices[0..10]).to eq( - [5, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15] - ) + expect(fd_indices[0..10]).to eq [5, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15] - expect(fd_indices[10..20]).to eq( - [15, 15, 15, 15, 15, 15, 15, 17, 17, 17, 17] - ) + expect(fd_indices[10..20]).to eq [15, 15, 15, 15, 15, 15, 15, 17, 17, 17, 17] - expect(fd_indices[-10..]).to eq( - [5, 5, 5, 5, 5, 5, 5, 5, 5, 5] - ) + expect(fd_indices[-10..]).to eq [5, 5, 5, 5, 5, 5, 5, 5, 5, 5] end it 'encodes correctly' do - charmap = Hash[(0..15).map { |i| [i, { old: i, new: i }] }] + charmap = (0..15).to_h { |i| [i, { old: i, new: i }] } result = fd_selector.encode(charmap) expect(result).to( # fmt | count | range 1 | range 2 | n glyphs - eq("\x03\x00\x02\x00\x00\x05\x00\x01\x0F\x00\x10") + eq("\x03\x00\x02\x00\x00\x05\x00\x01\x0F\x00\x10"), ) end end diff --git a/spec/ttfunk/table/cff/font_dict_spec.rb b/spec/ttfunk/table/cff/font_dict_spec.rb index 6a29b029..d2b0d6b0 100644 --- a/spec/ttfunk/table/cff/font_dict_spec.rb +++ b/spec/ttfunk/table/cff/font_dict_spec.rb @@ -37,10 +37,10 @@ eq( font_dict.to_h.merge( described_class::OPERATORS[:private] => [ - private_dict_length, dict_length - ] - ) - ) + private_dict_length, dict_length, + ], + ), + ), ) expect(new_dict.private_dict.count).to eq(font_dict.private_dict.count) diff --git a/spec/ttfunk/table/cff/index_spec.rb b/spec/ttfunk/table/cff/index_spec.rb index 9d206bc1..ebce3fac 100644 --- a/spec/ttfunk/table/cff/index_spec.rb +++ b/spec/ttfunk/table/cff/index_spec.rb @@ -15,7 +15,7 @@ # data 0xA, 0xB, - 0xC + 0xC, ] => [[10], [11], [12]], [ @@ -28,20 +28,18 @@ # data 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, - 0x77 + 0x77, ] => [[17, 34], [51, 68, 85, 102], [119]], - [0x00, 0x00] => [] + [0x00, 0x00] => [], } describe 'decoding' do test_cases.each_with_index do |(bytes, decoded_values), idx| - context "test case #{idx}" do + context "with example #{idx}" do subject(:index) do io = StringIO.new(bytes.pack('C*')) - described_class.new( - TestFile.new(io), 0, bytes.size - ) + described_class.new(TestFile.new(io), 0, bytes.size) end it 'parses correctly' do @@ -79,13 +77,10 @@ def encode_items(*) # offsets 0x01, 0x02, 0x03, 0x04, # data - 0x01, 0x02, 0x03 + 0x01, 0x02, 0x03, ].pack('C*') - index = - inc_index_class.new( - TestFile.new(StringIO.new(data)), 0, data.length - ) + index = inc_index_class.new(TestFile.new(StringIO.new(data)), 0, data.length) expect(index.encode.string).to eq("\00\03\01\01\02\03\04\02\03\04") end @@ -109,13 +104,10 @@ def encode_items(*) # offsets 0x01, 0x02, 0x03, 0x04, # data - 0x01, 0x02, 0x03 + 0x01, 0x02, 0x03, ].pack('C*') - index = - dup_index_class.new( - TestFile.new(StringIO.new(data)), 0, data.length - ) + index = dup_index_class.new(TestFile.new(StringIO.new(data)), 0, data.length) expect(index.encode.string).to eq("\00\06\01\01\02\03\04\05\06\07\01\01\02\02\03\03") end @@ -124,7 +116,7 @@ def encode_items(*) { item_size: 1, data_size: 6, offset_size: 1 }, { item_size: 0xff, data_size: 262, offset_size: 2 }, { item_size: 0xffff, data_size: 65_544, offset_size: 3 }, - { item_size: 0xffffff, data_size: 16_777_226, offset_size: 4 } + { item_size: 0xffffff, data_size: 16_777_226, offset_size: 4 }, ].each do |params| it "properly encodes offset size #{params[:offset_size]}" do gen_index_class = @@ -145,10 +137,7 @@ def encode_items(*) expect(data.length).to eq params[:data_size] - index = - described_class.new( - TestFile.new(StringIO.new(data)), 0, data.length - ) + index = described_class.new(TestFile.new(StringIO.new(data)), 0, data.length) expect(index.items_count).to eq 1 end diff --git a/spec/ttfunk/table/cff/name_index_spec.rb b/spec/ttfunk/table/cff/name_index_spec.rb index 6ff3f97b..de7fcae8 100644 --- a/spec/ttfunk/table/cff/name_index_spec.rb +++ b/spec/ttfunk/table/cff/name_index_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require 'ttfunk/table/cff' -RSpec.describe TTFunk::Table::Cff do +RSpec.describe TTFunk::Table::Cff, 'Name Index' do # rubocop: disable RSpec/DescribeMethod let(:font_path) { test_font('NotoSansCJKsc-Thin', :otf) } let(:font) { TTFunk::File.open(font_path) } let(:name_index) { font.cff.name_index } @@ -15,9 +15,7 @@ describe '#encode' do it 'encodes the index correctly' do encoded = name_index.encode - reconstituted = described_class::Index.new( - TestFile.new(StringIO.new(encoded.string)), 0 - ) + reconstituted = described_class::Index.new(TestFile.new(StringIO.new(encoded.string)), 0) expect(reconstituted.to_a).to eq(['NotoSansCJKsc-Thin']) end diff --git a/spec/ttfunk/table/cff/private_dict_spec.rb b/spec/ttfunk/table/cff/private_dict_spec.rb index fb767a5b..224686c5 100644 --- a/spec/ttfunk/table/cff/private_dict_spec.rb +++ b/spec/ttfunk/table/cff/private_dict_spec.rb @@ -33,9 +33,7 @@ # when constructing charstrings. In other words, these seemingly # random bytes mean something specific to the charstrings code. See # the subr index tests for more. - expect(subr_index[2].bytes).to( - eq([127, 171, 119, 159, 248, 122, 171, 18, 11]) - ) + expect(subr_index[2].bytes).to eq [127, 171, 119, 159, 248, 122, 171, 18, 11] end end @@ -52,9 +50,9 @@ expect(new_dict.to_h).to( eq( private_dict.to_h.merge( - described_class::OPERATORS[:subrs] => [dict_length] - ) - ) + described_class::OPERATORS[:subrs] => [dict_length], + ), + ), ) expect(new_dict.subr_index.items_count).to eq(private_dict.subr_index.items_count) diff --git a/spec/ttfunk/table/cff/subr_index_spec.rb b/spec/ttfunk/table/cff/subr_index_spec.rb index c34fe374..0ced24b7 100644 --- a/spec/ttfunk/table/cff/subr_index_spec.rb +++ b/spec/ttfunk/table/cff/subr_index_spec.rb @@ -9,17 +9,11 @@ let(:font_index) { font.cff.top_index[0].font_index } it 'parses subroutines correctly' do - expect(font_index[1].private_dict.subr_index[3].bytes).to( - eq([39, 10, 108, 116, 37, 10, 11]) - ) + expect(font_index[1].private_dict.subr_index[3].bytes).to eq [39, 10, 108, 116, 37, 10, 11] - expect(font_index[15].private_dict.subr_index[6].bytes).to( - eq([174, 3, 34, 10, 11]) - ) + expect(font_index[15].private_dict.subr_index[6].bytes).to eq [174, 3, 34, 10, 11] - expect(font_index[18].private_dict.subr_index[50].bytes).to( - eq([179, 172, 173, 179, 180, 172, 105, 99, 11]) - ) + expect(font_index[18].private_dict.subr_index[50].bytes).to eq [179, 172, 173, 179, 180, 172, 105, 99, 11] end context 'with an index with few subroutines' do diff --git a/spec/ttfunk/table/head_spec.rb b/spec/ttfunk/table/head_spec.rb index 718b21ea..54750aaf 100644 --- a/spec/ttfunk/table/head_spec.rb +++ b/spec/ttfunk/table/head_spec.rb @@ -21,8 +21,8 @@ expect( described_class.to_long_date_time( - described_class.from_long_date_time(time) - ) + described_class.from_long_date_time(time), + ), ).to eq time end end diff --git a/spec/ttfunk/table/loca_spec.rb b/spec/ttfunk/table/loca_spec.rb index d77ff2de..bffd2071 100644 --- a/spec/ttfunk/table/loca_spec.rb +++ b/spec/ttfunk/table/loca_spec.rb @@ -12,7 +12,7 @@ expect(result[:table].bytes).to eq [ 0x00, 0x00, 0x00, 0x01, - 0x00, 0x02 + 0x00, 0x02, ] end @@ -22,7 +22,7 @@ expect(result[:type]).to eq(0) expect(result[:table].bytes).to eq [ 0x00, 0x00, - 0xFF, 0xFF + 0xFF, 0xFF, ] end @@ -33,7 +33,7 @@ expect(result[:table].bytes).to eq [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x03 + 0x00, 0x00, 0x00, 0x03, ] end @@ -43,7 +43,7 @@ expect(result[:type]).to eq(1) expect(result[:table].bytes).to eq [ 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0xFF, 0xFF + 0x00, 0x01, 0xFF, 0xFF, ] end end diff --git a/spec/ttfunk/table/os2_spec.rb b/spec/ttfunk/table/os2_spec.rb index d2d6feea..a7ff11bb 100644 --- a/spec/ttfunk/table/os2_spec.rb +++ b/spec/ttfunk/table/os2_spec.rb @@ -31,7 +31,7 @@ let(:font_path) { test_font('DejaVuSans') } let(:font) { TTFunk::File.open(font_path) } - let(:expected_fields) do # rubocop: disable Metrics/BlockLength + let(:expected_fields) do { version: 1, ave_char_width: 1038, @@ -67,12 +67,12 @@ cap_height: nil, default_char: nil, break_char: nil, - max_context: nil + max_context: nil, } end let(:error_message) do - <<-ERROR_MESSAGE + <<~ERROR_MESSAGE field: %s expected: %s got: %s @@ -80,13 +80,11 @@ end def build_error_message(field, expected_value, actual_value) - strip_leading_spaces( - format( - error_message, - field: field, - expected_value: expected_value, - actual_value: actual_value - ) + format( + error_message, + field: field, + expected_value: expected_value, + actual_value: actual_value, ) end @@ -96,7 +94,7 @@ def build_error_message(field, expected_value, actual_value) actual_value = actual_value.value if actual_value.respond_to?(:value) expect(actual_value).to( eq(expected_value), - build_error_message(field, expected_value, actual_value) + build_error_message(field, expected_value, actual_value), ) end end @@ -108,16 +106,17 @@ def build_error_message(field, expected_value, actual_value) TTFunk::BitField.new( TTFunk::BinUtils.stitch_int( encoded[code_page_range_field_indices].unpack('N*'), - bit_width: 32 - ) + bit_width: 32, + ), ) end let(:char_range) do TTFunk::BitField.new( TTFunk::BinUtils.stitch_int( - encoded[char_range_field_indices].unpack('N*'), bit_width: 32 - ) + encoded[char_range_field_indices].unpack('N*'), + bit_width: 32, + ), ) end @@ -127,9 +126,7 @@ def build_error_message(field, expected_value, actual_value) it 'roundtrips correctly' do original_unicode_map.each_key { |char| subset.use(char) } - reconstituted = described_class.new( - TestFile.new(StringIO.new(encoded)) - ) + reconstituted = described_class.new(TestFile.new(StringIO.new(encoded))) skipped_fields = %i[char_range code_page_range] expected_fields.each do |field, expected_value| @@ -140,9 +137,7 @@ def build_error_message(field, expected_value, actual_value) expect(actual_value).to( eq(expected_value), - build_error_message( - field, expected_value, actual_value - ) + build_error_message(field, expected_value, actual_value), ) end @@ -161,13 +156,11 @@ def build_error_message(field, expected_value, actual_value) curr_symbols, shapes, ogham, - old_italic + old_italic, ] char_range_bits.each do |bit| - expect(reconstituted.char_range.on?(bit)).to( - eq(true), build_error_message(bit, true, false) - ) + expect(reconstituted.char_range.on?(bit)).to(be(true), build_error_message(bit, true, false)) end end @@ -179,11 +172,11 @@ def build_error_message(field, expected_value, actual_value) end end - expect(char_range.on?(greek)).to eq(false) - expect(char_range.on?(armenian)).to eq(true) - expect(char_range.on?(hebrew)).to eq(false) - expect(char_range.on?(shapes)).to eq(true) - expect(char_range.on?(old_italic)).to eq(false) + expect(char_range.on?(greek)).to be false + expect(char_range.on?(armenian)).to be true + expect(char_range.on?(hebrew)).to be false + expect(char_range.on?(shapes)).to be true + expect(char_range.on?(old_italic)).to be false end end @@ -192,9 +185,7 @@ def build_error_message(field, expected_value, actual_value) let(:mac_roman_code_page_bit) { 29 } before do - mapping = TTFunk::Subset::CodePage.unicode_mapping_for( - Encoding::MACROMAN - ) + mapping = TTFunk::Subset::CodePage.unicode_mapping_for(Encoding::MACROMAN) mapping.each_value { |code_point| subset.use(code_point) } end @@ -204,7 +195,7 @@ def build_error_message(field, expected_value, actual_value) end it 'sets the correct code page bit' do - expect(code_page_range.on?(mac_roman_code_page_bit)).to eq(true) + expect(code_page_range.on?(mac_roman_code_page_bit)).to be true end end @@ -213,9 +204,7 @@ def build_error_message(field, expected_value, actual_value) let(:windows_1252_code_page_bit) { 0 } before do - mapping = TTFunk::Subset::CodePage.unicode_mapping_for( - Encoding::CP1252 - ) + mapping = TTFunk::Subset::CodePage.unicode_mapping_for(Encoding::CP1252) mapping.each_value { |code_point| subset.use(code_point) } end @@ -225,7 +214,7 @@ def build_error_message(field, expected_value, actual_value) end it 'sets the correct code page bit' do - expect(code_page_range.on?(windows_1252_code_page_bit)).to eq(true) + expect(code_page_range.on?(windows_1252_code_page_bit)).to be true end end end diff --git a/spec/ttfunk/table/vorg_spec.rb b/spec/ttfunk/table/vorg_spec.rb index d2399f5d..b803ebf3 100644 --- a/spec/ttfunk/table/vorg_spec.rb +++ b/spec/ttfunk/table/vorg_spec.rb @@ -12,10 +12,7 @@ describe '#origins' do it 'includes origins for certain chars traditionally written vertically' do - code_points = - %w[〱 0 1 2 3 4 5 6 7 8 9].map do |c| - c.unpack1('U*') - end + code_points = %w[〱 0 1 2 3 4 5 6 7 8 9].map { |c| c.unpack1('U*') } glyph_ids = code_points.map { |cp| cmap[cp] } glyph_ids.each { |glyph_id| expect(origins).to include(glyph_id) } @@ -26,17 +23,13 @@ it 'finds the vertical origin when explicitly available' do glyph_id = cmap['〱'.unpack1('U*')] expect(vorg_table.origins).to include(glyph_id) - expect(vorg_table.for(glyph_id)).to_not( - eq(vorg_table.default_vert_origin_y) - ) + expect(vorg_table.for(glyph_id)).to_not eq(vorg_table.default_vert_origin_y) end it 'falls back to the default vertical origin' do glyph_id = cmap['ろ'.unpack1('U*')] expect(vorg_table.origins).to_not include(glyph_id) - expect(vorg_table.for(glyph_id)).to( - eq(vorg_table.default_vert_origin_y) - ) + expect(vorg_table.for(glyph_id)).to eq(vorg_table.default_vert_origin_y) end end @@ -60,9 +53,7 @@ end it 'includes the same default vertical origin' do - expect(reconstituted.default_vert_origin_y).to( - eq(vorg_table.default_vert_origin_y) - ) + expect(reconstituted.default_vert_origin_y).to eq(vorg_table.default_vert_origin_y) end end end diff --git a/spec/ttfunk/ttf_encoder_spec.rb b/spec/ttfunk/ttf_encoder_spec.rb index 64d2c660..07044d36 100644 --- a/spec/ttfunk/ttf_encoder_spec.rb +++ b/spec/ttfunk/ttf_encoder_spec.rb @@ -54,7 +54,7 @@ tables.each_cons(2) do |first_table, second_table| expect(new_font.directory.tables[first_table][:offset]).to( - be < new_font.directory.tables[second_table][:offset] + be < new_font.directory.tables[second_table][:offset], ) end end diff --git a/ttfunk.gemspec b/ttfunk.gemspec index e4e1d2a4..7ae51f2e 100644 --- a/ttfunk.gemspec +++ b/ttfunk.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |spec| spec.homepage = 'https://prawnpdf.org' spec.metadata = { - 'rubygems_mfa_required' => 'true' + 'rubygems_mfa_required' => 'true', } signing_key = File.expand_path('~/.gem/gem-private_key.pem') @@ -30,7 +30,7 @@ Gem::Specification.new do |spec| 'Daniel Nelson', 'Jonathan Greenberg', 'James Healy', - 'Cameron Dutro' + 'Cameron Dutro', ] spec.email = [ 'alex@pointless.one', @@ -39,11 +39,11 @@ Gem::Specification.new do |spec| 'dnelson@bluejade.com', 'greenberg@entryway.net', 'jimmy@deefa.com', - 'camertron@gmail.com' + 'camertron@gmail.com', ] spec.files = Dir.glob('lib/**/*') + ['CHANGELOG.md', 'README.md', 'COPYING', 'LICENSE', 'GPLv2', 'GPLv3'] spec.required_ruby_version = '>= 2.7' - spec.add_development_dependency('prawn-dev', '~> 0.3.0') + spec.add_development_dependency('prawn-dev', '~> 0.4.0') end