Class: Fontisan::Tables::Cff2::DictEncoder

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/tables/cff2/dict_encoder.rb

Overview

Encodes CFF2 DICT data: sequences of (operands, operator) pairs.

CFF2 DICTs use the same operand encoding as CFF1:

32..246  → integer  (value = b0 - 139, range -107..107)
247..250 → integer  (positive, 2 bytes, range 108..1131)
251..254 → integer  (negative, 2 bytes, range -1131..-108)
28       → integer  (3 bytes, range -32768..32767)
29       → integer  (5 bytes, full int32)
30       → real     (BCD nibble encoding)

Operators are 1 byte (0..21) or 2 bytes (12, xx) for escapes.

Class Method Summary collapse

Class Method Details

.encode_entry(operands, operator) ⇒ String

Encode a DICT entry: operands followed by operator.

Parameters:

  • operands (Array<Integer, Float>)
  • operator (Integer, Array<Integer>)

    1-byte or [12, xx] 2-byte

Returns:

  • (String)


57
58
59
60
61
62
63
64
# File 'lib/fontisan/tables/cff2/dict_encoder.rb', line 57

def self.encode_entry(operands, operator)
  io = +""
  operands.each do |operand|
    io << (operand.is_a?(Float) ? encode_real(operand) : encode_integer(operand.to_i))
  end
  io << encode_operator(operator)
  io
end

.encode_integer(value) ⇒ String

Encode a single integer operand.

Parameters:

  • value (Integer)

Returns:

  • (String)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/fontisan/tables/cff2/dict_encoder.rb', line 21

def self.encode_integer(value)
  case value
  when -107..107
    [value + 139].pack("C")
  when 108..1131
    v = value - 108
    [(v >> 8) + 247, v & 0xFF].pack("CC")
  when -1131..-108
    v = -value - 108
    [(-(v >> 8)) + 251, -(v & 0xFF) & 0xFF].pack("CC")
  when -32768..32767
    [28, value].pack("Cn")
  else
    [29, value].pack("CN") # 29 + 4-byte signed int (big-endian)
  end
end

.encode_operator(operator) ⇒ String

Parameters:

  • operator (Integer, Array<Integer>)

Returns:

  • (String)


68
69
70
# File 'lib/fontisan/tables/cff2/dict_encoder.rb', line 68

def self.encode_operator(operator)
  operator.is_a?(Array) ? operator.pack("C*") : [operator].pack("C")
end

.encode_real(value) ⇒ String

Encode a real number operand using BCD nibble encoding.

Parameters:

  • value (Float)

Returns:

  • (String)


41
42
43
44
45
46
47
48
49
50
51
# File 'lib/fontisan/tables/cff2/dict_encoder.rb', line 41

def self.encode_real(value)
  nibbles = real_to_nibbles(value)
  nibbles << 0x0F # end-of-number marker
  nibbles << 0x0F if nibbles.size.odd? # pad to even

  io = +""
  nibbles.each_slice(2) do |high, low|
    io << [(high << 4) | (low & 0x0F)].pack("C")
  end
  [30].pack("C") + io # prefix with operator byte 30
end