all files / fontkit/src/opentype/ ShapingPlan.coffee

93.48% Statements 43/46
75% Branches 15/20
100% Functions 8/8
93.33% Lines 42/45
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               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×    
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