Code coverage report for fontkit/src/tables/aat.coffee

Statements: 81.03% (47 / 58)      Branches: 100% (2 / 2)      Functions: 78.26% (18 / 23)      Lines: 88.46% (46 / 52)      Ignored: none     

All files » fontkit/src/tables/ » aat.coffee
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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 1301   1   27   1   96 96     1829 198 198 198 198   1829           96   1   1   12     1217 1217     45 45           12   12             12         12     263   12       12         13     22     9           1 4       4 5   4 96   4           4     1 1         1           1     1 1   1           1  
r = require 'restructure'
 
class UnboundedArray extends r.Array
  constructor: (@type) ->
    @length = 0
    
  class UnboundedArrayAccessor
    constructor: (@type, @stream, @parent) ->
      @base = @stream.pos
      @_items = []
      
    getItem: (index) ->
      unless @_items[index]?
        pos = @stream.pos
        @stream.pos = @base + @type.size(null, @parent) * index
        @_items[index] = @type.decode @stream, @parent
        @stream.pos = pos
        
      return @_items[index]
      
    inspect: ->
      return "[UnboundedArray #{@type.constructor.name}]"
      
  decode: (stream, parent) ->
    return new UnboundedArrayAccessor @type, stream, parent
 
exports.UnboundedArray = UnboundedArray
 
exports.LookupTable = LookupTable = (ValueType = r.uint16) ->
  # Helper class that makes internal structures invisible to pointers
  class Shadow
    constructor: (@type) ->
    decode: (stream, ctx) ->
      ctx = ctx.parent.parent
      return @type.decode stream, ctx
    
    size: (val, ctx) ->
      ctx = ctx.parent.parent
      return @type.size val, ctx
    
    encode: (stream, val, ctx) ->
      ctx = ctx.parent.parent
      @type.encode stream, val, ctx
  
  ValueType = new Shadow ValueType
  
  BinarySearchHeader = new r.Struct
    unitSize: r.uint16
    nUnits: r.uint16
    searchRange: r.uint16
    entrySelector: r.uint16
    rangeShift: r.uint16
  
  LookupSegmentSingle = new r.Struct
    lastGlyph: r.uint16
    firstGlyph: r.uint16
    value: ValueType
  
  LookupSegmentArray = new r.Struct
    lastGlyph: r.uint16
    firstGlyph: r.uint16
    values: new r.Pointer(r.uint16, new r.Array(ValueType, -> @lastGlyph - @firstGlyph + 1), type: 'parent')
  
  LookupSingle = new r.Struct
    glyph: r.uint16
    value: ValueType
  
  return new r.VersionedStruct r.uint16,
    0:
      values: new UnboundedArray(ValueType) # length == number of glyphs maybe?
    2:
      binarySearchHeader: BinarySearchHeader
      segments: new r.Array(LookupSegmentSingle, -> @binarySearchHeader.nUnits)
    4:
      binarySearchHeader: BinarySearchHeader
      segments: new r.Array(LookupSegmentArray, -> @binarySearchHeader.nUnits)
    6:
      binarySearchHeader: BinarySearchHeader
      segments: new r.Array(LookupSingle, -> @binarySearchHeader.nUnits)
    8:
      firstGlyph: r.uint16
      count: r.uint16
      values: new r.Array(ValueType, 'count')
 
exports.StateTable = (entryData = {}, lookupType = r.uint16) ->  
  entry = 
    newState: r.uint16
    flags: r.uint16
    
  for key, val of entryData
    entry[key] = val
    
  Entry = new r.Struct entry
  StateArray = new UnboundedArray(new r.Array(r.uint16, -> @nClasses))
 
  StateHeader = new r.Struct
    nClasses: r.uint32
    classTable: new r.Pointer(r.uint32, new LookupTable(lookupType))
    stateArray: new r.Pointer(r.uint32, StateArray)
    entryTable: new r.Pointer(r.uint32, new UnboundedArray(Entry))
    
  return StateHeader
  
# This is the old version of the StateTable structure
exports.StateTable1 = (entryData = {}, lookupType = r.uint16) ->
  ClassLookupTable = new r.Struct
    version: -> 8 # simulate LookupTable
    firstGlyph: r.uint16
    values: new r.Array(r.uint8, r.uint16)
    
  entry = 
    newStateOffset: r.uint16
    # convert offset to stateArray index
    newState: -> (@newStateOffset - (@parent.stateArray.base - @parent._startOffset)) / @parent.nClasses
    flags: r.uint16
    
  for key, val of entryData
    entry[key] = val
    
  Entry = new r.Struct entry
  StateArray = new UnboundedArray(new r.Array(r.uint8, -> @nClasses))
 
  StateHeader1 = new r.Struct
    nClasses: r.uint16
    classTable: new r.Pointer(r.uint16, ClassLookupTable)
    stateArray: new r.Pointer(r.uint16, StateArray)
    entryTable: new r.Pointer(r.uint16, new UnboundedArray(Entry))
    
  return StateHeader1