| 
					
				 | 
			
			
				@@ -0,0 +1,715 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// [VexFlow](http://vexflow.com) - Copyright (c) Mohit Muthanna 2010. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Vex } from './vex'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Element } from './element'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Flow } from './tables'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Barline } from './stavebarline'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { StaveModifier } from './stavemodifier'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Repetition } from './staverepetition'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { StaveSection } from './stavesection'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { StaveTempo } from './stavetempo'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { StaveText } from './stavetext'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { BoundingBox } from './boundingbox'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Clef } from './clef'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { KeySignature } from './keysignature'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { TimeSignature } from './timesignature'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Volta } from './stavevolta'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+export class Stave extends Element { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  constructor(x, y, width, options) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    super(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.setAttribute('type', 'Stave'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.x = x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.y = y; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.width = width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.formatted = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.setStartX(x + 5); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // this.start_x = x + 5; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.end_x = x + width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.modifiers = [];  // stave modifiers (clef, key, time, barlines, coda, segno, etc.) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.measure = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.clef = 'treble'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.endClef = undefined; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.font = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      family: 'sans-serif', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      size: 8, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      weight: '', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.options = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      vertical_bar_width: 10,       // Width around vertical bar end-marker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      glyph_spacing_px: 10, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      num_lines: 5, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      fill_style: '#999999', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      left_bar: true,               // draw vertical bar on left 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      right_bar: true,               // draw vertical bar on right 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      spacing_between_lines_px: 10, // in pixels 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      space_above_staff_ln: 4,      // in staff lines 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      space_below_staff_ln: 4,      // in staff lines 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      top_text_position: 1,          // in staff lines 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.bounds = { x: this.x, y: this.y, w: this.width, h: 0 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    Vex.Merge(this.options, options); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.resetLines(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const BARTYPE = Barline.type; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // beg bar 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.addModifier(new Barline(this.options.left_bar ? BARTYPE.SINGLE : BARTYPE.NONE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // end bar 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.addEndModifier(new Barline(this.options.right_bar ? BARTYPE.SINGLE : BARTYPE.NONE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  space(spacing) { return this.options.spacing_between_lines_px * spacing; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  resetLines() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.options.line_config = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let i = 0; i < this.options.num_lines; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.options.line_config.push({ visible: true }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.height = (this.options.num_lines + this.options.space_above_staff_ln) * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.options.spacing_between_lines_px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.options.bottom_text_position = this.options.num_lines; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getOptions() { return this.options; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setNoteStartX(x) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!this.formatted) this.format(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!(x >= 0)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      console.log("NaN here1"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.setStartX(x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const begBarline = this.modifiers[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    begBarline.setX(this.start_x - begBarline.getWidth()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setStartX(x) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!(x >= 0)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      console.log("vex: x not >= 0"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.start_x = x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getNoteStartX() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!this.formatted) this.format(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.start_x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getNoteEndX() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!this.formatted) this.format(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.end_x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getTieStartX() { return this.start_x; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getTieEndX() { return this.x + this.width; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getX() { return this.x; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getNumLines() { return this.options.num_lines; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setNumLines(lines) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.options.num_lines = parseInt(lines, 10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.resetLines(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setY(y) { this.y = y; return this; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getTopLineTopY() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.getYForLine(0) - (Flow.STAVE_LINE_THICKNESS / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getBottomLineBottomY() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.getYForLine(this.getNumLines() - 1) + (Flow.STAVE_LINE_THICKNESS / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setX(x) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const shift = x - this.x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.formatted = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.x = x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.start_x += shift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.end_x += shift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let i = 0; i < this.modifiers.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const mod = this.modifiers[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (mod.x !== undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        mod.x += shift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setWidth(width) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.formatted = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.width = width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.end_x = this.x + width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // reset the x position of the end barline (TODO(0xfe): This makes no sense) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // this.modifiers[1].setX(this.end_x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getWidth() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getStyle() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      fillStyle: this.options.fill_style, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      strokeStyle: this.options.fill_style, // yes, this is correct for legacy compatibility 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      lineWidth: Flow.STAVE_LINE_THICKNESS, ...this.style || {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setMeasure(measure) { this.measure = measure; return this; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * Gets the pixels to shift from the beginning of the stave 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * following the modifier at the provided index 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @param  {Number} index The index from which to determine the shift 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @return {Number}       The amount of pixels shifted 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getModifierXShift(index = 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (typeof index !== 'number') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      throw new Vex.RERR('InvalidIndex', 'Must be of number type'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!this.formatted) this.format(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (this.getModifiers(StaveModifier.Position.BEGIN).length === 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let start_x = this.start_x - this.x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const begBarline = this.modifiers[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (begBarline.getType() === Barline.type.REPEAT_BEGIN && start_x > begBarline.getWidth()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      start_x -= begBarline.getWidth(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return start_x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Coda & Segno Symbol functions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setRepetitionTypeLeft(type, y) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.modifiers.push(new Repetition(type, this.x, y)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setRepetitionTypeRight(type, y) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.modifiers.push(new Repetition(type, this.x, y)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Volta functions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setVoltaType(type, number_t, y) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.modifiers.push(new Volta(type, number_t, this.x, y)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Section functions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setSection(section, y) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.modifiers.push(new StaveSection(section, this.x, y)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Tempo functions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setTempo(tempo, y) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.modifiers.push(new StaveTempo(tempo, this.x, y)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Text functions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setText(text, position, options) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.modifiers.push(new StaveText(text, position, options)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getHeight() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.height; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getSpacingBetweenLines() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.options.spacing_between_lines_px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getBoundingBox() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return new BoundingBox(this.x, this.y, this.width, this.getBottomY() - this.y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getBottomY() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const options = this.options; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const spacing = options.spacing_between_lines_px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const score_bottom = this.getYForLine(options.num_lines) + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (options.space_below_staff_ln * spacing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return score_bottom; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getBottomLineY() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.getYForLine(this.options.num_lines); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // This returns the y for the *center* of a staff line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getYForLine(line) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const options = this.options; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const spacing = options.spacing_between_lines_px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const headroom = options.space_above_staff_ln; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const y = this.y + (line * spacing) + (headroom * spacing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return y; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getLineForY(y) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Does the reverse of getYForLine - somewhat dumb and just calls 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // getYForLine until the right value is reaches 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const options = this.options; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const spacing = options.spacing_between_lines_px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const headroom = options.space_above_staff_ln; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return ((y - this.y) / spacing) - headroom; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getYForTopText(line) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const l = line || 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.getYForLine(-l - this.options.top_text_position); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getYForBottomText(line) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const l = line || 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.getYForLine(this.options.bottom_text_position + l); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getYForNote(line) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const options = this.options; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const spacing = options.spacing_between_lines_px; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const headroom = options.space_above_staff_ln; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const y = this.y + (headroom * spacing) + (5 * spacing) - (line * spacing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return y; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getYForGlyphs() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.getYForLine(3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // This method adds a stave modifier to the stave. Note that the first two 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // modifiers (BarLines) are automatically added upon construction. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  addModifier(modifier, position) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (position !== undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      modifier.setPosition(position); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    modifier.setStave(this); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.formatted = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.modifiers.push(modifier); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  addEndModifier(modifier) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.addModifier(modifier, StaveModifier.Position.END); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Bar Line functions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setBegBarType(type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Only valid bar types at beginning of stave is none, single or begin repeat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const { SINGLE, REPEAT_BEGIN, NONE } = Barline.type; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (type === SINGLE || type === REPEAT_BEGIN || type === NONE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.modifiers[0].setType(type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.formatted = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setEndBarType(type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Repeat end not valid at end of stave 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (type !== Barline.type.REPEAT_BEGIN) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.modifiers[1].setType(type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.formatted = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setClef(clefSpec, size, annotation, position) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (position === undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      position = StaveModifier.Position.BEGIN; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (position === StaveModifier.Position.END) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.endClef = clefSpec; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.clef = clefSpec; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const clefs = this.getModifiers(position, Clef.CATEGORY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (clefs.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.addClef(clefSpec, size, annotation, position); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      clefs[0].setType(clefSpec, size, annotation); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setEndClef(clefSpec, size, annotation) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.setClef(clefSpec, size, annotation, StaveModifier.Position.END); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setKeySignature(keySpec, cancelKeySpec, position) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (position === undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      position = StaveModifier.Position.BEGIN; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const keySignatures = this.getModifiers(position, KeySignature.CATEGORY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (keySignatures.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.addKeySignature(keySpec, cancelKeySpec, position); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      keySignatures[0].setKeySig(keySpec, cancelKeySpec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setEndKeySignature(keySpec, cancelKeySpec) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.setKeySignature(keySpec, cancelKeySpec, StaveModifier.Position.END); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setTimeSignature(timeSpec, customPadding, position) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (position === undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      position = StaveModifier.Position.BEGIN; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const timeSignatures = this.getModifiers(position, TimeSignature.CATEGORY); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (timeSignatures.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.addTimeSignature(timeSpec, customPadding, position); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      timeSignatures[0].setTimeSig(timeSpec); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setEndTimeSignature(timeSpec, customPadding) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.setTimeSignature(timeSpec, customPadding, StaveModifier.Position.END); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  addKeySignature(keySpec, cancelKeySpec, position) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (position === undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      position = StaveModifier.Position.BEGIN; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.addModifier(new KeySignature(keySpec, cancelKeySpec) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      .setPosition(position), position); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  addClef(clef, size, annotation, position) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (position === undefined || position === StaveModifier.Position.BEGIN) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.clef = clef; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else if (position === StaveModifier.Position.END) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.endClef = clef; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.addModifier(new Clef(clef, size, annotation), position); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  addEndClef(clef, size, annotation) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.addClef(clef, size, annotation, StaveModifier.Position.END); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  addTimeSignature(timeSpec, customPadding, position) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.addModifier(new TimeSignature(timeSpec, customPadding), position); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  addEndTimeSignature(timeSpec, customPadding) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.addTimeSignature(timeSpec, customPadding, StaveModifier.Position.END); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Deprecated 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  addTrebleGlyph() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.addClef('treble'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getModifiers(position, category) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (position === undefined && category === undefined) return this.modifiers; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.modifiers.filter(modifier => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (position === undefined || position === modifier.getPosition()) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (category === undefined || category === modifier.getCategory()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  sortByCategory(items, order) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let i = items.length - 1; i >= 0; i--) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for (let j = 0; j < i; j++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (order[items[j].getCategory()] > order[items[j + 1].getCategory()]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const temp = items[j]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          items[j] = items[j + 1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          items[j + 1] = temp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  format() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const begBarline = this.modifiers[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const endBarline = this.modifiers[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const begModifiers = this.getModifiers(StaveModifier.Position.BEGIN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const endModifiers = this.getModifiers(StaveModifier.Position.END); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.sortByCategory(begModifiers, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      barlines: 0, clefs: 1, keysignatures: 2, timesignatures: 3, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.sortByCategory(endModifiers, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      timesignatures: 0, keysignatures: 1, barlines: 2, clefs: 3, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (begModifiers.length > 1 && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      begBarline.getType() === Barline.type.REPEAT_BEGIN) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      begModifiers.push(begModifiers.splice(0, 1)[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      begModifiers.splice(0, 0, new Barline(Barline.type.SINGLE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (endModifiers.indexOf(endBarline) > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      endModifiers.splice(0, 0, new Barline(Barline.type.NONE)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let padding; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let modifier; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let offset = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let x = this.x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let i = 0; i < begModifiers.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      modifier = begModifiers[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      padding = modifier.getPadding(i + offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      width = modifier.getWidth(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // VexFlowPatch: prevent modifier width being NaN and throwing Vexflow error 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (isNaN(width)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        modifier.setWidth(10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        width = 10; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      x += padding; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      modifier.setX(x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      x += width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (padding + width === 0) offset--; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.setStartX(x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // this.start_x = x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    x = this.x + this.width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const widths = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      left: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      right: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      paddingRight: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      paddingLeft: 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let lastBarlineIdx = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let i = 0; i < endModifiers.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      modifier = endModifiers[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      lastBarlineIdx = (modifier.getCategory() === 'barlines') ? i : lastBarlineIdx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      widths.right = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      widths.left = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      widths.paddingRight = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      widths.paddingLeft = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const layoutMetrics = modifier.getLayoutMetrics(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (layoutMetrics) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (i !== 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          widths.right = layoutMetrics.xMax || 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          widths.paddingRight = layoutMetrics.paddingRight || 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        widths.left = (-layoutMetrics.xMin) || 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        widths.paddingLeft = layoutMetrics.paddingLeft || 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (i === endModifiers.length - 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          widths.paddingLeft = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        widths.paddingRight = modifier.getPadding(i - lastBarlineIdx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (i !== 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          widths.right = modifier.getWidth(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (i === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          widths.left = modifier.getWidth(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      x -= widths.paddingRight; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      x -= widths.right; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      modifier.setX(x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      x -= widths.left; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      x -= widths.paddingLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.end_x = endModifiers.length === 1 ? this.x + this.width : x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.formatted = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * All drawing functions below need the context to be set. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  draw() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.checkContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.setRendered(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!this.formatted) this.format(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const num_lines = this.options.num_lines; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const width = this.width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const x = this.x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let y; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Render lines 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let line = 0; line < num_lines; line++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      y = this.getYForLine(line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.applyStyle(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (this.options.line_config[line].visible) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.context.beginPath(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.context.moveTo(x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.context.lineTo(x + width, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.context.stroke(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.restoreStyle(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Draw the modifiers (bar lines, coda, segno, repeat brackets, etc.) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let i = 0; i < this.modifiers.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // Only draw modifier if it has a draw function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (typeof this.modifiers[i].draw === 'function') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.modifiers[i].applyStyle(this.context); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.modifiers[i].draw(this, this.getModifierXShift(i)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.modifiers[i].restoreStyle(this.context); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Render measure numbers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (this.measure > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.context.save(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.context.setFont(this.font.family, this.font.size, this.font.weight); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const text_width = this.context.measureText('' + this.measure).width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      y = this.getYForTopText(0) + 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.context.fillText('' + this.measure, this.x - text_width / 2, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.context.restore(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Draw Simple barlines for backward compatability 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Do not delete - draws the beginning bar of the stave 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  drawVertical(x, isDouble) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.drawVerticalFixed(this.x + x, isDouble); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  drawVerticalFixed(x, isDouble) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.checkContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const top_line = this.getYForLine(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const bottom_line = this.getYForLine(this.options.num_lines - 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (isDouble) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.context.fillRect(x - 3, top_line, 1, bottom_line - top_line + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.context.fillRect(x, top_line, 1, bottom_line - top_line + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  drawVerticalBar(x) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.drawVerticalBarFixed(this.x + x, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  drawVerticalBarFixed(x) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.checkContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const top_line = this.getYForLine(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const bottom_line = this.getYForLine(this.options.num_lines - 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.context.fillRect(x, top_line, 1, bottom_line - top_line + 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * Get the current configuration for the Stave. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @return {Array} An array of configuration objects. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getConfigForLines() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this.options.line_config; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * Configure properties of the lines in the Stave 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @param line_number The index of the line to configure. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @param line_config An configuration object for the specified line. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @throws Vex.RERR "StaveConfigError" When the specified line number is out of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   *   range of the number of lines specified in the constructor. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setConfigForLine(line_number, line_config) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (line_number >= this.options.num_lines || line_number < 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      throw new Vex.RERR( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'StaveConfigError', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'The line number must be within the range of the number of lines in the Stave.' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (line_config.visible === undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      throw new Vex.RERR( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'StaveConfigError', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "The line configuration object is missing the 'visible' property." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (typeof (line_config.visible) !== 'boolean') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      throw new Vex.RERR( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'StaveConfigError', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "The line configuration objects 'visible' property must be true or false." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.options.line_config[line_number] = line_config; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * Set the staff line configuration array for all of the lines at once. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @param lines_configuration An array of line configuration objects.  These objects 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   *   are of the same format as the single one passed in to setLineConfiguration(). 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   *   The caller can set null for any line config entry if it is desired that the default be used 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * @throws Vex.RERR "StaveConfigError" When the lines_configuration array does not have 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   *   exactly the same number of elements as the num_lines configuration object set in 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   *   the constructor. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  setConfigForLines(lines_configuration) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (lines_configuration.length !== this.options.num_lines) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      throw new Vex.RERR( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'StaveConfigError', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        'The length of the lines configuration array must match the number of lines in the Stave' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Make sure the defaults are present in case an incomplete set of 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //  configuration options were supplied. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // eslint-disable-next-line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (const line_config in lines_configuration) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // Allow 'null' to be used if the caller just wants the default for a particular node. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (!lines_configuration[line_config]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lines_configuration[line_config] = this.options.line_config[line_config]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      Vex.Merge(this.options.line_config[line_config], lines_configuration[line_config]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.options.line_config = lines_configuration; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |