Code coverage report for fontkit/src/glyph/Glyph.coffee

Statements: 73.77% (45 / 61)      Branches: 62.5% (10 / 16)      Functions: 81.25% (13 / 16)      Lines: 74.58% (44 / 59)      Ignored: none     

All files » fontkit/src/glyph/ » Glyph.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 1111 1 1   1 1     284 284     1     20     6   1 189 168   21       21     168   168     168 21     147   147 147 147             168   1 40   1 7   1     62   1 247   1     1     5 5     5         5 5 2   3               1 6                           1  
Path = require './Path'
unicode = require 'unicode-properties'
StandardNames = require './StandardNames'
 
class Glyph
  get = require('../get')(this)
  constructor: (@id, @codePoints, @_font) ->
    # TODO: get this info from GDEF if available
    @isMark = @codePoints.every unicode.isMark
    @isLigature = @codePoints.length > 1
      
  _getPath: ->
    return new Path
      
  _getCBox: ->
    @path.cbox
    
  _getBBox: ->
    @path.bbox
    
  getMetrics = (table, gid) ->
    if gid < table.metrics.length
      return table.metrics.get gid
      
    res = 
      advance: table.metrics.get(table.metrics.length - 1)?.advance or 0
      bearing: table.bearings.get(gid - table.metrics.length) or 0
      
    return res
    
  _getMetrics: (cbox) ->
    Ireturn @_metrics if @_metrics
      
    {advance:advanceWidth, bearing:leftBearing} = getMetrics @_font.hmtx, @id
    
    # For vertical metrics, use vmtx if available, or fall back to global data from OS/2 or hhea
    if @_font.vmtx
      {advance:advanceHeight, bearing:topBearing} = getMetrics @_font.vmtx, @id
      
    else
      cbox ?= @cbox
      
      Eif (os2 = @_font['OS/2']) and os2.version > 0
        advanceHeight = Math.abs os2.typoAscender - os2.typoDescender
        topBearing = os2.typoAscender - cbox.maxY
    
      else
        hhea = @_font.hhea
        advanceHeight = Math.abs hhea.ascent - hhea.descent
        topBearing = hhea.ascent - cbox.maxY
    
    @_metrics = { advanceWidth, advanceHeight, leftBearing, topBearing }
      
  get 'cbox', ->
    @_cbox ?= @_getCBox()
      
  get 'bbox', ->
    @_bbox ?= @_getBBox()
    
  get 'path', ->
    # Cache the path so we only decode it once
    # Decoding is actually performed by subclasses
    @_path ?= @_getPath()
    
  get 'advanceWidth', ->
    @_advanceWidth ?= @_getMetrics().advanceWidth
    
  get 'advanceHeight', ->
    @_advanceHeight ?= @_getMetrics().advanceHeight
    
  get 'ligatureCaretPositions', ->
    
  _getName: ->
    post = @_font.post
    Iif not post
      return null
      
    switch post.version
      when 1
        StandardNames[@id]
        
      when 2
        id = post.glyphNameIndex[@id]
        if id < StandardNames.length
          StandardNames[id]
        else
          post.names[id - StandardNames.length]
          
      when 2.5
        StandardNames[@id + post.offsets[@id]]
        
      when 4
        String.fromCharCode post.map[@id]
    
  get 'name', ->
    @_name ?= @_getName()
    
  render: (ctx, size) ->
    ctx.save()
    
    scale = 1 / @_font.head.unitsPerEm * size
    ctx.scale(scale, scale)
 
    fn = @path.toFunction()
    fn(ctx)
    ctx.fill()
    
    ctx.restore()
    
module.exports = Glyph