Module: HexaPDF::Font::TrueType::Table::CmapSubtable::Format2

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

Overview

Cmap format 2

Defined Under Namespace

Classes: SubHeader

Class Method Summary collapse

Class Method Details

.mapper(sub_header_keys, sub_headers, glyph_indexes) ⇒ Object

:nodoc:



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/hexapdf/font/true_type/table/cmap_subtable.rb', line 231

def self.mapper(sub_header_keys, sub_headers, glyph_indexes) #:nodoc:
  Hash.new do |h, code|
    i = code
    i, j = i.divmod(256) if code > 255
    k = sub_header_keys[i]
    if !k
      glyph_id = 0
    elsif k > 0
      sub_header = sub_headers[k]
      raise HexaPDF::Error, "Second byte of character code missing" if j.nil?
      j -= sub_header.first_code
      if 0 <= j && j < sub_header.entry_count
        glyph_id = glyph_indexes[sub_header.first_glyph_index + j]
        glyph_id = (glyph_id + sub_header.id_delta) % 65536 if glyph_id != 0
      else
        glyph_id = 0
      end
    else
      glyph_id = glyph_indexes[i]
    end
    h[code] = glyph_id unless glyph_id == 0
  end
end

.parse(io, length) ⇒ Object

:call-seq:

Format2.parse(io, length)    -> code_map

Parses the format 2 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.



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/hexapdf/font/true_type/table/cmap_subtable.rb', line 199

def self.parse(io, length)
  sub_header_keys = io.read(512).unpack('n*')
  nr_sub_headers = 0
  sub_header_keys.map! do |key|
    nr_sub_headers = key if key > nr_sub_headers
    key / 8
  end
  nr_sub_headers = 1 + nr_sub_headers / 8

  sub_headers = []
  nr_sub_headers.times do |i|
    h = SubHeader.new(*io.read(8).unpack('n2s>n'))
    # Map the currently stored id_range_offset to the corresponding glyph index by first
    # changing the offset to begin from the position of the first glyph index and then
    # halfing the value since each glyph is a UInt16.
    h.first_glyph_index = (h.first_glyph_index - 2 - 8 * (nr_sub_headers - i - 1)) / 2
    sub_headers << h
  end
  glyph_indexes = io.read(length - 6 - 512 - 8 * nr_sub_headers).unpack('n*')

  gid_map = {}
  sub_headers.each_with_index do |sub_header, i|
    sub_header.entry_count.times do |j|
      glyph_id = glyph_indexes[sub_header.first_glyph_index + j]
      glyph_id = (glyph_id + sub_header.id_delta) % 65536 if glyph_id != 0
      gid_map[glyph_id] = (sub_header_keys.index(i) << 8) + j + sub_header.first_code
    end
  end

  [mapper(sub_header_keys, sub_headers, glyph_indexes), gid_map]
end