Code coverage report for fontkit/src/CmapProcessor.coffee

Statements: 77.63% (59 / 76)      Branches: 58.82% (20 / 34)      Functions: 100% (4 / 4)      Lines: 75% (51 / 68)      Ignored: none     

All files » fontkit/src/ » CmapProcessor.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 1211   21       21   37 9 9     12 12 12 12         327 327         197 197 197 816   816 345 471 275   196 196 128   68 68 68 68   196   1                 130 130 130 1467 1467   1467 728 739 609   130 130                         2 1   1 1         1 1 88 88   1                                         1   1  
class CmapProcessor
  constructor: (cmapTable) ->
    @_characterSet = null
    
    # find the unicode cmap
    # check for a 32-bit cmap first
    for cmap in cmapTable.tables
      # unicode or windows platform
      if (cmap.platformID is 0 and cmap.encodingID in [4, 6]) or (cmap.platformID is 3 and cmap.encodingID is 10)
         @cmap = cmap.table
         return
       
    # try "old" 16-bit cmap
    for cmap in cmapTable.tables
      Eif cmap.platformID is 0 or (cmap.platformID is 3 and cmap.encodingID is 1)
        @cmap = cmap.table
        return
      
    throw new Error "Could not find a unicode cmap"
    
  lookup: (codepoint) ->
    cmap = @cmap
    switch cmap.version
      when 0
        return cmap.codeMap.get(codepoint) or 0
        
      when 4
        min = 0
        max = cmap.segCount - 1
        while min <= max
          mid = (min + max) >> 1
          
          if codepoint < cmap.startCode.get(mid)
            max = mid - 1
          else if codepoint > cmap.endCode.get(mid)
            min = mid + 1
          else
            rangeOffset = cmap.idRangeOffset.get(mid)
            if rangeOffset is 0
              gid = codepoint + cmap.idDelta.get(mid)
            else
              index = rangeOffset / 2 + (codepoint - cmap.startCode.get(mid)) - (cmap.segCount - mid)
              gid = cmap.glyphIndexArray.get(index) or 0
              Eunless gid is 0
                gid += cmap.idDelta.get(mid)
                
            return gid & 0xffff
        
        return 0
        
      when 8
        throw new Error 'TODO: cmap format 8'
            
      when 6, 10
        return cmap.glyphIndices.get(codepoint - cmap.firstCode) or 0
        
      when 12, 13
        min = 0
        max = cmap.nGroups - 1
        while min <= max
          mid = (min + max) >> 1
          group = cmap.groups.get(mid)
          
          if codepoint < group.startCharCode
            max = mid - 1
          else if codepoint > group.endCharCode
            min = mid + 1
          else
            Eif cmap.version is 12
              return group.glyphID + (codepoint - group.startCharCode)
            else
              return group.glyphID
              
        return 0
        
      when 14
        throw new Error 'TODO: cmap format 14'
        
      else
        throw new Error 'Unknown cmap format ' + cmap.version
    
  getCharacterSet: ->
    if @_characterSet
      return @_characterSet
      
    cmap = @cmap
    switch cmap.version
      when 0
        @_characterSet = [0...cmap.codeMap.length]
          
      when 4
        res = []
        for tail, i in cmap.endCode.toArray()
          start = cmap.startCode.get(i)
          res.push [start..tail]...
          
        @_characterSet = res
      
      when 8
        throw new Error 'TODO: cmap format 8'
        
      when 6, 10
        @_characterSet = [cmap.firstCode...cmap.firstCode + cmap.glyphIndices.length]
        
      when 12, 13
        res = []
        for group in cmap.groups.toArray()
          res.push [group.startCharCode..group.endCharCode]...
          
        @_characterSet = res
        
      when 14
        throw new Error 'TODO: cmap format 14'
        
      else
        throw new Error 'Unknown cmap format ' + cmap.version
        
    return @_characterSet
 
module.exports = CmapProcessor