Class: Pdfrb::Font::CFF::Dict

Inherits:
Object
  • Object
show all
Defined in:
lib/pdfrb/font/cff/dict.rb

Overview

DICT data parsing (TN5176 s4): a sequence of operands (from the b0 byte ranges) followed by an operator byte.

Used both to READ the Top DICT (CharStrings offset, Private [size offset], charset) and to locate operator positions so a subsetter can patch offsets in place.

Defined Under Namespace

Classes: Entry

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(raw, entries) ⇒ Dict

Returns a new instance of Dict.



87
88
89
90
# File 'lib/pdfrb/font/cff/dict.rb', line 87

def initialize(raw, entries)
  @raw = raw
  @entries = entries
end

Instance Attribute Details

#entriesObject (readonly)

Returns the value of attribute entries.



22
23
24
# File 'lib/pdfrb/font/cff/dict.rb', line 22

def entries
  @entries
end

#rawObject (readonly)

Returns the value of attribute raw.



22
23
24
# File 'lib/pdfrb/font/cff/dict.rb', line 22

def raw
  @raw
end

Class Method Details

.parse(data) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/pdfrb/font/cff/dict.rb', line 24

def self.parse(data)
  entries = []
  operands = []
  pos = 0
  entry_start = 0
  while pos < data.bytesize
    b0 = data.getbyte(pos)
    case b0
    when 28 then operands << data.byteslice(pos + 1, 2).unpack1("n")
                 pos += 3
    when 29 then operands << data.byteslice(pos + 1, 4).unpack1("N")
                 pos += 5
    when 30
      real, pos = parse_real(data, pos + 1)
      operands << real
    when 32..246
      operands << (b0 - 139)
      pos += 1
    when 247..250
      operands << (((b0 - 247) * 256) + data.getbyte(pos + 1) + 108)
      pos += 2
    when 251..254
      operands << ((-(b0 - 251) * 256) - data.getbyte(pos + 1) - 108)
      pos += 2
    else
      # Operator (0..21, with 12 x for two-byte ops).
      if b0 == 12
        op = [12, data.getbyte(pos + 1)]
        pos += 2
      else
        op = b0
        pos += 1
      end
      entries << Entry.new(op, operands, entry_start, pos)
      operands = []
      entry_start = pos
    end
  end
  new(data, entries)
end

.parse_real(data, pos) ⇒ Object

Real operand (b0 30): nibble-encoded decimal terminated by 0xF. Returns [Float, next_pos].



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/pdfrb/font/cff/dict.rb', line 70

def self.parse_real(data, pos)
  buf = +""
  while pos < data.bytesize
    nibble_pair = data.getbyte(pos)
    pos += 1
    hi = nibble_pair >> 4
    lo = nibble_pair & 0xF
    break if hi == 0xF

    buf << NIBBLE_CHARS[hi]
    break if lo == 0xF

    buf << NIBBLE_CHARS[lo]
  end
  [buf.to_f, pos]
end

Instance Method Details

#charset_offsetObject

Top DICT helpers (operator numbers per TN5176 Table 6):

15 charset, 17 CharStrings, 18 Private [size offset].


100
101
102
# File 'lib/pdfrb/font/cff/dict.rb', line 100

def charset_offset
  entry_for(15)&.int_operand
end

#charstrings_offsetObject



104
105
106
# File 'lib/pdfrb/font/cff/dict.rb', line 104

def charstrings_offset
  entry_for(17)&.int_operand
end

#entry_for(operator) ⇒ Object

Entry for a one-byte Integer operator or a two-byte [12, x] operator.



94
95
96
# File 'lib/pdfrb/font/cff/dict.rb', line 94

def entry_for(operator)
  entries.find { |e| e.operator == operator }
end

#private_size_offsetObject

Returns [size, offset].



109
110
111
112
113
114
# File 'lib/pdfrb/font/cff/dict.rb', line 109

def private_size_offset
  e = entry_for(18)
  return nil unless e

  [e.int_operand(0), e.int_operand(1)]
end