all files / fontkit/src/ CFFFont.coffee

80.33% Statements 49/61
70% Branches 14/20
76.92% Functions 10/13
85.45% Lines 47/55
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                     48×                                 18× 10×     146×                           41×   41× 18× 23× 16×           30×   25×    
r = require 'restructure'
CFFIndex = require './cff/CFFIndex'
CFFTop = require './cff/CFFTop'
CFFPrivateDict = require './cff/CFFPrivateDict'
standardStrings = require './cff/CFFStandardStrings'
  
class CFFFont
  get = require('./get')(this)
  constructor: (@stream) ->
    @decode()
  
  @decode: (stream) ->
    return new CFFFont(stream)
    
  @open: (filename, name) ->
    contents = require?('fs').readFileSync filename
    return new CFFFont new r.DecodeStream(contents)  
      
  decode: ->
    start = @stream.pos
    top = CFFTop.decode(@stream)
    for key, val of top
      this[key] = val
    
    Iif @topDictIndex.length isnt 1
      throw new Error "Only a single font is allowed in CFF"
      
    @isCIDFont = @topDict.ROS?
      
    # if @topDict.CharstringType isnt 2
    #   throw new Error "Only CharstringType 2 is supported"
      
    # charset?
    switch @topDictIndex[0].Encoding
      when 0 # standard encoding
        break
      when 1 # expert encoding
        break
      else # custom
        break
    
    return this
  
  string: (sid) ->
    if sid <= standardStrings.length
      return standardStrings[sid]
    
    return @stringIndex[sid - standardStrings.length]
    
  get 'topDict', ->
    return @topDictIndex[0]
      
  get 'postscriptName', ->
    return @nameIndex[0]
    
  get 'fullName', ->
    return @string @topDict.FullName
    
  get 'familyName', ->
    return @string @topDict.FamilyName
    
  getCharString: (glyph) ->
    @stream.pos = @topDict.CharStrings[glyph].offset
    return @stream.readBuffer @topDict.CharStrings[glyph].length
    
  fdForGlyph: (gid) ->
    Ireturn null unless @topDict.FDSelect
    
    switch @topDict.FDSelect.version
      when 0
        return @topDict.FDSelect.fds[gid]
      when 3
        ranges = @topDict.FDSelect.ranges
        low = 0
        high = ranges.length - 1
      
        while low <= high
          mid = (low + high) >> 1
        
          if gid < ranges[mid].first
            high = mid - 1
          else if gid > ranges[mid + 1]?.first
            low = mid + 1
          else
            return ranges[mid].fd
      else
        throw new Error "Unknown FDSelect version: #{@topDict.FDSelect.version}"
    
  privateDictForGlyph: (gid) ->
    if @topDict.FDSelect
      fd = @fdForGlyph gid
      return Eif fd? then @topDict.FDArray[fd]?.Private else null
      
    return @topDict.Private
 
module.exports = CFFFont