all files / fontkit/src/cff/ CFFIndex.coffee

80.77% Statements 63/78
48.28% Branches 14/29
100% Functions 5/5
87.5% Lines 56/64
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100       66× 66×   66× 66× 28× 30×       66× 66×   66× 66× 153793×   153793× 8646× 8646×   8646× 8646× 8646×   145147×       153793×   66× 66×     72× 72×   72×     72× 72× 233712×   72× 39×         72× 72×   72×     15× 15×   15×     15× 15× 15× 16659× 16659× 16659×   15×           15×     15× 15×   15× 16659× 16659×   15× 16659×   15×    
r = require 'restructure'
 
class CFFIndex
  constructor: (@type) ->
  decode: (stream, parent) ->
    count = stream.readUInt16BE()
    Ireturn [] if count is 0
    
    offSize = stream.readUInt8()
    offsetType = switch offSize
      when 1 then r.uint8
      when 2 then r.uint16
      when 3 then r.uint24
      when 4 then r.uint32
      else throw new Error "Bad offset size in CFFIndex: " + offSize + " " + stream.pos
      
    ret = []
    startPos = stream.pos + ((count + 1) * offSize) - 1
    
    start = offsetType.decode(stream)
    for i in [0...count] by 1
      end = offsetType.decode(stream)
      
      if @type?
        pos = stream.pos
        stream.pos = startPos + start
                
        parent.length = end - start
        ret.push @type.decode(stream, parent)
        stream.pos = pos
      else
        ret.push
          offset: startPos + start
          length: end - start
          
      start = end
    
    stream.pos = startPos + start
    return ret
    
  size: (arr, parent) ->
    size = 2
    Ireturn size if arr.length is 0
    
    type = @type or new r.Buffer
    
    # find maximum offset to detminine offset type
    offset = 1
    for item in arr
      offset += type.size(item, parent)
    
    offsetType = if offset <= 0xff  then r.uint8
    else Eif offset <= 0xffff        then r.uint16
    else if offset <= 0xffffff      then r.uint24
    else if offset <= 0xffffffff    then r.uint32
    else throw new Error "Bad offset in CFFIndex"
    
    size += 1 + offsetType.size() * (arr.length + 1)
    size += offset - 1
 
    return size
  
  encode: (stream, arr, parent) ->
    stream.writeUInt16BE(arr.length)
    Ireturn if arr.length is 0
    
    type = @type or new r.Buffer
    
    # find maximum offset to detminine offset type
    sizes = []
    offset = 1
    for item in arr
      s = type.size(item, parent)
      sizes.push s
      offset += s
    
    offsetType = if offset <= 0xff  then r.uint8
    else Eif offset <= 0xffff        then r.uint16
    else if offset <= 0xffffff      then r.uint24
    else if offset <= 0xffffffff    then r.uint32
    else throw new Error "Bad offset in CFFIndex"
      
    # write offset size
    stream.writeUInt8(offsetType.size())
    
    # write elements
    offset = 1
    offsetType.encode(stream, offset)
    
    for item, i in arr
      offset += sizes[i]
      offsetType.encode(stream, offset)
      
    for item in arr
      type.encode(stream, item, parent)
      
    return
    
module.exports = CFFIndex