Module: HexaPDF::Font::TrueType::Table::CmapSubtable::Format4

Defined in:
lib/hexapdf/font/true_type/table/cmap_subtable.rb

Overview

Cmap format 4

Class Method Summary collapse

Class Method Details

.mapper(end_codes, start_codes, id_deltas, id_range_offsets, glyph_indexes) ⇒ Object

:nodoc:



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/hexapdf/font/true_type/table/cmap_subtable.rb', line 282

def self.mapper(end_codes, start_codes, id_deltas, id_range_offsets, glyph_indexes)
  compute_glyph_id = lambda do |index, code|
    offset = id_range_offsets[index]
    if offset == 0
      glyph_id = (code + id_deltas[index]) % 65536
    else
      glyph_id = glyph_indexes[offset - end_codes.length + (code - start_codes[index])]
      glyph_id ||= 0 # Handle invalid subtable entries
      glyph_id = (glyph_id + id_deltas[index]) % 65536 if glyph_id != 0
    end
    glyph_id
  end

  code_map = Hash.new do |h, code|
    i = end_codes.bsearch_index {|c| c >= code }
    glyph_id = (i && start_codes[i] <= code ? compute_glyph_id.call(i, code) : 0)
    h[code] = glyph_id unless glyph_id == 0
  end

  gid_map = {}
  end_codes.length.times do |i|
    start_codes[i].upto(end_codes[i]) do |code|
      gid_map[compute_glyph_id.call(i, code)] = code
    end
  end
  [code_map, gid_map]
end

.parse(io, length) ⇒ Object

:call-seq:

Format4.parse(io, length)    -> code_map

Parses the format 4 cmap subtable from the given IO at the current position and returns the contained code map.

It is assumed that the first six bytes of the subtable have already been consumed.



267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/hexapdf/font/true_type/table/cmap_subtable.rb', line 267

def self.parse(io, length)
  seg_count_x2 = io.read(8).unpack1('n')
  end_codes = io.read(seg_count_x2).unpack('n*')
  io.pos += 2
  start_codes = io.read(seg_count_x2).unpack('n*')
  id_deltas = io.read(seg_count_x2).unpack('n*')
  id_range_offsets = io.read(seg_count_x2).unpack('n*').map!.with_index do |offset, idx|
    # Change offsets to indexes, starting from the id_range_offsets array
    offset == 0 ? offset : offset / 2 + idx
  end
  glyph_indexes = io.read(length - 16 - seg_count_x2 * 4).unpack('n*')
  mapper(end_codes, start_codes, id_deltas, id_range_offsets, glyph_indexes)
end