Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Move to new open-source repo

  • Loading branch information...
commit 8c10ac8aee4cd92f71786ae1c6cd751497bcb753 0 parents
@0xfe authored
Showing with 29,977 additions and 0 deletions.
  1. +20 −0 LICENSE
  2. +44 −0 README
  3. +52 −0 SConstruct
  4. +2 −0  build.sh
  5. +99 −0 site_scons/vexflow_scons.py
  6. +47 −0 src/SConstruct
  7. +76 −0 src/accidental.js
  8. +56 −0 src/annotation.js
  9. +40 −0 src/barnote.js
  10. +205 −0 src/beam.js
  11. +108 −0 src/bend.js
  12. +20 −0 src/flow.js
  13. +1 −0  src/fonts/gonville.js
  14. +1 −0  src/fonts/gonville_all.js
  15. +1 −0  src/fonts/gonville_original.js
  16. +1 −0  src/fonts/vexflow_font.js
  17. +199 −0 src/formatter.js
  18. +40 −0 src/ghostnote.js
  19. +179 −0 src/glyph.js
  20. +122 −0 src/glyphs.html
  21. +31 −0 src/header.js
  22. +70 −0 src/modifier.js
  23. +213 −0 src/modifiercontext.js
  24. +150 −0 src/note.js
  25. +170 −0 src/raphaelcontext.js
  26. +103 −0 src/renderer.js
  27. +144 −0 src/stave.js
  28. +388 −0 src/stavenote.js
  29. +176 −0 src/stavetie.js
  30. +369 −0 src/tables.js
  31. +144 −0 src/tabnote.js
  32. +94 −0 src/tabslide.js
  33. +34 −0 src/tabstave.js
  34. +87 −0 src/tabtie.js
  35. +74 −0 src/tickable.js
  36. +108 −0 src/tickcontext.js
  37. +150 −0 src/transform.html
  38. +65 −0 src/tuning.js
  39. +189 −0 src/vex.js
  40. +108 −0 src/vibrato.js
  41. +116 −0 src/voice.js
  42. +30 −0 src/voicegroup.js
  43. BIN  support/compiler.jar
  44. +22 −0 tabdiv/SConstruct
  45. +23 −0 tabdiv/header.js
  46. +68 −0 tabdiv/style.css
  47. +6,240 −0 tabdiv/support/jquery.js
  48. +113 −0 tabdiv/support/raphael.js
  49. +33 −0 tabdiv/tabdiv.css
  50. +196 −0 tabdiv/tabdiv.js
  51. +266 −0 tabdiv/tutorial.html
  52. +157 −0 tests/accidental_tests.js
  53. +108 −0 tests/annotation_tests.js
  54. +261 −0 tests/beam_tests.js
  55. +120 −0 tests/bend_tests.js
  56. +161 −0 tests/flow.html
  57. +235 −0 tests/formatter_tests.js
  58. +35 −0 tests/mocks.js
  59. +30 −0 tests/modifier_tests.js
  60. +43 −0 tests/stave_tests.js
  61. +164 −0 tests/stavenote_tests.js
  62. +149 −0 tests/stavetie_tests.js
  63. +6,240 −0 tests/support/jquery.js
  64. +119 −0 tests/support/qunit.css
  65. +1,069 −0 tests/support/qunit.js
  66. +113 −0 tests/support/raphael.js
  67. +113 −0 tests/tabnote_tests.js
  68. +122 −0 tests/tabslide_tests.js
  69. +47 −0 tests/tabstave_tests.js
  70. +182 −0 tests/tabtie_tests.js
  71. +48 −0 tests/tickcontext_tests.js
  72. +63 −0 tests/tuning_tests.js
  73. +65 −0 tests/vexflow_test_helpers.js
  74. +93 −0 tests/vibrato_tests.js
  75. +44 −0 tests/voice_tests.js
  76. +123 −0 vextab/runtest.html
  77. +6,240 −0 vextab/support/jquery.js
  78. +119 −0 vextab/support/qunit.css
  79. +1,069 −0 vextab/support/qunit.js
  80. +113 −0 vextab/support/raphael.js
  81. +1,039 −0 vextab/vextab.js
  82. +206 −0 vextab/vextab_tests.js
20 LICENSE
@@ -0,0 +1,20 @@
+Vex Flow - A JavaScript library for rendering music notation.
+Copyright (c) 2010 Mohit Muthanna Cheppudira
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
44 README
@@ -0,0 +1,44 @@
+Vex Flow - A JavaScript library for rendering music notation.
+Copyright (c) 2010 Mohit Muthanna Cheppudira
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+This library makes use of Simon Tatham's awesome font - Gonville.
+
+----------------
+
+To build a minimized version, you need the JRE:
+
+ $ apt-get install sun-java6-bin (or sun-java6-jdk)
+
+This makes use of the Google Closure Compiler.
+
+You also need SCons and git for a full build.
+
+Build with:
+
+ $ scons
+
+Clean with:
+
+ $ scons -c
+
+Quiet build:
+
+ $ scons -Q
52 SConstruct
@@ -0,0 +1,52 @@
+"""
+VexFlow / TabDiv Build Script
+Requires: SCons, Git, and Google Closure Compiler
+
+Copyright Mohit Muthanna Cheppudira 2010
+"""
+
+from vexflow_scons import *
+
+# Create debug, opt, and licensed construction environments.
+
+env = default_env.Clone(VEX_VERSION = "1.0-pre2")
+
+# Create build directories and attach cleanup handlers to them
+
+mkdir_with_cleanup("build", env)
+mkdir_with_cleanup("build/vexflow", env)
+mkdir_with_cleanup("build/tabdiv", env)
+
+dbg = env.Clone(
+ JS_DEFINES = {
+ "Vex.Debug": "true",
+ "Vex.LogLevel": "4"
+ });
+
+opt = env.Clone(
+ VEX_BUILD_PREFIX = "prod-2",
+ JS_DEFINES = {
+ "Vex.Debug": "false",
+ "Vex.LogLevel": "4"
+ });
+
+# Export construction environments to SConscripts
+Export("dbg opt")
+
+# Build VexFlow
+SConscript("src/SConstruct", variant_dir="build/vexflow", duplicate=0)
+
+# Build TabDiv
+SConscript("tabdiv/SConstruct", variant_dir="build/tabdiv", duplicate=0)
+
+# Create Zip archives for distribution
+
+Zip("build/tabdiv-free.zip",
+ ["build/vexflow/vexflow-free.js",
+ "build/tabdiv/vextabdiv-free.js",
+ "tabdiv/tabdiv.css"])
+
+# Copy over tests for distribution
+
+cpdir_with_cleanup("build/tests", "tests", env)
+cpdir_with_cleanup("build/vextab", "vextab", env)
2  build.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+scons
99 site_scons/vexflow_scons.py
@@ -0,0 +1,99 @@
+"""
+VexFlow / TabDiv Build Script
+Requires: SCons, Git, and Google Closure Compiler
+
+Copyright Mohit Cheppudira 2010
+"""
+
+import os
+from datetime import datetime
+from SCons.Script import *
+
+"""
+Make the default zip action use the external zip command. Also
+add -j (--junk-paths) to the command to store only the name of the
+file and strip out the directory name.
+"""
+DefaultEnvironment(ZIPCOM = "zip -r -j $TARGET $SOURCES")
+
+default_env = Environment(
+ VEX_BUILD_PREFIX = "debug-4",
+ VEX_VERSION = "1.0-pre",
+ VEX_BUILD_DATE = str(datetime.now()),
+ JAVA = "java",
+ JS_COMPILER = "support/compiler.jar",
+ JS_DEFINES = {},
+ JS_COMPILATION_LEVEL = "SIMPLE_OPTIMIZATIONS",
+ ENV = os.environ)
+
+def js_builder(target, source, env):
+ """ A JavaScript builder using Google Closure Compiler. """
+
+ cmd = env.subst(
+ "$JAVA -jar $JS_COMPILER --compilation_level $JS_COMPILATION_LEVEL");
+
+ # Add defines to the command
+ for define in env['JS_DEFINES'].keys():
+ cmd += " --define=\"%s=%s\"" % (define, env['JS_DEFINES'][define])
+
+ # Add the source files
+ for file in source:
+ cmd += " --js " + str(file)
+
+ # Add the output file
+ cmd += " --js_output_file " + str(target[0])
+
+ # Log the command and run
+ print env.subst(cmd)
+ os.system(env.subst(cmd))
+
+def vexflow_stamper(target, source, env):
+ """ A Build Stamper for VexFlow """
+
+ cmd = "sed "
+ cmd += " -e s/__VEX_BUILD_PREFIX__/$VEX_BUILD_PREFIX/"
+ cmd += " -e s/__VEX_VERSION__/$VEX_VERSION/"
+ cmd += ' -e "s/__VEX_BUILD_DATE__/${VEX_BUILD_DATE}/"'
+ cmd += " -e s/__VEX_GIT_SHA1__/`git rev-list --max-count=1 HEAD`/ "
+ cmd += ("%s > %s" % (source[0], target[0]))
+
+ print env.subst(cmd)
+ os.system(env.subst(cmd))
+
+"""
+Add our custom builders to the environment.
+"""
+default_env.Append(
+ BUILDERS = {'JavaScript': Builder(action = js_builder),
+ 'VexFlowStamp': Builder(action = vexflow_stamper)})
+
+def build_and_stamp(target, sources, env):
+ """
+ A helper command to build the javascript output and stamp
+ the header files.
+ """
+
+ pre_node = env.JavaScript(target + ".pre", sources)
+ final_node = env.VexFlowStamp(target, pre_node)
+ return final_node
+
+def mkdir_with_cleanup(dirname, env):
+ """
+ Helper function to create directories and attach cleanup
+ handlers. This is the only way to get implicitly created directories
+ cleaned up.
+ """
+ dir = env.subst(dirname)
+ t = Command(dir, [], Mkdir("$TARGET"))
+ Clean(t, dir) # Cleanup handler
+
+def cpdir_with_cleanup(targetdirname, srcdirname, env):
+ """
+ Helper function to copy directories and attach cleanup
+ handlers. This is the only way to get implicitly created directories
+ cleaned up.
+ """
+ targetdir = env.subst(targetdirname)
+ srcdir = env.subst(srcdirname)
+ t = Command(targetdir, srcdir, Copy("$TARGET", "$SOURCE"))
+ Clean(t, targetdir)
47 src/SConstruct
@@ -0,0 +1,47 @@
+"""
+VexFlow / TabDiv Build Script
+Requires: SCons, Git, and Google Closure Compiler
+
+Copyright Mohit Cheppudira 2010
+"""
+
+from vexflow_scons import *
+
+vexflow_sources = [
+ "header.js",
+ "vex.js",
+ "tea.js",
+ "vexcrypt.js",
+ "flow.js",
+ "tables.js",
+ "fonts/vexflow_font.js",
+ "glyph.js",
+ "stave.js",
+ "tabstave.js",
+ "tickcontext.js",
+ "tickable.js",
+ "note.js",
+ "barnote.js",
+ "ghostnote.js",
+ "stavenote.js",
+ "tabnote.js",
+ "beam.js",
+ "voice.js",
+ "modifier.js",
+ "modifiercontext.js",
+ "accidental.js",
+ "formatter.js",
+ "stavetie.js",
+ "tabtie.js",
+ "tabslide.js",
+ "bend.js",
+ "vibrato.js",
+ "annotation.js",
+ "tuning.js",
+ "renderer.js",
+ "raphaelcontext.js"
+ ]
+
+Import('dbg opt')
+build_and_stamp("vexflow-dbg.js", vexflow_sources, dbg);
+build_and_stamp("vexflow-free.js", vexflow_sources, opt);
76 src/accidental.js
@@ -0,0 +1,76 @@
+// VexFlow - Music Engraving for HTML5
+// Copyright Mohit Muthanna 2010
+//
+// This class implements accidentals.
+
+/**
+ * @constructor
+ */
+Vex.Flow.Accidental = function(type) {
+ if (arguments.length > 0) this.init(type);
+}
+Vex.Flow.Accidental.prototype = new Vex.Flow.Modifier();
+Vex.Flow.Accidental.prototype.constructor = Vex.Flow.Accidental;
+Vex.Flow.Accidental.superclass = Vex.Flow.Modifier.prototype;
+
+Vex.Flow.Accidental.prototype.init = function(type) {
+ var superclass = Vex.Flow.Accidental.superclass;
+ superclass.init.call(this);
+
+ this.note = null;
+ this.index = null;
+ this.type = type;
+ this.position = Vex.Flow.Modifier.Position.LEFT;
+
+ this.render_options = {
+ font_scale: 38,
+ stroke_px: 3,
+ stroke_spacing: 10
+ };
+
+ this.accidental = Vex.Flow.accidentalCodes(this.type);
+ this.setWidth(this.accidental.width);
+}
+
+Vex.Flow.Accidental.prototype.getCategory = function() { return "accidentals"; }
+Vex.Flow.Accidental.prototype.getNote = function() { return this.note; }
+Vex.Flow.Accidental.prototype.setNote = function(note)
+ { this.note = note; return this; }
+Vex.Flow.Accidental.prototype.getIndex = function() { return this.index; }
+Vex.Flow.Accidental.prototype.setIndex = function(index) {
+ this.index = index; return this; }
+
+Vex.Flow.Accidental.prototype.draw = function() {
+ if (!this.context) throw new Vex.RERR("NoContext",
+ "Can't draw accidental without a context.");
+ if (!(this.note && (this.index != null))) throw new Vex.RERR("NoAttachedNote",
+ "Can't draw accidental without a note and index.");
+
+ var start = this.note.getModifierStartXY(this.position, this.index);
+ var acc_x = (start.x + this.x_shift) - this.width;
+ var acc_y = start.y + this.y_shift;
+
+ Vex.Flow.renderGlyph(this.context, acc_x, acc_y,
+ this.render_options.font_scale, this.accidental.code);
+
+ /**
+ * Accidentals need no stroking...
+
+ var keyProps = this.note.getKeyProps();
+ if (keyProps[this.index].stroke != 0) {
+ var stroke_begin_y = start.y;
+ for (var j = 0; j < 5; ++j) {
+ this.context.fillRect(
+ acc_x - this.render_options.stroke_px, stroke_begin_y,
+ this.width + (this.render_options.stroke_px * 2), 1);
+
+ stroke_begin_y -= (this.render_options.stroke_spacing * keyProps.stroke);
+ if (stroke_begin_y >= this.note.getStave().getYForLine(0) &&
+ stroke_begin_y <= this.note.getStave().getYForLine(6)) {
+ break;
+ }
+ } // for j = 0 -> 4
+ }
+
+ */
+}
56 src/annotation.js
@@ -0,0 +1,56 @@
+// VexFlow - Music Engraving for HTML5
+// Copyright Mohit Muthanna 2010
+//
+// This class implements text annotations.
+
+/**
+ * @constructor
+ */
+Vex.Flow.Annotation = function(text) {
+ if (arguments.length > 0) this.init(text);
+}
+Vex.Flow.Annotation.prototype = new Vex.Flow.Modifier();
+Vex.Flow.Annotation.prototype.constructor = Vex.Flow.Annotation;
+Vex.Flow.Annotation.superclass = Vex.Flow.Modifier.prototype;
+
+Vex.Flow.Annotation.prototype.init = function(text) {
+ var superclass = Vex.Flow.Annotation.superclass;
+ superclass.init.call(this);
+
+ this.note = null;
+ this.index = null;
+ this.text_line = 0;
+ this.text = text;
+ this.font = {
+ family: "Arial",
+ size: 8,
+ weight: "bold"
+ };
+
+ this.setWidth(Vex.Flow.textWidth(text));
+}
+
+Vex.Flow.Annotation.prototype.getCategory = function() { return "annotations"; }
+Vex.Flow.Annotation.prototype.setTextLine = function(line)
+ { this.text_line = line; return this; }
+Vex.Flow.Annotation.prototype.setFont = function(family, size, weight) {
+ this.font = { family: family, size: size, weight: weight };
+ return this;
+}
+
+Vex.Flow.Annotation.prototype.draw = function() {
+ if (!this.context) throw new Vex.RERR("NoContext",
+ "Can't draw vibrato without a context.");
+ if (!this.note) throw new Vex.RERR("NoNoteForAnnotation",
+ "Can't draw vibrato without an attached note.");
+
+ var start = this.note.getModifierStartXY(Vex.Flow.Modifier.Position.LEFT,
+ this.index);
+ var x = start.x - (this.getWidth() / 2) + 2;
+ var y = this.note.getStave().getYForTopText(this.text_line);
+
+ this.context.save();
+ this.context.setFont(this.font.family, this.font.size, this.font.weight);
+ this.context.fillText(this.text, x, y);
+ this.context.restore();
+}
40 src/barnote.js
@@ -0,0 +1,40 @@
+// Vex Flow Notation
+// Mohit Muthanna <mohit@muthanna.com>
+//
+// Copyright Mohit Muthanna 2010
+//
+// Requires vex.js.
+
+/** @constructor */
+Vex.Flow.BarNote = function() { this.init(); }
+Vex.Flow.BarNote.prototype = new Vex.Flow.Note();
+Vex.Flow.BarNote.superclass = Vex.Flow.Note.prototype;
+Vex.Flow.BarNote.constructor = Vex.Flow.BarNote;
+
+Vex.Flow.BarNote.prototype.init = function() {
+ var superclass = Vex.Flow.BarNote.superclass;
+ superclass.init.call(this, "b");
+
+ // Note properties
+ this.setWidth(8);
+ this.ignore_ticks = true;
+}
+
+Vex.Flow.BarNote.prototype.setStave = function(stave) {
+ var superclass = Vex.Flow.BarNote.superclass;
+ superclass.setStave.call(this, stave);
+}
+
+Vex.Flow.BarNote.prototype.addToModifierContext = function(mc) {
+ return this;
+}
+
+Vex.Flow.BarNote.prototype.preFormat = function() {
+ this.setPreFormatted(true);
+ return this;
+}
+
+Vex.Flow.BarNote.prototype.draw = function() {
+ if (!this.stave) throw new Vex.RERR("NoStave", "Can't draw without a stave.");
+ this.stave.drawVerticalBarFixed(this.getAbsoluteX() + this.x_shift);
+}
205 src/beam.js
@@ -0,0 +1,205 @@
+// Vex Flow Notation
+// Mohit Muthanna <mohit@muthanna.com>
+//
+// Copyright Mohit Muthanna 2010
+//
+// Requires: vex.js, vexmusic.js, note.js
+
+/**
+ * Create a new beam from the specified notes. The notes must
+ * be part of the same line, and have the same duration (in ticks).
+ *
+ * @constructor
+ * @param {Array.<Vex.Flow.StaveNote>} A set of notes.
+ */
+Vex.Flow.Beam = function(notes) {
+ if (arguments.length > 0) this.init(notes);
+}
+
+/**
+ * Set the notes to attach this beam to.
+ *
+ * @param {Array.<Vex.Flow.StaveNote>} The notes.
+ */
+Vex.Flow.Beam.prototype.init = function(notes) {
+ if (!notes || notes == []) {
+ throw new Vex.RuntimeError("BadArguments", "No notes provided for beam.");
+ }
+
+ if (notes.length == 1) {
+ throw new Vex.RuntimeError("BadArguments", "Too few notes for beam.");
+ }
+
+ // Validate beam line, direction and ticks.
+ this.stem_direction = notes[0].getStemDirection();
+ this.ticks = notes[0].getTicks();
+
+ if (this.ticks > Vex.Flow.durationToTicks["8d"]) {
+ throw new Vex.RuntimeError("BadArguments",
+ "Beams can be at most dotted eighth notes.");
+ }
+
+ for (var i = 1; i < notes.length; ++i) {
+ var note = notes[i];
+ if (note.getStemDirection() != this.stem_direction) {
+ throw new Vex.RuntimeError("BadArguments",
+ "Notes in a beam all have the same stem direction");
+ }
+
+ /*
+ if (note.getTicks() != this.ticks) {
+ throw new Vex.RuntimeError("BadArguments",
+ "Notes in a beam should have the same duration.");
+ }
+ */
+ }
+
+ // Success. Lets grab 'em notes.
+ for (var i = 0; i < notes.length; ++i) {
+ var note = notes[i];
+ note.setBeam(this);
+ }
+
+ this.notes = notes;
+ this.beam_count =
+ Vex.Flow.durationToGlyph(this.notes[0].getDuration()).beam_count;
+ this.render_options = { beam_width: 5 };
+}
+
+Vex.Flow.Beam.prototype.setContext = function(context) {
+ this.context = context; return this; }
+
+/**
+ * @return {Array.<Vex.Flow.Note>} Returns notes in this beam.
+ */
+Vex.Flow.Beam.prototype.getNotes = function() {
+ return this.notes;
+}
+
+Vex.Flow.Beam.prototype.draw = function(notes) {
+ if (!this.context) throw new Vex.RERR("NoCanvasContext",
+ "Can't draw without a canvas context.");
+
+ var first_note = this.notes[0];
+ var last_note = this.notes[this.notes.length - 1];
+
+ var first_y_px = first_note.getStemExtents().topY;
+ var last_y_px = last_note.getStemExtents().topY;
+
+ var first_x_px = first_note.getStemX();
+ var last_x_px = last_note.getStemX();
+
+ var beam_width = this.render_options.beam_width * this.stem_direction;
+
+ // Calculate slope for beam.
+ var slope = (last_y_px - first_y_px) / (last_x_px - first_x_px);
+
+ // Returns the Y coordinate for the slope at position X.
+ function getSlopeY(x) {
+ return first_y_px + ((x - first_x_px) * slope);
+ }
+
+ // Iterate over notes, shifting beam up if necessary.
+ var y_shift = 0;
+ for (var i = 1; i < this.notes.length; ++i) {
+ var note = this.notes[i];
+
+ var x_px = note.getStemX();
+ var y_px = note.getStemExtents().topY;
+ var slope_y_px = getSlopeY(x_px);
+
+ if ((y_px + y_shift) * this.stem_direction <
+ slope_y_px * this.stem_direction) {
+ y_shift += Math.abs(y_px - slope_y_px) * -this.stem_direction;
+ }
+ }
+
+ // Draw the stems
+ for (var i = 0; i < this.notes.length; ++i) {
+ var note = this.notes[i];
+ var x_px = note.getStemX();
+ var y_extents = note.getStemExtents();
+ var base_y_px = y_extents.baseY;
+
+ // Draw the stem
+ this.context.fillRect(x_px, base_y_px, 1,
+ ((Math.abs(base_y_px - (getSlopeY(x_px) + y_shift)))) *
+ -this.stem_direction);
+ }
+
+ var that = this;
+ function getBeamLines(duration) {
+ var beam_lines = [];
+ var beam_started = false;
+
+ for (var i = 0; i < that.notes.length; ++i) {
+ var note = that.notes[i];
+ var ticks = note.getTicks();
+
+ // Atleast 8th note
+ if (ticks <= Vex.Flow.durationToTicks[duration]) {
+ if (!beam_started) {
+ beam_lines.push({start: note.getStemX(), end: null});
+ beam_started = true;
+ } else {
+ var current_beam = beam_lines[beam_lines.length - 1];
+ current_beam.end = note.getStemX();
+ }
+ } else {
+ if (!beam_started) {
+ // we don't care
+ } else {
+ var current_beam = beam_lines[beam_lines.length - 1];
+ if (current_beam.end == null) {
+ // single note
+ current_beam.end = current_beam.start + 10; // TODO
+ } else {
+ // we don't care
+ }
+ }
+
+ beam_started = false;
+ }
+ }
+
+ if (beam_started == true) {
+ var current_beam = beam_lines[beam_lines.length - 1];
+ if (current_beam.end == null) {
+ // single note
+ current_beam.end = current_beam.start - 10; // TODO
+ }
+ }
+
+ return beam_lines;
+ }
+
+ var valid_beam_durations = ["8d", "16d", "32d"];
+
+ // Draw the beams.
+ for (var i = 0; i < valid_beam_durations.length; ++i) {
+ var duration = valid_beam_durations[i];
+ var beam_lines = getBeamLines(duration);
+
+ for (var j = 0; j < beam_lines.length; ++j) {
+ var beam_line = beam_lines[j];
+ var first_x = beam_line.start;
+ var first_y = getSlopeY(first_x);
+
+ var last_x = beam_line.end;
+ var last_y = getSlopeY(last_x);
+
+ this.context.beginPath();
+ this.context.moveTo(first_x, first_y + y_shift);
+ this.context.lineTo(first_x, first_y + beam_width + y_shift);
+ this.context.lineTo(last_x + 1, last_y + beam_width + y_shift);
+ this.context.lineTo(last_x + 1, last_y + y_shift);
+ this.context.closePath();
+ this.context.fill();
+ }
+
+ first_y_px += beam_width * 1.5;
+ last_y_px += beam_width * 1.5;
+ }
+
+ return true;
+}
108 src/bend.js
@@ -0,0 +1,108 @@
+// VexFlow - Music Engraving for HTML5
+// Copyright Mohit Muthanna 2010
+//
+// This class implements bends.
+
+/**
+ * @constructor
+ */
+Vex.Flow.Bend = function(text, release) {
+ if (arguments.length > 0) this.init(text, release);
+}
+Vex.Flow.Bend.prototype = new Vex.Flow.Modifier();
+Vex.Flow.Bend.prototype.constructor = Vex.Flow.Bend;
+Vex.Flow.Bend.superclass = Vex.Flow.Modifier.prototype;
+
+Vex.Flow.Bend.prototype.init = function(text, release) {
+ var superclass = Vex.Flow.Bend.superclass;
+ superclass.init.call(this);
+
+ this.text = text;
+ this.release = release || false;
+ this.font = "bold 8pt Arial";
+ this.render_options = {
+ bend_width: 8,
+ release_width: 8
+ };
+
+ this.bend_width = this.render_options.bend_width;
+ this.release_width = this.release ? this.render_options.release_width:0;
+
+ this.updateWidth();
+}
+
+Vex.Flow.Bend.prototype.getCategory = function() { return "bends"; }
+Vex.Flow.Bend.prototype.getText = function() { return this.text; }
+Vex.Flow.Bend.prototype.updateWidth = function() {
+ this.setWidth(
+ this.bend_width +
+ this.release_width +
+ (Vex.Flow.textWidth(this.text) / 2));
+}
+Vex.Flow.Bend.prototype.setBendWidth = function(width) {
+ this.bend_width = width; this.updateWidth();
+}
+Vex.Flow.Bend.prototype.setReleaseWidth = function(width) {
+ this.release_width = width; this.updateWidth();
+}
+Vex.Flow.Bend.prototype.hasRelease = function() { return this.release; }
+Vex.Flow.Bend.prototype.setFont = function(font) {
+ this.font = font; return this; }
+
+Vex.Flow.Bend.prototype.draw = function() {
+ if (!this.context) throw new Vex.RERR("NoContext",
+ "Can't draw bend without a context.");
+ if (!(this.note && (this.index != null))) throw new Vex.RERR("NoNoteForBend",
+ "Can't draw bend without a note or index.");
+
+ var start = this.note.getModifierStartXY(Vex.Flow.Modifier.Position.RIGHT,
+ this.index);
+
+ var ctx = this.context;
+ var that = this;
+ var bend_height = this.note.getStave().getYForTopText(this.text_line) + 2;
+
+ function renderBend(x, y) {
+ var cp_x = x + that.bend_width;
+ var cp_y = y;
+
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.quadraticCurveTo(cp_x, cp_y, x + that.bend_width, bend_height);
+
+ if (that.release) {
+ ctx.quadraticCurveTo(
+ x + that.bend_width + that.release_width + 2, bend_height,
+ x + that.bend_width + that.release_width, y);
+ }
+
+ ctx.stroke();
+ }
+
+ function renderArrowHead(x, y, direction) {
+ var width = 3;
+ var dir = direction || 1;
+
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.lineTo(x - width, y + width * dir);
+ ctx.lineTo(x + width, y + width * dir);
+ ctx.closePath();
+ ctx.fill();
+ }
+
+ renderBend(start.x, start.y + 0.5);
+ if (!this.release) {
+ renderArrowHead(start.x + this.bend_width, bend_height);
+ } else {
+ renderArrowHead(start.x + this.bend_width + this.release_width,
+ start.y + 0.5, -1);
+ }
+
+ var annotation_y = this.note.getStave().getYForTopText(this.text_line);
+ var text_x = start.x + this.bend_width - (Vex.Flow.textWidth(this.text) / 2);
+ ctx.save();
+ ctx.font = this.font;
+ ctx.fillText(this.text, text_x, annotation_y);
+ ctx.restore();
+}
20 src/flow.js
@@ -0,0 +1,20 @@
+/**
+ * Vex Flow - Mohit Muthanna <mohit@muthanna.com>
+ */
+
+/**
+ * New namespace.
+ */
+Vex.Flow = {}
+
+/**
+ * The resolution used for all the rhythm timing in this
+ * library.
+ *
+ * @const
+ * @type {number}
+ */
+Vex.Flow.RESOLUTION = 16384;
+
+/* Kerning (DEPRECATED) */
+Vex.Flow.IsKerned = true;
1  src/fonts/gonville.js
@@ -0,0 +1 @@
+Vex.Music.Font = {"glyphs":{"vb":{"x_min":0,"x_max":428.75,"ha":438,"o":"m 262 186 b 273 186 266 186 272 186 b 274 186 273 186 274 186 b 285 186 274 186 280 186 b 428 48 375 181 428 122 b 386 -68 428 12 416 -29 b 155 -187 329 -145 236 -187 b 12 -111 92 -187 38 -162 b 0 -51 4 -91 0 -72 b 262 186 0 58 122 179 "},"vc":{"x_min":0,"x_max":447.8125,"ha":457,"o":"m 0 86 l 0 173 l 223 173 l 447 173 l 447 86 l 447 0 l 223 0 l 0 0 l 0 86 "},"v18":{"x_min":0,"x_max":323.9375,"ha":331,"o":"m 217 535 b 225 537 220 537 221 537 b 245 524 235 537 242 533 l 246 521 l 247 390 l 247 258 l 273 265 b 306 270 288 269 299 270 b 322 259 315 270 319 267 b 323 208 323 256 323 233 b 322 158 323 184 323 159 b 288 140 318 148 315 147 b 247 130 254 131 247 130 b 247 65 247 130 247 104 b 247 20 247 51 247 36 l 247 -88 l 273 -81 b 306 -76 289 -77 299 -76 b 318 -81 311 -76 315 -77 b 323 -123 323 -87 323 -86 l 323 -138 l 323 -154 b 318 -195 323 -191 323 -190 b 269 -210 314 -199 315 -199 b 249 -216 259 -213 250 -216 l 247 -216 l 247 -349 l 246 -483 l 245 -487 b 225 -499 242 -495 234 -499 b 206 -487 219 -499 210 -495 l 205 -483 l 205 -355 l 205 -227 l 204 -227 l 181 -233 l 138 -244 b 117 -249 127 -247 117 -249 b 115 -385 115 -249 115 -256 l 115 -523 l 114 -526 b 95 -538 110 -534 102 -538 b 74 -526 87 -538 78 -534 l 73 -523 l 73 -391 b 72 -260 73 -269 73 -260 b 72 -260 72 -260 72 -260 b 19 -273 61 -263 23 -273 b 0 -260 10 -273 4 -267 b 0 -209 0 -256 0 -256 l 0 -162 l 1 -158 b 61 -134 5 -148 5 -148 l 73 -131 l 73 -22 b 72 86 73 79 73 86 b 72 86 72 86 72 86 b 19 74 61 83 23 74 b 0 86 10 74 4 79 b 0 137 0 90 0 90 l 0 184 l 1 188 b 61 212 5 198 5 198 l 73 215 l 73 348 l 73 481 l 74 485 b 95 498 78 492 87 498 b 103 495 98 498 100 496 b 114 485 107 494 111 489 l 115 481 l 115 353 l 115 226 l 121 226 b 159 235 123 227 141 231 l 198 247 l 205 248 l 205 384 l 205 521 l 206 524 b 217 535 209 528 212 533 m 205 9 b 205 119 205 70 205 119 l 205 119 b 182 113 204 119 194 116 l 138 102 b 117 97 127 99 117 97 b 115 -12 115 97 115 91 l 115 -122 l 121 -120 b 159 -111 123 -119 141 -115 l 198 -101 l 205 -98 l 205 9 "},"v1d":{"x_min":0,"x_max":619.3125,"ha":632,"o":"m 274 184 b 307 186 285 186 296 186 b 616 22 465 186 597 116 b 619 -1 617 13 619 5 b 308 -187 619 -104 483 -187 b 0 -1 133 -187 0 -102 b 5 36 0 11 1 23 b 274 184 29 115 141 176 m 289 161 b 272 162 284 162 277 162 b 171 41 209 162 171 108 b 205 -73 171 5 182 -34 b 345 -163 243 -133 298 -163 b 436 -98 385 -163 420 -142 b 446 -43 443 -80 446 -62 b 289 161 446 47 377 147 "},"v26":{"x_min":-21.78125,"x_max":483.1875,"ha":493,"o":"m -8 631 b -1 632 -6 632 -4 632 b 19 620 8 632 16 628 b 20 383 20 616 20 616 l 20 148 l 21 151 b 140 199 59 183 102 199 b 206 179 164 199 187 192 l 210 176 l 210 396 l 210 617 l 212 621 b 231 632 216 628 223 632 b 250 620 239 632 247 628 b 251 383 251 616 251 616 l 251 148 l 254 151 b 370 199 291 183 332 199 b 415 191 385 199 400 197 b 483 84 458 176 483 134 b 461 0 483 58 476 29 b 332 -142 439 -40 411 -72 l 255 -215 b 231 -229 240 -229 239 -229 b 216 -223 224 -229 220 -227 b 210 -158 210 -217 210 -223 b 210 -120 210 -148 210 -136 l 210 -29 l 205 -34 b 100 -142 182 -65 159 -88 l 23 -215 b -1 -229 9 -229 6 -229 b -20 -216 -9 -229 -17 -224 l -21 -212 l -21 201 l -21 616 l -20 620 b -8 631 -17 624 -13 630 m 110 131 b 96 133 106 133 100 133 b 89 133 93 133 91 133 b 24 87 63 129 40 113 l 20 80 l 20 -37 l 20 -156 l 23 -152 b 144 81 96 -72 144 20 l 144 83 b 110 131 144 113 134 126 m 341 131 b 328 133 337 133 332 133 b 322 133 326 133 323 133 b 257 87 296 129 273 113 l 251 80 l 251 -37 l 251 -156 l 255 -152 b 375 81 328 -72 375 20 l 375 83 b 341 131 375 113 367 126 "},"v2a":{"x_min":-21.78125,"x_max":366.140625,"ha":374,"o":"m 276 1378 b 284 1379 279 1379 281 1379 b 306 1360 292 1379 298 1374 b 352 1247 326 1326 343 1286 b 366 1139 362 1213 366 1175 b 347 1009 366 1093 359 1049 l 344 1002 l 347 992 b 352 971 348 986 351 977 b 366 863 362 936 366 899 b 347 732 366 818 359 773 l 344 725 l 347 716 b 352 695 348 710 351 700 b 366 588 362 659 366 623 b 223 262 366 464 314 345 b 189 233 212 252 212 252 b 35 76 126 183 73 129 b -1 16 20 56 2 27 b -19 4 -4 9 -12 4 l -21 4 l -21 137 l -21 270 l -17 270 b 186 344 59 281 134 308 b 319 606 270 399 319 499 b 317 650 319 620 319 635 l 315 659 l 314 655 b 223 537 288 607 258 570 b 189 509 212 528 212 528 b 35 352 126 459 73 405 b -1 292 20 333 2 303 b -19 280 -4 285 -12 280 l -21 280 l -21 413 l -21 546 l -17 546 b 186 620 59 557 134 584 b 319 882 270 675 319 775 b 317 925 319 896 319 911 l 315 935 l 314 931 b 223 813 288 884 258 846 b 189 785 212 805 212 805 b 35 628 126 735 73 681 b -1 569 20 609 2 580 b -19 556 -4 562 -12 556 l -21 556 l -21 689 l -21 823 l -17 823 b 202 907 68 835 152 867 b 319 1157 280 968 319 1061 b 270 1338 319 1218 303 1281 b 262 1358 264 1349 262 1353 b 262 1364 262 1360 262 1363 b 276 1378 265 1371 269 1376 "},"v2f":{"x_min":-1.359375,"x_max":680.5625,"ha":694,"o":"m 597 1042 b 604 1042 600 1042 602 1042 b 642 1002 627 1042 642 1022 b 619 966 642 988 635 974 b 439 927 574 942 503 927 l 426 927 l 426 921 b 430 838 428 893 430 866 b 345 480 430 696 398 560 b 179 391 307 423 249 391 b 156 392 171 391 164 392 b 138 394 149 394 142 394 b 103 434 115 396 103 416 b 129 471 103 451 111 466 b 141 474 133 473 137 474 b 172 459 153 474 164 469 b 181 455 175 456 176 455 b 187 456 182 455 185 455 b 253 520 212 460 234 483 b 315 836 294 605 315 714 b 311 928 315 867 314 898 b 302 945 310 943 311 942 b 245 953 283 950 262 953 b 130 891 193 953 149 931 b 84 860 119 870 102 860 b 36 905 61 860 39 877 b 36 910 36 907 36 909 b 80 970 36 931 50 949 b 249 1017 125 1000 187 1017 b 322 1009 273 1017 299 1014 l 341 1003 b 436 991 372 995 406 991 b 577 1031 495 991 545 1004 b 597 1042 583 1038 590 1041 m 416 360 b 424 360 419 360 421 360 b 481 309 454 360 479 338 b 503 145 484 280 495 199 b 585 -185 525 16 555 -106 b 630 -245 596 -213 613 -237 l 634 -247 l 638 -245 b 647 -244 641 -245 645 -244 b 680 -278 666 -244 680 -262 b 664 -308 680 -290 675 -301 b 638 -312 658 -310 650 -312 b 613 -309 631 -312 623 -310 b 477 -201 555 -303 502 -260 b 417 -2 460 -159 434 -72 b 416 5 417 1 416 5 b 416 5 416 5 416 5 b 411 -5 415 5 413 0 b 359 -97 397 -33 377 -70 b 353 -106 355 -102 353 -105 b 359 -112 353 -108 355 -109 b 409 -130 375 -123 390 -129 b 426 -134 420 -130 421 -131 b 431 -147 428 -137 431 -141 b 420 -162 431 -152 427 -159 b 382 -169 409 -166 396 -169 b 323 -155 363 -169 341 -165 l 317 -152 l 314 -155 b 62 -303 240 -240 148 -295 b 36 -305 55 -305 44 -305 b 23 -303 29 -305 24 -305 b -1 -273 6 -299 -1 -287 b 31 -240 -1 -256 10 -240 b 36 -240 32 -240 34 -240 b 42 -241 38 -241 39 -241 b 134 -204 63 -241 99 -226 b 367 288 265 -115 357 81 b 375 330 368 313 370 320 b 416 360 383 347 400 358 m 360 -359 b 379 -359 363 -359 371 -359 b 424 -360 396 -359 416 -359 b 646 -502 536 -373 624 -430 b 649 -527 649 -510 649 -519 b 530 -673 649 -578 604 -635 l 521 -677 l 529 -681 b 653 -811 592 -714 637 -762 b 660 -853 658 -827 660 -839 b 645 -911 660 -873 656 -892 b 426 -1021 608 -981 519 -1021 b 283 -989 377 -1021 328 -1011 b 235 -949 249 -972 239 -964 b 234 -936 234 -946 234 -941 b 234 -928 234 -934 234 -931 l 235 -925 l 234 -927 l 225 -934 b 87 -982 186 -966 138 -982 b 80 -982 85 -982 83 -982 b 55 -981 70 -981 58 -981 b 17 -943 32 -981 17 -964 b 54 -904 17 -921 35 -904 b 78 -914 62 -904 72 -909 l 83 -918 l 88 -918 b 190 -831 122 -918 166 -881 b 269 -506 242 -727 269 -612 b 268 -462 269 -492 269 -477 b 266 -449 266 -458 266 -452 b 265 -444 266 -445 266 -444 b 257 -446 264 -444 261 -445 b 132 -545 196 -470 152 -505 b 88 -573 122 -563 104 -573 b 39 -523 63 -573 39 -553 b 63 -476 39 -505 44 -494 b 360 -359 136 -408 235 -369 m 419 -424 b 393 -423 411 -423 406 -423 l 375 -423 l 377 -426 b 379 -439 377 -427 378 -434 b 383 -510 382 -463 383 -487 b 314 -811 383 -609 360 -710 b 266 -893 296 -850 285 -870 b 264 -898 265 -896 264 -898 l 264 -898 b 264 -898 264 -898 264 -898 b 268 -898 264 -898 266 -898 b 273 -898 270 -898 272 -898 b 300 -909 283 -898 291 -900 b 426 -957 340 -941 385 -957 b 476 -949 443 -957 460 -954 b 547 -853 522 -931 547 -893 b 485 -745 547 -816 526 -775 b 397 -707 460 -727 432 -714 b 366 -675 375 -703 366 -692 b 396 -642 366 -657 377 -645 b 530 -557 455 -637 511 -601 b 536 -527 534 -548 536 -537 b 419 -424 536 -480 490 -437 "},"v3c":{"x_min":0,"x_max":450.53125,"ha":460,"o":"m 189 302 b 204 303 193 302 198 303 b 303 224 250 303 292 270 b 306 199 304 216 306 208 b 279 129 306 173 296 147 l 276 126 l 281 127 b 408 249 337 142 385 190 b 412 259 409 254 412 258 b 430 267 417 265 423 267 b 450 247 441 267 450 259 b 200 -605 450 242 204 -599 b 182 -616 197 -612 190 -616 b 163 -602 174 -616 166 -610 b 161 -598 161 -601 161 -601 b 217 -402 161 -589 170 -562 b 272 -213 247 -298 272 -213 b 272 -213 272 -213 272 -213 b 264 -219 272 -213 268 -216 b 140 -262 227 -247 182 -262 b 36 -226 102 -262 65 -249 b 0 -145 12 -206 0 -176 b 17 -84 0 -124 5 -104 b 103 -38 38 -54 70 -38 b 191 -91 137 -38 172 -56 b 205 -141 201 -106 205 -124 b 178 -212 205 -167 196 -194 l 175 -215 l 182 -213 b 307 -93 236 -198 284 -151 b 372 129 308 -88 372 127 b 372 129 372 129 372 129 b 364 122 372 129 368 126 b 240 80 328 94 283 80 b 137 115 202 80 166 91 b 99 194 111 136 99 165 b 189 302 99 244 133 292 "},"v3e":{"x_min":0,"x_max":406.96875,"ha":415,"o":"m 21 183 b 28 183 24 183 25 183 b 42 181 34 183 39 183 b 127 108 47 179 47 179 b 202 41 168 72 202 41 b 279 108 204 41 238 72 b 357 177 321 145 356 176 b 375 183 363 181 370 183 b 406 151 392 183 406 169 b 404 137 406 147 405 141 b 322 62 401 131 398 129 b 251 0 284 27 251 0 b 322 -63 251 -1 284 -29 b 404 -138 398 -130 401 -133 b 406 -152 405 -142 406 -148 b 375 -184 406 -170 392 -184 b 357 -179 370 -184 363 -183 b 279 -109 356 -177 321 -147 b 202 -43 238 -73 204 -43 b 127 -109 202 -43 168 -73 b 49 -179 85 -147 50 -177 b 31 -184 43 -183 36 -184 b 0 -152 13 -184 0 -170 b 2 -138 0 -148 0 -142 b 83 -63 5 -133 8 -130 b 155 0 122 -29 155 -1 b 83 62 155 0 122 27 b 8 129 43 97 10 127 b 0 151 2 136 0 144 b 21 183 0 165 8 177 "},"v3f":{"x_min":-24.5,"x_max":317.140625,"ha":324,"o":"m -24 -147 l -24 -5 l -20 -5 b -1 -19 -12 -5 -4 -11 b 58 -123 6 -43 31 -86 b 196 -278 93 -173 134 -219 b 317 -570 274 -356 317 -460 b 294 -713 317 -617 308 -666 l 289 -724 l 294 -735 b 317 -873 308 -780 317 -827 b 235 -1132 317 -963 288 -1054 b 209 -1165 228 -1140 224 -1146 b 189 -1177 204 -1172 196 -1177 b 171 -1164 182 -1177 175 -1172 b 168 -1154 170 -1161 168 -1159 b 181 -1132 168 -1149 172 -1142 b 269 -891 238 -1064 269 -975 b 269 -881 269 -886 269 -884 b 262 -814 269 -857 265 -827 b 258 -800 261 -811 259 -806 b 142 -628 240 -731 198 -667 b -8 -589 112 -606 47 -589 b -20 -589 -13 -589 -19 -589 l -24 -589 l -24 -449 l -24 -308 l -20 -308 b -1 -322 -12 -308 -4 -313 b 58 -424 6 -345 31 -388 b 194 -580 93 -476 136 -523 b 259 -660 221 -606 245 -635 b 261 -663 259 -662 261 -663 b 264 -656 262 -663 262 -660 b 269 -587 268 -632 269 -610 b 264 -521 269 -566 268 -544 b 262 -512 264 -517 262 -513 b 258 -498 261 -509 259 -503 b 142 -326 240 -428 198 -365 b -8 -287 112 -303 47 -288 b -20 -287 -13 -287 -19 -287 l -24 -287 l -24 -147 "},"v44":{"x_min":-21.78125,"x_max":251.8125,"ha":257,"o":"m -8 631 b -1 632 -6 632 -4 632 b 19 620 8 632 16 628 b 20 383 20 616 20 616 l 20 148 l 21 151 b 137 199 59 183 99 199 b 182 191 152 199 167 197 b 251 84 227 176 251 134 b 228 0 251 58 243 29 b 100 -142 206 -40 178 -72 l 23 -215 b 0 -229 9 -229 6 -229 b -20 -216 -9 -229 -17 -224 l -21 -212 l -21 201 l -21 616 l -20 620 b -8 631 -17 624 -13 630 m 110 131 b 96 133 106 133 100 133 b 89 133 93 133 91 133 b 24 87 63 129 40 113 l 20 80 l 20 -37 l 20 -156 l 23 -152 b 144 81 96 -72 144 20 l 144 83 b 110 131 144 113 134 126 "},"v47":{"x_min":-24.5,"x_max":315.78125,"ha":322,"o":"m -24 -145 l -24 -5 l -20 -5 b 1 -26 -10 -5 -6 -9 b 175 -241 31 -86 96 -166 b 314 -548 259 -323 304 -420 b 315 -589 315 -555 315 -571 b 314 -630 315 -606 315 -623 b 298 -730 311 -664 306 -699 l 295 -742 l 296 -748 b 314 -850 304 -778 311 -813 b 315 -892 315 -857 315 -874 b 314 -932 315 -909 315 -925 b 298 -1032 311 -967 306 -1002 l 295 -1045 l 296 -1050 b 314 -1153 304 -1081 311 -1115 b 315 -1193 315 -1160 315 -1177 b 314 -1235 315 -1211 315 -1228 b 217 -1526 306 -1338 270 -1444 b 201 -1533 213 -1532 208 -1533 b 182 -1522 193 -1533 185 -1529 b 179 -1514 181 -1518 179 -1517 b 189 -1489 179 -1508 182 -1501 b 266 -1217 240 -1403 266 -1308 b 262 -1156 266 -1196 265 -1177 b 110 -907 247 -1043 190 -950 b 0 -889 87 -895 50 -889 l -1 -889 l -24 -889 l -24 -749 l -24 -610 l -20 -610 b 1 -631 -10 -610 -6 -614 b 175 -846 31 -691 96 -771 b 259 -956 213 -884 236 -914 b 265 -966 262 -961 264 -966 b 265 -966 265 -966 265 -966 b 265 -953 265 -964 265 -959 b 266 -920 266 -943 266 -932 b 262 -853 266 -898 265 -873 b 110 -605 247 -741 190 -648 b 0 -587 87 -592 50 -587 l -1 -587 l -24 -587 l -24 -448 l -24 -308 l -20 -308 b 1 -328 -10 -308 -6 -312 b 175 -544 31 -388 96 -469 b 259 -655 213 -581 236 -612 b 265 -663 262 -659 264 -663 b 265 -663 265 -663 265 -663 b 265 -650 265 -663 265 -657 b 266 -617 266 -641 266 -630 b 262 -551 266 -595 265 -570 b 110 -303 247 -438 190 -345 b 0 -284 87 -290 50 -284 l -1 -284 l -24 -284 l -24 -145 "},"v4e":{"x_min":0,"x_max":239.5625,"ha":244,"o":"m 10 460 b 20 462 13 462 14 462 b 39 449 28 462 35 458 l 40 446 l 40 326 b 40 205 40 259 40 205 b 127 227 40 205 80 215 b 220 249 196 244 213 249 b 227 247 224 249 225 248 b 238 237 231 245 235 241 l 239 233 l 239 -106 l 239 -448 l 238 -451 b 219 -463 234 -459 225 -463 b 198 -451 210 -463 202 -459 l 197 -448 l 197 -324 b 197 -201 197 -248 197 -201 b 110 -223 196 -201 157 -210 b 17 -245 42 -240 24 -245 b 10 -242 13 -245 13 -244 b 0 -233 6 -241 2 -237 l 0 -230 l 0 108 l 0 446 l 0 449 b 10 460 2 453 6 458 m 197 22 b 197 70 197 41 197 58 b 196 116 197 113 197 116 l 196 116 b 118 97 196 116 160 106 l 40 77 l 40 -18 b 40 -112 40 -69 40 -112 l 119 -93 l 197 -73 l 197 22 "},"v54":{"x_min":-24.5,"x_max":317.140625,"ha":324,"o":"m -24 -161 l -24 -5 l -20 -5 b 0 -24 -9 -5 -2 -12 b 171 -315 21 -124 84 -233 b 317 -660 268 -406 317 -531 b 187 -1014 317 -782 274 -909 b 161 -1034 172 -1034 171 -1034 b 141 -1013 149 -1034 141 -1025 b 152 -991 141 -1004 142 -1002 b 266 -682 228 -899 266 -788 b 174 -430 266 -588 236 -498 b -23 -317 136 -388 66 -348 b -24 -161 -23 -316 -24 -285 "},"v55":{"x_min":0,"x_max":551.25,"ha":563,"o":"m 289 644 b 304 645 294 645 299 645 b 404 566 349 645 392 613 b 406 541 405 557 406 549 b 379 471 406 514 397 489 l 377 467 l 382 470 b 509 591 438 485 485 531 b 513 601 510 595 513 599 b 530 609 518 607 524 609 b 551 588 540 609 551 602 b 200 -605 551 584 204 -599 b 182 -616 197 -612 190 -616 b 163 -602 174 -616 166 -610 b 161 -598 161 -601 161 -601 b 217 -402 161 -589 170 -562 b 272 -213 247 -298 272 -213 b 272 -213 272 -213 272 -213 b 264 -219 272 -213 268 -216 b 140 -262 227 -247 182 -262 b 36 -226 102 -262 65 -249 b 0 -145 12 -206 0 -176 b 17 -84 0 -124 5 -104 b 103 -38 38 -54 70 -38 b 191 -91 137 -38 172 -56 b 205 -141 201 -106 205 -124 b 178 -212 205 -167 196 -194 l 175 -215 l 182 -213 b 307 -93 236 -198 284 -151 b 372 129 308 -88 372 127 b 372 129 372 129 372 129 b 364 122 372 129 368 126 b 240 80 328 94 283 80 b 137 115 202 80 166 91 b 99 195 112 136 99 165 b 118 256 99 217 106 238 b 204 303 138 287 171 303 b 292 249 238 303 273 285 b 306 199 302 234 306 217 b 279 129 306 173 296 148 l 276 126 l 281 127 b 408 248 336 142 385 190 b 473 470 409 254 473 469 b 473 470 473 470 473 470 b 465 464 473 470 469 467 b 341 421 428 435 383 421 b 236 458 303 421 266 433 b 200 537 212 478 200 508 b 289 644 200 585 234 635 "},"v5c":{"x_min":0,"x_max":447.8125,"ha":457,"o":"m 0 -87 l 0 0 l 223 0 l 447 0 l 447 -87 l 447 -174 l 223 -174 l 0 -174 l 0 -87 "},"v7c":{"x_min":0,"x_max":300.8125,"ha":307,"o":"m 49 505 b 53 506 50 505 51 506 b 70 496 58 506 62 503 b 81 485 73 492 78 488 l 96 473 l 111 459 l 122 449 l 134 438 l 182 396 l 255 330 b 292 291 292 298 292 298 l 292 290 l 292 284 l 283 270 b 209 36 234 197 209 113 b 288 -170 209 -44 235 -119 b 299 -184 295 -179 299 -181 b 300 -191 300 -187 300 -188 b 285 -206 300 -199 294 -206 b 280 -206 283 -206 281 -206 b 247 -201 270 -202 259 -201 b 176 -222 223 -201 197 -208 b 114 -340 136 -249 114 -292 b 172 -471 114 -384 134 -433 b 185 -492 182 -481 185 -487 b 181 -502 185 -496 183 -499 b 171 -508 176 -505 174 -508 b 152 -498 166 -508 160 -503 b 0 -284 65 -428 12 -352 b 0 -260 0 -278 0 -270 b 1 -238 0 -252 0 -242 b 148 -140 16 -177 73 -140 b 209 -148 167 -140 189 -142 b 215 -149 212 -148 215 -149 b 215 -149 215 -149 215 -149 l 215 -149 b 201 -136 215 -148 209 -142 l 157 -97 l 96 -41 b 17 34 21 24 17 29 b 17 37 17 36 17 36 b 17 38 17 37 17 38 b 25 56 17 44 17 44 b 110 298 81 131 110 219 b 46 474 110 367 88 431 b 38 491 40 480 38 487 b 49 505 38 498 42 502 "},"v7f":{"x_min":0,"x_max":367.5,"ha":375,"o":"m 0 124 l 0 187 l 61 187 l 122 187 l 122 138 l 122 91 l 153 61 l 183 30 l 213 61 l 243 91 l 243 138 l 243 187 l 306 187 l 367 187 l 367 124 l 367 61 l 321 61 l 274 61 l 243 30 l 213 0 l 243 -31 l 274 -62 l 321 -62 l 367 -62 l 367 -124 l 367 -188 l 306 -188 l 243 -188 l 243 -140 l 243 -93 l 213 -62 l 183 -31 l 153 -62 l 122 -93 l 122 -140 l 122 -188 l 61 -188 l 0 -188 l 0 -124 l 0 -62 l 46 -62 l 92 -62 l 123 -31 l 153 0 l 123 30 l 92 61 l 46 61 l 0 61 l 0 124 "},"v81":{"x_min":0,"x_max":428.75,"ha":438,"o":"m 262 186 b 273 186 266 186 272 186 b 274 186 273 186 274 186 b 285 186 274 186 280 186 b 428 48 375 181 428 122 b 386 -68 428 12 416 -29 b 155 -187 329 -145 236 -187 b 12 -111 92 -187 38 -162 b 0 -51 4 -91 0 -72 b 262 186 0 58 122 179 m 366 131 b 352 134 362 133 357 134 b 219 81 321 134 269 115 b 47 -111 126 23 50 -62 b 47 -112 47 -111 47 -112 b 77 -136 47 -129 58 -136 b 264 -45 118 -136 194 -101 b 382 109 336 12 382 76 b 366 131 382 120 377 129 "},"v83":{"x_min":-1.359375,"x_max":847.96875,"ha":865,"o":"m 488 1499 b 495 1500 490 1500 492 1500 b 541 1465 507 1500 521 1490 b 679 1078 622 1372 679 1210 b 677 1050 679 1068 677 1060 b 477 642 668 893 604 764 l 443 609 l 431 596 l 431 592 l 438 562 l 449 508 l 460 458 b 481 355 475 390 481 355 b 481 355 481 355 481 355 b 490 356 481 355 485 355 b 528 358 495 356 511 358 b 558 356 540 358 552 356 b 839 95 699 338 808 237 b 847 22 845 72 847 47 b 631 -303 847 -113 766 -242 b 620 -309 623 -308 620 -309 l 620 -310 b 631 -359 620 -310 626 -333 l 646 -435 l 660 -496 b 672 -588 668 -535 672 -563 b 664 -653 672 -610 669 -630 b 383 -875 630 -792 509 -875 b 201 -810 321 -875 257 -855 b 129 -680 151 -768 129 -730 b 274 -530 129 -592 200 -530 b 351 -553 300 -530 326 -538 b 412 -669 393 -582 412 -626 b 287 -805 412 -735 366 -800 l 279 -805 l 285 -809 b 383 -830 318 -823 351 -830 b 586 -718 464 -830 540 -789 b 626 -584 612 -678 626 -631 b 619 -528 626 -566 623 -548 b 612 -495 619 -526 616 -510 b 577 -324 590 -387 577 -324 b 577 -324 577 -324 577 -324 b 568 -326 575 -324 571 -324 b 528 -334 558 -328 537 -333 b 465 -338 506 -337 485 -338 b 24 -11 269 -338 87 -206 b -1 145 8 41 -1 93 b 96 442 -1 249 32 351 b 322 714 166 541 236 626 l 352 745 l 345 782 l 332 843 l 315 921 b 303 984 310 950 304 978 b 295 1082 298 1017 295 1049 b 413 1426 295 1208 336 1329 b 488 1499 436 1456 477 1496 m 549 1301 b 541 1301 547 1301 544 1301 b 411 1207 500 1301 447 1263 b 355 1004 374 1152 355 1079 b 359 942 355 984 356 963 b 371 881 362 927 363 917 l 385 818 b 392 782 389 799 392 784 l 392 782 b 434 828 393 782 424 816 b 607 1165 534 941 594 1060 b 608 1193 608 1175 608 1183 b 597 1270 608 1224 604 1254 b 549 1301 589 1286 571 1299 m 398 528 b 393 555 396 542 393 553 b 392 555 393 555 393 555 b 317 470 390 555 347 505 b 190 298 266 408 212 334 b 127 70 148 227 127 148 b 155 -77 127 19 137 -30 b 468 -303 209 -216 333 -303 b 519 -299 484 -303 502 -302 b 568 -284 541 -295 568 -287 l 568 -284 b 563 -263 568 -284 566 -274 l 534 -120 l 511 -13 l 496 61 l 480 133 b 469 187 472 176 469 187 b 468 188 469 187 469 188 b 416 162 462 188 430 172 b 337 13 364 126 337 69 b 413 -124 337 -40 363 -93 b 428 -144 424 -131 428 -137 b 428 -149 428 -145 428 -148 b 409 -166 426 -161 419 -166 b 394 -162 405 -166 400 -165 b 240 77 302 -122 240 -27 l 240 77 b 430 342 240 197 315 301 l 436 344 l 426 394 l 398 528 m 548 194 b 526 195 540 195 532 195 b 519 195 524 195 521 195 l 514 195 l 518 177 l 539 79 l 552 15 l 566 -48 l 594 -187 l 605 -240 b 612 -266 609 -254 611 -266 b 612 -266 612 -266 612 -266 b 641 -248 613 -266 630 -256 b 744 -98 692 -212 730 -156 b 751 -40 749 -79 751 -59 b 548 194 751 76 665 181 "},"v8f":{"x_min":-21.78125,"x_max":362.0625,"ha":369,"o":"m 302 1031 b 308 1032 304 1032 307 1032 b 330 1016 318 1032 325 1027 b 362 867 351 970 362 920 b 340 738 362 824 353 780 l 336 727 l 340 717 b 362 591 355 677 362 634 b 257 323 362 496 325 401 b 204 272 243 306 227 290 b 20 56 129 206 66 133 b -1 18 12 44 0 22 b -19 4 -4 9 -12 4 l -21 4 l -21 140 l -21 276 l -12 277 b 167 333 61 288 127 309 b 319 598 262 388 319 491 b 311 664 319 620 317 642 l 310 673 l 304 664 b 204 548 279 620 250 587 b 20 333 129 483 66 409 b -1 292 12 320 0 298 b -19 280 -4 285 -12 280 l -21 280 l -21 416 l -21 552 l -12 553 b 167 609 61 564 127 585 b 319 874 264 666 319 770 b 294 992 319 914 311 954 b 288 1011 288 1004 288 1007 b 302 1031 288 1021 294 1028 "},"v9a":{"x_min":-21.78125,"x_max":367.5,"ha":375,"o":"m 230 1031 b 238 1032 232 1032 235 1032 b 259 1014 245 1032 251 1027 b 367 662 330 906 367 782 b 364 602 367 641 367 621 b 232 317 352 488 304 384 b 57 120 155 245 103 187 b -1 18 31 84 6 40 b -19 4 -4 11 -12 4 l -21 4 l -21 159 l -21 315 l -16 315 b 96 335 10 315 62 324 b 315 695 227 380 315 527 b 313 738 315 709 314 724 b 224 991 304 825 273 916 b 216 1013 219 999 216 1007 b 230 1031 216 1021 220 1028 "},"va5":{"x_min":0,"x_max":349.8125,"ha":357,"o":"m 88 302 b 103 303 93 302 98 303 b 202 224 149 303 191 270 b 205 199 204 216 205 208 b 178 129 205 173 196 147 l 175 126 l 182 127 b 307 249 236 142 284 190 b 313 259 308 254 311 258 b 329 267 317 265 323 267 b 349 247 340 267 349 259 b 201 -263 349 242 204 -258 b 182 -273 197 -270 190 -273 b 163 -260 174 -273 166 -269 b 161 -256 161 -259 161 -258 b 217 -59 161 -248 170 -220 b 272 129 247 43 272 127 b 272 129 272 129 272 129 b 264 122 272 129 268 126 b 140 80 227 94 183 80 b 36 115 102 80 65 91 b 0 194 10 136 0 165 b 88 302 0 244 32 292 "}},"cssFontWeight":"normal","ascender":1903,"underlinePosition":-125,"cssFontStyle":"normal","boundingBox":{"yMin":-2065.375,"xMin":-695.53125,"yMax":1901.578125,"xMax":1159.671875},"resolution":1000,"descender":-2066,"familyName":"VexNotation-18","lineHeight":4093,"underlineThickness":50};
1  src/fonts/gonville_all.js
1 addition, 0 deletions not shown
1  src/fonts/gonville_original.js
1 addition, 0 deletions not shown
1  src/fonts/vexflow_font.js
@@ -0,0 +1 @@
+Vex.Flow.Font = {"glyphs":{"vb":{"x_min":0,"x_max":428.75,"ha":438,"o":"m 262 186 b 273 186 266 186 272 186 b 274 186 273 186 274 186 b 285 186 274 186 280 186 b 428 48 375 181 428 122 b 386 -68 428 12 416 -29 b 155 -187 329 -145 236 -187 b 12 -111 92 -187 38 -162 b 0 -51 4 -91 0 -72 b 262 186 0 58 122 179 "},"vc":{"x_min":0,"x_max":447.8125,"ha":457,"o":"m 0 86 l 0 173 l 223 173 l 447 173 l 447 86 l 447 0 l 223 0 l 0 0 l 0 86 "},"v18":{"x_min":0,"x_max":323.9375,"ha":331,"o":"m 217 535 b 225 537 220 537 221 537 b 245 524 235 537 242 533 l 246 521 l 247 390 l 247 258 l 273 265 b 306 270 288 269 299 270 b 322 259 315 270 319 267 b 323 208 323 256 323 233 b 322 158 323 184 323 159 b 288 140 318 148 315 147 b 247 130 254 131 247 130 b 247 65 247 130 247 104 b 247 20 247 51 247 36 l 247 -88 l 273 -81 b 306 -76 289 -77 299 -76 b 318 -81 311 -76 315 -77 b 323 -123 323 -87 323 -86 l 323 -138 l 323 -154 b 318 -195 323 -191 323 -190 b 269 -210 314 -199 315 -199 b 249 -216 259 -213 250 -216 l 247 -216 l 247 -349 l 246 -483 l 245 -487 b 225 -499 242 -495 234 -499 b 206 -487 219 -499 210 -495 l 205 -483 l 205 -355 l 205 -227 l 204 -227 l 181 -233 l 138 -244 b 117 -249 127 -247 117 -249 b 115 -385 115 -249 115 -256 l 115 -523 l 114 -526 b 95 -538 110 -534 102 -538 b 74 -526 87 -538 78 -534 l 73 -523 l 73 -391 b 72 -260 73 -269 73 -260 b 72 -260 72 -260 72 -260 b 19 -273 61 -263 23 -273 b 0 -260 10 -273 4 -267 b 0 -209 0 -256 0 -256 l 0 -162 l 1 -158 b 61 -134 5 -148 5 -148 l 73 -131 l 73 -22 b 72 86 73 79 73 86 b 72 86 72 86 72 86 b 19 74 61 83 23 74 b 0 86 10 74 4 79 b 0 137 0 90 0 90 l 0 184 l 1 188 b 61 212 5 198 5 198 l 73 215 l 73 348 l 73 481 l 74 485 b 95 498 78 492 87 498 b 103 495 98 498 100 496 b 114 485 107 494 111 489 l 115 481 l 115 353 l 115 226 l 121 226 b 159 235 123 227 141 231 l 198 247 l 205 248 l 205 384 l 205 521 l 206 524 b 217 535 209 528 212 533 m 205 9 b 205 119 205 70 205 119 l 205 119 b 182 113 204 119 194 116 l 138 102 b 117 97 127 99 117 97 b 115 -12 115 97 115 91 l 115 -122 l 121 -120 b 159 -111 123 -119 141 -115 l 198 -101 l 205 -98 l 205 9 "},"v1d":{"x_min":0,"x_max":619.3125,"ha":632,"o":"m 274 184 b 307 186 285 186 296 186 b 616 22 465 186 597 116 b 619 -1 617 13 619 5 b 308 -187 619 -104 483 -187 b 0 -1 133 -187 0 -102 b 5 36 0 11 1 23 b 274 184 29 115 141 176 m 289 161 b 272 162 284 162 277 162 b 171 41 209 162 171 108 b 205 -73 171 5 182 -34 b 345 -163 243 -133 298 -163 b 436 -98 385 -163 420 -142 b 446 -43 443 -80 446 -62 b 289 161 446 47 377 147 "},"v26":{"x_min":-21.78125,"x_max":483.1875,"ha":493,"o":"m -8 631 b -1 632 -6 632 -4 632 b 19 620 8 632 16 628 b 20 383 20 616 20 616 l 20 148 l 21 151 b 140 199 59 183 102 199 b 206 179 164 199 187 192 l 210 176 l 210 396 l 210 617 l 212 621 b 231 632 216 628 223 632 b 250 620 239 632 247 628 b 251 383 251 616 251 616 l 251 148 l 254 151 b 370 199 291 183 332 199 b 415 191 385 199 400 197 b 483 84 458 176 483 134 b 461 0 483 58 476 29 b 332 -142 439 -40 411 -72 l 255 -215 b 231 -229 240 -229 239 -229 b 216 -223 224 -229 220 -227 b 210 -158 210 -217 210 -223 b 210 -120 210 -148 210 -136 l 210 -29 l 205 -34 b 100 -142 182 -65 159 -88 l 23 -215 b -1 -229 9 -229 6 -229 b -20 -216 -9 -229 -17 -224 l -21 -212 l -21 201 l -21 616 l -20 620 b -8 631 -17 624 -13 630 m 110 131 b 96 133 106 133 100 133 b 89 133 93 133 91 133 b 24 87 63 129 40 113 l 20 80 l 20 -37 l 20 -156 l 23 -152 b 144 81 96 -72 144 20 l 144 83 b 110 131 144 113 134 126 m 341 131 b 328 133 337 133 332 133 b 322 133 326 133 323 133 b 257 87 296 129 273 113 l 251 80 l 251 -37 l 251 -156 l 255 -152 b 375 81 328 -72 375 20 l 375 83 b 341 131 375 113 367 126 "},"v2a":{"x_min":-21.78125,"x_max":366.140625,"ha":374,"o":"m 276 1378 b 284 1379 279 1379 281 1379 b 306 1360 292 1379 298 1374 b 352 1247 326 1326 343 1286 b 366 1139 362 1213 366 1175 b 347 1009 366 1093 359 1049 l 344 1002 l 347 992 b 352 971 348 986 351 977 b 366 863 362 936 366 899 b 347 732 366 818 359 773 l 344 725 l 347 716 b 352 695 348 710 351 700 b 366 588 362 659 366 623 b 223 262 366 464 314 345 b 189 233 212 252 212 252 b 35 76 126 183 73 129 b -1 16 20 56 2 27 b -19 4 -4 9 -12 4 l -21 4 l -21 137 l -21 270 l -17 270 b 186 344 59 281 134 308 b 319 606 270 399 319 499 b 317 650 319 620 319 635 l 315 659 l 314 655 b 223 537 288 607 258 570 b 189 509 212 528 212 528 b 35 352 126 459 73 405 b -1 292 20 333 2 303 b -19 280 -4 285 -12 280 l -21 280 l -21 413 l -21 546 l -17 546 b 186 620 59 557 134 584 b 319 882 270 675 319 775 b 317 925 319 896 319 911 l 315 935 l 314 931 b 223 813 288 884 258 846 b 189 785 212 805 212 805 b 35 628 126 735 73 681 b -1 569 20 609 2 580 b -19 556 -4 562 -12 556 l -21 556 l -21 689 l -21 823 l -17 823 b 202 907 68 835 152 867 b 319 1157 280 968 319 1061 b 270 1338 319 1218 303 1281 b 262 1358 264 1349 262 1353 b 262 1364 262 1360 262 1363 b 276 1378 265 1371 269 1376 "},"v2f":{"x_min":-1.359375,"x_max":680.5625,"ha":694,"o":"m 597 1042 b 604 1042 600 1042 602 1042 b 642 1002 627 1042 642 1022 b 619 966 642 988 635 974 b 439 927 574 942 503 927 l 426 927 l 426 921 b 430 838 428 893 430 866 b 345 480 430 696 398 560 b 179 391 307 423 249 391 b 156 392 171 391 164 392 b 138 394 149 394 142 394 b 103 434 115 396 103 416 b 129 471 103 451 111 466 b 141 474 133 473 137 474 b 172 459 153 474 164 469 b 181 455 175 456 176 455 b 187 456 182 455 185 455 b 253 520 212 460 234 483 b 315 836 294 605 315 714 b 311 928 315 867 314 898 b 302 945 310 943 311 942 b 245 953 283 950 262 953 b 130 891 193 953 149 931 b 84 860 119 870 102 860 b 36 905 61 860 39 877 b 36 910 36 907 36 909 b 80 970 36 931 50 949 b 249 1017 125 1000 187 1017 b 322 1009 273 1017 299 1014 l 341 1003 b 436 991 372 995 406 991 b 577 1031 495 991 545 1004 b 597 1042 583 1038 590 1041 m 416 360 b 424 360 419 360 421 360 b 481 309 454 360 479 338 b 503 145 484 280 495 199 b 585 -185 525 16 555 -106 b 630 -245 596 -213 613 -237 l 634 -247 l 638 -245 b 647 -244 641 -245 645 -244 b 680 -278 666 -244 680 -262 b 664 -308 680 -290 675 -301 b 638 -312 658 -310 650 -312 b 613 -309 631 -312 623 -310 b 477 -201 555 -303 502 -260 b 417 -2 460 -159 434 -72 b 416 5 417 1 416 5 b 416 5 416 5 416 5 b 411 -5 415 5 413 0 b 359 -97 397 -33 377 -70 b 353 -106 355 -102 353 -105 b 359 -112 353 -108 355 -109 b 409 -130 375 -123 390 -129 b 426 -134 420 -130 421 -131 b 431 -147 428 -137 431 -141 b 420 -162 431 -152 427 -159 b 382 -169 409 -166 396 -169 b 323 -155 363 -169 341 -165 l 317 -152 l 314 -155 b 62 -303 240 -240 148 -295 b 36 -305 55 -305 44 -305 b 23 -303 29 -305 24 -305 b -1 -273 6 -299 -1 -287 b 31 -240 -1 -256 10 -240 b 36 -240 32 -240 34 -240 b 42 -241 38 -241 39 -241 b 134 -204 63 -241 99 -226 b 367 288 265 -115 357 81 b 375 330 368 313 370 320 b 416 360 383 347 400 358 m 360 -359 b 379 -359 363 -359 371 -359 b 424 -360 396 -359 416 -359 b 646 -502 536 -373 624 -430 b 649 -527 649 -510 649 -519 b 530 -673 649 -578 604 -635 l 521 -677 l 529 -681 b 653 -811 592 -714 637 -762 b 660 -853 658 -827 660 -839 b 645 -911 660 -873 656 -892 b 426 -1021 608 -981 519 -1021 b 283 -989 377 -1021 328 -1011 b 235 -949 249 -972 239 -964 b 234 -936 234 -946 234 -941 b 234 -928 234 -934 234 -931 l 235 -925 l 234 -927 l 225 -934 b 87 -982 186 -966 138 -982 b 80 -982 85 -982 83 -982 b 55 -981 70 -981 58 -981 b 17 -943 32 -981 17 -964 b 54 -904 17 -921 35 -904 b 78 -914 62 -904 72 -909 l 83 -918 l 88 -918 b 190 -831 122 -918 166 -881 b 269 -506 242 -727 269 -612 b 268 -462 269 -492 269 -477 b 266 -449 266 -458 266 -452 b 265 -444 266 -445 266 -444 b 257 -446 264 -444 261 -445 b 132 -545 196 -470 152 -505 b 88 -573 122 -563 104 -573 b 39 -523 63 -573 39 -553 b 63 -476 39 -505 44 -494 b 360 -359 136 -408 235 -369 m 419 -424 b 393 -423 411 -423 406 -423 l 375 -423 l 377 -426 b 379 -439 377 -427 378 -434 b 383 -510 382 -463 383 -487 b 314 -811 383 -609 360 -710 b 266 -893 296 -850 285 -870 b 264 -898 265 -896 264 -898 l 264 -898 b 264 -898 264 -898 264 -898 b 268 -898 264 -898 266 -898 b 273 -898 270 -898 272 -898 b 300 -909 283 -898 291 -900 b 426 -957 340 -941 385 -957 b 476 -949 443 -957 460 -954 b 547 -853 522 -931 547 -893 b 485 -745 547 -816 526 -775 b 397 -707 460 -727 432 -714 b 366 -675 375 -703 366 -692 b 396 -642 366 -657 377 -645 b 530 -557 455 -637 511 -601 b 536 -527 534 -548 536 -537 b 419 -424 536 -480 490 -437 "},"v3c":{"x_min":0,"x_max":450.53125,"ha":460,"o":"m 189 302 b 204 303 193 302 198 303 b 303 224 250 303 292 270 b 306 199 304 216 306 208 b 279 129 306 173 296 147 l 276 126 l 281 127 b 408 249 337 142 385 190 b 412 259 409 254 412 258 b 430 267 417 265 423 267 b 450 247 441 267 450 259 b 200 -605 450 242 204 -599 b 182 -616 197 -612 190 -616 b 163 -602 174 -616 166 -610 b 161 -598 161 -601 161 -601 b 217 -402 161 -589 170 -562 b 272 -213 247 -298 272 -213 b 272 -213 272 -213 272 -213 b 264 -219 272 -213 268 -216 b 140 -262 227 -247 182 -262 b 36 -226 102 -262 65 -249 b 0 -145 12 -206 0 -176 b 17 -84 0 -124 5 -104 b 103 -38 38 -54 70 -38 b 191 -91 137 -38 172 -56 b 205 -141 201 -106 205 -124 b 178 -212 205 -167 196 -194 l 175 -215 l 182 -213 b 307 -93 236 -198 284 -151 b 372 129 308 -88 372 127 b 372 129 372 129 372 129 b 364 122 372 129 368 126 b 240 80 328 94 283 80 b 137 115 202 80 166 91 b 99 194 111 136 99 165 b 189 302 99 244 133 292 "},"v3e":{"x_min":0,"x_max":406.96875,"ha":415,"o":"m 21 183 b 28 183 24 183 25 183 b 42 181 34 183 39 183 b 127 108 47 179 47 179 b 202 41 168 72 202 41 b 279 108 204 41 238 72 b 357 177 321 145 356 176 b 375 183 363 181 370 183 b 406 151 392 183 406 169 b 404 137 406 147 405 141 b 322 62 401 131 398 129 b 251 0 284 27 251 0 b 322 -63 251 -1 284 -29 b 404 -138 398 -130 401 -133 b 406 -152 405 -142 406 -148 b 375 -184 406 -170 392 -184 b 357 -179 370 -184 363 -183 b 279 -109 356 -177 321 -147 b 202 -43 238 -73 204 -43 b 127 -109 202 -43 168 -73 b 49 -179 85 -147 50 -177 b 31 -184 43 -183 36 -184 b 0 -152 13 -184 0 -170 b 2 -138 0 -148 0 -142 b 83 -63 5 -133 8 -130 b 155 0 122 -29 155 -1 b 83 62 155 0 122 27 b 8 129 43 97 10 127 b 0 151 2 136 0 144 b 21 183 0 165 8 177 "},"v3f":{"x_min":-24.5,"x_max":317.140625,"ha":324,"o":"m -24 -147 l -24 -5 l -20 -5 b -1 -19 -12 -5 -4 -11 b 58 -123 6 -43 31 -86 b 196 -278 93 -173 134 -219 b 317 -570 274 -356 317 -460 b 294 -713 317 -617 308 -666 l 289 -724 l 294 -735 b 317 -873 308 -780 317 -827 b 235 -1132 317 -963 288 -1054 b 209 -1165 228 -1140 224 -1146 b 189 -1177 204 -1172 196 -1177 b 171 -1164 182 -1177 175 -1172 b 168 -1154 170 -1161 168 -1159 b 181 -1132 168 -1149 172 -1142 b 269 -891 238 -1064 269 -975 b 269 -881 269 -886 269 -884 b 262 -814 269 -857 265 -827 b 258 -800 261 -811 259 -806 b 142 -628 240 -731 198 -667 b -8 -589 112 -606 47 -589 b -20 -589 -13 -589 -19 -589 l -24 -589 l -24 -449 l -24 -308 l -20 -308 b -1 -322 -12 -308 -4 -313 b 58 -424 6 -345 31 -388 b 194 -580 93 -476 136 -523 b 259 -660 221 -606 245 -635 b 261 -663 259 -662 261 -663 b 264 -656 262 -663 262 -660 b 269 -587 268 -632 269 -610 b 264 -521 269 -566 268 -544 b 262 -512 264 -517 262 -513 b 258 -498 261 -509 259 -503 b 142 -326 240 -428 198 -365 b -8 -287 112 -303 47 -288 b -20 -287 -13 -287 -19 -287 l -24 -287 l -24 -147 "},"v44":{"x_min":-21.78125,"x_max":251.8125,"ha":257,"o":"m -8 631 b -1 632 -6 632 -4 632 b 19 620 8 632 16 628 b 20 383 20 616 20 616 l 20 148 l 21 151 b 137 199 59 183 99 199 b 182 191 152 199 167 197 b 251 84 227 176 251 134 b 228 0 251 58 243 29 b 100 -142 206 -40 178 -72 l 23 -215 b 0 -229 9 -229 6 -229 b -20 -216 -9 -229 -17 -224 l -21 -212 l -21 201 l -21 616 l -20 620 b -8 631 -17 624 -13 630 m 110 131 b 96 133 106 133 100 133 b 89 133 93 133 91 133 b 24 87 63 129 40 113 l 20 80 l 20 -37 l 20 -156 l 23 -152 b 144 81 96 -72 144 20 l 144 83 b 110 131 144 113 134 126 "},"v47":{"x_min":-24.5,"x_max":315.78125,"ha":322,"o":"m -24 -145 l -24 -5 l -20 -5 b 1 -26 -10 -5 -6 -9 b 175 -241 31 -86 96 -166 b 314 -548 259 -323 304 -420 b 315 -589 315 -555 315 -571 b 314 -630 315 -606 315 -623 b 298 -730 311 -664 306 -699 l 295 -742 l 296 -748 b 314 -850 304 -778 311 -813 b 315 -892 315 -857 315 -874 b 314 -932 315 -909 315 -925 b 298 -1032 311 -967 306 -1002 l 295 -1045 l 296 -1050 b 314 -1153 304 -1081 311 -1115 b 315 -1193 315 -1160 315 -1177 b 314 -1235 315 -1211 315 -1228 b 217 -1526 306 -1338 270 -1444 b 201 -1533 213 -1532 208 -1533 b 182 -1522 193 -1533 185 -1529 b 179 -1514 181 -1518 179 -1517 b 189 -1489 179 -1508 182 -1501 b 266 -1217 240 -1403 266 -1308 b 262 -1156 266 -1196 265 -1177 b 110 -907 247 -1043 190 -950 b 0 -889 87 -895 50 -889 l -1 -889 l -24 -889 l -24 -749 l -24 -610 l -20 -610 b 1 -631 -10 -610 -6 -614 b 175 -846 31 -691 96 -771 b 259 -956 213 -884 236 -914 b 265 -966 262 -961 264 -966 b 265 -966 265 -966 265 -966 b 265 -953 265 -964 265 -959 b 266 -920 266 -943 266 -932 b 262 -853 266 -898 265 -873 b 110 -605 247 -741 190 -648 b 0 -587 87 -592 50 -587 l -1 -587 l -24 -587 l -24 -448 l -24 -308 l -20 -308 b 1 -328 -10 -308 -6 -312 b 175 -544 31 -388 96 -469 b 259 -655 213 -581 236 -612 b 265 -663 262 -659 264 -663 b 265 -663 265 -663 265 -663 b 265 -650 265 -663 265 -657 b 266 -617 266 -641 266 -630 b 262 -551 266 -595 265 -570 b 110 -303 247 -438 190 -345 b 0 -284 87 -290 50 -284 l -1 -284 l -24 -284 l -24 -145 "},"v4e":{"x_min":0,"x_max":239.5625,"ha":244,"o":"m 10 460 b 20 462 13 462 14 462 b 39 449 28 462 35 458 l 40 446 l 40 326 b 40 205 40 259 40 205 b 127 227 40 205 80 215 b 220 249 196 244 213 249 b 227 247 224 249 225 248 b 238 237 231 245 235 241 l 239 233 l 239 -106 l 239 -448 l 238 -451 b 219 -463 234 -459 225 -463 b 198 -451 210 -463 202 -459 l 197 -448 l 197 -324 b 197 -201 197 -248 197 -201 b 110 -223 196 -201 157 -210 b 17 -245 42 -240 24 -245 b 10 -242 13 -245 13 -244 b 0 -233 6 -241 2 -237 l 0 -230 l 0 108 l 0 446 l 0 449 b 10 460 2 453 6 458 m 197 22 b 197 70 197 41 197 58 b 196 116 197 113 197 116 l 196 116 b 118 97 196 116 160 106 l 40 77 l 40 -18 b 40 -112 40 -69 40 -112 l 119 -93 l 197 -73 l 197 22 "},"v54":{"x_min":-24.5,"x_max":317.140625,"ha":324,"o":"m -24 -161 l -24 -5 l -20 -5 b 0 -24 -9 -5 -2 -12 b 171 -315 21 -124 84 -233 b 317 -660 268 -406 317 -531 b 187 -1014 317 -782 274 -909 b 161 -1034 172 -1034 171 -1034 b 141 -1013 149 -1034 141 -1025 b 152 -991 141 -1004 142 -1002 b 266 -682 228 -899 266 -788 b 174 -430 266 -588 236 -498 b -23 -317 136 -388 66 -348 b -24 -161 -23 -316 -24 -285 "},"v55":{"x_min":0,"x_max":551.25,"ha":563,"o":"m 289 644 b 304 645 294 645 299 645 b 404 566 349 645 392 613 b 406 541 405 557 406 549 b 379 471 406 514 397 489 l 377 467 l 382 470 b 509 591 438 485 485 531 b 513 601 510 595 513 599 b 530 609 518 607 524 609 b 551 588 540 609 551 602 b 200 -605 551 584 204 -599 b 182 -616 197 -612 190 -616 b 163 -602 174 -616 166 -610 b 161 -598 161 -601 161 -601 b 217 -402 161 -589 170 -562 b 272 -213 247 -298 272 -213 b 272 -213 272 -213 272 -213 b 264 -219 272 -213 268 -216 b 140 -262 227 -247 182 -262 b 36 -226 102 -262 65 -249 b 0 -145 12 -206 0 -176 b 17 -84 0 -124 5 -104 b 103 -38 38 -54 70 -38 b 191 -91 137 -38 172 -56 b 205 -141 201 -106 205 -124 b 178 -212 205 -167 196 -194 l 175 -215 l 182 -213 b 307 -93 236 -198 284 -151 b 372 129 308 -88 372 127 b 372 129 372 129 372 129 b 364 122 372 129 368 126 b 240 80 328 94 283 80 b 137 115 202 80 166 91 b 99 195 112 136 99 165 b 118 256 99 217 106 238 b 204 303 138 287 171 303 b 292 249 238 303 273 285 b 306 199 302 234 306 217 b 279 129 306 173 296 148 l 276 126 l 281 127 b 408 248 336 142 385 190 b 473 470 409 254 473 469 b 473 470 473 470 473 470 b 465 464 473 470 469 467 b 341 421 428 435 383 421 b 236 458 303 421 266 433 b 200 537 212 478 200 508 b 289 644 200 585 234 635 "},"v5c":{"x_min":0,"x_max":447.8125,"ha":457,"o":"m 0 -87 l 0 0 l 223 0 l 447 0 l 447 -87 l 447 -174 l 223 -174 l 0 -174 l 0 -87 "},"v7c":{"x_min":0,"x_max":300.8125,"ha":307,"o":"m 49 505 b 53 506 50 505 51 506 b 70 496 58 506 62 503 b 81 485 73 492 78 488 l 96 473 l 111 459 l 122 449 l 134 438 l 182 396 l 255 330 b 292 291 292 298 292 298 l 292 290 l 292 284 l 283 270 b 209 36 234 197 209 113 b 288 -170 209 -44 235 -119 b 299 -184 295 -179 299 -181 b 300 -191 300 -187 300 -188 b 285 -206 300 -199 294 -206 b 280 -206 283 -206 281 -206 b 247 -201 270 -202 259 -201 b 176 -222 223 -201 197 -208 b 114 -340 136 -249 114 -292 b 172 -471 114 -384 134 -433 b 185 -492 182 -481 185 -487 b 181 -502 185 -496 183 -499 b 171 -508 176 -505 174 -508 b 152 -498 166 -508 160 -503 b 0 -284 65 -428 12 -352 b 0 -260 0 -278 0 -270 b 1 -238 0 -252 0 -242 b 148 -140 16 -177 73 -140 b 209 -148 167 -140 189 -142 b 215 -149 212 -148 215 -149 b 215 -149 215 -149 215 -149 l 215 -149 b 201 -136 215 -148 209 -142 l 157 -97 l 96 -41 b 17 34 21 24 17 29 b 17 37 17 36 17 36 b 17 38 17 37 17 38 b 25 56 17 44 17 44 b 110 298 81 131 110 219 b 46 474 110 367 88 431 b 38 491 40 480 38 487 b 49 505 38 498 42 502 "},"v7f":{"x_min":0,"x_max":367.5,"ha":375,"o":"m 0 124 l 0 187 l 61 187 l 122 187 l 122 138 l 122 91 l 153 61 l 183 30 l 213 61 l 243 91 l 243 138 l 243 187 l 306 187 l 367 187 l 367 124 l 367 61 l 321 61 l 274 61 l 243 30 l 213 0 l 243 -31 l 274 -62 l 321 -62 l 367 -62 l 367 -124 l 367 -188 l 306 -188 l 243 -188 l 243 -140 l 243 -93 l 213 -62 l 183 -31 l 153 -62 l 122 -93 l 122 -140 l 122 -188 l 61 -188 l 0 -188 l 0 -124 l 0 -62 l 46 -62 l 92 -62 l 123 -31 l 153 0 l 123 30 l 92 61 l 46 61 l 0 61 l 0 124 "},"v81":{"x_min":0,"x_max":428.75,"ha":438,"o":"m 262 186 b 273 186 266 186 272 186 b 274 186 273 186 274 186 b 285 186 274 186 280 186 b 428 48 375 181 428 122 b 386 -68 428 12 416 -29 b 155 -187 329 -145 236 -187 b 12 -111 92 -187 38 -162 b 0 -51 4 -91 0 -72 b 262 186 0 58 122 179 m 366 131 b 352 134 362 133 357 134 b 219 81 321 134 269 115 b 47 -111 126 23 50 -62 b 47 -112 47 -111 47 -112 b 77 -136 47 -129 58 -136 b 264 -45 118 -136 194 -101 b 382 109 336 12 382 76 b 366 131 382 120 377 129 "},"v83":{"x_min":-1.359375,"x_max":847.96875,"ha":865,"o":"m 488 1499 b 495 1500 490 1500 492 1500 b 541 1465 507 1500 521 1490 b 679 1078 622 1372 679 1210 b 677 1050 679 1068 677 1060 b 477 642 668 893 604 764 l 443 609 l 431 596 l 431 592 l 438 562 l 449 508 l 460 458 b 481 355 475 390 481 355 b 481 355 481 355 481 355 b 490 356 481 355 485 355 b 528 358 495 356 511 358 b 558 356 540 358 552 356 b 839 95 699 338 808 237 b 847 22 845 72 847 47 b 631 -303 847 -113 766 -242 b 620 -309 623 -308 620 -309 l 620 -310 b 631 -359 620 -310 626 -333 l 646 -435 l 660 -496 b 672 -588 668 -535 672 -563 b 664 -653 672 -610 669 -630 b 383 -875 630 -792 509 -875 b 201 -810 321 -875 257 -855 b 129 -680 151 -768 129 -730 b 274 -530 129 -592 200 -530 b 351 -553 300 -530 326 -538 b 412 -669 393 -582 412 -626 b 287 -805 412 -735 366 -800 l 279 -805 l 285 -809 b 383 -830 318 -823 351 -830 b 586 -718 464 -830 540 -789 b 626 -584 612 -678 626 -631 b 619 -528 626 -566 623 -548 b 612 -495 619 -526 616 -510 b 577 -324 590 -387 577 -324 b 577 -324 577 -324 577 -324 b 568 -326 575 -324 571 -324 b 528 -334 558 -328 537 -333 b 465 -338 506 -337 485 -338 b 24 -11 269 -338 87 -206 b -1 145 8 41 -1 93 b 96 442 -1 249 32 351 b 322 714 166 541 236 626 l 352 745 l 345 782 l 332 843 l 315 921 b 303 984 310 950 304 978 b 295 1082 298 1017 295 1049 b 413 1426 295 1208 336 1329 b 488 1499 436 1456 477 1496 m 549 1301 b 541 1301 547 1301 544 1301 b 411 1207 500 1301 447 1263 b 355 1004 374 1152 355 1079 b 359 942 355 984 356 963 b 371 881 362 927 363 917 l 385 818 b 392 782 389 799 392 784 l 392 782 b 434 828 393 782 424 816 b 607 1165 534 941 594 1060 b 608 1193 608 1175 608 1183 b 597 1270 608 1224 604 1254 b 549 1301 589 1286 571 1299 m 398 528 b 393 555 396 542 393 553 b 392 555 393 555 393 555 b 317 470 390 555 347 505 b 190 298 266 408 212 334 b 127 70 148 227 127 148 b 155 -77 127 19 137 -30 b 468 -303 209 -216 333 -303 b 519 -299 484 -303 502 -302 b 568 -284 541 -295 568 -287 l 568 -284 b 563 -263 568 -284 566 -274 l 534 -120 l 511 -13 l 496 61 l 480 133 b 469 187 472 176 469 187 b 468 188 469 187 469 188 b 416 162 462 188 430 172 b 337 13 364 126 337 69 b 413 -124 337 -40 363 -93 b 428 -144 424 -131 428 -137 b 428 -149 428 -145 428 -148 b 409 -166 426 -161 419 -166 b 394 -162 405 -166 400 -165 b 240 77 302 -122 240 -27 l 240 77 b 430 342 240 197 315 301 l 436 344 l 426 394 l 398 528 m 548 194 b 526 195 540 195 532 195 b 519 195 524 195 521 195 l 514 195 l 518 177 l 539 79 l 552 15 l 566 -48 l 594 -187 l 605 -240 b 612 -266 609 -254 611 -266 b 612 -266 612 -266 612 -266 b 641 -248 613 -266 630 -256 b 744 -98 692 -212 730 -156 b 751 -40 749 -79 751 -59 b 548 194 751 76 665 181 "},"v8f":{"x_min":-21.78125,"x_max":362.0625,"ha":369,"o":"m 302 1031 b 308 1032 304 1032 307 1032 b 330 1016 318 1032 325 1027 b 362 867 351 970 362 920 b 340 738 362 824 353 780 l 336 727 l 340 717 b 362 591 355 677 362 634 b 257 323 362 496 325 401 b 204 272 243 306 227 290 b 20 56 129 206 66 133 b -1 18 12 44 0 22 b -19 4 -4 9 -12 4 l -21 4 l -21 140 l -21 276 l -12 277 b 167 333 61 288 127 309 b 319 598 262 388 319 491 b 311 664 319 620 317 642 l 310 673 l 304 664 b 204 548 279 620 250 587 b 20 333 129 483 66 409 b -1 292 12 320 0 298 b -19 280 -4 285 -12 280 l -21 280 l -21 416 l -21 552 l -12 553 b 167 609 61 564 127 585 b 319 874 264 666 319 770 b 294 992 319 914 311 954 b 288 1011 288 1004 288 1007 b 302 1031 288 1021 294 1028 "},"v9a":{"x_min":-21.78125,"x_max":367.5,"ha":375,"o":"m 230 1031 b 238 1032 232 1032 235 1032 b 259 1014 245 1032 251 1027 b 367 662 330 906 367 782 b 364 602 367 641 367 621 b 232 317 352 488 304 384 b 57 120 155 245 103 187 b -1 18 31 84 6 40 b -19 4 -4 11 -12 4 l -21 4 l -21 159 l -21 315 l -16 315 b 96 335 10 315 62 324 b 315 695 227 380 315 527 b 313 738 315 709 314 724 b 224 991 304 825 273 916 b 216 1013 219 999 216 1007 b 230 1031 216 1021 220 1028 "},"va5":{"x_min":0,"x_max":349.8125,"ha":357,"o":"m 88 302 b 103 303 93 302 98 303 b 202 224 149 303 191 270 b 205 199 204 216 205 208 b 178 129 205 173 196 147 l 175 126 l 182 127 b 307 249 236 142 284 190 b 313 259 308 254 311 258 b 329 267 317 265 323 267 b 349 247 340 267 349 259 b 201 -263 349 242 204 -258 b 182 -273 197 -270 190 -273 b 163 -260 174 -273 166 -269 b 161 -256 161 -259 161 -258 b 217 -59 161 -248 170 -220 b 272 129 247 43 272 127 b 272 129 272 129 272 129 b 264 122 272 129 268 126 b 140 80 227 94 183 80 b 36 115 102 80 65 91 b 0 194 10 136 0 165 b 88 302 0 244 32 292 "}},"cssFontWeight":"normal","ascender":1903,"underlinePosition":-125,"cssFontStyle":"normal","boundingBox":{"yMin":-2065.375,"xMin":-695.53125,"yMax":1901.578125,"xMax":1159.671875},"resolution":1000,"descender":-2066,"familyName":"VexNotation-18","lineHeight":4093,"underlineThickness":50};
199 src/formatter.js
@@ -0,0 +1,199 @@
+// Vex Music Notation
+// Mohit Muthanna <mohit@muthanna.com>
+//
+// Copyright Mohit Muthanna 2010
+
+/** @constructor */
+Vex.Flow.Formatter = function(){
+ this.minTotalWidth = 0;
+ this.minTicks = null;
+ this.pixelsPerTick = 0;
+ this.totalTicks = 0;
+ this.tContexts = null;
+
+ this.render_options = {
+ perTickableWidth: 15,
+ maxExtraWidthPerTickable: 40
+ };
+}
+
+// Helper function to format and draw a single voice
+Vex.Flow.Formatter.FormatAndDraw = function(ctx, stave, notes, width) {
+ var voice = new Vex.Flow.Voice(Vex.Flow.TIME4_4).setStrict(false);
+ voice.addTickables(notes);
+
+ var formatter = new Vex.Flow.Formatter().joinVoices([voice]).
+ format([voice], width);
+
+ voice.draw(ctx, stave);
+}
+
+// Helper function to format and draw a single voice
+Vex.Flow.Formatter.FormatAndDrawTab = function(ctx,
+ tabstave, stave, tabnotes, notes, width) {
+ var tabvoice = new Vex.Flow.Voice(Vex.Flow.TIME4_4).setStrict(false);
+ tabvoice.addTickables(tabnotes);
+
+ var notevoice = new Vex.Flow.Voice(Vex.Flow.TIME4_4).setStrict(false);
+ notevoice.addTickables(notes);
+
+ var formatter = new Vex.Flow.Formatter().
+ joinVoices([tabvoice]).
+ joinVoices([notevoice]).
+ format([tabvoice, notevoice], width);
+
+ tabvoice.draw(ctx, tabstave);
+ notevoice.draw(ctx, stave);
+}
+
+Vex.Flow.Formatter.prototype.getMinTotalWidth = function() {
+ return this.minTotalWidth; }
+
+/**
+ * Take a set of voices and place aligned tickables in the same modifier
+ * context.
+ */
+Vex.Flow.Formatter.createContexts = function(voices, context_type, add_fn) {
+ if (!voices || !voices.length) throw new Vex.RERR("BadArgument",
+ "No voices to format");
+
+ var totalTicks = voices[0].getTotalTicks();
+ var tickToContextMap = {};
+ var tickList = [];
+
+ for (var i = 0; i < voices.length; ++i) {
+ var voice = voices[i];
+ if (voice.getTotalTicks() != totalTicks)
+ throw new Vex.RERR("TickMismatch",
+ "Voices should have same time signature.");
+
+ if (!voice.isComplete()) throw new Vex.RERR("IncompleteVoice",
+ "Voice does not have enough notes.");
+
+ var tickables = voice.getTickables();
+ var ticksUsed = 0;
+ for (var j = 0; j < tickables.length; ++j) {
+ var tickable = tickables[j];
+
+ // If we have no tick context for this tick, create one
+ if (!tickToContextMap[ticksUsed])
+ tickToContextMap[ticksUsed] = new context_type();
+
+ // Add this tickable to the TickContext
+ add_fn(tickable, tickToContextMap[ticksUsed]);
+
+ // Maintain a sorted list of tick contexts
+ tickList.push(ticksUsed);
+ ticksUsed += tickable.getTicks();
+ }
+ }
+
+ return {
+ map: tickToContextMap,
+ list: Vex.SortAndUnique(tickList, function(a, b) { return a - b; })
+ };
+}
+
+Vex.Flow.Formatter.prototype.createModifierContexts = function(voices) {
+ var contexts = Vex.Flow.Formatter.createContexts(voices,
+ Vex.Flow.ModifierContext,
+ function(tickable, context) {
+ tickable.addToModifierContext(context);
+ });
+ return contexts;
+}
+
+/**
+ * Take a set of voices and place aligned tickables in the same modifier
+ * tick context.
+ */
+Vex.Flow.Formatter.prototype.createTickContexts = function(voices) {
+ var contexts = Vex.Flow.Formatter.createContexts(voices,
+ Vex.Flow.TickContext,
+ function(tickable, context) { context.addTickable(tickable); });
+
+ this.totalTicks = voices[0].getTicksUsed();
+ this.tContexts = contexts;
+ return contexts;
+}
+
+/**
+ * Take a set of tick contexts and align thier X-positions and space usage.
+ */
+Vex.Flow.Formatter.prototype.preFormat = function(justifyWidth) {
+ var contexts = this.tContexts;
+ var contextList = contexts.list;
+ var contextMap = contexts.map;
+
+ this.minTotalWidth = 0;
+
+ // Go through each tick context and calculate total width and smallest
+ // ticks.
+ for (var i = 0; i < contextList.length; ++i) {
+ var context = contextMap[contextList[i]];
+
+ // preFormat() gets them to descend down to their tickables and modifier
+ // contexts, and calculate their widths.
+ context.preFormat();
+ this.minTotalWidth += context.getWidth();
+
+ var minTicks = context.getMinTicks();
+ if (i == 0) this.minTicks = minTicks;
+ if (minTicks < this.minTicks) this.minTicks = minTicks;
+ }
+
+ if (justifyWidth < this.minTotalWidh) throw new Vex.RERR("NoRoomForNotes",
+ "Justification width too small to fit all notes.");
+
+ // Figure out how many pixels to allocate per tick.
+ var justified = false;
+ if (justifyWidth) {
+ this.pixelsPerTick = justifyWidth / this.totalTicks;
+ justified = true;
+ } else {
+ this.pixelsPerTick = this.render_options.perTickableWidth / this.minTicks;
+ }
+
+ // Now distribute the ticks to each tick context, and assign them their
+ // own X positions.
+ var x = 0;
+ for (var i = 0; i < contextList.length; ++i) {
+ var tick = contextList[i];
+ var context = contextMap[tick];
+ var width = context.getWidth();
+ var minTicks = context.getMinTicks();
+
+ var pixels_used = Math.max(width, minTicks * this.pixelsPerTick);
+ pixels_used = Math.min(width + 20, pixels_used);
+
+ var set_x = x;
+
+ if (!justified) {
+ // Rate limit pixel usage
+ var maxWidth = width + this.render_options.maxExtraWidthPerTickable;
+ if (pixels_used > maxWidth) pixels_used = maxWidth;
+ } else {
+ set_x = tick * this.pixelsPerTick;
+
+ // Make way for accidentals, etc. Prefer pushing out over the edge
+ // to overlapping over other notes.
+ if (set_x < x) set_x += (x - set_x);
+ }
+
+ context.setX(set_x);
+ context.setPixelsUsed(pixels_used);
+
+ x += pixels_used;
+ }
+}
+
+Vex.Flow.Formatter.prototype.joinVoices = function(voices) {
+ this.createModifierContexts(voices);
+ return this;
+}
+
+Vex.Flow.Formatter.prototype.format = function(voices, justifyWidth) {
+ this.createTickContexts(voices);
+ this.preFormat(justifyWidth);
+ return this;
+}
40 src/ghostnote.js
@@ -0,0 +1,40 @@
+// Vex Flow Notation
+// Mohit Muthanna <mohit@muthanna.com>
+//
+// Copyright Mohit Muthanna 2010
+//
+// Requires vex.js.
+
+/** @constructor */
+Vex.Flow.GhostNote = function(duration) {
+ if (arguments.length > 0) this.init(duration); }
+Vex.Flow.GhostNote.prototype = new Vex.Flow.Note();
+Vex.Flow.GhostNote.superclass = Vex.Flow.Note.prototype;
+Vex.Flow.GhostNote.constructor = Vex.Flow.GhostNote;
+
+Vex.Flow.GhostNote.prototype.init = function(duration) {
+ var superclass = Vex.Flow.GhostNote.superclass;
+ superclass.init.call(this, duration);
+
+ // Note properties
+ this.setWidth(0);
+}
+
+Vex.Flow.GhostNote.prototype.setStave = function(stave) {
+ var superclass = Vex.Flow.GhostNote.superclass;
+ superclass.setStave.call(this, stave);
+}
+
+Vex.Flow.GhostNote.prototype.addToModifierContext = function(mc) {
+ return this;
+}
+
+Vex.Flow.GhostNote.prototype.preFormat = function() {
+ this.setPreFormatted(true);
+ return this;
+}
+
+Vex.Flow.GhostNote.prototype.draw = function() {
+ if (!this.stave) throw new Vex.RERR("NoStave", "Can't draw without a stave.");
+ // Nothing to draw
+}
179 src/glyph.js
@@ -0,0 +1,179 @@
+// Vex Flow
+// Mohit Muthanna <mohit@muthanna.com>
+//
+// Copyright Mohit Muthanna 2010
+//
+// Requires a glyph font to be loaded and Vex.Flow.Font to be set.
+
+/**
+ * A quick and dirty static glyph renderer. Renders glyphs from the default
+ * font defined in Vex.Flow.Font.
+ *
+ * @param {!Object} ctx The canvas context.
+ * @param {number} x_pos X coordinate.
+ * @param {number} y_pos Y coordinate.
+ * @param {number} point The point size to use.
+ * @param {string} val The glyph code in Vex.Flow.Font.
+ * @param {boolean} nocache If set, disables caching of font outline.
+ */
+Vex.Flow.renderGlyph = function(ctx, x_pos, y_pos, point, val, nocache) {
+ var scale = point * 72 / (Vex.Flow.Font.resolution * 100);
+ var metrics = Vex.Flow.Glyph.loadMetrics(Vex.Flow.Font, val, !nocache);
+ Vex.Flow.Glyph.renderOutline(ctx, metrics.outline, scale, x_pos, y_pos);
+}
+
+/**
+ * @constructor
+ */
+Vex.Flow.Glyph = function(code, point, options) {
+ this.code = code;
+ this.point = point;
+ this.context = null;
+ this.options = {
+ cache: true,
+ font: Vex.Flow.Font
+ };
+
+ this.width = null;
+ this.metrics = null;
+ this.x_shift = 0;
+ this.y_shift = 0;
+
+ if (options) this.setOptions(options); else this.reset();
+}
+
+Vex.Flow.Glyph.prototype.setOptions = function(options) {
+ Vex.Merge(this.options, options);
+ this.reset();
+}
+
+Vex.Flow.Glyph.prototype.setStave = function(stave) {
+ this.stave = stave; return this; }
+Vex.Flow.Glyph.prototype.setXShift = function(x_shift) {
+ this.x_shift = x_shift; return this; }
+Vex.Flow.Glyph.prototype.setYShift = function(y_shift) {
+ this.y_shift = y_shift; return this; }
+Vex.Flow.Glyph.prototype.setContext = function(context) {
+ this.context = context; return this; }
+Vex.Flow.Glyph.prototype.getContext = function(context) {
+ return this.context; }
+
+Vex.Flow.Glyph.prototype.reset = function() {
+ this.metrics = Vex.Flow.Glyph.loadMetrics(this.options.font, this.code,
+ this.options.cache);
+ this.scale = this.point * 72 / (this.options.font.resolution * 100);
+}
+
+Vex.Flow.Glyph.prototype.getMetrics = function() {
+ if (!this.metrics) throw new Vex.RuntimeError("BadGlyph", "Glyph " +
+ this.code + " is not initialized.");
+ return {
+ x_min: this.metrics.x_min * this.scale,
+ x_max: this.metrics.x_max * this.scale,
+ width: (this.metrics.x_max - this.metrics.x_min) * this.scale
+ };
+}
+
+Vex.Flow.Glyph.prototype.render = function(ctx, x_pos, y_pos) {
+ if (!this.metrics) throw new Vex.RuntimeError("BadGlyph", "Glyph " +
+ this.code + " is not initialized.");
+
+ var outline = this.metrics.outline;
+ var scale = this.scale;
+ var outlineLength = outline.length;
+
+ Vex.Flow.Glyph.renderOutline(ctx, outline, scale, x_pos, y_pos);
+}
+
+Vex.Flow.Glyph.prototype.renderToStave = function(x) {
+ if (!this.metrics) throw new Vex.RuntimeError("BadGlyph", "Glyph " +
+ this.code + " is not initialized.");
+ if (!this.stave) throw new Vex.RuntimeError("GlyphError", "No valid stave");
+ if (!this.context) throw new Vex.RERR("GlyphError", "No valid context");
+
+ var outline = this.metrics.outline;
+ var scale = this.scale;
+ var outlineLength = outline.length;
+
+ Vex.Flow.Glyph.renderOutline(this.context, outline, scale,
+ x + this.x_shift, this.stave.getYForGlyphs() + this.y_shift);
+}
+
+/* Static methods used to implement loading / unloading of glyphs */
+
+Vex.Flow.Glyph.loadMetrics = function(font, code, cache) {
+ var glyph = font.glyphs[code];
+ if (!glyph) throw new Vex.RuntimeError("BadGlyph", "Glyph " + code +
+ " does not exist in font.");
+
+ var x_min = glyph["x_min"];
+ var x_max = glyph["x_max"];
+
+ var outline;
+
+ if (glyph["o"]) {
+ if (cache) {
+ if (glyph.cached_outline) {
+ outline = glyph.cached_outline;
+ } else {
+ outline = glyph["o"].split(' ');
+ glyph.cached_outline = outline;
+ }
+ } else {
+ if (glyph.cached_outline) delete glyph.cached_outline;
+ outline = glyph["o"].split(' ');
+ }
+
+ return {
+ x_min: x_min,
+ x_max: x_max,
+ outline: outline
+ };
+ } else {
+ throw new Vex.RuntimeError("BadGlyph", "Glyph " + this.code +
+ " has no outline defined.");
+ }
+}
+
+Vex.Flow.Glyph.renderOutline = function(ctx, outline, scale, x_pos, y_pos) {
+ var outlineLength = outline.length;
+
+ ctx.beginPath();
+
+ ctx.moveTo(x_pos, y_pos);
+
+ for (var i = 0; i < outlineLength; ) {
+ var action = outline[i++];
+
+ switch(action) {
+ case 'm':
+ ctx.moveTo(x_pos + outline[i++] * scale,
+ y_pos + outline[i++] * -scale);
+ break;
+ case 'l':
+ ctx.lineTo(x_pos + outline[i++] * scale,
+ y_pos + outline[i++] * -scale);
+ break;
+
+ case 'q':
+ var cpx = x_pos + outline[i++] * scale;
+ var cpy = y_pos + outline[i++] * -scale;
+
+ ctx.quadraticCurveTo(
+ x_pos + outline[i++] * scale,
+ y_pos + outline[i++] * -scale, cpx, cpy);
+ break;
+
+ case 'b':
+ var x = x_pos + outline[i++] * scale;
+ var y = y_pos + outline[i++] * -scale;
+
+ ctx.bezierCurveTo(
+ x_pos + outline[i++] * scale, y_pos + outline[i++] * -scale,
+ x_pos + outline[i++] * scale, y_pos + outline[i++] * -scale,
+ x, y);
+ break;
+ }
+ }
+ ctx.fill();
+}
122 src/glyphs.html
@@ -0,0 +1,122 @@
+<html>
+
+<head>
+ <title>Vex Glyphs</title>
+ <script src="../tests/support/jquery.js"
+ type="text/javascript" charset="utf-8"></script>
+ <style type="text/css">
+ body {
+ padding: 20px;
+ background: white;
+ font-family: Caslon, Garamond, Arial, Helvetica, sans-serif;
+ font-size: 18px;
+ color: green;
+ margin: 0px;
+ height: 80%;
+ }
+
+ a {
+ color: #green;
+ text-decoration: none;
+ border-bottom: dotted 2px;
+ }
+
+ a.button {
+ color: #green;
+ background: #bfb;
+ text-decoration: none;
+ padding: 5px;
+ margin: 2px;
+ border: 5px solid #aea;
+ }
+
+ div#error {
+ width: 60%;
+ padding: 10px;
+ color: red;
+ background: #faa;
+ border: 15px solid #d99;
+ }
+ </style>
+
+ <script src="vex.js"></script>
+ <script src="flow.js"></script>
+ <script src="fonts/gonville_all.js"></script>
+ <script src="glyph.js"></script>
+ <script>
+ $(function() {
+ var canvas = document.getElementById("glyphs");
+ var x = 0;
+
+ // Get number of glyphs and rename elements
+ var counter = 0;
+ for (var glyph in Vex.Flow.Font.glyphs) {
+ Vex.Flow.Font.glyphs[glyph] = Vex.Flow.Font.glyphs[glyph];
+ counter++;
+ }
+
+ var canvas_height = ((counter + 1) / (800 / (60 * 2))) * 40;
+ canvas.height = canvas_height;
+ canvas.width = 800;
+
+ var ctx = canvas.getContext("2d");
+ ctx.font = "16pt Arial";
+
+ var y = 60;
+ for (var glyph in Vex.Flow.Font.glyphs) {
+ ctx.fillStyle = "#666";
+ ctx.fillText(glyph, x, y);
+ x += 60;
+
+ ctx.strokeStyle = "#888";
+ ctx.beginPath();
+ ctx.moveTo(x - 5, y);
+ ctx.lineTo(x + 5, y);
+ ctx.stroke()
+
+ ctx.beginPath();
+ ctx.moveTo(x, y - 5);
+ ctx.lineTo(x, y + 5);
+ ctx.stroke()
+
+ ctx.fillStyle = "green";
+
+ if (Vex.Flow.Font.glyphs[glyph].o) {
+ g = new Vex.Flow.Glyph(glyph, 40);
+ g.render(ctx, x, y);
+ ctx.save();
+ ctx.font = "6pt Arial";
+ var metrics = g.getMetrics();
+ ctx.fillText(Math.floor(g.getMetrics().width), x - 25, y - 15 );
+ ctx.restore();
+ }
+ x += 60;
+
+ if (x >= 800) {
+ x = 0;
+ y += 40;
+ }
+ }
+ });
+ </script>
+</head>
+
+<body>
+ <center>
+ <h1>Vex Glyphs</h1>
+ <p>
+ <i>Cross indicates render coordinates.</i>
+ </p>
+
+ <canvas id="glyphs" width="800" height="1600">
+ HTML5 Canvas not supported on this browser.
+ </canvas>
+
+ <p>
+ For more information visit <a href="http://0xfe.blogspot.com">0xfe.blogspot.com</a>.
+ </p>
+
+ </center>
+</body>
+
+</html>
31 src/header.js
@@ -0,0 +1,31 @@
+/**
+ * @preserve
+ * VexFlow Engraver __VEX_VERSION__
+ * A library for rendering musical notation and guitar tablature in HTML5.
+ *
+ * Copyright (c) 2010 Mohit Muthanna Cheppudira <mohit@muthanna.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This library makes use of Simon Tatham's awesome font - Gonville.
+ *
+ * Build ID: __VEX_BUILD_PREFIX__@__VEX_GIT_SHA1__
+ * Build date: __VEX_BUILD_DATE__
+ *
+ */
70 src/modifier.js
@@ -0,0 +1,70 @@
+// VexFlow - Music Engraving for HTML5
+// Copyright Mohit Muthanna 2010
+//
+// This class implements varies types of modifiers to notes (e.g. bends,
+// fingering positions etc.) Accidentals should also be implemented as
+// modifiers, eventually.
+
+/**
+ * Create a new modifier for the specified note.
+ *
+ * @constructor
+ */
+Vex.Flow.Modifier = function() { this.init() }
+
+Vex.Flow.Modifier.Position = {
+ LEFT: 1,
+ RIGHT: 2,
+ ABOVE: 3,
+ BELOW: 4
+};
+
+Vex.Flow.Modifier.prototype.init = function() {
+ this.width = 0;
+ this.context = null;
+ this.note = null;
+ this.index = null;
+ this.text_line = 0;
+ this.position = Vex.Flow.Modifier.Position.LEFT;
+ this.modifier_context = null;
+ this.x_shift = 0;
+ this.y_shift = 0;
+}
+
+// Accessors
+Vex.Flow.Modifier.prototype.getCategory = function() { return "none"; }
+Vex.Flow.Modifier.prototype.getWidth = function() { return this.width; }
+Vex.Flow.Modifier.prototype.setWidth = function(width) {
+ this.width = width; return this; }
+Vex.Flow.Modifier.prototype.getNote = function() { return this.note; }
+Vex.Flow.Modifier.prototype.setNote = function(note)
+ { this.note = note; return this; }
+Vex.Flow.Modifier.prototype.getIndex = function() { return this.index; }
+Vex.Flow.Modifier.prototype.setIndex = function(index) {
+ this.index = index; return this; }
+Vex.Flow.Modifier.prototype.getContext = function() { return this.context; }
+Vex.Flow.Modifier.prototype.setContext = function(context) {
+ this.context = context; return this; }
+Vex.Flow.Modifier.prototype.getModifierContext = function() {
+ return this.modifier_context; }
+Vex.Flow.Modifier.prototype.setModifierContext = function(c) {
+ this.modifier_context = c; return this; }
+Vex.Flow.Modifier.prototype.setTextLine = function(line)
+ { this.text_line = line; return this; }
+
+// Shift x pixels in the direction of the modifier
+Vex.Flow.Modifier.prototype.setXShift = function(x) {
+ this.x_shift = 0;
+ if (this.position == Vex.Flow.Modifier.Position.LEFT) {
+ this.x_shift -= x;
+ } else {
+ this.x_shift += x;
+ }
+}
+
+Vex.Flow.Modifier.prototype.draw = function() {
+ if (!this.context) throw new Vex.RERR("NoCanvasContext",
+ "Can't draw without a canvas context.");
+ throw new Vex.RERR("MethodNotImplemented",
+ "Draw() not implemented for this modifier.");
+}
213 src/modifiercontext.js
@@ -0,0 +1,213 @@
+// VexFlow - Music Engraving for HTML5
+// Copyright Mohit Muthanna 2010
+//
+// This class implements varies types of modifiers to notes (e.g. bends,
+// fingering positions etc.) Accidentals should also be implemented as
+// modifiers, eventually.
+
+/**
+ * @constructor
+ */
+Vex.Flow.ModifierContext = function() {
+ // Current modifiers
+ this.modifiers = {};
+
+ // Formatting data.
+ this.preFormatted = false;
+ this.width = 0;
+ this.spacing = 0;
+ this.state = {
+ left_shift: 0,
+ right_shift: 0,
+ text_line: 0
+ };
+}
+
+Vex.Flow.ModifierContext.prototype.addModifier = function(modifier) {
+ var type = modifier.getCategory();
+ if (!this.modifiers[type]) this.modifiers[type] = [];
+ this.modifiers[type].push(modifier);
+ modifier.setModifierContext(this);
+ this.preFormatted = false;
+ return this;
+}
+
+Vex.Flow.ModifierContext.prototype.getModifiers = function(type) {
+ return this.modifiers[type];
+}
+
+Vex.Flow.ModifierContext.prototype.getWidth = function() {
+ return this.width;
+}
+
+Vex.Flow.ModifierContext.prototype.getExtraLeftPx = function() {
+ return this.state.left_shift;
+}
+
+Vex.Flow.ModifierContext.prototype.getExtraRightPx = function() {
+ return this.state.right_shift;
+}
+
+Vex.Flow.ModifierContext.prototype.getMetrics = function(modifier) {
+ if (!this.formatted) throw new Vex.RERR("UnformattedModifier",
+ "Unformatted modifier has no metrics.");
+
+ return {
+ width: this.state.left_shift + this.state.right_shift + this.spacing,
+ spacing: this.spacing,
+ extra_left_px: this.state.left_shift,
+ extra_right_px: this.state.right_shift
+ }
+}
+
+Vex.Flow.ModifierContext.prototype.formatNotes = function() {
+ var notes = this.modifiers['stavenotes'];
+ if (!notes || notes.length < 2) return this;
+
+ var top_note = notes[0];
+ var bottom_note = notes[1];
+
+ // If notes intersect, then shift the bottom stemmed note right
+ if (notes[0].getStemDirection() == Vex.Flow.StaveNote.STEM_DOWN) {
+ bottom_note = notes[0];
+ top_note = notes[1];
+ }
+
+ var top_keys = top_note.getKeyProps();
+ var bottom_keys = bottom_note.getKeyProps();
+
+ var x_shift = 0;
+ if (top_keys[0].line <= (bottom_keys[bottom_keys.length - 1].line + 0.5)) {
+ x_shift = top_note.getVoiceShiftWidth();
+ bottom_note.setXShift(x_shift);
+ }
+
+ this.state.right_shift += x_shift;
+ return this;
+}
+
+Vex.Flow.ModifierContext.prototype.formatAccidentals = function() {
+ var left_shift = this.state.left_shift;
+ var accidentals = this.modifiers['accidentals'];
+ var accidental_spacing = 2;
+
+ if (!accidentals || accidentals.length == 0) return this;
+
+ var acc_list = [];
+ for (var i = 0; i < accidentals.length; ++i) {
+ var acc = accidentals[i];
+ var line = acc.getNote().getKeyProps()[acc.getIndex()].line;
+ acc_list.push({ line: line, acc: acc });
+ }
+
+ // Sort accidentals by line number.
+ acc_list.sort(function(a, b) { return (b.line - a.line); });
+
+ var acc_shift = left_shift;
+ var x_width = 0;
+ var top_line = acc_list[0].line;
+ for (var i = 0; i < acc_list.length; ++i) {
+ var acc = acc_list[i].acc;
+ var line = acc_list[i].line;
+
+ // Once you hit three stave lines, you can reset the position of the
+ // accidental.
+ if (line < top_line - 3.0) {
+ top_line = line;
+ acc_shift = left_shift;
+ }
+
+ acc.setXShift(acc_shift);
+ acc_shift += acc.getWidth() + accidental_spacing; // spacing
+ x_width = (acc_shift > x_width) ? acc_shift : x_width;
+ }
+
+ this.state.left_shift += x_width;
+ return this;
+}
+
+Vex.Flow.ModifierContext.prototype.formatBends = function() {
+ var right_shift = this.state.right_shift;
+ var bends = this.modifiers['bends'];
+ if (!bends || bends.length == 0) return this;
+
+ var width = 0;
+ var text_line = this.state.text_line;
+
+ // Format Bends
+ for (var i = 0; i < bends.length; ++i) {
+ var bend = bends[i];
+ var text_width = Vex.Flow.textWidth(bend.getText());
+ width += bend.render_options.bend_width + text_width / 2;
+ bend.setBendWidth(width);
+ width += bend.release_width + text_width / 2;
+ bend.setTextLine(text_line);
+ }
+
+ this.state.right_shift += width;
+ this.state.text_line += 1;
+ return this;
+}
+
+Vex.Flow.ModifierContext.prototype.formatVibratos = function() {
+ var vibratos = this.modifiers['vibratos'];
+ if (!vibratos || vibratos.length == 0) return this;
+
+ var text_line = this.state.text_line;
+ var width = 0;
+ var shift = this.state.right_shift - 7;
+
+ // If there's a bend, drop the text line
+ var bends = this.modifiers['bends'];
+ if (bends && bends.length > 0) {
+ text_line--;
+ }
+
+ // Format Vibratos
+ for (var i = 0; i < vibratos.length; ++i) {
+ var vibrato = vibratos[i];
+ vibrato.setXShift(shift);
+ vibrato.setTextLine(text_line);
+ width += vibrato.getWidth();
+ shift += width;
+ }
+
+ this.state.right_shift += width;
+ this.state.text_line += 1;
+ return this;
+}
+
+Vex.Flow.ModifierContext.prototype.formatAnnotations = function() {
+ var annotations = this.modifiers['annotations'];
+ if (!annotations || annotations.length == 0) return this;
+
+ var text_line = this.state.text_line;
+ var max_width = 0;
+
+ // Format Annotations
+ for (var i = 0; i < annotations.length; ++i) {
+ var annotation = annotations[i];
+ annotation.setTextLine(text_line);
+ var width = annotation.getWidth() > max_width ?
+ annotation.getWidth() : max_width;
+ text_line++;
+ }
+
+ this.state.left_shift += width / 2;
+ this.state.right_shift += width / 2;
+ // No need to update text_line because we leave lots of room on the same
+ // line.
+ return this;
+}
+
+Vex.Flow.ModifierContext.prototype.preFormat = function() {
+ if (this.preFormatted) return;
+
+ // Format modifiers in the following order:
+ this.formatNotes().formatAccidentals().formatAnnotations().
+ formatBends().formatVibratos();
+
+ // Update width of this modifier context
+ this.width = this.state.left_shift + this.state.right_shift;
+ this.preFormatted = true;
+}
150 src/note.js
@@ -0,0 +1,150 @@
+// Vex Flow Notation
+// Mohit Muthanna <mohit@muthanna.com>
+//
+// Copyright Mohit Muthanna 2010
+//
+// Requires vex.js.
+
+/** @constructor */
+Vex.Flow.Note = function(duration) {
+ if (arguments.length > 0) this.init(duration); }
+
+// Inherits from Vex.Flow.Tickable
+Vex.Flow.Note.prototype = new Vex.Flow.Tickable();
+Vex.Flow.Note.superclass = Vex.Flow.Tickable.prototype;
+Vex.Flow.Note.constructor = Vex.Flow.Note;
+
+Vex.Flow.Note.prototype.init = function(duration) {
+ var superclass = Vex.Flow.Note.superclass;
+ superclass.init.call(this);
+
+ // Note properties
+ this.duration = duration;
+
+ // Sanity check
+ if (!this.duration)
+ throw new Vex.RuntimeError("BadArguments", "Note must have duration.");
+
+ if (this.positions &&
+ (typeof(this.positions) != "object" || !this.positions.length)) {
+ throw new Vex.RuntimeError(
+ "BadArguments", "Note keys must be array type.");
+ }
+
+ this.ticks = Vex.Flow.durationToTicks[this.duration];
+ if (!this.ticks) {
+ throw new Vex.RuntimeError("BadArguments",
+ "Invalid duration string (No ticks found): " + this.duration);
+ }
+
+
+ // Positioning contexts
+ this.tickContext = null; // The current tick context
+ this.modifierContext = null;
+
+ // Positioning variables
+ this.width = 0; // Width in pixels calculated after preFormat
+ this.extraLeftPx = 0; // Extra room on left
+ this.extraRightPx = 0; // Extra room on right
+ this.x_shift = 0; // X shift from tick context X
+ this.voice = null; // The voice that this note is in
+ this.preFormatted = false; // Is this note preFormatted?
+ this.ys = []; // list of y coordinates for each note
+ // we need to hold on to these for ties and beams.
+ // Drawing
+ this.context = null;
+ this.stave = null;
+}
+
+Vex.Flow.Note.prototype.setYs = function(ys) {
+ this.ys = ys; return this; }
+Vex.Flow.Note.prototype.getStave = function() { return this.stave; }
+Vex.Flow.Note.prototype.setStave = function(stave) {
+ this.stave = stave; return this; }
+Vex.Flow.Note.prototype.setContext = function(context) {
+ this.context = context; return this; }
+Vex.Flow.Note.prototype.getTicks = function() { return this.ticks; }
+Vex.Flow.Note.prototype.getExtraLeftPx = function() {
+ return this.extraLeftPx; }
+Vex.Flow.Note.prototype.getExtraRightPx = function() {
+ return this.extraRightPx; }
+Vex.Flow.Note.prototype.setExtraLeftPx = function(x) {
+ this.extraLeftPx = x; return this; }
+Vex.Flow.Note.prototype.setExtraRightPx = function(x) {
+ this.extraRightPx = x; return this; }
+
+Vex.Flow.Note.prototype.getYs = function() {
+ if (this.ys.length == 0) throw new Vex.RERR("NoYValues",
+ "No Y-values calculated for this note.");
+ return this.ys;
+}
+
+Vex.Flow.Note.prototype.getVoice = function() {
+ if (!this.voice) throw new Vex.RERR("NoVoice", "Note has no voice.");
+ return this.voice;
+}
+
+Vex.Flow.Note.prototype.setVoice = function(voice) {
+ this.voice = voice;
+ this.preFormatted = false;
+ return this;
+}
+
+Vex.Flow.Note.prototype.getTickContext = function() { return this.tickContext; }
+Vex.Flow.Note.prototype.setTickContext = function(tc) {
+ this.tickContext = tc;
+ this.preFormatted = false;
+ return this;
+}
+
+Vex.Flow.Note.prototype.getDuration = function() {
+ return this.duration;
+}
+
+Vex.Flow.Note.prototype.setModifierContext = function(mc) {
+ this.modifierContext = mc;
+ return this;
+}
+
+Vex.Flow.Note.prototype.getWidth = function() {
+ if (!this.preFormatted) throw new Vex.RERR("UnformattedNote",
+ "Can't call GetWidth on an unformatted note.");
+ return this.width + this.x_shift +
+ (this.modifierContext ? this.modifierContext.getWidth() : 0);
+}
+
+Vex.Flow.Note.prototype.setWidth = function(width) { this.width = width; }
+
+Vex.Flow.Note.prototype.setXShift = function(x) {
+ this.x_shift = x;
+ return this;
+}
+
+Vex.Flow.Note.prototype.getX = function(x) {
+ if (!this.tickContext) throw new Vex.RERR("NoTickContext",
+ "Note needs a TickContext assigned for an X-Value");
+ return this.tickContext.getX() + this.x_shift;
+}
+
+Vex.Flow.Note.prototype.getAbsoluteX = function(x) {
+ if (!this.tickContext) throw new Vex.RERR("NoTickContext",
+ "Note needs a TickContext assigned for an X-Value");
+
+ // Center the note in the tick context
+ var x = this.tickContext.getX() +
+ (this.tickContext.getPixelsUsed() / 2) +
+ (this.extraLeftPx / 2) -
+ (this.extraRightPx / 2);
+
+ if (this.modifierContext)
+ x += (this.modifierContext.getExtraLeftPx() / 2) -
+ (this.modifierContext.getExtraRightPx() / 2);
+
+ if (this.stave) x += this.stave.getNoteStartX();
+
+ return x;
+}
+
+Vex.Flow.Note.prototype.setPreFormatted = function(value) {
+ this.preFormatted = value;
+}
170 src/raphaelcontext.js
@@ -0,0 +1,170 @@
+// Vex Flow
+// Mohit Muthanna <mohit@muthanna.com>
+//
+// A rendering context for the Raphael backend.
+//
+// Copyright Mohit Cheppudira 2010
+
+/** @constructor */
+Vex.Flow.RaphaelContext = function(element) {
+ if (arguments.length > 0) this.init(element)
+}
+
+Vex.Flow.RaphaelContext.prototype.init = function(element) {
+ this.element = element;
+ this.paper = Raphael(element);
+ this.path = "";
+
+ this.state = {
+ scale: { x: 1, y: 1 },
+ font_family: "Arial",
+ font_size: 8,
+ font_weight: 800
+ };
+
+ this.attributes = {
+ "stroke-width": 0.3,
+ "fill": "black",
+ "font": "8pt Arial"
+ };
+
+ this.state_stack= [];
+}
+
+Vex.Flow.RaphaelContext.prototype.setFont = function(family, size, weight) {
+ this.state.font_family = family;
+ this.state.font_size = size;
+ this.state.font_weight = weight;
+ this.attributes.font = (this.state.font_weight || "") + " " +
+ (this.state.font_size * this.state.scale.x) + "pt " +
+ this.state.font_family;
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.setFillStyle = function(style) {
+ this.attributes.fill = style;
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.setStrokeStyle = function(style) {
+ this.attributes.stroke = style;
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.scale = function(x, y) {
+ this.state.scale = { x: x, y: y };
+ this.attributes.scale = x + "," + y + ",0,0";
+ this.attributes.font = this.state.font_size * this.state.scale.x + "pt " +
+ this.state.font_family;
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.clear = function() {
+ this.paper.clear();
+}
+
+Vex.Flow.RaphaelContext.prototype.resize = function(width, height) {
+ this.element.style.width = width;
+ this.paper.setSize(width, height);
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.fillRect = function(x, y, width, height) {
+ if (height < 0) {
+ y += height;
+ height = -height
+ }
+
+ var r = this.paper.rect(x, y, width - 0.5, height - 0.5).
+ attr(this.attributes);
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.beginPath = function() {
+ this.path = "";
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.moveTo = function(x, y) {
+ this.path += "M" + x + "," + y;
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.lineTo = function(x, y) {
+ this.path += "L" + x + "," + y;
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.bezierCurveTo =
+ function(x1, y1, x2, y2, x, y) {
+ this.path += "C" +
+ x1 + "," +
+ y1 + "," +
+ x2 + "," +
+ y2 + "," +
+ x + "," +
+ y;
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.quadraticCurveTo =
+ function(x1, y1, x, y) {
+ this.path += "Q" +
+ x1 + "," +
+ y1 + "," +
+ x + "," +
+ y;
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.fill = function() {
+ this.paper.path(this.path).
+ attr(this.attributes).
+ attr("stroke-width", 0);
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.stroke = function() {
+ this.paper.path(this.path).
+ attr(this.attributes).
+ attr("fill", "none").
+ attr("stroke-width", 1.0);
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.closePath = function() {
+ this.path += "Z";
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.fillText = function(text, x, y) {
+ var shift = 0;
+ if (this.state.font_size == 9) shift = 1;
+
+ this.paper.text(x + (Vex.Flow.textWidth(text) / 2) + 2,
+ (y - (this.state.font_size / (3.5 * this.state.scale.y))) + shift, text).
+ attr(this.attributes);
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.save = function() {
+ // TODO(mmuthanna): State needs to be deep-copied.
+ this.state_stack.push({
+ state: {
+ font_family: this.state.font_family
+ },
+ attributes: {
+ font: this.attributes.font
+ }
+ });
+ return this;
+}
+
+Vex.Flow.RaphaelContext.prototype.restore = function() {
+ // TODO(mmuthanna): State needs to be deep-restored.
+ var state = this.state_stack.pop();
+ this.state.font_family = state.state.font_family;
+ this.attributes.font = state.attributes.font;
+
+ return this;
+}
103 src/renderer.js
@@ -0,0 +1,103 @@
+// Vex Flow
+// Mohit Muthanna <mohit@muthanna.com>
+//
+// Support for different rendering contexts: Canvas, Raphael
+//
+// Copyright Mohit Cheppudira 2010
+
+/** @constructor */
+Vex.Flow.Renderer = function(sel, backend) {
+ if (arguments.length > 0) this.init(sel, backend)
+}
+
+Vex.Flow.Renderer.Backends = {
+ CANVAS: 1,
+ RAPHAEL: 2,
+ SVG: 3,
+ VML: 4
+}
+
+Vex.Flow.Renderer.buildContext = function(sel, backend, width, height) {
+ var renderer = new Vex.Flow.Renderer(sel, backend);
+ if (width && height) { renderer.resize(width, height); }
+ return renderer.getContext();
+}
+
+Vex.Flow.Renderer.getCanvasContext = function(sel, width, height) {
+ return Vex.Flow.Renderer.buildContext(sel,
+ Vex.Flow.Renderer.Backends.CANVAS,
+ width, height);
+}
+
+Vex.Flow.Renderer.getRaphaelContext = function(sel, width, height) {
+ return Vex.Flow.Renderer.buildContext(sel,
+ Vex.Flow.Renderer.Backends.RAPHAEL,
+ width, height);
+}
+
+Vex.Flow.Renderer.bolsterCanvasContext = function(ctx) {
+ ctx.clear = function() {
+ // TODO: get real widht and height of context.
+ ctx.clearRect(0, 0, 2000,2000);
+ }
+ ctx.setFont = function(family, size, weight) {
+ this.font = (weight || "") + " " + size + "pt " + family;
+ return this;
+ }
+ ctx.setFillStyle = function(style) {
+ this.fillStyle = style;
+ return this;
+ }
+ ctx.setStrokeStyle = function(style) {
+ this.strokeStyle = style;
+ return this;
+ }
+ return ctx;
+}
+
+Vex.Flow.Renderer.prototype.init = function(sel, backend) {
+ // Verify selector
+ this.sel = sel;
+ if (!this.sel) throw new Vex.RERR("BadArgument",
+ "Invalid selector for renderer.");
+
+ // Get element from selector
+ this.element = document.getElementById(sel);
+ if (!this.element) this.element = sel;
+
+ // Verify backend and create context
+ this.ctx = null;
+ this.paper = null;
+ this.backend = backend;
+ if (this.backend == Vex.Flow.Renderer.Backends.CANVAS) {
+ // Create context.
+ if (!this.element.getContext) throw new Vex.RERR("BadElement",
+ "Can't get canvas context from element: " + sel);
+ this.ctx = Vex.Flow.Renderer.bolsterCanvasContext(
+ this.element.getContext('2d'));
+ } else if (this.backend == Vex.Flow.Renderer.Backends.RAPHAEL) {
+ this.ctx = new Vex.Flow.RaphaelContext(this.element);
+ } else {
+ throw new Vex.RERR("InvalidBackend",
+ "No support for backend: " + this.backend);
+ }
+}
+
+Vex.Flow.Renderer.prototype.resize = function(width, height) {
+ if (this.backend == Vex.Flow.Renderer.Backends.CANVAS) {
+ if (!this.element.getContext) throw new Vex.RERR("BadElement",
+ "Can't get canvas context from element: " + sel);
+ this.element.width = width;
+ this.element.height = height;
+ this.ctx = Vex.Flow.Renderer.bolsterCanvasContext(
+ this.element.getContext('2d'));
+ } else {
+ this.ctx.resize(width, height);
+ }
+
+ return this;
+}
+
+Vex.Flow.Renderer.prototype.getContext = function() {
+ return this.ctx;
+}
144 src/stave.js
@@ -0,0 +1,144 @@
+// Vex Flow
+// Mohit Muthanna <mohit@muthanna.com>
+//
+// Copyright Mohit Cheppudira 2010
+
+/** @constructor */
+Vex.Flow.Stave = function(x, y, width, options) {
+ if (arguments.length > 0) this.init(x, y, width, options);
+}
+
+Vex.Flow.Stave.prototype.init = function(x, y, width, options) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.glyph_start_x = x + 5;
+ this.start_x = this.glyph_start_x + 5;
+ this.context = null;
+ this.glyphs = [];
+ this.options = {
+ vertical_bar_width: 10, // Width around vertical bar end-marker
+ glyph_spacing_px: 10,
+ num_lines: 5,
+ 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.height =
+ (this.options.num_lines + this.options.space_above_staff_ln) *
+ this.options.spacing_between_lines_px;
+ Vex.Merge(this.options, options);
+}
+
+Vex.Flow.Stave.prototype.setNoteStartX = function(x) {