class TTFunk::Table::Cff::Index

Attributes

count[R]

number of objects in the index

data_start_pos[R]
offset_size[R]

offset array element size

offsets[R]
raw_data[R]
raw_offset_length[R]

Public Instance Methods

[](index) click to toggle source
# File lib/ttfunk/table/cff/index.rb, line 18
def [](index)
  entry_cache[index] ||= raw_data[
    offsets[index]...offsets[index + 1]
  ]
end
each() { |self| ... } click to toggle source
# File lib/ttfunk/table/cff/index.rb, line 24
def each
  return to_enum(__method__) unless block_given?

  count.times { |i| yield self[i] }
end
encode() { |entry, index| ... } click to toggle source
# File lib/ttfunk/table/cff/index.rb, line 30
def encode
  result = EncodedString.new

  entries =
    each_with_object([]).with_index do |(entry, ret), index|
      new_entry = block_given? ? yield(entry, index) : entry
      ret << new_entry if new_entry
    end

  # "An empty INDEX is represented by a count field with a 0 value and
  # no additional fields. Thus, the total size of an empty INDEX is 2
  # bytes."
  result << [entries.size].pack('n')
  return result if entries.empty?

  offset_size = (Math.log2(entries.size) / 8.0).round + 1
  result << [offset_size].pack('C')
  data_offset = 1

  data = EncodedString.new

  entries.each do |entry|
    result << encode_offset(data_offset, offset_size)
    data << entry
    data_offset += entry.length
  end

  unless entries.empty?
    result << encode_offset(data_offset, offset_size)
  end

  result << data
end

Private Instance Methods

absolute_offsets_for(index) click to toggle source
# File lib/ttfunk/table/cff/index.rb, line 70
def absolute_offsets_for(index)
  [
    table_offset + offsets[index] + data_start_pos,
    table_offset + offsets[index + 1] + data_start_pos
  ]
end
encode_offset(offset, offset_size) click to toggle source
# File lib/ttfunk/table/cff/index.rb, line 77
def encode_offset(offset, offset_size)
  case offset_size
  when 1
    [offset].pack('C')
  when 2
    [offset].pack('n')
  when 3
    [offset].pack('N')[1..-1]
  when 4
    [offset].pack('N')
  end
end
entry_cache() click to toggle source
# File lib/ttfunk/table/cff/index.rb, line 66
def entry_cache
  @entry_cache ||= {}
end
parse!() click to toggle source
# File lib/ttfunk/table/cff/index.rb, line 90
def parse!
  @count = read(2, 'n').first

  if count.zero?
    @length = 2
    @data = []
    return
  end

  @offset_size = read(1, 'C').first

  # read an extra offset_size bytes to get rid of the first offset,
  # which is always 1
  io.read(offset_size)

  @raw_offset_length = count * offset_size
  raw_offsets = io.read(raw_offset_length)

  @offsets = [0] + Array.new(count) do |idx|
    start = offset_size * idx
    finish = offset_size * (idx + 1)
    unpack_offset(raw_offsets[start...finish]) - 1
  end

  @raw_data = io.read(offsets.last)
  @data_start_pos = 3 + offset_size + raw_offset_length
  @length = data_start_pos + raw_data.size
end
unpack_offset(offset_data) click to toggle source
# File lib/ttfunk/table/cff/index.rb, line 119
def unpack_offset(offset_data)
  padding = "\x00" * (4 - offset_size)
  (padding + offset_data).unpack1('N')
end