Code coverage report for fontkit/src/opentype/ShapingPlan.coffee

Statements: 93.48% (43 / 46)      Branches: 75% (15 / 20)      Functions: 100% (8 / 8)      Lines: 93.33% (42 / 45)      Ignored: none     

All files » fontkit/src/opentype/ » ShapingPlan.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 851             1   19 19 19 19         101 101 396 380 380   101       50 270   50       101 19   101 48   101 82 82 31   19 19 19 19 19             48     48 48       19 205 2803   19       36   36 116     116 116   36   1  
Script = require '../layout/Script'
 
# ShapingPlans are used by the OpenType shapers to store which
# features should by applied, and in what order to apply them.
# The features are applied in groups called stages. A feature
# can be applied globally to all glyphs, or locally to only
# specific glyphs.
class ShapingPlan
  constructor: (@font, @script, @language) ->
    @direction = Script.direction(@script)
    @stages = []
    @globalFeatures = {}
    @allFeatures = {}
    
  # Adds the given features to the last stage.
  # Ignores features that have already been applied.
  _addFeatures: (features) ->
    stage = @stages[@stages.length - 1]
    for feature in features
      unless @allFeatures[feature]
        stage.push feature
        @allFeatures[feature] = true
      
    return
    
  # Adds the given features to the global list
  _addGlobal: (features) ->
    for feature in features
      @globalFeatures[feature] = true
      
    return
    
  # Add features to the last stage
  add: (arg, global = true) ->
    if @stages.length is 0
      @stages.push []
    
    if typeof arg is 'string'
      arg = [arg]
    
    if Array.isArray(arg)
      @_addFeatures arg
      if global
        @_addGlobal arg
        
    else Eif typeof arg is 'object'
      features = (arg.global || []).concat(arg.local || [])
      @_addFeatures features
      Eif arg.global
        @_addGlobal arg.global
        
    else
      throw new Error "Unsupported argument to ShapingPlan#add"
  
  # Add a new stage
  addStage: (arg, global) ->
    Iif typeof arg is 'function'
      @stages.push arg, []
    else
      @stages.push []
      @add arg, global
      
  # Assigns the global features to the given glyphs
  assignGlobalFeatures: (glyphs) ->
    for glyph in glyphs
      for feature of @globalFeatures
        glyph.features[feature] = true
        
    return
    
  # Executes the planned stages using the given OTProcessor
  process: (processor, glyphs, positions) ->
    processor.selectScript @script, @language
    
    for item in @stages
      Iif typeof item is 'function'
        item(glyphs, positions)
        
      else Eif item.length > 0
        processor.applyFeatures(item, glyphs, positions)
        
    return
  
module.exports = ShapingPlan