vexflow
Version:
A JavaScript library for rendering music notation and guitar tablature
14,921 lines • 507 kB
JavaScript
/**
* VexFlow 1.2.89 built on 2019-03-18.
* Copyright (c) 2010 Mohit Muthanna Cheppudira <mohit@muthanna.com>
*
* http://www.vexflow.com http://github.com/0xfe/vexflow
*//**
* VexFlow Test Support Library
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
/*
eslint-disable
no-require,
global-require,
import/no-unresolved,
import/no-extraneous-dependencies,
*/
// Mock out the QUnit stuff for generating svg images,
// since we don't really care about the assertions.
if (!window.QUnit) {
window.QUnit = {};
QUnit = window.QUnit;
QUnit.assertions = {
ok: function() { return true; },
equal: function() { return true; },
deepEqual: function() { return true; },
expect: function() { return true; },
throws: function() { return true; },
notOk: function() { return true; },
notEqual: function() { return true; },
notDeepEqual: function() { return true; },
strictEqual: function() { return true; },
notStrictEqual: function() { return true; },
};
QUnit.module = function(name) {
QUnit.current_module = name;
};
/* eslint-disable */
QUnit.test = function(name, func) {
QUnit.current_test = name;
process.stdout.write(" \u001B[0G" + QUnit.current_module + " :: " + name + "\u001B[0K");
func(QUnit.assertions);
};
test = QUnit.test;
ok = QUnit.assertions.ok;
equal = QUnit.assertions.equal;
deepEqual = QUnit.assertions.deepEqual;
expect = QUnit.assertions.expect;
throws = QUnit.assertions.throws;
notOk = QUnit.assertions.notOk;
notEqual = QUnit.assertions.notEqual;
notDeepEqual = QUnit.assertions.notDeepEqual;
strictEqual = QUnit.assertions.strictEqual;
notStrictEqual = QUnit.assertions.notStrictEqual;
}
if (typeof require === 'function') {
Vex = require('./vexflow-debug.js');
}
var VF = Vex.Flow;
VF.Test = (function() {
var Test = {
// Test Options.
RUN_CANVAS_TESTS: true,
RUN_SVG_TESTS: true,
RUN_RAPHAEL_TESTS: false,
RUN_NODE_TESTS: false,
// Where images are stored for NodeJS tests.
NODE_IMAGEDIR: 'images',
// Default font properties for tests.
Font: { size: 10 },
// Returns a unique ID for a test.
genID: function(prefix) {
return prefix + VF.Test.genID.ID++;
},
genTitle: function(type, assert, name) {
return assert.test.module.name + ' (' + type + '): ' + name;
},
// Run `func` inside a QUnit test for each of the enabled
// rendering backends.
runTests: function(name, func, params) {
if (VF.Test.RUN_CANVAS_TESTS) {
VF.Test.runCanvasTest(name, func, params);
}
if (VF.Test.RUN_SVG_TESTS) {
VF.Test.runSVGTest(name, func, params);
}
if (VF.Test.RUN_RAPHAEL_TESTS) {
VF.Test.runRaphaelTest(name, func, params);
}
if (VF.Test.RUN_NODE_TESTS) {
VF.Test.runNodeTest(name, func, params);
}
},
// Run `func` inside a QUnit test for each of the enabled
// rendering backends. These are for interactivity tests, and
// currently only work with the SVG backend.
runUITests: function(name, func, params) {
if (VF.Test.RUN_SVG_TESTS) {
VF.Test.runSVGTest(name, func, params);
}
},
createTestCanvas: function(testId, testName) {
var testContainer = $('<div></div>').addClass('testcanvas');
testContainer.append(
$('<div></div>')
.addClass('name')
.text(testName)
);
testContainer.append(
$('<canvas></canvas>')
.addClass('vex-tabdiv')
.attr('id', testId)
.addClass('name')
.text(name)
);
$(VF.Test.testRootSelector).append(testContainer);
},
createTestSVG: function(testId, testName) {
var testContainer = $('<div></div>').addClass('testcanvas');
testContainer.append(
$('<div></div>')
.addClass('name')
.text(testName)
);
testContainer.append(
$('<div></div>')
.addClass('vex-tabdiv')
.attr('id', testId)
);
$(VF.Test.testRootSelector).append(testContainer);
},
resizeCanvas: function(elementId, width, height) {
$('#' + elementId).width(width);
$('#' + elementId).attr('width', width);
$('#' + elementId).attr('height', height);
},
makeFactory: function(options, width, height) {
return new VF.Factory({
renderer: {
elementId: options.elementId,
backend: options.backend,
width: width || 450,
height: height || 140,
},
});
},
runCanvasTest: function(name, func, params) {
QUnit.test(name, function(assert) {
var elementId = VF.Test.genID('canvas_');
var title = VF.Test.genTitle('Canvas', assert, name);
VF.Test.createTestCanvas(elementId, title);
var testOptions = {
backend: VF.Renderer.Backends.CANVAS,
elementId: elementId,
params: params,
assert: assert,
};
func(testOptions, VF.Renderer.getCanvasContext);
});
},
runRaphaelTest: function(name, func, params) {
QUnit.test(name, function(assert) {
var elementId = VF.Test.genID('raphael_');
var title = VF.Test.genTitle('Raphael', assert, name);
VF.Test.createTestSVG(elementId, title);
var testOptions = {
elementId: elementId,
backend: VF.Renderer.Backends.RAPHAEL,
params: params,
assert: assert,
};
func(testOptions, VF.Renderer.getRaphaelContext);
});
},
runSVGTest: function(name, func, params) {
if (!VF.Test.RUN_SVG_TESTS) return;
QUnit.test(name, function(assert) {
var elementId = VF.Test.genID('svg_');
var title = VF.Test.genTitle('SVG', assert, name);
VF.Test.createTestSVG(elementId, title);
var testOptions = {
elementId: elementId,
backend: VF.Renderer.Backends.SVG,
params: params,
assert: assert,
};
func(testOptions, VF.Renderer.getSVGContext);
});
},
runNodeTest: function(name, func, params) {
var fs = require('fs');
// Allows `name` to be used inside file names.
function sanitizeName(name) {
return name.replace(/[^a-zA-Z0-9]/g, '_');
}
QUnit.test(name, function(assert) {
var elementId = VF.Test.genID('nodecanvas_');
var canvas = document.createElement('canvas');
canvas.setAttribute('id', elementId);
document.body.appendChild(canvas);
var testOptions = {
elementId: elementId,
backend: VF.Renderer.Backends.CANVAS,
params: params,
assert: assert,
};
func(testOptions, VF.Renderer.getCanvasContext);
if (VF.Renderer.lastContext !== null) {
var moduleName = sanitizeName(QUnit.current_module);
var testName = sanitizeName(QUnit.current_test);
var fileName = `${VF.Test.NODE_IMAGEDIR}/${moduleName}.${testName}.png`;
var imageData = canvas.toDataURL().split(';base64,').pop();
var image = Buffer.from(imageData, 'base64');
fs.writeFileSync(fileName, image, { encoding: 'base64' });
}
});
},
plotNoteWidth: VF.Note.plotMetrics,
plotLegendForNoteWidth: function(ctx, x, y) {
ctx.save();
ctx.setFont('Arial', 8, '');
var spacing = 12;
var lastY = y;
function legend(color, text) {
ctx.beginPath();
ctx.setStrokeStyle(color);
ctx.setFillStyle(color);
ctx.setLineWidth(10);
ctx.moveTo(x, lastY - 4);
ctx.lineTo(x + 10, lastY - 4);
ctx.stroke();
ctx.setFillStyle('black');
ctx.fillText(text, x + 15, lastY);
lastY += spacing;
}
legend('green', 'Note + Flag');
legend('red', 'Modifiers');
legend('#999', 'Displaced Head');
legend('#DDD', 'Formatter Shift');
ctx.restore();
},
almostEqual: function(value, expectedValue, errorMargin) {
return equal(Math.abs(value - expectedValue) < errorMargin, true);
},
};
Test.genID.ID = 0;
Test.testRootSelector = '#vexflow_testoutput';
return Test;
}());
/**
* VexFlow - TickContext Mocks
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
/* Mock Tickable */
VF.Test.MockTickable = (function() {
function MockTickable() {
this.ignore_ticks = false;
}
MockTickable.prototype = {
init: function() {},
getX: function() { return this.tickContext.getX(); },
getIntrinsicTicks: function() { return this.ticks; },
getTicks: function() { return this.ticks; },
setTicks: function(t) { this.ticks = new VF.Fraction(t, 1); return this; },
getMetrics: function() {
return { noteWidth: this.width,
left_shift: 0,
modLeftPx: 0, modRightPx: 0,
extraLeftPx: 0, extraRightPx: 0 };
},
getWidth: function() { return this.width; },
setWidth: function(w) { this.width = w; return this; },
setVoice: function(v) { this.voice = v; return this; },
setStave: function(stave) { this.stave = stave; return this; },
setTickContext: function(tc) { this.tickContext = tc; return this; },
setIgnoreTicks: function(ignore_ticks) { this.ignore_ticks = ignore_ticks; return this; },
shouldIgnoreTicks: function() { return this.ignore_ticks; },
preFormat: function() {},
};
return MockTickable;
})();
/**
* VexFlow - Accidental Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
Vex.Flow.Test.Accidental = (function() {
function hasAccidental(note) {
return note.modifiers.reduce(function(hasAcc, modifier) {
return hasAcc || modifier.getCategory() === 'accidentals';
}, false);
}
// newAccid factory
function makeNewAccid(factory) {
return function(accidType) {
return factory.Accidental({ type: accidType });
};
}
var Accidental = {
Start: function() {
QUnit.module('Accidental');
Vex.Flow.Test.runTests('Basic', Vex.Flow.Test.Accidental.basic);
Vex.Flow.Test.runTests('Stem Down', Vex.Flow.Test.Accidental.basicStemDown);
Vex.Flow.Test.runTests('Cautionary Accidental', Vex.Flow.Test.Accidental.cautionary);
Vex.Flow.Test.runTests('Accidental Arrangement Special Cases', Vex.Flow.Test.Accidental.specialCases);
Vex.Flow.Test.runTests('Multi Voice', Vex.Flow.Test.Accidental.multiVoice);
Vex.Flow.Test.runTests('Microtonal', Vex.Flow.Test.Accidental.microtonal);
Vex.Flow.Test.runTests('Microtonal (Iranian)', Vex.Flow.Test.Accidental.microtonal_iranian);
test('Automatic Accidentals - Simple Tests', Vex.Flow.Test.Accidental.autoAccidentalWorking);
Vex.Flow.Test.runTests('Automatic Accidentals', Vex.Flow.Test.Accidental.automaticAccidentals0);
Vex.Flow.Test.runTests('Automatic Accidentals - C major scale in Ab', Vex.Flow.Test.Accidental.automaticAccidentals1);
Vex.Flow.Test.runTests('Automatic Accidentals - No Accidentals Necsesary', Vex.Flow.Test.Accidental.automaticAccidentals2);
Vex.Flow.Test.runTests('Automatic Accidentals - Multi Voice Inline', Vex.Flow.Test.Accidental.automaticAccidentalsMultiVoiceInline);
Vex.Flow.Test.runTests('Automatic Accidentals - Multi Voice Offset', Vex.Flow.Test.Accidental.automaticAccidentalsMultiVoiceOffset);
Vex.Flow.Test.runTests('Factory API', Vex.Flow.Test.Accidental.factoryAPI);
},
basic: function(options) {
var vf = VF.Test.makeFactory(options, 700, 240);
var newAccid = makeNewAccid(vf);
vf.Stave({ x: 10, y: 10, width: 550 });
var notes = [
vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], duration: '1' })
.addAccidental(0, newAccid('b'))
.addAccidental(1, newAccid('#')),
vf.StaveNote({ keys: ['d/4', 'e/4', 'f/4', 'a/4', 'c/5', 'e/5', 'g/5'], duration: '2' })
.addAccidental(0, newAccid('##'))
.addAccidental(1, newAccid('n'))
.addAccidental(2, newAccid('bb'))
.addAccidental(3, newAccid('b'))
.addAccidental(4, newAccid('#'))
.addAccidental(5, newAccid('n'))
.addAccidental(6, newAccid('bb')),
vf.StaveNote({ keys: ['f/4', 'g/4', 'a/4', 'b/4', 'c/5', 'e/5', 'g/5'], duration: '16' })
.addAccidental(0, newAccid('n'))
.addAccidental(1, newAccid('#'))
.addAccidental(2, newAccid('#'))
.addAccidental(3, newAccid('b'))
.addAccidental(4, newAccid('bb'))
.addAccidental(5, newAccid('##'))
.addAccidental(6, newAccid('#')),
vf.StaveNote({ keys: ['a/3', 'c/4', 'e/4', 'b/4', 'd/5', 'g/5'], duration: '1' })
.addAccidental(0, newAccid('#'))
.addAccidental(1, newAccid('##').setAsCautionary())
.addAccidental(2, newAccid('#').setAsCautionary())
.addAccidental(3, newAccid('b'))
.addAccidental(4, newAccid('bb').setAsCautionary())
.addAccidental(5, newAccid('b').setAsCautionary()),
];
VF.Formatter.SimpleFormat(notes, 10, { paddingBetween: 45 });
notes.forEach(function(note, index) {
Vex.Flow.Test.plotNoteWidth(vf.getContext(), note, 140);
ok(note.getAccidentals().length > 0, 'Note ' + index + ' has accidentals');
note.getAccidentals().forEach(function(accid, index) {
ok(accid.getWidth() > 0, 'Accidental ' + index + ' has set width');
});
});
vf.draw();
Vex.Flow.Test.plotLegendForNoteWidth(vf.getContext(), 480, 140);
ok(true, 'Full Accidental');
},
cautionary: function(options) {
var vf = VF.Test.makeFactory(options, 700, 240);
var stave = vf.Stave({ x: 10, y: 10, width: 550 });
var score = vf.EasyScore();
var accids = Object
.keys(VF.accidentalCodes.accidentals)
.filter(function(accid) { return accid !== '{' && accid !== '}'; });
var notes = accids
.map(function(accid) {
return vf
.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: VF.Stem.UP })
.addAccidental(0, vf.Accidental({ type: accid }));
});
var voice = score.voice(notes, { time: accids.length + '/4' });
voice
.getTickables()
.forEach(function(tickable) {
tickable.modifiers
.filter(function(modifier) {
return modifier.getAttribute('type') === 'Accidental';
})
.forEach(function(accid) {
accid.setAsCautionary();
});
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Must successfully render cautionary accidentals');
},
specialCases: function(options) {
var vf = VF.Test.makeFactory(options, 700, 240);
var newAccid = makeNewAccid(vf);
vf.Stave({ x: 10, y: 10, width: 550 });
var notes = [
vf.StaveNote({ keys: ['f/4', 'd/5'], duration: '1' })
.addAccidental(0, newAccid('#'))
.addAccidental(1, newAccid('b')),
vf.StaveNote({ keys: ['c/4', 'g/4'], duration: '2' })
.addAccidental(0, newAccid('##'))
.addAccidental(1, newAccid('##')),
vf.StaveNote({ keys: ['b/3', 'd/4', 'f/4'], duration: '16' })
.addAccidental(0, newAccid('#'))
.addAccidental(1, newAccid('#'))
.addAccidental(2, newAccid('##')),
vf.StaveNote({ keys: ['g/4', 'a/4', 'c/5', 'e/5'], duration: '16' })
.addAccidental(0, newAccid('b'))
.addAccidental(1, newAccid('b'))
.addAccidental(3, newAccid('n')),
vf.StaveNote({ keys: ['e/4', 'g/4', 'b/4', 'c/5'], duration: '4' })
.addAccidental(0, newAccid('b').setAsCautionary())
.addAccidental(1, newAccid('b').setAsCautionary())
.addAccidental(2, newAccid('bb'))
.addAccidental(3, newAccid('b')),
vf.StaveNote({ keys: ['b/3', 'e/4', 'a/4', 'd/5', 'g/5'], duration: '8' })
.addAccidental(0, newAccid('bb'))
.addAccidental(1, newAccid('b').setAsCautionary())
.addAccidental(2, newAccid('n').setAsCautionary())
.addAccidental(3, newAccid('#'))
.addAccidental(4, newAccid('n').setAsCautionary()),
];
VF.Formatter.SimpleFormat(notes, 0, { paddingBetween: 20 });
notes.forEach(function(note, index) {
Vex.Flow.Test.plotNoteWidth(vf.getContext(), note, 140);
ok(note.getAccidentals().length > 0, 'Note ' + index + ' has accidentals');
note.getAccidentals().forEach(function(accid, index) {
ok(accid.getWidth() > 0, 'Accidental ' + index + ' has set width');
});
});
vf.draw();
Vex.Flow.Test.plotLegendForNoteWidth(vf.getContext(), 480, 140);
ok(true, 'Full Accidental');
},
basicStemDown: function(options) {
var vf = VF.Test.makeFactory(options, 700, 240);
var newAccid = makeNewAccid(vf);
vf.Stave({ x: 10, y: 10, width: 550 });
var notes = [
vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], duration: 'w', stem_direction: -1 })
.addAccidental(0, newAccid('b'))
.addAccidental(1, newAccid('#')),
vf.StaveNote({ keys: ['d/4', 'e/4', 'f/4', 'a/4', 'c/5', 'e/5', 'g/5'], duration: '2', stem_direction: -1 })
.addAccidental(0, newAccid('##'))
.addAccidental(1, newAccid('n'))
.addAccidental(2, newAccid('bb'))
.addAccidental(3, newAccid('b'))
.addAccidental(4, newAccid('#'))
.addAccidental(5, newAccid('n'))
.addAccidental(6, newAccid('bb')),
vf.StaveNote({ keys: ['f/4', 'g/4', 'a/4', 'b/4', 'c/5', 'e/5', 'g/5'], duration: '16', stem_direction: -1 })
.addAccidental(0, newAccid('n'))
.addAccidental(1, newAccid('#'))
.addAccidental(2, newAccid('#'))
.addAccidental(3, newAccid('b'))
.addAccidental(4, newAccid('bb'))
.addAccidental(5, newAccid('##'))
.addAccidental(6, newAccid('#')),
];
VF.Formatter.SimpleFormat(notes, 0, { paddingBetween: 30 });
notes.forEach(function(note, index) {
Vex.Flow.Test.plotNoteWidth(vf.getContext(), note, 140);
ok(note.getAccidentals().length > 0, 'Note ' + index + ' has accidentals');
note.getAccidentals().forEach(function(accid, index) {
ok(accid.getWidth() > 0, 'Accidental ' + index + ' has set width');
});
});
vf.draw();
Vex.Flow.Test.plotLegendForNoteWidth(vf.getContext(), 480, 140);
ok(true, 'Full Accidental');
},
showNotes: function(note1, note2, stave, ctx, x) {
var modifierContext = new Vex.Flow.ModifierContext();
note1.addToModifierContext(modifierContext);
note2.addToModifierContext(modifierContext);
new VF.TickContext()
.addTickable(note1)
.addTickable(note2)
.preFormat()
.setX(x);
note1.setContext(ctx).draw();
note2.setContext(ctx).draw();
Vex.Flow.Test.plotNoteWidth(ctx, note1, 180);
Vex.Flow.Test.plotNoteWidth(ctx, note2, 15);
},
multiVoice: function(options) {
var vf = VF.Test.makeFactory(options, 460, 250);
var newAccid = makeNewAccid(vf);
var stave = vf.Stave({ x: 10, y: 45, width: 420 });
var ctx = vf.getContext();
stave.draw();
var note1 = vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], duration: '2', stem_direction: -1 })
.addAccidental(0, newAccid('b'))
.addAccidental(1, newAccid('n'))
.addAccidental(2, newAccid('#'))
.setStave(stave);
var note2 = vf.StaveNote({ keys: ['d/5', 'a/5', 'b/5'], duration: '2', stem_direction: 1 })
.addAccidental(0, newAccid('b'))
.addAccidental(1, newAccid('bb'))
.addAccidental(2, newAccid('##'))
.setStave(stave);
Vex.Flow.Test.Accidental.showNotes(note1, note2, stave, ctx, 60);
note1 = vf.StaveNote({ keys: ['c/4', 'e/4', 'c/5'], duration: '2', stem_direction: -1 })
.addAccidental(0, newAccid('b'))
.addAccidental(1, newAccid('n'))
.addAccidental(2, newAccid('#'))
.setStave(stave);
note2 = vf.StaveNote({ keys: ['d/5', 'a/5', 'b/5'], duration: '4', stem_direction: 1 })
.addAccidental(0, newAccid('b'))
.setStave(stave);
Vex.Flow.Test.Accidental.showNotes(note1, note2, stave, ctx, 150);
note1 = vf.StaveNote({ keys: ['d/4', 'c/5', 'd/5'], duration: '2', stem_direction: -1 })
.addAccidental(0, newAccid('b'))
.addAccidental(1, newAccid('n'))
.addAccidental(2, newAccid('#'))
.setStave(stave);
note2 = vf.StaveNote({ keys: ['d/5', 'a/5', 'b/5'], duration: '4', stem_direction: 1 })
.addAccidental(0, newAccid('b'))
.setStave(stave);
Vex.Flow.Test.Accidental.showNotes(note1, note2, stave, ctx, 250);
Vex.Flow.Test.plotLegendForNoteWidth(ctx, 350, 150);
ok(true, 'Full Accidental');
},
microtonal: function(options) {
var assert = options.assert;
var vf = VF.Test.makeFactory(options, 700, 240);
var newAccid = makeNewAccid(vf);
var ctx = vf.getContext();
vf.Stave({ x: 10, y: 10, width: 650 });
var notes = [
vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], duration: '1' })
.addAccidental(0, newAccid('db'))
.addAccidental(1, newAccid('d')),
vf.StaveNote({ keys: ['d/4', 'e/4', 'f/4', 'a/4', 'c/5', 'e/5', 'g/5'], duration: '2' })
.addAccidental(0, newAccid('bbs'))
.addAccidental(1, newAccid('++'))
.addAccidental(2, newAccid('+'))
.addAccidental(3, newAccid('d'))
.addAccidental(4, newAccid('db'))
.addAccidental(5, newAccid('+'))
.addAccidental(6, newAccid('##')),
vf.StaveNote({ keys: ['f/4', 'g/4', 'a/4', 'b/4', 'c/5', 'e/5', 'g/5'], duration: '16' })
.addAccidental(0, newAccid('++'))
.addAccidental(1, newAccid('bbs'))
.addAccidental(2, newAccid('+'))
.addAccidental(3, newAccid('b'))
.addAccidental(4, newAccid('db'))
.addAccidental(5, newAccid('##'))
.addAccidental(6, newAccid('#')),
vf.StaveNote({ keys: ['a/3', 'c/4', 'e/4', 'b/4', 'd/5', 'g/5'], duration: '1' })
.addAccidental(0, newAccid('#'))
.addAccidental(1, newAccid('db').setAsCautionary())
.addAccidental(2, newAccid('bbs').setAsCautionary())
.addAccidental(3, newAccid('b'))
.addAccidental(4, newAccid('++').setAsCautionary())
.addAccidental(5, newAccid('d').setAsCautionary()),
vf.StaveNote({ keys: ['f/4', 'g/4', 'a/4', 'b/4'], duration: '16' })
.addAccidental(0, newAccid('++-'))
.addAccidental(1, newAccid('+-'))
.addAccidental(2, newAccid('bs'))
.addAccidental(3, newAccid('bss')),
];
VF.Formatter.SimpleFormat(notes, 0, { paddingBetween: 35 });
notes.forEach(function(note, index) {
Vex.Flow.Test.plotNoteWidth(vf.getContext(), note, 140);
assert.ok(note.getAccidentals().length > 0, 'Note ' + index + ' has accidentals');
note.getAccidentals().forEach(function(accid, index) {
assert.ok(accid.getWidth() > 0, 'Accidental ' + index + ' has set width');
});
});
vf.draw();
Vex.Flow.Test.plotLegendForNoteWidth(ctx, 580, 140);
ok(true, 'Microtonal Accidental');
},
microtonal_iranian: function(options) {
var assert = options.assert;
var vf = VF.Test.makeFactory(options, 700, 240);
var newAccid = makeNewAccid(vf);
var ctx = vf.getContext();
vf.Stave({ x: 10, y: 10, width: 650 });
var notes = [
vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], duration: '1' })
.addAccidental(0, newAccid('k'))
.addAccidental(1, newAccid('o')),
vf.StaveNote({ keys: ['d/4', 'e/4', 'f/4', 'a/4', 'c/5', 'e/5', 'g/5'], duration: '2' })
.addAccidental(0, newAccid('b'))
.addAccidental(1, newAccid('k'))
.addAccidental(2, newAccid('n'))
.addAccidental(3, newAccid('o'))
.addAccidental(4, newAccid('#'))
.addAccidental(5, newAccid('bb'))
.addAccidental(6, newAccid('##')),
vf.StaveNote({ keys: ['f/4', 'g/4', 'a/4', 'b/4', 'c/5', 'e/5', 'g/5'], duration: '16' })
.addAccidental(0, newAccid('o'))
.addAccidental(1, newAccid('k'))
.addAccidental(2, newAccid('n'))
.addAccidental(3, newAccid('b'))
.addAccidental(4, newAccid('bb'))
.addAccidental(5, newAccid('##'))
.addAccidental(6, newAccid('#')),
vf.StaveNote({ keys: ['a/3', 'c/4', 'e/4', 'b/4', 'd/5', 'g/5'], duration: '1' })
.addAccidental(0, newAccid('#'))
.addAccidental(1, newAccid('o').setAsCautionary())
.addAccidental(2, newAccid('n').setAsCautionary())
.addAccidental(3, newAccid('b'))
.addAccidental(4, newAccid('k').setAsCautionary()),
vf.StaveNote({ keys: ['f/4', 'g/4', 'a/4', 'b/4'], duration: '16' })
.addAccidental(0, newAccid('k'))
.addAccidental(1, newAccid('k'))
.addAccidental(2, newAccid('k'))
.addAccidental(3, newAccid('k')),
];
VF.Formatter.SimpleFormat(notes, 0, { paddingBetween: 35 });
notes.forEach(function(note, index) {
Vex.Flow.Test.plotNoteWidth(vf.getContext(), note, 140);
assert.ok(note.getAccidentals().length > 0, 'Note ' + index + ' has accidentals');
note.getAccidentals().forEach(function(accid, index) {
assert.ok(accid.getWidth() > 0, 'Accidental ' + index + ' has set width');
});
});
vf.draw();
Vex.Flow.Test.plotLegendForNoteWidth(ctx, 580, 140);
ok(true, 'Microtonal Accidental (Iranian)');
},
automaticAccidentals0: function(options) {
var vf = VF.Test.makeFactory(options, 700, 200);
var stave = vf.Stave();
const notes = [
{ keys: ['c/4', 'c/5'], duration: '4' },
{ keys: ['c#/4', 'c#/5'], duration: '4' },
{ keys: ['c#/4', 'c#/5'], duration: '4' },
{ keys: ['c##/4', 'c##/5'], duration: '4' },
{ keys: ['c##/4', 'c##/5'], duration: '4' },
{ keys: ['c/4', 'c/5'], duration: '4' },
{ keys: ['cn/4', 'cn/5'], duration: '4' },
{ keys: ['cbb/4', 'cbb/5'], duration: '4' },
{ keys: ['cbb/4', 'cbb/5'], duration: '4' },
{ keys: ['cb/4', 'cb/5'], duration: '4' },
{ keys: ['cb/4', 'cb/5'], duration: '4' },
{ keys: ['c/4', 'c/5'], duration: '4' },
].map(vf.StaveNote.bind(vf));
const gracenotes = [
{ keys: ['d#/4'], duration: '16', slash: true },
].map(vf.GraceNote.bind(vf));
notes[0].addModifier(0, vf.GraceNoteGroup({ notes: gracenotes }).beamNotes());
const voice = vf.Voice()
.setMode(Vex.Flow.Voice.Mode.SOFT)
.addTickable(new Vex.Flow.TimeSigNote('12/4').setStave(stave))
.addTickables(notes);
Vex.Flow.Accidental.applyAccidentals([voice], 'C');
new Vex.Flow.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
automaticAccidentals1: function(options) {
var vf = VF.Test.makeFactory(options, 700, 150);
var stave = vf.Stave().addKeySignature('Ab');
var notes = [
{ keys: ['c/4'], duration: '4' },
{ keys: ['d/4'], duration: '4' },
{ keys: ['e/4'], duration: '4' },
{ keys: ['f/4'], duration: '4' },
{ keys: ['g/4'], duration: '4' },
{ keys: ['a/4'], duration: '4' },
{ keys: ['b/4'], duration: '4' },
{ keys: ['c/5'], duration: '4' },
].map(vf.StaveNote.bind(vf));
var voice = vf.Voice()
.setMode(Vex.Flow.Voice.Mode.SOFT)
.addTickables(notes);
Vex.Flow.Accidental.applyAccidentals([voice], 'Ab');
new Vex.Flow.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
automaticAccidentals2: function(options) {
var vf = VF.Test.makeFactory(options, 700, 150);
var stave = vf.Stave().addKeySignature('A');
var notes = [
{ keys: ['a/4'], duration: '4' },
{ keys: ['b/4'], duration: '4' },
{ keys: ['c#/5'], duration: '4' },
{ keys: ['d/5'], duration: '4' },
{ keys: ['e/5'], duration: '4' },
{ keys: ['f#/5'], duration: '4' },
{ keys: ['g#/5'], duration: '4' },
{ keys: ['a/5'], duration: '4' },
].map(vf.StaveNote.bind(vf));
var voice = vf.Voice()
.setMode(Vex.Flow.Voice.Mode.SOFT)
.addTickables(notes);
Vex.Flow.Accidental.applyAccidentals([voice], 'A');
new Vex.Flow.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
automaticAccidentalsMultiVoiceInline: function(options) {
var vf = VF.Test.makeFactory(options, 700, 150);
var stave = vf.Stave().addKeySignature('Ab');
var notes0 = [
{ keys: ['c/4'], duration: '4', stem_direction: -1 },
{ keys: ['d/4'], duration: '4', stem_direction: -1 },
{ keys: ['e/4'], duration: '4', stem_direction: -1 },
{ keys: ['f/4'], duration: '4', stem_direction: -1 },
{ keys: ['g/4'], duration: '4', stem_direction: -1 },
{ keys: ['a/4'], duration: '4', stem_direction: -1 },
{ keys: ['b/4'], duration: '4', stem_direction: -1 },
{ keys: ['c/5'], duration: '4', stem_direction: -1 },
].map(vf.StaveNote.bind(vf));
var notes1 = [
{ keys: ['c/5'], duration: '4' },
{ keys: ['d/5'], duration: '4' },
{ keys: ['e/5'], duration: '4' },
{ keys: ['f/5'], duration: '4' },
{ keys: ['g/5'], duration: '4' },
{ keys: ['a/5'], duration: '4' },
{ keys: ['b/5'], duration: '4' },
{ keys: ['c/6'], duration: '4' },
].map(vf.StaveNote.bind(vf));
var voice0 = vf.Voice()
.setMode(Vex.Flow.Voice.Mode.SOFT)
.addTickables(notes0);
var voice1 = vf.Voice()
.setMode(Vex.Flow.Voice.Mode.SOFT)
.addTickables(notes1);
// Ab Major
Vex.Flow.Accidental.applyAccidentals([voice0, voice1], 'Ab');
equal(hasAccidental(notes0[0]), false);
equal(hasAccidental(notes0[1]), true);
equal(hasAccidental(notes0[2]), true);
equal(hasAccidental(notes0[3]), false);
equal(hasAccidental(notes0[4]), false);
equal(hasAccidental(notes0[5]), true);
equal(hasAccidental(notes0[6]), true);
equal(hasAccidental(notes0[7]), false);
equal(hasAccidental(notes1[0]), false);
equal(hasAccidental(notes1[1]), true);
equal(hasAccidental(notes1[2]), true);
equal(hasAccidental(notes1[3]), false);
equal(hasAccidental(notes1[4]), false);
equal(hasAccidental(notes1[5]), true);
equal(hasAccidental(notes1[6]), true);
equal(hasAccidental(notes1[7]), false);
new Vex.Flow.Formatter()
.joinVoices([voice0, voice1])
.formatToStave([voice0, voice1], stave);
vf.draw();
ok(true);
},
automaticAccidentalsMultiVoiceOffset: function(options) {
var vf = VF.Test.makeFactory(options, 700, 150);
var stave = vf.Stave().addKeySignature('Cb');
var notes0 = [
{ keys: ['c/4'], duration: '4', stem_direction: -1 },
{ keys: ['d/4'], duration: '4', stem_direction: -1 },
{ keys: ['e/4'], duration: '4', stem_direction: -1 },
{ keys: ['f/4'], duration: '4', stem_direction: -1 },
{ keys: ['g/4'], duration: '4', stem_direction: -1 },
{ keys: ['a/4'], duration: '4', stem_direction: -1 },
{ keys: ['b/4'], duration: '4', stem_direction: -1 },
{ keys: ['c/5'], duration: '4', stem_direction: -1 },
].map(vf.StaveNote.bind(vf));
var notes1 = [
{ keys: ['c/5'], duration: '8' },
{ keys: ['c/5'], duration: '4' },
{ keys: ['d/5'], duration: '4' },
{ keys: ['e/5'], duration: '4' },
{ keys: ['f/5'], duration: '4' },
{ keys: ['g/5'], duration: '4' },
{ keys: ['a/5'], duration: '4' },
{ keys: ['b/5'], duration: '4' },
{ keys: ['c/6'], duration: '4' },
].map(vf.StaveNote.bind(vf));
var voice0 = vf.Voice()
.setMode(Vex.Flow.Voice.Mode.SOFT)
.addTickables(notes0);
var voice1 = vf.Voice()
.setMode(Vex.Flow.Voice.Mode.SOFT)
.addTickables(notes1);
// Cb Major (All flats)
Vex.Flow.Accidental.applyAccidentals([voice0, voice1], 'Cb');
equal(hasAccidental(notes0[0]), true);
equal(hasAccidental(notes0[1]), true);
equal(hasAccidental(notes0[2]), true);
equal(hasAccidental(notes0[3]), true);
equal(hasAccidental(notes0[4]), true);
equal(hasAccidental(notes0[5]), true);
equal(hasAccidental(notes0[6]), true);
equal(hasAccidental(notes0[7]), false, 'Natural Remembered');
equal(hasAccidental(notes1[0]), true);
equal(hasAccidental(notes1[1]), false);
equal(hasAccidental(notes1[2]), false);
equal(hasAccidental(notes1[3]), false);
equal(hasAccidental(notes1[4]), false);
equal(hasAccidental(notes1[5]), false);
equal(hasAccidental(notes1[6]), false);
equal(hasAccidental(notes1[7]), false);
new Vex.Flow.Formatter()
.joinVoices([voice0, voice1])
.formatToStave([voice0, voice1], stave);
vf.draw();
ok(true);
},
autoAccidentalWorking: function() {
function makeNote(noteStruct) { return new VF.StaveNote(noteStruct); }
var notes = [
{ keys: ['bb/4'], duration: '4' },
{ keys: ['bb/4'], duration: '4' },
{ keys: ['g#/4'], duration: '4' },
{ keys: ['g/4'], duration: '4' },
{ keys: ['b/4'], duration: '4' },
{ keys: ['b/4'], duration: '4' },
{ keys: ['a#/4'], duration: '4' },
{ keys: ['g#/4'], duration: '4' },
].map(makeNote);
var voice = new VF.Voice()
.setMode(Vex.Flow.Voice.Mode.SOFT)
.addTickables(notes);
// F Major (Bb)
Vex.Flow.Accidental.applyAccidentals([voice], 'F');
equal(hasAccidental(notes[0]), false, 'No flat because of key signature');
equal(hasAccidental(notes[1]), false, 'No flat because of key signature');
equal(hasAccidental(notes[2]), true, 'Added a sharp');
equal(hasAccidental(notes[3]), true, 'Back to natural');
equal(hasAccidental(notes[4]), true, 'Back to natural');
equal(hasAccidental(notes[5]), false, 'Natural remembered');
equal(hasAccidental(notes[6]), true, 'Added sharp');
equal(hasAccidental(notes[7]), true, 'Added sharp');
notes = [
{ keys: ['e#/4'], duration: '4' },
{ keys: ['cb/4'], duration: '4' },
{ keys: ['fb/4'], duration: '4' },
{ keys: ['b#/4'], duration: '4' },
{ keys: ['b#/4'], duration: '4' },
{ keys: ['cb/5'], duration: '4' },
{ keys: ['fb/5'], duration: '4' },
{ keys: ['e#/4'], duration: '4' },
].map(makeNote);
voice = new VF.Voice()
.setMode(Vex.Flow.Voice.Mode.SOFT)
.addTickables(notes);
// A Major (F#,G#,C#)
Vex.Flow.Accidental.applyAccidentals([voice], 'A');
equal(hasAccidental(notes[0]), true, 'Added sharp');
equal(hasAccidental(notes[1]), true, 'Added flat');
equal(hasAccidental(notes[2]), true, 'Added flat');
equal(hasAccidental(notes[3]), true, 'Added sharp');
equal(hasAccidental(notes[4]), false, 'Sharp remembered');
equal(hasAccidental(notes[5]), false, 'Flat remembered');
equal(hasAccidental(notes[6]), false, 'Flat remembered');
equal(hasAccidental(notes[7]), false, 'sharp remembered');
notes = [
{ keys: ['c/4'], duration: '4' },
{ keys: ['cb/4'], duration: '4' },
{ keys: ['cb/4'], duration: '4' },
{ keys: ['c#/4'], duration: '4' },
{ keys: ['c#/4'], duration: '4' },
{ keys: ['cbb/4'], duration: '4' },
{ keys: ['cbb/4'], duration: '4' },
{ keys: ['c##/4'], duration: '4' },
{ keys: ['c##/4'], duration: '4' },
{ keys: ['c/4'], duration: '4' },
{ keys: ['c/4'], duration: '4' },
].map(makeNote);
voice = new VF.Voice()
.setMode(Vex.Flow.Voice.Mode.SOFT)
.addTickables(notes);
// C Major (no sharps/flats)
Vex.Flow.Accidental.applyAccidentals([voice], 'C');
equal(hasAccidental(notes[0]), false, 'No accidental');
equal(hasAccidental(notes[1]), true, 'Added flat');
equal(hasAccidental(notes[2]), false, 'Flat remembered');
equal(hasAccidental(notes[3]), true, 'Sharp added');
equal(hasAccidental(notes[4]), false, 'Sharp remembered');
equal(hasAccidental(notes[5]), true, 'Added doubled flat');
equal(hasAccidental(notes[6]), false, 'Double flat remembered');
equal(hasAccidental(notes[7]), true, 'Added double sharp');
equal(hasAccidental(notes[8]), false, 'Double sharp rememberd');
equal(hasAccidental(notes[9]), true, 'Added natural');
equal(hasAccidental(notes[10]), false, 'Natural remembered');
},
factoryAPI: function(options) {
var assert = options.assert;
var vf = VF.Test.makeFactory(options, 700, 240);
vf.Stave({ x: 10, y: 10, width: 550 });
function newAcc(type) { return vf.Accidental({ type: type }); }
var notes = [
vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], duration: 'w' })
.addAccidental(0, newAcc('b'))
.addAccidental(1, newAcc('#')),
vf.StaveNote({ keys: ['d/4', 'e/4', 'f/4', 'a/4', 'c/5', 'e/5', 'g/5'], duration: 'h' })
.addAccidental(0, newAcc('##'))
.addAccidental(1, newAcc('n'))
.addAccidental(2, newAcc('bb'))
.addAccidental(3, newAcc('b'))
.addAccidental(4, newAcc('#'))
.addAccidental(5, newAcc('n'))
.addAccidental(6, newAcc('bb')),
vf.StaveNote({ keys: ['f/4', 'g/4', 'a/4', 'b/4', 'c/5', 'e/5', 'g/5'], duration: '16' })
.addAccidental(0, newAcc('n'))
.addAccidental(1, newAcc('#'))
.addAccidental(2, newAcc('#'))
.addAccidental(3, newAcc('b'))
.addAccidental(4, newAcc('bb'))
.addAccidental(5, newAcc('##'))
.addAccidental(6, newAcc('#')),
vf.StaveNote({ keys: ['a/3', 'c/4', 'e/4', 'b/4', 'd/5', 'g/5'], duration: 'w' })
.addAccidental(0, newAcc('#'))
.addAccidental(1, newAcc('##').setAsCautionary())
.addAccidental(2, newAcc('#').setAsCautionary())
.addAccidental(3, newAcc('b'))
.addAccidental(4, newAcc('bb').setAsCautionary())
.addAccidental(5, newAcc('b').setAsCautionary()),
];
VF.Formatter.SimpleFormat(notes);
notes.forEach(function(n, i) {
assert.ok(n.getAccidentals().length > 0, 'Note ' + i + ' has accidentals');
n.getAccidentals().forEach(function(accid, i) {
assert.ok(accid.getWidth() > 0, 'Accidental ' + i + ' has set width');
});
});
vf.draw();
assert.ok(true, 'Factory API');
},
};
return Accidental;
})();
/**
* VexFlow - Annotation Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Annotation = (function() {
var runTests = VF.Test.runTests;
var Annotation = {
Start: function() {
QUnit.module('Annotation');
runTests('Simple Annotation', Annotation.simple);
runTests('Standard Notation Annotation', Annotation.standard);
runTests('Harmonics', Annotation.harmonic);
runTests('Fingerpicking', Annotation.picking);
runTests('Bottom Annotation', Annotation.bottom);
runTests('Bottom Annotations with Beams', Annotation.bottomWithBeam);
runTests('Test Justification Annotation Stem Up', Annotation.justificationStemUp);
runTests('Test Justification Annotation Stem Down', Annotation.justificationStemDown);
runTests('TabNote Annotations', Annotation.tabNotes);
},
simple: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
ctx.font = ' 10pt Arial';
var stave = new VF.TabStave(10, 10, 450)
.addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newBend(text) { return new VF.Bend(text); }
function newAnnotation(text) { return new VF.Annotation(text); }
var notes = [
newNote({
positions: [{ str: 2, fret: 10 }, { str: 4, fret: 9 }], duration: 'h',
})
.addModifier(newAnnotation('T'), 0),
newNote({
positions: [{ str: 2, fret: 10 }], duration: 'h',
})
.addModifier(newAnnotation('T'), 0)
.addModifier(newBend('Full'), 0),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes, 200);
ok(true, 'Simple Annotation');
},
standard: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
var stave = new VF.Stave(10, 10, 450)
.addClef('treble').setContext(ctx).draw();
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
function newAnnotation(text) {
return (new VF.Annotation(text)).setFont('Times',
VF.Test.Font.size, 'italic');
}
var notes = [
newNote({ keys: ['c/4', 'e/4'], duration: 'h' })
.addAnnotation(0, newAnnotation('quiet')),
newNote({ keys: ['c/4', 'e/4', 'c/5'], duration: 'h' })
.addAnnotation(2, newAnnotation('Allegro')),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes, 200);
ok(true, 'Standard Notation Annotation');
},
harmonic: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
ctx.font = ' 10pt Arial';
var stave = new VF.TabStave(10, 10, 450)
.addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newAnnotation(text) { return new VF.Annotation(text); }
var notes = [
newNote({
positions: [{ str: 2, fret: 12 }, { str: 3, fret: 12 }], duration: 'h',
})
.addModifier(newAnnotation('Harm.'), 0),
newNote({
positions: [{ str: 2, fret: 9 }], duration: 'h',
})
.addModifier(newAnnotation('(8va)').setFont('Times',
VF.Test.Font.size, 'italic'), 0)
.addModifier(newAnnotation('A.H.'), 0),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes, 200);
ok(true, 'Simple Annotation');
},
picking: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5); ctx.setFillStyle('#221'); ctx.setStrokeStyle('#221');
ctx.setFont('Arial', VF.Test.Font.size, '');
var stave = new VF.TabStave(10, 10, 450)
.addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newAnnotation(text) {
return new VF.Annotation(text)
.setFont('Times', VF.Test.Font.size, 'italic');
}
var notes = [
newNote({
positions: [
{ str: 1, fret: 0 },
{ str: 2, fret: 1 },
{ str: 3, fret: 2 },
{ str: 4, fret: 2 },
{ str: 5, fret: 0 },
], duration: 'h',
})
.addModifier(new VF.Vibrato().setVibratoWidth(40)),
newNote({
positions: [{ str: 6, fret: 9 }], duration: '8',
})
.addModifier(newAnnotation('p'), 0),
newNote({
positions: [{ str: 3, fret: 9 }], duration: '8',
})
.addModifier(newAnnotation('i'), 0),
newNote({
positions: [{ str: 2, fret: 9 }], duration: '8',
})
.addModifier(newAnnotation('m'), 0),
newNote({
positions: [{ str: 1, fret: 9 }], duration: '8',
})
.addModifier(newAnnotation('a'), 0),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes, 200);
ok(true, 'Fingerpicking');
},
bottom: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
var stave = new VF.Stave(10, 10, 300)
.addClef('treble').setContext(ctx).draw();
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
function newAnnotation(text) {
return (
new VF.Annotation(text))
.setFont('Times', VF.Test.Font.size)
.setVerticalJustification(VF.Annotation.VerticalJustify.BOTTOM);
}
var notes = [
newNote({ keys: ['f/4'], duration: 'w' })
.addAnnotation(0, newAnnotation('F')),
newNote({ keys: ['a/4'], duration: 'w' })
.addAnnotation(0, newAnnotation('A')),
newNote({ keys: ['c/5'], duration: 'w' })
.addAnnotation(0, newAnnotation('C')),
newNote({ keys: ['e/5'], duration: 'w' })
.addAnnotation(0, newAnnotation('E')),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes, 100);
ok(true, 'Bottom Annotation');
},
bottomWithBeam: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
var stave = new VF.Stave(10, 10, 300)
.addClef('treble').setContext(ctx).draw();
// Create some notes
var notes = [
new VF.StaveNote({ keys: ['a/3'], duration: '8' })
.addModifier(0, new VF.Annotation('good')
.setVerticalJustification(VF.Annotation.VerticalJustify.BOTTOM)),
new VF.StaveNote({ keys: ['g/3'], duration: '8' })
.addModifier(0, new VF.Annotation('even')
.setVerticalJustification(VF.Annotation.VerticalJustify.BOTTOM)),
new VF.StaveNote({ keys: ['c/4'], duration: '8' })
.addModifier(0, new VF.Annotation('under')
.setVerticalJustification(VF.Annotation.VerticalJustify.BOTTOM)),
new VF.StaveNote({ keys: ['d/4'], duration: '8' })
.addModifier(0, new VF.Annotation('beam')
.setVerticalJustification(VF.Annotation.VerticalJustify.BOTTOM)),
];
var beam = new VF.Beam(notes.slice(1));
VF.Formatter.FormatAndDraw(ctx, stave, notes);
beam.setContext(ctx).draw();
ok(true, 'Bottom Annotation with Beams');
},
justificationStemUp: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 650, 950);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
function newAnnotation(text, hJustifcation, vJustifcation) {
return (
new VF.Annotation(text))
.setFont('Arial', VF.Test.Font.size)
.setJustification(hJustifcation)
.setVerticalJustification(vJustifcation);
}
for (var v = 1; v <= 4; ++v) {
var stave = new VF.Stave(10, (v - 1) * 150 + 40, 400)
.addClef('treble').setContext(ctx).draw();
var notes = [];
notes.push(newNote({ keys: ['c/3'], duration: 'q' }).addAnnotation(0, newAnnotation('Text', 1, v)));
notes.push(newNote({ keys: ['c/4'], duration: 'q' }).addAnnotation(0, newAnnotation('Text', 2, v)));
notes.push(newNote({ keys: ['c/5'], duration: 'q' }).addAnnotation(0, newAnnotation('Text', 3, v)));
notes.push(newNote({ keys: ['c/6'], duration: 'q' }).addAnnotation(0, newAnnotation('Text', 4, v)));
VF.Formatter.FormatAndDraw(ctx, stave, notes, 100);
}
ok(true, 'Test Justification Annotation');
},
justificationStemDown: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 650, 1000);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
function newAnnotation(text, hJustifcation, vJustifcation) {
return (
new VF.Annotation(text))
.setFont('Arial', VF.Test.Font.size)
.setJustification(hJustifcation)
.setVerticalJustification(vJustifcation);
}
for (var v = 1; v <= 4; ++v) {
var stave = new VF.Stave(10, (v - 1) * 150 + 40, 400)
.addClef('treble').setContext(ctx).draw();
var notes = [];
notes.push(newNote({ keys: ['c/3'], duration: 'q', stem_direction: -1 }).addAnnotation(0, newAnnotation('Text', 1, v)));
notes.push(newNote({ keys: ['c/4'], duration: 'q', stem_direction: -1 }).addAnnotation(0, newAnnotation('Text', 2, v)));
notes.push(newNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }).addAnnotation(0, newAnnotation('Text', 3, v)));
notes.push(newNote({ keys: ['c/6'], duration: 'q', stem_direction: -1 }).addAnnotation(0, newAnnotation('Text', 4, v)));
VF.Formatter.FormatAndDraw(ctx, stave, notes, 100);
}
ok(true, 'Test Justification Annotation');
},
tabNotes: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 200);
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 10, 550);
stave.setContext(ctx);
stave.draw();
var specs = [
{ positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '8' },
{ positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 3, fret: 5 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 3, fret: 5 }], duration: '8' },
];
var notes = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
return tabNote;
});
var notes2 = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
tabNote.setStemDirection(-1);
return tabNote;
});
var notes3 = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
return tabNote;
});
notes[0].addModifier(new VF.Annotation('Text').setJustification(1).setVerticalJustification(1), 0); // U
notes[1].addModifier(new VF.Annotation('Text').setJustification(2).setVerticalJustification(2), 0); // D
notes[2].addModifier(new VF.Annotation('Text').setJustification(3).setVerticalJustification(3), 0); // U
notes[3].addModifier(new VF.Annotation('Text').setJustification(4).setVerticalJustification(4), 0); // D
notes2[0].addModifier(new VF.Annotation('Text').setJustification(3).setVerticalJustification(1), 0); // U
notes2[1].addModifier(new VF.Annotation('Text').setJustification(3).setVerticalJustification(2), 0); // D
notes2[2].addModifier(new VF.Annotation('Text').setJustification(3).setVerticalJustification(3), 0); // U
notes2[3].addModifier(new VF.Annotation('Text').setJustification(3).setVerticalJustification(4), 0); // D
notes3[0].addModifier(new VF.Annotation('Text').setVerticalJustification(1), 0); // U
notes3[1].addModifier(new VF.Annotation('Text').setVerticalJustification(2), 0); // D
notes3[2].addModifier(new VF.Annotation('Text').setVerticalJustification(3), 0); // U
notes3[3].addModifier(new VF.Annotation('Text').setVerticalJustification(4), 0); // D
var voice = new VF.Voice(VF.Test.TIME4_4).setMode(VF.Voice.Mode.SOFT);
voice.addTickables(notes);
voice.addTickables(notes2);
voice.addTickables(notes3);
new VF.Formatter().joinVoices([voice])
.formatToStave([voice], stave);
voice.draw(ctx, stave);
ok(true, 'TabNotes successfully drawn');
},
};
return Annotation;
})();
/**
* VexFlow - Articulation Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
var VF = Vex.Flow;
VF.Test.Articulation = (function() {
var Articulation = {
Start: function() {
QUnit.module('Articulation');
Articulation.runTests('Articulation - Staccato/Staccatissimo', 'a.', 'av', Articulation.drawArticulations);
Articulation.runTests('Articulation - Accent/Tenuto', 'a>', 'a-', Articulation.drawArticulations);
Articulation.runTests('Articulation - Marcato/L.H. Pizzicato', 'a^', 'a+', Articulation.drawArticulations);
Articulation.runTests('Articulation - Snap Pizzicato/Fermata', 'ao', 'ao', Articulation.drawArticulations);
Articulation.runTests('Articulation - Up-stroke/Down-Stroke', 'a|', 'am', Articulation.drawArticulations);
Articulation.runTests('Articulation - Fermata Above/Below', 'a@a', 'a@u', Articulation.drawFermata);
Articulation.runTests('Articulation - Inline/Multiple', 'a.', 'a.', Articulation.drawArticulations2);
Articulation.runTests('TabNote Articulation', 'a.', 'a.', Articulation.tabNotes);
},
runTests: function(name, sym1, sym2, func) {
var params = {
sym1: sym1,
sym2: sym2,
};
VF.Test.runTests(name, func, params);
},
drawArticulations: function(options, contextBuilder) {
var sym1 = options.params.sym1;
var sym2 = options.params.sym2;
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 625, 195);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 125);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['a/3'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: 1 }),
];
notesBar1[0].addArticulation(0, new VF.Articulation(sym1).setPosition(4));
notesBar1[1].addArticulation(0, new VF.Articulation(sym1).setPosition(4));
notesBar1[2].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar1[3].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
// bar 2 - juxtaposing second bar next to first bar
var staveBar2 = new VF.Stave(staveBar1.width + staveBar1.x, staveBar1.y, 125);
staveBar2.setEndBarType(VF.Barline.type.DOUBLE);
staveBar2.setContext(ctx).draw();
var notesBar2 = [
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
];
notesBar2[0].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar2[1].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar2[2].addArticulation(0, new VF.Articulation(sym1).setPosition(4));
notesBar2[3].addArticulation(0, new VF.Articulation(sym1).setPosition(4));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar2, notesBar2);
// bar 3 - juxtaposing second bar next to first bar
var staveBar3 = new VF.Stave(staveBar2.width + staveBar2.x, staveBar2.y, 125);
staveBar3.setContext(ctx).draw();
var notesBar3 = [
new VF.StaveNote({ keys: ['c/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: 1 }),
];
notesBar3[0].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
notesBar3[1].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
notesBar3[2].addArticulation(0, new VF.Articulation(sym2).setPosition(3));
notesBar3[3].addArticulation(0, new VF.Articulation(sym2).setPosition(3));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar3, notesBar3);
// bar 4 - juxtaposing second bar next to first bar
var staveBar4 = new VF.Stave(staveBar3.width + staveBar3.x, staveBar3.y, 125);
staveBar4.setEndBarType(VF.Barline.type.END);
staveBar4.setContext(ctx).draw();
var notesBar4 = [
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
];
notesBar4[0].addArticulation(0, new VF.Articulation(sym2).setPosition(3));
notesBar4[1].addArticulation(0, new VF.Articulation(sym2).setPosition(3));
notesBar4[2].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
notesBar4[3].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar4, notesBar4);
},
drawFermata: function(options, contextBuilder) {
var sym1 = options.params.sym1;
var sym2 = options.params.sym2;
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 400, 200);
// bar 1
var staveBar1 = new VF.Stave(50, 30, 150);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['c/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/4'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: -1 }),
];
notesBar1[0].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar1[1].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar1[2].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
notesBar1[3].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
// bar 2 - juxtaposing second bar next to first bar
var staveBar2 = new VF.Stave(staveBar1.width + staveBar1.x, staveBar1.y, 150);
staveBar2.setEndBarType(VF.Barline.type.DOUBLE);
staveBar2.setContext(ctx).draw();
var notesBar2 = [
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
];
notesBar2[0].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar2[1].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar2[2].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
notesBar2[3].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar2, notesBar2);
},
drawArticulations2: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 725, 200);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 250);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['c/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['d/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['e/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['g/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['b/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/5'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['d/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['e/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['f/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['g/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['b/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['c/6'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['d/6'], duration: '16', stem_direction: -1 }),
];
var i;
for (i = 0; i < 16; i++) {
notesBar1[i].addArticulation(0, new VF.Articulation('a.').setPosition(4));
notesBar1[i].addArticulation(0, new VF.Articulation('a>').setPosition(4));
if (i === 15) {
notesBar1[i].addArticulation(0, new VF.Articulation('a@u').setPosition(4));
}
}
var beam1 = new VF.Beam(notesBar1.slice(0, 8));
var beam2 = new VF.Beam(notesBar1.slice(8, 16));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
beam1.setContext(ctx).draw();
beam2.setContext(ctx).draw();
// bar 2 - juxtaposing second bar next to first bar
var staveBar2 = new VF.Stave(staveBar1.width + staveBar1.x, staveBar1.y, 250);
staveBar2.setContext(ctx).draw();
var notesBar2 = [
new VF.StaveNote({ keys: ['f/3'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['g/3'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/3'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['b/3'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['d/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['e/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['g/4'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['b/4'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['c/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['d/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['e/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['f/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['g/5'], duration: '16', stem_direction: -1 }),
];
for (i = 0; i < 16; i++) {
notesBar2[i].addArticulation(0, new VF.Articulation('a-').setPosition(3));
notesBar2[i].addArticulation(0, new VF.Articulation('a^').setPosition(3));
if (i === 15) {
notesBar2[i].addArticulation(0, new VF.Articulation('a@u').setPosition(4));
}
}
var beam3 = new VF.Beam(notesBar2.slice(0, 8));
var beam4 = new VF.Beam(notesBar2.slice(8, 16));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar2, notesBar2);
beam3.setContext(ctx).draw();
beam4.setContext(ctx).draw();
// bar 3 - juxtaposing second bar next to first bar
var staveBar3 = new VF.Stave(staveBar2.width + staveBar2.x, staveBar2.y, 75);
staveBar3.setContext(ctx).draw();
var notesBar3 = [
new VF.StaveNote({ keys: ['c/4'], duration: 'w', stem_direction: 1 }),
];
notesBar3[0].addArticulation(0, new VF.Articulation('a-').setPosition(3));
notesBar3[0].addArticulation(0, new VF.Articulation('a>').setPosition(3));
notesBar3[0].addArticulation(0, new VF.Articulation('a@a').setPosition(3));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar3, notesBar3);
// bar 4 - juxtaposing second bar next to first bar
var staveBar4 = new VF.Stave(staveBar3.width + staveBar3.x, staveBar3.y, 125);
staveBar4.setEndBarType(VF.Barline.type.END);
staveBar4.setContext(ctx).draw();
var notesBar4 = [
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
];
for (i = 0; i < 4; i++) {
var position1 = 3;
if (i > 1) {
position1 = 4;
}
notesBar4[i].addArticulation(0, new VF.Articulation('a-').setPosition(position1));
}
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar4, notesBar4);
},
tabNotes: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 200);
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 10, 550);
stave.setContext(ctx);
stave.draw();
var specs = [
{ positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '8' },
{ positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 3, fret: 5 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 3, fret: 5 }], duration: '8' },
];
var notes = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
return tabNote;
});
var notes2 = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
tabNote.setStemDirection(-1);
return tabNote;
});
var notes3 = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
return tabNote;
});
notes[0].addModifier(new VF.Articulation('a>').setPosition(3), 0); // U
notes[1].addModifier(new VF.Articulation('a>').setPosition(4), 0); // D
notes[2].addModifier(new VF.Articulation('a.').setPosition(3), 0); // U
notes[3].addModifier(new VF.Articulation('a.').setPosition(4), 0); // D
notes2[0].addModifier(new VF.Articulation('a>').setPosition(3), 0);
notes2[1].addModifier(new VF.Articulation('a>').setPosition(4), 0);
notes2[2].addModifier(new VF.Articulation('a.').setPosition(3), 0);
notes2[3].addModifier(new VF.Articulation('a.').setPosition(4), 0);
notes3[0].addModifier(new VF.Articulation('a>').setPosition(3), 0);
notes3[1].addModifier(new VF.Articulation('a>').setPosition(4), 0);
notes3[2].addModifier(new VF.Articulation('a.').setPosition(3), 0);
notes3[3].addModifier(new VF.Articulation('a.').setPosition(4), 0);
var voice = new VF.Voice(VF.Test.TIME4_4).setMode(VF.Voice.Mode.SOFT);
voice.addTickables(notes);
voice.addTickables(notes2);
voice.addTickables(notes3);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
voice.draw(ctx, stave);
ok(true, 'TabNotes successfully drawn');
},
};
return Articulation;
}());
/**
* VexFlow - Auto-beaming Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
var VF = Vex.Flow;
VF.Test.AutoBeamFormatting = (function() {
function concat(a, b) { return a.concat(b); }
var AutoBeamFormatting = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('Auto-Beaming');
runTests('Simple Auto Beaming', AutoBeamFormatting.simpleAuto);
runTests('Even Group Stem Directions', AutoBeamFormatting.evenGroupStemDirections);
runTests('Odd Group Stem Directions', AutoBeamFormatting.oddGroupStemDirections);
runTests('Odd Beam Groups Auto Beaming', AutoBeamFormatting.oddBeamGroups);
runTests('More Simple Auto Beaming 0', AutoBeamFormatting.moreSimple0);
runTests('More Simple Auto Beaming 1', AutoBeamFormatting.moreSimple1);
runTests('Beam Across All Rests', AutoBeamFormatting.beamAcrossAllRests);
runTests('Beam Across All Rests with Stemlets', AutoBeamFormatting.beamAcrossAllRestsWithStemlets);
runTests('Break Beams on Middle Rests Only', AutoBeamFormatting.beamAcrossMiddleRests);
runTests('Break Beams on Rest', AutoBeamFormatting.breakBeamsOnRests);
runTests('Maintain Stem Directions', AutoBeamFormatting.maintainStemDirections);
runTests('Maintain Stem Directions - Beam Over Rests', AutoBeamFormatting.maintainStemDirectionsBeamAcrossRests);
runTests('Beat group with unbeamable note - 2/2', AutoBeamFormatting.groupWithUnbeamableNote);
runTests('Offset beat grouping - 6/8 ', AutoBeamFormatting.groupWithUnbeamableNote1);
runTests('Odd Time - Guessing Default Beam Groups', AutoBeamFormatting.autoOddBeamGroups);
runTests('Custom Beam Groups', AutoBeamFormatting.customBeamGroups);
runTests('Simple Tuplet Auto Beaming', AutoBeamFormatting.simpleTuplets);
runTests('More Simple Tuplet Auto Beaming', AutoBeamFormatting.moreSimpleTuplets);
runTests('More Automatic Beaming', AutoBeamFormatting.moreBeaming);
runTests('Duration-Based Secondary Beam Breaks', AutoBeamFormatting.secondaryBreaks);
runTests('Duration-Based Secondary Beam Breaks 2', AutoBeamFormatting.secondaryBreaks2);
runTests('Flat Beams Up', AutoBeamFormatting.flatBeamsUp);
runTests('Flat Beams Down', AutoBeamFormatting.flatBeamsDown);
runTests('Flat Beams Mixed Direction', AutoBeamFormatting.flatBeamsMixed);
runTests('Flat Beams Up (uniform)', AutoBeamFormatting.flatBeamsUpUniform);
runTests('Flat Beams Down (uniform)', AutoBeamFormatting.flatBeamsDownUniform);
runTests('Flat Beams Up Bounds', AutoBeamFormatting.flatBeamsUpBounds);
runTests('Flat Beams Down Bounds', AutoBeamFormatting.flatBeamsDownBounds);
},
simpleAuto: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'f5/8, e5, d5, c5/16, c5, d5/8, e5, f5, f5/32, f5, f5, f5'
), { time: '4/4' });
// Takes a voice and returns it's auto beamsj
var beams = VF.Beam.applyAndGetBeams(voice);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beaming Applicator Test');
},
evenGroupStemDirections: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'a4/8, b4, g4, c5, f4, d5, e4, e5, b4, b4, g4, d5'
), { time: '6/4' });
// Takes a voice and returns it's auto beams
var beams = VF.Beam.applyAndGetBeams(voice);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
var UP = VF.Stem.UP;
var DOWN = VF.Stem.DOWN;
equal(beams[0].stem_direction, UP);
equal(beams[1].stem_direction, UP);
equal(beams[2].stem_direction, UP);
equal(beams[3].stem_direction, UP);
equal(beams[4].stem_direction, DOWN);
equal(beams[5].stem_direction, DOWN);
ok(true, 'Auto Beaming Applicator Test');
},
oddGroupStemDirections: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'g4/8, b4, d5, c5, f4, d5, e4, g5, g4, b4, g4, d5, a4, c5, a4'
), { time: '15/8' });
var groups = [new VF.Fraction(3, 8)];
var beams = VF.Beam.applyAndGetBeams(voice, null, groups);
var UP = VF.Stem.UP;
var DOWN = VF.Stem.DOWN;
equal(beams[0].stem_direction, DOWN, 'Notes are equadistant from middle line');
equal(beams[1].stem_direction, DOWN);
equal(beams[2].stem_direction, UP);
equal(beams[3].stem_direction, DOWN, 'Notes are equadistant from middle line');
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beaming Applicator Test');
},
oddBeamGroups: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'f5, e5, d5, c5, c5, d5, e5, f5, f5, f4, f3, f5/16, f5'
), { time: '6/4' });
var groups = [
new VF.Fraction(2, 8),
new VF.Fraction(3, 8),
new VF.Fraction(1, 8),
];
// Takes a voice and returns it's auto beamsj
var beams = VF.Beam.applyAndGetBeams(voice, undefined, groups);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
moreSimple0: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'c4/8, g4, c5, g5, a5, c4, d4, a5'
), { time: '4/4' });
var beams = VF.Beam.applyAndGetBeams(voice);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
moreSimple1: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'c5/16, g5, c5, c5/r, c5/r, (c4 e4 g4), d4, a5, c4, g4, c5, b4/r, (c4 e4), b4/r, b4/r, a4'
), { time: '4/4' });
var beams = VF.Beam.applyAndGetBeams(voice);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
breakBeamsOnRests: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'c5/16, g5, c5, c5/r, c5/r, (c4 e4 g4), d4, a5, c4, g4, c5, b4/r, (c4 e4), b4/r, b4/r, a4'
), { time: '4/4' });
var beams = VF.Beam.generateBeams(voice.getTickables(), {
beam_rests: false,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
beamAcrossAllRestsWithStemlets: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'c5/16, g5, c5, c5/r, c5/r, (c4 e4 g4), d4, a5, c4, g4, c5, b4/r, (c4 e4), b4/r, b4/r, a4'
), { time: '4/4' });
var beams = VF.Beam.generateBeams(voice.getTickables(), {
beam_rests: true,
show_stemlets: true,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
beamAcrossAllRests: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'c5/16, g5, c5, c5/r, c5/r, (c4 e4 g4), d4, a5, c4, g4, c5, b4/r, (c4 e4), b4/r, b4/r, a4'
), { time: '4/4' });
var beams = VF.Beam.generateBeams(voice.getTickables(), {
beam_rests: true,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
beamAcrossMiddleRests: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'c5/16, g5, c5, c5/r, c5/r, (c4 e4 g4), d4, a5, c4, g4, c5, b4/r, (c4 e4), b4/r, b4/r, a4'
), { time: '4/4' });
var beams = VF.Beam.generateBeams(voice.getTickables(), {
beam_rests: true,
beam_middle_only: true,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
maintainStemDirections: function(options) {
var vf = VF.Test.makeFactory(options, 450, 200);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes([
'b4/16, b4, b4[stem="down"], b4/r',
'b4/r, b4[stem="down"], b4, b4',
'b4[stem="down"], b4[stem="down"], b4, b4/r',
'b4/32, b4[stem="down"], b4[stem="down"], b4, b4/16/r, b4',
].join(', '), { stem: 'up' }), { time: '4/4' });
var beams = VF.Beam.generateBeams(voice.getTickables(), {
beam_rests: false,
maintain_stem_directions: true,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
maintainStemDirectionsBeamAcrossRests: function(options) {
var vf = VF.Test.makeFactory(options, 450, 200);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes([
'b4/16, b4, b4[stem="down"], b4/r',
'b4/r, b4[stem="down"], b4, b4',
'b4[stem="down"], b4[stem="down"], b4, b4/r',
'b4/32, b4[stem="down"], b4[stem="down"], b4, b4/16/r, b4',
].join(', '), { stem: 'up' }), { time: '4/4' });
var beams = VF.Beam.generateBeams(voice.getTickables(), {
beam_rests: true,
maintain_stem_directions: true,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
groupWithUnbeamableNote: function(options) {
var vf = VF.Test.makeFactory(options, 450, 200);
var stave = vf.Stave().addTimeSignature('2/4');
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'b4/16, b4, b4/4, b4/16, b4'
), { time: '2/4' });
var beams = VF.Beam.generateBeams(voice.getTickables(), {
groups: [new VF.Fraction(2, 2)],
beam_rests: false,
maintain_stem_directions: true,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
groupWithUnbeamableNote1: function(options) {
var vf = VF.Test.makeFactory(options, 450, 200);
var stave = vf.Stave().addTimeSignature('6/8');
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'b4/4, b4/4, b4/8, b4/8'
), { time: '6/8' });
var beams = VF.Beam.generateBeams(voice.getTickables(), {
groups: [new VF.Fraction(3, 8)],
beam_rests: false,
maintain_stem_directions: true,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
autoOddBeamGroups: function(options) {
var vf = VF.Test.makeFactory(options, 450, 400);
var score = vf.EasyScore();
var stave1 = vf.Stave({ y: 10 }).addTimeSignature('5/4');
var voice1 = score.voice(score.notes('c5/8, g5, c5, b4, b4, c4, d4, a5, c4, g4'), { time: '5/4' });
var stave2 = vf.Stave({ y: 150 }).addTimeSignature('5/8');
var voice2 = score.voice(score.notes('c5/8, g5, c5, b4, b4'), { time: '5/8' });
var stave3 = vf.Stave({ y: 290 }).addTimeSignature('13/16');
var voice3 = score.voice(score.notes('c5/16, g5, c5, b4, b4, c5, g5, c5, b4, b4, c5, b4, b4'), { time: '13/16' });
var beams = [
VF.Beam.applyAndGetBeams(voice1, undefined, VF.Beam.getDefaultBeamGroups('5/4')),
VF.Beam.applyAndGetBeams(voice2, undefined, VF.Beam.getDefaultBeamGroups('5/8')),
VF.Beam.applyAndGetBeams(voice3, undefined, VF.Beam.getDefaultBeamGroups('13/16')),
].reduce(concat);
vf.Formatter()
.formatToStave([voice1], stave1)
.formatToStave([voice2], stave2)
.formatToStave([voice3], stave3);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
customBeamGroups: function(options) {
var vf = VF.Test.makeFactory(options, 450, 400);
var score = vf.EasyScore();
var stave1 = vf.Stave({ y: 10 }).addTimeSignature('5/4');
var voice1 = score.voice(score.notes('c5/8, g5, c5, b4, b4, c4, d4, a5, c4, g4'), { time: '5/4' });
var stave2 = vf.Stave({ y: 150 }).addTimeSignature('5/8');
var voice2 = score.voice(score.notes('c5/8, g5, c5, b4, b4'), { time: '5/8' });
var stave3 = vf.Stave({ y: 290 }).addTimeSignature('13/16');
var voice3 = score.voice(score.notes('c5/16, g5, c5, b4, b4, c5, g5, c5, b4, b4, c5, b4, b4'), { time: '13/16' });
var group1 = [
new VF.Fraction(5, 8),
];
var group2 = [
new VF.Fraction(3, 8),
new VF.Fraction(2, 8),
];
var group3 = [
new VF.Fraction(7, 16),
new VF.Fraction(2, 16),
new VF.Fraction(4, 16),
];
var beams = [
VF.Beam.applyAndGetBeams(voice1, undefined, group1),
VF.Beam.applyAndGetBeams(voice2, undefined, group2),
VF.Beam.applyAndGetBeams(voice3, undefined, group3),
].reduce(concat);
vf.Formatter()
.formatToStave([voice1], stave1)
.formatToStave([voice2], stave2)
.formatToStave([voice3], stave3);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
simpleTuplets: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var notes = score.notes.bind(score);
var tuplet = score.tuplet.bind(score);
var voice = score.voice([
tuplet(notes('c4/8, g4, c5')),
notes('g5/8, a5'),
tuplet(notes('a5/16, (c5 e5), a5, d5, a5'), {
ratioed: false,
notes_occupied: 4,
}),
].reduce(concat), { time: '3/4' });
var beams = VF.Beam.applyAndGetBeams(voice);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
moreSimpleTuplets: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var notes = score.notes.bind(score);
var tuplet = score.tuplet.bind(score);
var voice = score.voice([
tuplet(notes('d4/4, g4, c5')),
notes('g5/16, a5, a5, (c5 e5)'),
].reduce(concat), { time: '3/4' });
var beams = VF.Beam.applyAndGetBeams(voice);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
moreBeaming: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'c4/8, g4/4, c5/8., g5/16, a5/4, a5/16, (c5 e5)/16, a5/8'
), { time: '9/8' });
var beams = VF.Beam.applyAndGetBeams(voice);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Auto Beam Applicator Test');
},
secondaryBreaks: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes([
'f5/32, f5, f5, f5, f5/16., f5/32',
'f5/16, f5/8, f5/16',
'f5/32, f5/16., f5., f5/32',
'f5/16., f5/32, f5, f5/16.',
].join(',')));
var beams = VF.Beam.generateBeams(voice.getTickables(), {
secondary_breaks: '8',
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Duration-Based Secondary Breaks Test');
},
secondaryBreaks2: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var notes = score.notes.bind(score);
var tuplet = score.tuplet.bind(score);
var voice = score.voice([
tuplet(notes('e5/16, f5, f5')),
tuplet(notes('f5/16, f5, c5')),
notes('a4/16., f4/32'),
tuplet(notes('d4/16, d4, d4')),
tuplet(notes('a5/8, (e5 g5), a5')),
tuplet(notes('f5/16, f5, f5')),
tuplet(notes('f5/16, f5, a4')),
].reduce(concat));
var beams = VF.Beam.generateBeams(voice.getTickables(), {
secondary_breaks: '8',
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Duration-Based Secondary Breaks Test');
},
flatBeamsUp: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var tuplet = score.tuplet.bind(score);
var notes = score.notes.bind(score);
var voice = score.voice([
tuplet(notes('c4/8, g4, f5')),
notes('d5/8'),
tuplet(notes('c5/16, (c4 e4 g4), f4')),
notes('d5/8, e5, c4, f5/32, f5, f5, f5'),
].reduce(concat));
var beams = VF.Beam.generateBeams(voice.getTickables(), {
flat_beams: true,
stem_direction: 1,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Flat Beams Up Test');
},
flatBeamsDown: function(options) {
var vf = VF.Test.makeFactory(options, 450, 200);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var voice = score.voice(
score.notes(
'c5/64, c5, c5, c5, c5, c5, c5, c5, a5/8, g5, (d4 f4 a4)/16, d4, d5/8, e5, g5, a6/32, a6, a6, g4/64, g4'
)
);
var beams = VF.Beam.generateBeams(voice.getTickables(), {
flat_beams: true,
stem_direction: -1,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Flat Beams Down Test');
},
flatBeamsMixed: function(options) {
var vf = VF.Test.makeFactory(options, 450, 200);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'c5/64, d5, e5, c5, f5, c5, a5, c5, a5/8, g5, (d4 f4 a4)/16, d4, d5/8, e5, c4, a4/32, a4, a4, g4/64, g4'
));
var beams = VF.Beam.generateBeams(voice.getTickables(), {
flat_beams: true,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Flat Beams Mixed Direction Test');
},
flatBeamsUpUniform: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var tuplet = score.tuplet.bind(score);
var notes = score.notes.bind(score);
var voice = score.voice([
tuplet(notes('c4/8, g4, g5')),
notes('d5/8, c5/16, (c4 e4 g4), d5/8, e5, c4, f5/32, f5, f5, f5'),
].reduce(concat));
var beams = VF.Beam.generateBeams(voice.getTickables(), {
flat_beams: true,
flat_beam_offset: 50,
stem_direction: 1,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Flat Beams Up (uniform) Test');
},
flatBeamsDownUniform: function(options) {
var vf = VF.Test.makeFactory(options, 450, 200);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'c5/64, c5, c5, c5, c5, c5, c5, c5, a5/8, g5, (e4 g4 b4)/16, e5, d5/8, e5/8, g5/8, a6/32, a6, a6, g4/64, g4'
));
var beams = VF.Beam.generateBeams(voice.getTickables(), {
flat_beams: true,
flat_beam_offset: 155,
stem_direction: -1,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Flat Beams Down (uniform) Test');
},
flatBeamsUpBounds: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var tuplet = score.tuplet.bind(score);
var notes = score.notes.bind(score);
var voice = score.voice([
tuplet(notes('c4/8, g4/8, g5/8')),
notes('d5/8, c5/16, (c4 e4 g4)/16, d5/8, e5/8, c4/8, f5/32, f5/32, f5/32, f5/32'),
].reduce(concat));
var beams = VF.Beam.generateBeams(voice.getTickables(), {
flat_beams: true,
flat_beam_offset: 60,
stem_direction: 1,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Flat Beams Up (uniform) Test');
},
flatBeamsDownBounds: function(options) {
var vf = VF.Test.makeFactory(options, 450, 200);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var voice = score.voice(score.notes([
'g5/8, a6/32, a6/32, a6/32, g4/64, g4/64',
'c5/64, c5/64, c5/64, c5/64, c5/64, c5/64, c5/64, c5/64, a5/8',
'g5/8, (e4 g4 b4)/16, e5/16',
'd5/8, e5/8',
].join(','), { stem: 'down' }));
var beams = VF.Beam.generateBeams(voice.getTickables(), {
flat_beams: true,
flat_beam_offset: 145,
stem_direction: -1,
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
return beam.setContext(vf.getContext()).draw();
});
ok(true, 'Flat Beams Down (uniform) Test');
},
};
return AutoBeamFormatting;
})();
/**
* VexFlow - Auto-beaming Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
var VF = Vex.Flow;
VF.Test.BachDemo = (function() {
function concat(a, b) { return a.concat(b); }
var BachDemo = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('Bach Demo');
runTests('Minuet 1', BachDemo.minuet1);
},
minuet1: function(options) {
var registry = new VF.Registry();
VF.Registry.enableDefaultRegistry(registry);
var vf = VF.Test.makeFactory(options, 1100, 900);
var score = vf.EasyScore({ throwOnError: true });
var voice = score.voice.bind(score);
var notes = score.notes.bind(score);
var beam = score.beam.bind(score);
var x = 120;
var y = 80;
function makeSystem(width) {
var system = vf.System({ x: x, y: y, width: width, spaceBetweenStaves: 10 });
x += width;
return system;
}
function id(id) { return registry.getElementById(id); }
score.set({ time: '3/4' });
/* Measure 1 */
var system = makeSystem(220);
system.addStave({
voices: [
voice([
notes('D5/q[id="m1a"]'),
beam(notes('G4/8, A4, B4, C5', { stem: 'up' })),
].reduce(concat)),
voice([vf.TextDynamics({ text: 'p', duration: 'h', dots: 1, line: 9 })]),
],
})
.addClef('treble')
.addKeySignature('G')
.addTimeSignature('3/4')
.setTempo({ name: 'Allegretto', duration: 'h', dots: 1, bpm: 66 }, -30);
system.addStave({ voices: [voice(notes('(G3 B3 D4)/h, A3/q', { clef: 'bass' }))] })
.addClef('bass').addKeySignature('G').addTimeSignature('3/4');
system.addConnector('brace');
system.addConnector('singleRight');
system.addConnector('singleLeft');
id('m1a').addModifier(0, vf.Fingering({ number: '5' }));
/* Measure 2 */
system = makeSystem(150);
system.addStave({ voices: [voice(notes('D5/q[id="m2a"], G4[id="m2b"], G4[id="m2c"]'))] });
system.addStave({ voices: [voice(notes('B3/h.', { clef: 'bass' }))] });
system.addConnector('singleRight');
id('m2a').addModifier(0, vf.Articulation({ type: 'a.', position: 'above' }));
id('m2b').addModifier(0, vf.Articulation({ type: 'a.', position: 'below' }));
id('m2c').addModifier(0, vf.Articulation({ type: 'a.', position: 'below' }));
vf.Curve({
from: id('m1a'),
to: id('m2a'),
options: { cps: [{ x: 0, y: 40 }, { x: 0, y: 40 }] },
});
/* Measure 3 */
system = makeSystem(150);
system.addStave({
voices: [
voice([
notes('E5/q[id="m3a"]'),
beam(notes('C5/8, D5, E5, F5', { stem: 'down' })),
].reduce(concat)),
],
});
id('m3a').addModifier(0, vf.Fingering({ number: '3', position: 'above' }));
system.addStave({ voices: [voice(notes('C4/h.', { clef: 'bass' }))] });
system.addConnector('singleRight');
/* Measure 4 */
system = makeSystem(150);
system.addStave({ voices: [voice(notes('G5/q[id="m4a"], G4[id="m4b"], G4[id="m4c"]'))] });
system.addStave({ voices: [voice(notes('B3/h.', { clef: 'bass' }))] });
system.addConnector('singleRight');
id('m4a').addModifier(0, vf.Articulation({ type: 'a.', position: 'above' }));
id('m4b').addModifier(0, vf.Articulation({ type: 'a.', position: 'below' }));
id('m4c').addModifier(0, vf.Articulation({ type: 'a.', position: 'below' }));
vf.Curve({
from: id('m3a'),
to: id('m4a'),
options: { cps: [{ x: 0, y: 20 }, { x: 0, y: 20 }] },
});
/* Measure 5 */
system = makeSystem(150);
system.addStave({
voices: [
voice([
notes('C5/q[id="m5a"]'),
beam(notes('D5/8, C5, B4, A4', { stem: 'down' })),
].reduce(concat)),
],
});
id('m5a').addModifier(0, vf.Fingering({ number: '4', position: 'above' }));
system.addStave({ voices: [voice(notes('A3/h.', { clef: 'bass' }))] });
system.addConnector('singleRight');
/* Measure 6 */
system = makeSystem(150);
system.addStave({
voices: [
voice([
notes('B5/q'),
beam(notes('C5/8, B4, A4, G4[id="m6a"]', { stem: 'up' })),
].reduce(concat)),
],
});
system.addStave({ voices: [voice(notes('G3/h.', { clef: 'bass' }))] });
system.addConnector('singleRight');
vf.Curve({
from: id('m5a'),
to: id('m6a'),
options: {
cps: [{ x: 0, y: 20 }, { x: 0, y: 20 }],
invert: true,
position_end: 'nearTop',
y_shift: 20,
},
});
/* Measure 7 (New system) */
x = 20;
y += 230;
system = makeSystem(220);
system.addStave({
voices: [
voice([
notes('F4/q[id="m7a"]'),
beam(notes('G4/8[id="m7b"], A4, B4, G4', { stem: 'up' })),
].reduce(concat)),
],
}).addClef('treble').addKeySignature('G');
system.addStave({ voices: [voice(notes('D4/q, B3[id="m7c"], G3', { clef: 'bass' }))] })
.addClef('bass').addKeySignature('G');
system.addConnector('brace');
system.addConnector('singleRight');
system.addConnector('singleLeft');
id('m7a').addModifier(0, vf.Fingering({ number: '2', position: 'below' }));
id('m7b').addModifier(0, vf.Fingering({ number: '1' }));
id('m7c').addModifier(0, vf.Fingering({ number: '3', position: 'above' }));
/* Measure 8 */
system = makeSystem(180);
var grace = vf.GraceNote({ keys: ['d/3'], clef: 'bass', duration: '8', slash: true });
system.addStave({ voices: [voice(notes('A4/h.[id="m8c"]'))] });
system.addStave({
voices: [
score.set({ clef: 'bass' }).voice([
notes('D4/q[id="m8a"]'),
beam(notes('D3/8, C4, B3[id="m8b"], A3', { stem: 'down' })),
].reduce(concat)),
],
});
system.addConnector('singleRight');
id('m8b').addModifier(0, vf.Fingering({ number: '1', position: 'above' }));
id('m8c').addModifier(0, vf.GraceNoteGroup({ notes: [grace] }));
vf.Curve({
from: id('m7a'),
to: id('m8c'),
options: {
cps: [{ x: 0, y: 20 }, { x: 0, y: 20 }],
invert: true,
position: 'nearTop',
position_end: 'nearTop',
},
});
vf.StaveTie({ from: grace, to: id('m8c') });
/* Measure 9 */
system = makeSystem(180);
system.addStave({
voices: [
score.set({ clef: 'treble' }).voice([
notes('D5/q[id="m9a"]'),
beam(notes('G4/8, A4, B4, C5', { stem: 'up' })),
].reduce(concat)),
],
});
system.addStave({ voices: [voice(notes('B3/h, A3/q', { clef: 'bass' }))] });
system.addConnector('singleRight');
id('m9a').addModifier(0, vf.Fingering({ number: '5' }));
/* Measure 10 */
system = makeSystem(170);
system.addStave({ voices: [voice(notes('D5/q[id="m10a"], G4[id="m10b"], G4[id="m10c"]'))] });
system.addStave({ voices: [voice(notes('G3/q[id="m10d"], B3, G3', { clef: 'bass' }))] });
system.addConnector('singleRight');
id('m10a').addModifier(0, vf.Articulation({ type: 'a.', position: 'above' }));
id('m10b').addModifier(0, vf.Articulation({ type: 'a.', position: 'below' }));
id('m10c').addModifier(0, vf.Articulation({ type: 'a.', position: 'below' }));
id('m10d').addModifier(0, vf.Fingering({ number: '4' }));
vf.Curve({
from: id('m9a'),
to: id('m10a'),
options: { cps: [{ x: 0, y: 40 }, { x: 0, y: 40 }] },
});
/* Measure 11 */
system = makeSystem(150);
system.addStave({
voices: [
voice([
notes('E5/q[id="m11a"]'),
beam(notes('C5/8, D5, E5, F5', { stem: 'down' })),
].reduce(concat)),
],
});
id('m11a').addModifier(0, vf.Fingering({ number: '3', position: 'above' }));
system.addStave({ voices: [voice(notes('C4/h.', { clef: 'bass' }))] });
system.addConnector('singleRight');
/* Measure 12 */
system = makeSystem(170);
system.addStave({ voices: [voice(notes('G5/q[id="m12a"], G4[id="m12b"], G4[id="m12c"]'))] });
system.addStave({
voices: [
score.set({ clef: 'bass' }).voice([
notes('B3/q[id="m12d"]'),
beam(notes('C4/8, B3, A3, G3[id="m12e"]', { stem: 'down' })),
].reduce(concat)),
],
});
system.addConnector('singleRight');
id('m12a').addModifier(0, vf.Articulation({ type: 'a.', position: 'above' }));
id('m12b').addModifier(0, vf.Articulation({ type: 'a.', position: 'below' }));
id('m12c').addModifier(0, vf.Articulation({ type: 'a.', position: 'below' }));
id('m12d').addModifier(0, vf.Fingering({ number: '2', position: 'above' }));
id('m12e').addModifier(0, vf.Fingering({ number: '4', position: 'above' }));
vf.Curve({
from: id('m11a'),
to: id('m12a'),
options: { cps: [{ x: 0, y: 20 }, { x: 0, y: 20 }] },
});
/* Measure 13 (New system) */
x = 20;
y += 230;
system = makeSystem(220);
system.addStave({
voices: [
score.set({ clef: 'treble' }).voice([
notes('c5/q[id="m13a"]'),
beam(notes('d5/8, c5, b4, a4', { stem: 'down' })),
].reduce(concat)),
],
}).addClef('treble').addKeySignature('G');
system.addStave({ voices: [voice(notes('a3/h[id="m13b"], f3/q[id="m13c"]', { clef: 'bass' }))] })
.addClef('bass').addKeySignature('G');
system.addConnector('brace');
system.addConnector('singleRight');
system.addConnector('singleLeft');
id('m13a').addModifier(0, vf.Fingering({ number: '4', position: 'above' }));
id('m13b').addModifier(0, vf.Fingering({ number: '1' }));
id('m13c').addModifier(0, vf.Fingering({ number: '3', position: 'above' }));
/* Measure 14 */
system = makeSystem(180);
system.addStave({
voices: [
score.set({ clef: 'treble' }).voice([
notes('B4/q'),
beam(notes('C5/8, b4, a4, g4', { stem: 'up' })),
].reduce(concat)),
],
});
system.addStave({ voices: [voice(notes('g3/h[id="m14a"], b3/q[id="m14b"]', { clef: 'bass' }))] });
system.addConnector('singleRight');
id('m14a').addModifier(0, vf.Fingering({ number: '2' }));
id('m14b').addModifier(0, vf.Fingering({ number: '1' }));
/* Measure 15 */
system = makeSystem(180);
system.addStave({
voices: [
score.set({ clef: 'treble' }).voice([
notes('a4/q'),
beam(notes('b4/8, a4, g4, f4[id="m15a"]', { stem: 'up' })),
].reduce(concat)),
],
});
system.addStave({ voices: [voice(notes('c4/q[id="m15b"], d4, d3', { clef: 'bass' }))] });
system.addConnector('singleRight');
id('m15a').addModifier(0, vf.Fingering({ number: '2' }));
id('m15b').addModifier(0, vf.Fingering({ number: '2' }));
/* Measure 16 */
system = makeSystem(130);
system.addStave({
voices: [
score.set({ clef: 'treble' }).voice([
notes('g4/h.[id="m16a"]'),
].reduce(concat)),
],
}).setEndBarType(VF.Barline.type.REPEAT_END);
system.addStave({ voices: [voice(notes('g3/h[id="m16b"], g2/q', { clef: 'bass' }))] })
.setEndBarType(VF.Barline.type.REPEAT_END);
system.addConnector('boldDoubleRight');
id('m16a').addModifier(0, vf.Fingering({ number: '1' }));
id('m16b').addModifier(0, vf.Fingering({ number: '1' }));
vf.Curve({
from: id('m13a'),
to: id('m16a'),
options: {
cps: [{ x: 0, y: 50 }, { x: 0, y: 20 }],
invert: true,
position_end: 'nearTop',
},
});
/* Measure 17 */
system = makeSystem(180);
system.addStave({
voices: [
score.set({ clef: 'treble' }).voice([
notes('b5/q[id="m17a"]'),
beam(notes('g5/8, a5, b5, g5', { stem: 'down' })),
].reduce(concat)),
voice([vf.TextDynamics({ text: 'mf', duration: 'h', dots: 1, line: 10 })]),
],
}).setBegBarType(VF.Barline.type.REPEAT_BEGIN);
system.addStave({ voices: [voice(notes('g3/h.', { clef: 'bass' }))] })
.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
system.addConnector('boldDoubleLeft');
system.addConnector('singleRight');
id('m17a').addModifier(0, vf.Fingering({ number: '5', position: 'above' }));
/* Measure 18 */
system = makeSystem(180);
system.addStave({
voices: [
score.set({ clef: 'treble' }).voice([
notes('a5/q[id="m18a"]'),
beam(notes('d5/8, e5, f5, d5[id="m18b"]', { stem: 'down' })),
].reduce(concat)),
],
});
system.addStave({ voices: [voice(notes('f3/h.', { clef: 'bass' }))] });
system.addConnector('singleRight');
id('m18a').addModifier(0, vf.Fingering({ number: '4', position: 'above' }));
vf.Curve({
from: id('m17a'),
to: id('m18b'),
options: {
cps: [{ x: 0, y: 20 }, { x: 0, y: 30 }],
},
});
/* Done */
vf.draw();
VF.Registry.disableDefaultRegistry();
ok(true, 'Bach Minuet 1');
},
};
return BachDemo;
})();
/**
* VexFlow - Barline Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Barline = (function() {
return {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('Barline');
run('Simple BarNotes', function(options) {
var vf = VF.Test.makeFactory(options, 380, 160);
var stave = vf.Stave();
var notes = [
vf.StaveNote({ keys: ['d/4', 'e/4', 'f/4'], stem_direction: -1, duration: '2' }),
vf.BarNote({ type: 'single' }),
vf.StaveNote({ keys: ['c/4', 'f/4', 'a/4'], stem_direction: -1, duration: '2' })
.addAccidental(0, vf.Accidental({ type: 'n' }))
.addAccidental(1, vf.Accidental({ type: '#' })),
];
var voice = vf.Voice().addTickables(notes);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Simple Test');
});
},
};
}());
/**
* VexFlow - Beam Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
/*
eslint-disable
no-var,
no-undef,
wrap-iife,
func-names,
vars-on-top,
max-len,
*/
VF.Test.Beam = (function() {
var runTests = VF.Test.runTests;
function concat(a, b) { return a.concat(b); }
var Beam = {
Start: function() {
QUnit.module('Beam');
runTests('Simple Beam', Beam.simple);
runTests('Multi Beam', Beam.multi);
runTests('Sixteenth Beam', Beam.sixteenth);
runTests('Slopey Beam', Beam.slopey);
runTests('Auto-stemmed Beam', Beam.autoStem);
runTests('Mixed Beam 1', Beam.mixed);
runTests('Mixed Beam 2', Beam.mixed2);
runTests('Dotted Beam', Beam.dotted);
runTests('Close Trade-offs Beam', Beam.tradeoffs);
runTests('Insane Beam', Beam.insane);
runTests('Lengthy Beam', Beam.lenghty);
runTests('Outlier Beam', Beam.outlier);
runTests('Break Secondary Beams', Beam.breakSecondaryBeams);
runTests('TabNote Beams Up', Beam.tabBeamsUp);
runTests('TabNote Beams Down', Beam.tabBeamsDown);
runTests('TabNote Auto Create Beams', Beam.autoTabBeams);
runTests('TabNote Beams Auto Stem', Beam.tabBeamsAutoStem);
runTests('Complex Beams with Annotations', Beam.complexWithAnnotation);
runTests('Complex Beams with Articulations', Beam.complexWithArticulation);
},
simple: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var beam = score.beam.bind(score);
var notes = score.notes.bind(score);
var voice = score.voice([
notes('(cb4 e#4 a4)/2'),
beam(notes('(cb4 e#4 a4)/8, (d4 f4 a4), (ebb4 g##4 b4), (f4 a4 c5)', { stem: 'up' })),
].reduce(concat), { time: '2/2' });
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Simple Test');
},
multi: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice.bind(score);
var beam = score.beam.bind(score);
var notes = score.notes.bind(score);
var voices = [
voice([
beam(notes('f5/8, e5, d5, c5', { stem: 'up' })),
beam(notes('c5, d5, e5, f5', { stem: 'up' })),
].reduce(concat)),
voice([
beam(notes('f4/8, e4, d4, c4', { stem: 'down' })),
beam(notes('c4/8, d4, e4, f4', { stem: 'down' })),
].reduce(concat)),
];
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave);
vf.draw();
ok(true, 'Multi Test');
},
sixteenth: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice.bind(score);
var beam = score.beam.bind(score);
var notes = score.notes.bind(score);
var voices = [
voice([
beam(notes('f5/16, f5, d5, c5', { stem: 'up' })),
beam(notes('c5/16, d5, f5, e5', { stem: 'up' })),
notes('f5/2', { stem: 'up' }),
].reduce(concat)),
voice([
beam(notes('f4/16, e4/16, d4/16, c4/16', { stem: 'down' })),
beam(notes('c4/16, d4/16, f4/16, e4/16', { stem: 'down' })),
notes('f4/2', { stem: 'down' }),
].reduce(concat)),
];
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave);
vf.draw();
ok(true, 'Sixteenth Test');
},
breakSecondaryBeams: function(options) {
var vf = VF.Test.makeFactory(options, 600, 200);
var stave = vf.Stave({ y: 20 });
var score = vf.EasyScore();
var voice = score.voice.bind(score);
var beam = score.beam.bind(score);
var notes = score.notes.bind(score);
var voices = [
voice([
beam(
notes('f5/16., f5/32, c5/16., d5/32, c5/16., d5/32', { stem: 'up' }),
{ secondaryBeamBreaks: [1, 3] }
),
beam(
notes('f5/16, e5, e5, e5, e5, e5', { stem: 'up' }),
{ secondaryBeamBreaks: [2] }
),
].reduce(concat), { time: '3/4' }),
voice([
beam(
notes('f4/32, d4, e4, c4, d4, c4, f4, d4, e4, c4, c4, d4', { stem: 'down' }),
{ secondaryBeamBreaks: [3, 7] }
),
beam(
notes('d4/16, f4, d4, e4, e4, e4', { stem: 'down' }),
{ secondaryBeamBreaks: [3] }
),
].reduce(concat), { time: '3/4' }),
];
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave);
vf.draw();
ok(true, 'Breaking Secondary Beams Test');
},
slopey: function(options) {
var vf = VF.Test.makeFactory(options, 350, 140);
var stave = vf.Stave({ y: 20 });
var score = vf.EasyScore();
var beam = score.beam.bind(score);
var notes = score.notes.bind(score);
var voice = score.voice([
beam(notes('c4/8, f4/8, d5/8, g5/8', { stem: 'up' })),
beam(notes('d6/8, f5/8, d4/8, g3/8', { stem: 'up' })),
].reduce(concat));
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Slopey Test');
},
autoStem: function(options) {
var vf = VF.Test.makeFactory(options, 350, 140);
var stave = vf.Stave({ y: 20 });
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'a4/8, b4/8, g4/8, c5/8, f4/8, d5/8, e4/8, e5/8, b4/8, b4/8, g4/8, d5/8'
), { time: '6/4' });
var notes = voice.getTickables();
var beams = [
vf.Beam({ notes: notes.slice(0, 2), options: { autoStem: true } }),
vf.Beam({ notes: notes.slice(2, 4), options: { autoStem: true } }),
vf.Beam({ notes: notes.slice(4, 6), options: { autoStem: true } }),
vf.Beam({ notes: notes.slice(6, 8), options: { autoStem: true } }),
vf.Beam({ notes: notes.slice(8, 10), options: { autoStem: true } }),
vf.Beam({ notes: notes.slice(10, 12), options: { autoStem: true } }),
];
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
var UP = VF.Stem.UP;
var DOWN = VF.Stem.DOWN;
equal(beams[0].stem_direction, UP);
equal(beams[1].stem_direction, UP);
equal(beams[2].stem_direction, UP);
equal(beams[3].stem_direction, UP);
equal(beams[4].stem_direction, DOWN);
equal(beams[5].stem_direction, DOWN);
vf.draw();
ok(true, 'AutoStem Beam Test');
},
mixed: function(options) {
var vf = VF.Test.makeFactory(options, 350, 140);
var stave = vf.Stave({ y: 20 });
var score = vf.EasyScore();
var voice1 = score.voice(score.notes(
'f5/8, d5/16, c5/16, c5/16, d5/16, e5/8, f5/8, d5/16, c5/16, c5/16, d5/16, e5/8',
{ stem: 'up' }
));
var voice2 = score.voice(score.notes(
'f4/16, e4/8, d4/16, c4/16, d4/8, f4/16, f4/16, e4/8, d4/16, c4/16, d4/8, f4/16',
{ stem: 'down' }
));
[[0, 4], [4, 8], [8, 12]].forEach(function(range) {
vf.Beam({ notes: voice1.getTickables().slice(range[0], range[1]) });
});
[[0, 4], [4, 8], [8, 12]].forEach(function(range) {
vf.Beam({ notes: voice2.getTickables().slice(range[0], range[1]) });
});
vf.Formatter()
.joinVoices([voice1, voice2])
.formatToStave([voice1, voice2], stave);
vf.draw();
ok(true, 'Multi Test');
},
mixed2: function(options) {
var vf = VF.Test.makeFactory(options, 450, 180);
var stave = vf.Stave({ y: 20 });
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'f5/32, d5/16, c5/32, c5/64, d5/128, e5/8, f5/16, d5/32, c5/64, c5/32, d5/16, e5/128',
{ stem: 'up' }
), { time: '31/64' });
var voice2 = score.voice(score.notes(
'f4/32, d4/16, c4/32, c4/64, d4/128, e4/8, f4/16, d4/32, c4/64, c4/32, d4/16, e4/128',
{ stem: 'down' }
), { time: '31/64' });
vf.Beam({ notes: voice.getTickables().slice(0, 12) });
vf.Beam({ notes: voice2.getTickables().slice(0, 12) });
vf.Formatter()
.joinVoices([voice, voice2])
.formatToStave([voice, voice2], stave);
vf.draw();
ok(true, 'Multi Test');
},
dotted: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'd4/8, b3/8., a3/16, a3/8, b3/8., c4/16, d4/8, b3/8, a3/8., a3/16, b3/8., c4/16',
{ stem: 'up' }
), { time: '6/4' });
var notes = voice.getTickables();
vf.Beam({ notes: notes.slice(0, 4) });
vf.Beam({ notes: notes.slice(4, 8) });
vf.Beam({ notes: notes.slice(8, 12) });
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Dotted Test');
},
tradeoffs: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'a4/8, b4/8, c4/8, d4/8, g4/8, a4/8, b4/8, c4/8',
{ stem: 'up' }
));
var notes = voice.getTickables();
vf.Beam({ notes: notes.slice(0, 4) });
vf.Beam({ notes: notes.slice(4, 8) });
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Close Trade-offs Test');
},
insane: function(options) {
var vf = VF.Test.makeFactory(options, 450, 180);
var stave = vf.Stave({ y: 20 });
var score = vf.EasyScore();
var voice = score.voice(score.notes(
'g4/8, g5/8, c4/8, b5/8, g4/8[stem="down"], a5[stem="down"], b4[stem="down"], c4/8', { stem: 'up' }
));
var notes = voice.getTickables();
vf.Beam({ notes: notes.slice(0, 4) });
vf.Beam({ notes: notes.slice(4, 7) });
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Insane Test');
},
lenghty: function(options) {
var vf = VF.Test.makeFactory(options, 450, 180);
var stave = vf.Stave({ y: 20 });
var score = vf.EasyScore();
var voice = score.voice(score.beam(score.notes(
'g4/8, g4, g4, a4',
{ stem: 'up' }
)), { time: '2/4' });
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Lengthy Test');
},
outlier: function(options) {
var vf = VF.Test.makeFactory(options, 450, 180);
var stave = vf.Stave({ y: 20 });
var score = vf.EasyScore();
var voice = score.voice(score.notes([
'g4/8[stem="up"], f4[stem="up"], d5[stem="up"], e4[stem="up"]',
'd5/8[stem="down"], d5[stem="down"], c5[stem="down"], d5[stem="down"]',
].join()));
var notes = voice.getTickables();
vf.Beam({ notes: notes.slice(0, 4) });
vf.Beam({ notes: notes.slice(4, 8) });
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave, { stave: stave });
vf.draw();
ok(true, 'Outlier Test');
},
tabBeamsUp: function(options) {
var vf = VF.Test.makeFactory(options, 600, 200);
var stave = vf.TabStave({ y: 20 });
var specs = [
{ positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '4' },
{ positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '32' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '64' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '128' },
{ positions: [{ str: 3, fret: 6 }], duration: '8' },
{ positions: [{ str: 3, fret: 6 }], duration: '8' },
{ positions: [{ str: 3, fret: 6 }], duration: '8' },
{ positions: [{ str: 3, fret: 6 }], duration: '8' },
];
var notes = specs.map(function(noteSpec) {
var tabNote = vf.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
return tabNote;
});
vf.Beam({ notes: notes.slice(1, 7) });
vf.Beam({ notes: notes.slice(8, 11) });
vf.Tuplet({ notes: notes.slice(8, 11), options: { ratioed: true } });
var voice = vf.Voice().setMode(VF.Voice.Mode.SOFT).addTickables(notes);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'All objects have been drawn');
},
tabBeamsDown: function(options) {
var vf = VF.Test.makeFactory(options, 600, 250);
var stave = vf.TabStave({ options: { num_lines: 10 } });
var specs = [
{ stem_direction: -1, positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '4' },
{ stem_direction: -1, positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '8dd' },
{ stem_direction: -1, positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '8' },
{ stem_direction: -1, positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16' },
{ stem_direction: -1, positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '32' },
{ stem_direction: -1, positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '64' },
{ stem_direction: -1, positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '128' },
{ stem_direction: -1, positions: [{ str: 1, fret: 6 }], duration: '8' },
{ stem_direction: -1, positions: [{ str: 1, fret: 6 }], duration: '8' },
{ stem_direction: -1, positions: [{ str: 1, fret: 6 }], duration: '8' },
{ stem_direction: -1, positions: [{ str: 7, fret: 6 }], duration: '8' },
{ stem_direction: -1, positions: [{ str: 7, fret: 6 }], duration: '8' },
{ stem_direction: -1, positions: [{ str: 10, fret: 6 }], duration: '8' },
{ stem_direction: -1, positions: [{ str: 10, fret: 6 }], duration: '8' },
];
var notes = specs.map(function(noteSpec) {
var tabNote = vf.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
tabNote.render_options.draw_dots = true;
return tabNote;
});
notes[1].addDot();
notes[1].addDot();
vf.Beam({ notes: notes.slice(1, 7) });
vf.Beam({ notes: notes.slice(8, 11) });
vf.Tuplet({ notes: notes.slice(8, 11), options: { location: -1 } });
vf.Tuplet({ notes: notes.slice(11, 14), options: { location: -1 } });
var voice = vf.Voice().setMode(VF.Voice.Mode.SOFT).addTickables(notes);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'All objects have been drawn');
},
autoTabBeams: function(options) {
var vf = VF.Test.makeFactory(options, 600, 200);
var stave = vf.TabStave();
var specs = [
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16' },
{ positions: [{ str: 1, fret: 6 }], duration: '32' },
{ positions: [{ str: 1, fret: 6 }], duration: '32' },
{ positions: [{ str: 1, fret: 6 }], duration: '32' },
{ positions: [{ str: 6, fret: 6 }], duration: '32' },
{ positions: [{ str: 6, fret: 6 }], duration: '16' },
{ positions: [{ str: 6, fret: 6 }], duration: '16' },
{ positions: [{ str: 6, fret: 6 }], duration: '16' },
{ positions: [{ str: 6, fret: 6 }], duration: '16' },
];
var notes = specs.map(function(noteSpec) {
var tabNote = vf.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
tabNote.render_options.draw_dots = true;
return tabNote;
});
var voice = vf.Voice().setMode(VF.Voice.Mode.SOFT).addTickables(notes);
var beams = VF.Beam.applyAndGetBeams(voice, -1);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
beams.forEach(function(beam) {
beam.setContext(vf.getContext()).draw();
});
ok(true, 'All objects have been drawn');
},
// This tests makes sure the auto_stem functionality is works.
// TabNote stems within a beam group should end up normalized
tabBeamsAutoStem: function(options) {
var vf = VF.Test.makeFactory(options, 600, 300);
var stave = vf.TabStave();
var specs = [
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '8', stem_direction: -1 },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '8', stem_direction: 1 },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16', stem_direction: -1 },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16', stem_direction: 1 },
{ positions: [{ str: 1, fret: 6 }], duration: '32', stem_direction: 1 },
{ positions: [{ str: 1, fret: 6 }], duration: '32', stem_direction: -1 },
{ positions: [{ str: 1, fret: 6 }], duration: '32', stem_direction: -1 },
{ positions: [{ str: 6, fret: 6 }], duration: '32', stem_direction: -1 },
{ positions: [{ str: 6, fret: 6 }], duration: '16', stem_direction: 1 },
{ positions: [{ str: 6, fret: 6 }], duration: '16', stem_direction: 1 },
{ positions: [{ str: 6, fret: 6 }], duration: '16', stem_direction: 1 },
{ positions: [{ str: 6, fret: 6 }], duration: '16', stem_direction: -1 },
];
var notes = specs.map(function(noteSpec) {
var tabNote = vf.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
tabNote.render_options.draw_dots = true;
return tabNote;
});
// Stems should format down
vf.Beam({ notes: notes.slice(0, 8), options: { autoStem: true } });
// Stems should format up
vf.Beam({ notes: notes.slice(8, 12), options: { autoStem: true } });
var voice = vf.Voice().setMode(VF.Voice.Mode.SOFT).addTickables(notes);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'All objects have been drawn');
},
complexWithAnnotation: function(options) {
var vf = VF.Test.makeFactory(options, 500, 200);
var stave = vf.Stave({ y: 40 });
var notes = [
{ keys: ['e/4'], duration: '128', stem_direction: 1 },
{ keys: ['d/4'], duration: '16', stem_direction: 1 },
{ keys: ['e/4'], duration: '8', stem_direction: 1 },
{ keys: ['c/4', 'g/4'], duration: '32', stem_direction: 1 },
{ keys: ['c/4'], duration: '32', stem_direction: 1 },
{ keys: ['c/4'], duration: '32', stem_direction: 1 },
{ keys: ['c/4'], duration: '32', stem_direction: 1 },
];
var notes2 = [
{ keys: ['e/5'], duration: '128', stem_direction: -1 },
{ keys: ['d/5'], duration: '16', stem_direction: -1 },
{ keys: ['e/5'], duration: '8', stem_direction: -1 },
{ keys: ['c/5', 'g/5'], duration: '32', stem_direction: -1 },
{ keys: ['c/5'], duration: '32', stem_direction: -1 },
{ keys: ['c/5'], duration: '32', stem_direction: -1 },
{ keys: ['c/5'], duration: '32', stem_direction: -1 },
];
notes = notes.map(function(note) {
return vf.StaveNote(note).addModifier(0, vf.Annotation({ text: '1', vJustify: 'above' }));
});
notes2 = notes2.map(function(note) {
return vf.StaveNote(note).addModifier(0, vf.Annotation({ text: '3', vJustify: 'below' }));
});
vf.Beam({ notes: notes });
vf.Beam({ notes: notes2 });
var voice = vf.Voice()
.setMode(VF.Voice.Mode.SOFT)
.addTickables(notes)
.addTickables(notes2);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave, { stave: stave });
vf.draw();
ok(true, 'Complex beam annotations');
},
complexWithArticulation: function(options) {
var vf = VF.Test.makeFactory(options, 500, 200);
var stave = vf.Stave({ y: 40 });
var notes = [
{ keys: ['e/4'], duration: '128', stem_direction: 1 },
{ keys: ['d/4'], duration: '16', stem_direction: 1 },
{ keys: ['e/4'], duration: '8', stem_direction: 1 },
{ keys: ['c/4', 'g/4'], duration: '32', stem_direction: 1 },
{ keys: ['c/4'], duration: '32', stem_direction: 1 },
{ keys: ['c/4'], duration: '32', stem_direction: 1 },
{ keys: ['c/4'], duration: '32', stem_direction: 1 },
];
var notes2 = [
{ keys: ['e/5'], duration: '128', stem_direction: -1 },
{ keys: ['d/5'], duration: '16', stem_direction: -1 },
{ keys: ['e/5'], duration: '8', stem_direction: -1 },
{ keys: ['c/5', 'g/5'], duration: '32', stem_direction: -1 },
{ keys: ['c/5'], duration: '32', stem_direction: -1 },
{ keys: ['c/5'], duration: '32', stem_direction: -1 },
{ keys: ['c/5'], duration: '32', stem_direction: -1 },
];
notes = notes.map(function(note) {
return vf.StaveNote(note).addModifier(0, vf.Articulation({ type: 'am', position: 'above' }));
});
notes2 = notes2.map(function(note) {
return vf.StaveNote(note).addModifier(0, vf.Articulation({ type: 'a>', position: 'below' }));
});
vf.Beam({ notes: notes });
vf.Beam({ notes: notes2 });
var voice = vf.Voice()
.setMode(VF.Voice.Mode.SOFT)
.addTickables(notes)
.addTickables(notes2);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave, { stave: stave });
vf.draw();
ok(true, 'Complex beam articulations');
},
};
return Beam;
})();
/**
* VexFlow - Accidental Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Bend = (function() {
var Bend = {
Start: function() {
QUnit.module('Bend');
VF.Test.runTests('Double Bends', VF.Test.Bend.doubleBends);
VF.Test.runTests('Reverse Bends', VF.Test.Bend.reverseBends);
VF.Test.runTests('Bend Phrase', VF.Test.Bend.bendPhrase);
VF.Test.runTests('Double Bends With Release',
VF.Test.Bend.doubleBendsWithRelease);
VF.Test.runTests('Whako Bend', VF.Test.Bend.whackoBends);
},
doubleBends: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
ctx.setRawFont(' 10pt Arial');
var stave = new VF.TabStave(10, 10, 450)
.addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newBend(text) { return new VF.Bend(text); }
var notes = [
newNote({
positions: [{ str: 2, fret: 10 }, { str: 4, fret: 9 }], duration: 'q',
})
.addModifier(newBend('Full'), 0)
.addModifier(newBend('1/2'), 1),
newNote({
positions: [{ str: 2, fret: 5 }, { str: 3, fret: 5 }], duration: 'q',
})
.addModifier(newBend('1/4'), 0)
.addModifier(newBend('1/4'), 1),
newNote({
positions: [{ str: 4, fret: 7 }], duration: 'h',
}),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes);
notes.forEach(function(note) {
VF.Test.plotNoteWidth(ctx, note, 140);
});
ok(true, 'Double Bends');
},
doubleBendsWithRelease: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 550, 240);
ctx.scale(1.0, 1.0);
ctx.setBackgroundFillStyle('#FFF');
ctx.setFont('Arial', VF.Test.Font.size);
var stave = new VF.TabStave(10, 10, 550)
.addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newBend(text, release) { return new VF.Bend(text, release); }
var notes = [
newNote({
positions: [{ str: 1, fret: 10 }, { str: 4, fret: 9 }], duration: 'q',
})
.addModifier(newBend('1/2', true), 0)
.addModifier(newBend('Full', true), 1),
newNote({
positions: [{ str: 2, fret: 5 },
{ str: 3, fret: 5 },
{ str: 4, fret: 5 }], duration: 'q',
})
.addModifier(newBend('1/4', true), 0)
.addModifier(newBend('Monstrous', true), 1)
.addModifier(newBend('1/4', true), 2),
newNote({
positions: [{ str: 4, fret: 7 }], duration: 'q',
}),
newNote({
positions: [{ str: 4, fret: 7 }], duration: 'q',
}),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes);
notes.forEach(function(note) {
VF.Test.plotNoteWidth(ctx, note, 140);
});
ok(true, 'Bend Release');
},
reverseBends: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
ctx.setRawFont('10pt Arial');
var stave = new VF.TabStave(10, 10, 450)
.addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newBend(text) { return new VF.Bend(text); }
var notes = [
newNote({
positions: [{ str: 2, fret: 10 }, { str: 4, fret: 9 }], duration: 'w',
})
.addModifier(newBend('Full'), 1)
.addModifier(newBend('1/2'), 0),
newNote({
positions: [{ str: 2, fret: 5 }, { str: 3, fret: 5 }], duration: 'w',
})
.addModifier(newBend('1/4'), 1)
.addModifier(newBend('1/4'), 0),
newNote({
positions: [{ str: 4, fret: 7 }], duration: 'w',
}),
];
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
var mc = new VF.ModifierContext();
note.addToModifierContext(mc);
var tickContext = new VF.TickContext();
tickContext.addTickable(note).preFormat().setX(75 * i);
note.setStave(stave).setContext(ctx).draw();
VF.Test.plotNoteWidth(ctx, note, 140);
ok(true, 'Bend ' + i);
}
},
bendPhrase: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
ctx.setRawFont(' 10pt Arial');
var stave = new VF.TabStave(10, 10, 450).addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newBend(phrase) { return new VF.Bend(null, null, phrase); }
var phrase1 = [
{ type: VF.Bend.UP, text: 'Full' },
{ type: VF.Bend.DOWN, text: 'Monstrous' },
{ type: VF.Bend.UP, text: '1/2' },
{ type: VF.Bend.DOWN, text: '' },
];
var bend1 = newBend(phrase1).setContext(ctx);
var notes = [
newNote({
positions: [{ str: 2, fret: 10 }], duration: 'w',
})
.addModifier(bend1, 0),
];
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
var mc = new VF.ModifierContext();
note.addToModifierContext(mc);
var tickContext = new VF.TickContext();
tickContext.addTickable(note).preFormat().setX(75 * i);
note.setStave(stave).setContext(ctx).draw();
VF.Test.plotNoteWidth(ctx, note, 140);
ok(true, 'Bend ' + i);
}
},
whackoBends: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 240);
ctx.scale(1.0, 1.0); ctx.setBackgroundFillStyle('#FFF');
ctx.setFont('Arial', VF.Test.Font.size);
var stave = new VF.TabStave(10, 10, 350).addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newBend(phrase) { return new VF.Bend(null, null, phrase); }
var phrase1 = [
{ type: VF.Bend.UP, text: 'Full' },
{ type: VF.Bend.DOWN, text: '' },
{ type: VF.Bend.UP, text: '1/2' },
{ type: VF.Bend.DOWN, text: '' },
];
var phrase2 = [
{ type: VF.Bend.UP, text: 'Full' },
{ type: VF.Bend.UP, text: 'Full' },
{ type: VF.Bend.UP, text: '1/2' },
{ type: VF.Bend.DOWN, text: '' },
{ type: VF.Bend.DOWN, text: 'Full' },
{ type: VF.Bend.DOWN, text: 'Full' },
{ type: VF.Bend.UP, text: '1/2' },
{ type: VF.Bend.DOWN, text: '' },
];
var notes = [
newNote({
positions: [{ str: 2, fret: 10 }, { str: 3, fret: 9 }], duration: 'q',
})
.addModifier(newBend(phrase1), 0)
.addModifier(newBend(phrase2), 1),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes);
VF.Test.plotNoteWidth(ctx, notes[0], 140);
ok(true, 'Whako Release');
},
};
return Bend;
})();
/**
* VexFlow - Bounding Box Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.BoundingBox = (function() {
var BoundingBox = {
Start: function() {
QUnit.module('BoundingBox');
test('Initialization Test', VF.Test.BoundingBox.initialization);
test('Merging Text', VF.Test.BoundingBox.merging);
},
initialization: function() {
var bb = new VF.BoundingBox(4, 5, 6, 7);
equal(bb.getX(), 4, 'Bad X');
equal(bb.getY(), 5, 'Bad Y');
equal(bb.getW(), 6, 'Bad W');
equal(bb.getH(), 7, 'Bad H');
bb.setX(5);
equal(bb.getX(), 5, 'Bad X');
},
merging: function() {
var tests = [
{
type: 'Intersection',
bb1: new VF.BoundingBox(10, 10, 10, 10),
bb2: new VF.BoundingBox(15, 20, 10, 10),
merged: new VF.BoundingBox(10, 10, 15, 20),
},
{
type: '1 contains 2',
bb1: new VF.BoundingBox(10, 10, 30, 30),
bb2: new VF.BoundingBox(15, 15, 10, 10),
merged: new VF.BoundingBox(10, 10, 30, 30),
},
{
type: '2 contains 1',
bb1: new VF.BoundingBox(15, 15, 10, 10),
bb2: new VF.BoundingBox(10, 10, 30, 30),
merged: new VF.BoundingBox(10, 10, 30, 30),
},
];
tests.forEach(function(test) {
const type = test.type;
const bb1 = test.bb1;
const bb2 = test.bb2;
const merged = test.merged;
bb1.mergeWith(bb2);
equal(bb1.getX(), merged.getX(), type + ' - Bad X');
equal(bb1.getY(), merged.getY(), type + ' - Bad Y');
equal(bb1.getW(), merged.getW(), type + ' - Bad W');
equal(bb1.getH(), merged.getH(), type + ' - Bad H');
});
},
};
return BoundingBox;
})();
/**
* VexFlow - Clef Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Clef = (function() {
var Clef = {
Start: function() {
QUnit.module('Clef');
VF.Test.runTests('Clef Test', VF.Test.Clef.draw);
VF.Test.runTests('Clef End Test', VF.Test.Clef.drawEnd);
VF.Test.runTests('Small Clef Test', VF.Test.Clef.drawSmall);
VF.Test.runTests('Small Clef End Test', VF.Test.Clef.drawSmallEnd);
VF.Test.runTests('Clef Change Test', VF.Test.Clef.drawClefChange);
},
draw: function(options) {
var vf = VF.Test.makeFactory(options, 800, 120);
vf.Stave()
.addClef('treble')
.addClef('treble', 'default', '8va')
.addClef('treble', 'default', '8vb')
.addClef('alto')
.addClef('tenor')
.addClef('soprano')
.addClef('bass')
.addClef('bass', 'default', '8vb')
.addClef('mezzo-soprano')
.addClef('baritone-c')
.addClef('baritone-f')
.addClef('subbass')
.addClef('percussion')
.addClef('french')
.addEndClef('treble');
vf.draw();
ok(true, 'all pass');
},
drawEnd: function(options) {
var vf = VF.Test.makeFactory(options, 800, 120);
vf.Stave()
.addClef('bass')
.addEndClef('treble')
.addEndClef('treble', 'default', '8va')
.addEndClef('treble', 'default', '8vb')
.addEndClef('alto')
.addEndClef('tenor')
.addEndClef('soprano')
.addEndClef('bass')
.addEndClef('bass', 'default', '8vb')
.addEndClef('mezzo-soprano')
.addEndClef('baritone-c')
.addEndClef('baritone-f')
.addEndClef('subbass')
.addEndClef('percussion')
.addEndClef('french');
vf.draw();
ok(true, 'all pass');
},
drawSmall: function(options) {
var vf = VF.Test.makeFactory(options, 800, 120);
vf.Stave()
.addClef('treble', 'small')
.addClef('treble', 'small', '8va')
.addClef('treble', 'small', '8vb')
.addClef('alto', 'small')
.addClef('tenor', 'small')
.addClef('soprano', 'small')
.addClef('bass', 'small')
.addClef('bass', 'small', '8vb')
.addClef('mezzo-soprano', 'small')
.addClef('baritone-c', 'small')
.addClef('baritone-f', 'small')
.addClef('subbass', 'small')
.addClef('percussion', 'small')
.addClef('french', 'small')
.addEndClef('treble', 'small');
vf.draw();
ok(true, 'all pass');
},
drawSmallEnd: function(options) {
var vf = VF.Test.makeFactory(options, 800, 120);
vf.Stave()
.addClef('bass', 'small')
.addEndClef('treble', 'small')
.addEndClef('treble', 'small', '8va')
.addEndClef('treble', 'small', '8vb')
.addEndClef('alto', 'small')
.addEndClef('tenor', 'small')
.addEndClef('soprano', 'small')
.addEndClef('bass', 'small')
.addEndClef('bass', 'small', '8vb')
.addEndClef('mezzo-soprano', 'small')
.addEndClef('baritone-c', 'small')
.addEndClef('baritone-f', 'small')
.addEndClef('subbass', 'small')
.addEndClef('percussion', 'small')
.addEndClef('french', 'small');
vf.draw();
ok(true, 'all pass');
},
drawClefChange: function(options) {
var vf = VF.Test.makeFactory(options, 800, 180);
var stave = vf.Stave().addClef('treble');
var notes = [
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'treble' }),
vf.ClefNote({ type: 'alto', options: { size: 'small' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'alto' }),
vf.ClefNote({ type: 'tenor', options: { size: 'small' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'tenor' }),
vf.ClefNote({ type: 'soprano', options: { size: 'small' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'soprano' }),
vf.ClefNote({ type: 'bass', options: { size: 'small' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'bass' }),
vf.ClefNote({ type: 'mezzo-soprano', options: { size: 'small' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'mezzo-soprano' }),
vf.ClefNote({ type: 'baritone-c', options: { size: 'small' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'baritone-c' }),
vf.ClefNote({ type: 'baritone-f', options: { size: 'small' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'baritone-f' }),
vf.ClefNote({ type: 'subbass', options: { size: 'small' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'subbass' }),
vf.ClefNote({ type: 'french', options: { size: 'small' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'french' }),
vf.ClefNote({ type: 'treble', options: { size: 'small', annotation: '8vb' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'treble', octave_shift: -1 }),
vf.ClefNote({ type: 'treble', options: { size: 'small', annotation: '8va' } }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'treble', octave_shift: 1 }),
];
var voice = vf.Voice({ time: '12/4' }).addTickables(notes);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'all pass');
},
};
return Clef;
})();
/**
* VexFlow - Curve Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
var VF = Vex.Flow;
VF.Test.Curve = (function() {
function concat(a, b) { return a.concat(b); }
function createTest(beamGroup1, beamGroup2, setupCurves) {
return function(options) {
var vf = VF.Test.makeFactory(options, 350, 200);
var stave = vf.Stave({ y: 50 });
var score = vf.EasyScore();
var notes = [
score.beam(score.notes.apply(score, beamGroup1)),
score.beam(score.notes.apply(score, beamGroup2)),
].reduce(concat);
setupCurves(vf, notes);
var voice = score.voice(notes, { time: '4/4' });
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok('Simple Curve');
};
}
return {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('Curve');
run('Simple Curve', createTest(
['c4/8, f5, d5, g5', { stem: 'up' }],
['d6/8, f5, d5, g5', { stem: 'down' }],
function(vf, notes) {
vf.Curve({
from: notes[0],
to: notes[3],
options: {
cps: [{ x: 0, y: 10 }, { x: 0, y: 50 }],
},
});
vf.Curve({
from: notes[4],
to: notes[7],
options: {
cps: [{ x: 0, y: 10 }, { x: 0, y: 20 }],
},
});
}
));
run('Rounded Curve', createTest(
['c5/8, f4, d4, g5', { stem: 'up' }],
['d5/8, d6, d6, g5', { stem: 'down' }],
function(vf, notes) {
vf.Curve({
from: notes[0],
to: notes[3],
options: {
x_shift: -10,
y_shift: 30,
cps: [{ x: 0, y: 20 }, { x: 0, y: 50 }],
},
});
vf.Curve({
from: notes[4],
to: notes[7],
options: {
cps: [{ x: 0, y: 50 }, { x: 0, y: 50 }],
},
});
}
));
run('Thick Thin Curves', createTest(
['c5/8, f4, d4, g5', { stem: 'up' }],
['d5/8, d6, d6, g5', { stem: 'down' }],
function(vf, notes) {
vf.Curve({
from: notes[0],
to: notes[3],
options: {
thickness: 10,
x_shift: -10,
y_shift: 30,
cps: [{ x: 0, y: 20 }, { x: 0, y: 50 }],
},
});
vf.Curve({
from: notes[4],
to: notes[7],
options: {
thickness: 0,
cps: [{ x: 0, y: 50 }, { x: 0, y: 50 }],
},
});
}
));
run('Top Curve', createTest(
['c5/8, f4, d4, g5', { stem: 'up' }],
['d5/8, d6, d6, g5', { stem: 'down' }],
function(vf, notes) {
vf.Curve({
from: notes[0],
to: notes[7],
options: {
x_shift: -3,
y_shift: 10,
position: VF.Curve.Position.NEAR_TOP,
position_end: VF.Curve.Position.NEAR_HEAD,
cps: [{ x: 0, y: 20 }, { x: 40, y: 80 }],
},
});
}
));
},
};
})();
/**
* VexFlow - Dot Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Dot = (function() {
function showNote(note, stave, ctx, x) {
note
.setStave(stave)
.addToModifierContext(new VF.ModifierContext());
new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(x);
note.setContext(ctx).draw();
VF.Test.plotNoteWidth(ctx, note, 140);
return note;
}
function showNotes(note1, note2, stave, ctx, x) {
var modifierContext = new VF.ModifierContext();
note1.setStave(stave).addToModifierContext(modifierContext);
note2.setStave(stave).addToModifierContext(modifierContext);
new VF.TickContext()
.addTickable(note1)
.addTickable(note2)
.setX(x)
.preFormat();
note1.setContext(ctx).draw();
note2.setContext(ctx).draw();
VF.Test.plotNoteWidth(ctx, note1, 180);
VF.Test.plotNoteWidth(ctx, note2, 20);
}
var Dot = {
Start: function() {
QUnit.module('Dot');
VF.Test.runTests('Basic', VF.Test.Dot.basic);
VF.Test.runTests('Multi Voice', VF.Test.Dot.multiVoice);
},
basic: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 1000, 240);
ctx.setFillStyle('#221');
ctx.setStrokeStyle('#221');
var stave = new VF.Stave(10, 10, 975);
stave.setContext(ctx);
stave.draw();
var notes = [
new VF.StaveNote({ keys: ['c/4', 'e/4', 'a/4', 'b/4'], duration: 'w' })
.addDotToAll(),
new VF.StaveNote({ keys: ['a/4', 'b/4', 'c/5'], duration: '4', stem_direction: 1 })
.addDotToAll(),
new VF.StaveNote({ keys: ['g/4', 'a/4', 'b/4'], duration: '4', stem_direction: -1 })
.addDotToAll(),
new VF.StaveNote({ keys: ['e/4', 'f/4', 'b/4', 'c/5'], duration: '4' })
.addDotToAll(),
new VF.StaveNote({ keys: ['g/4', 'a/4', 'd/5', 'e/5', 'g/5'], duration: '4', stem_direction: -1 })
.addDotToAll(),
new VF.StaveNote({ keys: ['g/4', 'b/4', 'd/5', 'e/5'], duration: '4', stem_direction: -1 })
.addDotToAll(),
new VF.StaveNote({ keys: ['e/4', 'g/4', 'b/4', 'c/5'], duration: '4', stem_direction: 1 })
.addDotToAll(),
new VF.StaveNote({ keys: ['d/4', 'e/4', 'f/4', 'a/4', 'c/5', 'e/5', 'g/5'], duration: '2' })
.addDotToAll()
.addDotToAll(),
new VF.StaveNote({ keys: ['f/4', 'g/4', 'a/4', 'b/4', 'c/5', 'e/5', 'g/5'], duration: '16', stem_direction: -1 })
.addDotToAll()
.addDotToAll()
.addDotToAll(),
new VF.StaveNote({ keys: ['f/4', 'g/4', 'a/4', 'b/4', 'c/5', 'e/5', 'g/5'], duration: '16', stem_direction: 1 })
.addDotToAll()
.addDotToAll()
.addDotToAll(),
new VF.StaveNote({ keys: ['e/4', 'g/4', 'a/4', 'b/4', 'c/5', 'e/5', 'f/5'], duration: '16', stem_direction: 1 })
.addDotToAll(),
];
for (var i = 0; i < notes.length; i++) {
showNote(notes[i], stave, ctx, 30 + (i * 65));
var dots = notes[i].getDots();
ok(dots.length > 0, 'Note ' + i + ' has dots');
for (var j = 0; j < dots.length; ++j) {
ok(dots[j].width > 0, 'Dot ' + j + ' has width set');
}
}
VF.Test.plotLegendForNoteWidth(ctx, 770, 140);
ok(true, 'Full Dot');
},
multiVoice: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 750, 300);
ctx.setFillStyle('#221');
ctx.setStrokeStyle('#221');
var stave = new VF.Stave(30, 40, 700).setContext(ctx).draw();
var note1 = new VF.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], duration: '2', stem_direction: -1 })
.addDotToAll()
.addDotToAll();
var note2 = new VF.StaveNote({ keys: ['d/5', 'a/5', 'b/5'], duration: '2', stem_direction: 1 })
.addDotToAll();
showNotes(note1, note2, stave, ctx, 60);
note1 = new VF.StaveNote({ keys: ['c/4', 'e/4', 'c/5'], duration: '2', stem_direction: -1 })
.addDot(0)
.addDot(0)
.addDot(1)
.addDot(1)
.addDot(2)
.addDot(2)
.addDot(2);
note2 = new VF.StaveNote({ keys: ['d/5', 'a/5', 'b/5'], duration: '4', stem_direction: 1 })
.addDotToAll()
.addDotToAll();
showNotes(note1, note2, stave, ctx, 150);
note1 = new VF.StaveNote({ keys: ['d/4', 'c/5', 'd/5'], duration: '2', stem_direction: -1 })
.addDotToAll()
.addDotToAll()
.addDot(0);
note2 = new VF.StaveNote({ keys: ['d/5', 'a/5', 'b/5'], duration: '4', stem_direction: 1 })
.addDotToAll();
showNotes(note1, note2, stave, ctx, 250);
note1 = new VF.StaveNote({ keys: ['d/4', 'c/5', 'd/5'], duration: '8', stem_direction: -1 })
.addDotToAll()
.addDotToAll()
.addDot(0);
note2 = new VF.StaveNote({ keys: ['d/5', 'g/5', 'a/5', 'b/5'], duration: '8', stem_direction: 1 })
.addDotToAll();
showNotes(note1, note2, stave, ctx, 350);
note1 = new VF.StaveNote({ keys: ['d/4', 'c/5', 'd/5'], duration: '8', stem_direction: -1 })
.addDotToAll()
.addDotToAll()
.addDot(0);
note2 = new VF.StaveNote({ keys: ['d/5', 'a/5', 'b/5'], duration: '8', stem_direction: 1 })
.addDotToAll();
showNotes(note1, note2, stave, ctx, 450);
VF.Test.plotLegendForNoteWidth(ctx, 620, 180);
ok(true, 'Full Dot');
},
};
return Dot;
})();
/**
* VexFlow - EasyScore Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
Vex.Flow.Test.EasyScore = (function() {
var EasyScore = {
Start: function() {
QUnit.module('EasyScore');
var VFT = Vex.Flow.Test;
QUnit.test('Basic', VFT.EasyScore.basic);
QUnit.test('Accidentals', VFT.EasyScore.accidentals);
QUnit.test('Durations', VFT.EasyScore.durations);
QUnit.test('Chords', VFT.EasyScore.chords);
QUnit.test('Dots', VFT.EasyScore.dots);
QUnit.test('Options', VFT.EasyScore.options);
VFT.runTests('Draw Basic', VFT.EasyScore.drawBasicTest);
VFT.runTests('Draw Accidentals', VFT.EasyScore.drawAccidentalsTest);
VFT.runTests('Draw Beams', VFT.EasyScore.drawBeamsTest);
VFT.runTests('Draw Tuplets', VFT.EasyScore.drawTupletsTest);
VFT.runTests('Draw Options', VFT.EasyScore.drawOptionsTest);
},
basic: function(assert) {
var score = new VF.EasyScore();
var mustPass = ['c4', 'c#4', 'c4/r', 'c#5', 'c3/x', 'c3//x'];
var mustFail = ['', '()', '7', '(c#4 e5 g6'];
mustPass.forEach(function(line) { assert.equal(score.parse(line).success, true, line); });
mustFail.forEach(function(line) { assert.equal(score.parse(line).success, false, line); });
},
accidentals: function(assert) {
var score = new VF.EasyScore();
var mustPass = [
'c3', 'c##3, cb3', 'Cn3', 'f3//x', '(c##3 cbb3 cn3), cb3',
'cbbs7', 'cbb7', 'cbss7', 'cbs7', 'cb7', 'cdb7', 'cd7', 'c##7', 'c#7', 'cn7', 'c++-7',
'c++7', 'c+-7', 'c+7', '(cbs3 bbs3 dbs3), ebs3', '(cd7 cbb3 cn3), cb3', 'co7', 'ck7',
];
var mustFail = [
'ct3', 'cdbb7', '(cq cbb3 cn3), cb3', '(cdd7 cbb3 cn3), cb3',
'cbbbs7', 'cbbss7', 'cbsss7', 'csbs7', 'cddb7', 'cddbb7', 'cdd7', 'c##b7', 'c#bs7',
'cnb#7', 'c+#+b-d7', 'c+--7', 'c++--7', 'c+++7', 'cbk7', 'cok7', 'cko7', 'c#s7',
];
mustPass.forEach(function(line) { assert.equal(score.parse(line).success, true, line); });
mustFail.forEach(function(line) { assert.equal(score.parse(line).success, false, line); });
},
durations: function(assert) {
var score = new VF.EasyScore();
var mustPass = ['c3/4', 'c##3/w, cb3', 'c##3/w, cb3/q', 'c##3/q, cb3/32', '(c##3 cbb3 cn3), cb3'];
var mustFail = ['Cn3/]', '/', '(cq cbb3 cn3), cb3', '(cdd7 cbb3 cn3), cb3'];
mustPass.forEach(function(line) { assert.equal(score.parse(line).success, true, line); });
mustFail.forEach(function(line) { assert.equal(score.parse(line).success, false, line); });
},
chords: function(assert) {
var score = new VF.EasyScore();
var mustPass = [
'(c5)', '(c3 e0 g9)',
'(c##4 cbb4 cn4)/w, (c#5 cb2 a3)/32',
'(d##4 cbb4 cn4)/w/r, (c#5 cb2 a3)',
'(c##4 cbb4 cn4)/4, (c#5 cb2 a3)',
'(c##4 cbb4 cn4)/x, (c#5 cb2 a3)',
];
var mustFail = ['(c)'];
mustPass.forEach(function(line) { assert.equal(score.parse(line).success, true, line); });
mustFail.forEach(function(line) { assert.equal(score.parse(line).success, false, line); });
},
dots: function(assert) {
var score = new VF.EasyScore();
var mustPass = [
'c3/4.',
'c##3/w.., cb3',
'f##3/s, cb3/q...',
'c##3/q, cb3/32',
'(c##3 cbb3 cn3)., cb3',
'(c5).',
'(c##4 cbb4 cn4)/w.., (c#5 cb2 a3)/32',
];
var mustFail = ['.', 'c.#', 'c#4./4'];
mustPass.forEach(function(line) { assert.equal(score.parse(line).success, true, line); });
mustFail.forEach(function(line) { assert.equal(score.parse(line).success, false, line); });
},
types: function(assert) {
var score = new VF.EasyScore();
var mustPass = [
'c3/4/x.',
'c##3//r.., cb3',
'c##3/x.., cb3',
'c##3/r.., cb3',
'd##3/w/s, cb3/q...',
'c##3/q, cb3/32',
'(c##3 cbb3 cn3)., cb3',
'(c5).',
'(c##4 cbb4 cn4)/w.., (c#5 cb2 a3)/32',
];
var mustFail = ['c4/q/U', '(c##4, cbb4 cn4)/w.., (c#5 cb2 a3)/32'];
mustPass.forEach(function(line) { assert.equal(score.parse(line).success, true, line); });
mustFail.forEach(function(line) { assert.equal(score.parse(line).success, false, line); });
},
options: function(assert) {
var score = new VF.EasyScore();
var mustPass = [
'c3/4.[foo="bar"]',
'c##3/w.., cb3[id="blah"]',
'c##3/q, cb3/32',
'(c##3 cbb3 cn3).[blah="bod4o"], cb3',
'(c5)[fooooo="booo"]',
'c#5[id="foobar"]',
];
var mustFail = ['.[', 'f##3/w[], cb3/q...'];
mustPass.forEach(function(line) { assert.equal(score.parse(line).success, true, line); });
mustFail.forEach(function(line) { assert.equal(score.parse(line).success, false, line); });
},
drawBasicTest: function(options) {
var vf = VF.Test.makeFactory(options, 600, 350);
var score = vf.EasyScore();
var system = vf.System();
var voice = score.voice.bind(score);
var notes = score.notes.bind(score);
system.addStave({
voices: [
voice(notes('(d4 e4 g4)/q, c4/q, c4/q/r, c4/q', { stem: 'down' })),
voice(notes('c#5/h., c5/q', { stem: 'up' })),
],
}).addClef('treble');
system.addStave({
voices: [voice(notes('c#3/q, cn3/q, bb3/q, d##3/q', { clef: 'bass' }))],
}).addClef('bass');
system.addConnector().setType(VF.StaveConnector.type.BRACKET);
vf.draw();
expect(0);
},
drawAccidentalsTest: function(options) {
var vf = VF.Test.makeFactory(options, 600, 350);
var score = vf.EasyScore();
var system = vf.System();
var voice = score.voice.bind(score);
var notes = score.notes.bind(score);
system.addStave({
voices: [
voice(notes('(cbbs4 ebb4 gbss4)/q, cbs4/q, cdb4/q/r, cd4/q', { stem: 'down' })),
voice(notes('c++-5/h., c++5/q', { stem: 'up' })),
],
}).addClef('treble');
system.addStave({
voices: [voice(notes('c+-3/q, c+3/q, bb3/q, d##3/q', { clef: 'bass' }))],
}).addClef('bass');
system.addConnector().setType(VF.StaveConnector.type.BRACKET);
vf.draw();
expect(0);
},
drawBeamsTest: function(options) {
var vf = VF.Test.makeFactory(options, 600, 250);
const score = vf.EasyScore();
const system = vf.System();
var voice = score.voice.bind(score);
var notes = score.notes.bind(score);
var beam = score.beam.bind(score);
system.addStave({
voices: [
voice(notes('(c4 e4 g4)/q, c4/q, c4/q/r, c4/q', { stem: 'down' })),
voice(notes('c#5/h.', { stem: 'up' }).concat(beam(notes('c5/8, c5/8', { stem: 'up' })))),
],
}).addClef('treble');
vf.draw();
expect(0);
},
drawTupletsTest: function(options) {
var vf = VF.Test.makeFactory(options, 600, 250);
const score = vf.EasyScore();
const system = vf.System();
var voice = score.voice.bind(score);
var notes = score.notes.bind(score);
var tuplet = score.tuplet.bind(score);
var beam = score.beam.bind(score);
system.addStave({
voices: [
voice(
tuplet(
notes('(c4 e4 g4)/q, cbb4/q, c4/q', { stem: 'down' }),
{ location: VF.Tuplet.LOCATION_BOTTOM }
).concat(notes('c4/h', { stem: 'down' }))
),
voice(
notes('c#5/h.', { stem: 'up' })
.concat(tuplet(beam(notes('cb5/8, cn5/8, c5/8', { stem: 'up' }))))
),
],
}).addClef('treble');
vf.draw();
expect(0);
},
drawOptionsTest: function(options) {
var vf = VF.Test.makeFactory(options, 500, 200);
const score = vf.EasyScore();
const system = vf.System();
const notes = score.notes('B4/h[id="foobar", class="red,bold", stem="up", articulations="staccato.below,tenuto"], B4/h[stem="down"]');
system.addStave({
voices: [score.voice(notes)],
});
vf.draw();
const assert = options.assert;
assert.equal(notes[0].getAttribute('id'), 'foobar');
assert.ok(notes[0].hasClass('red'));
assert.ok(notes[0].hasClass('bold'));
assert.equal(notes[0].modifiers[0].getCategory(), 'articulations');
assert.equal(notes[0].modifiers[0].type, 'a.');
assert.equal(notes[0].modifiers[0].position, VF.Modifier.Position.BELOW);
assert.equal(notes[0].modifiers[1].getCategory(), 'articulations');
assert.equal(notes[0].modifiers[1].type, 'a-');
assert.equal(notes[0].modifiers[1].position, VF.Modifier.Position.ABOVE);
assert.equal(notes[0].getStemDirection(), VF.StaveNote.STEM_UP);
assert.equal(notes[1].getStemDirection(), VF.StaveNote.STEM_DOWN);
},
};
return EasyScore;
})();
/**
* VexFlow - Factory Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
Vex.Flow.Test.Factory = (function() {
var Factory = {
Start: function() {
QUnit.module('Factory');
var VFT = Vex.Flow.Test;
QUnit.test('Defaults', VFT.Factory.defaults);
VFT.runSVGTest('Draw', VFT.Factory.draw);
},
defaults: function(assert) {
assert.throws(function() {
return new VF.Factory({
renderer: {
width: 700,
height: 500,
},
});
});
var vf = new VF.Factory({
renderer: {
elementId: null,
width: 700,
height: 500,
},
});
var options = vf.getOptions();
assert.equal(options.renderer.width, 700);
assert.equal(options.renderer.height, 500);
assert.equal(options.renderer.elementId, null);
assert.equal(options.stave.space, 10);
},
draw: function(options) {
var vf = VF.Factory.newFromElementId(options.elementId);
vf.Stave().setClef('treble');
vf.draw();
expect(0);
},
};
return Factory;
})();
/**
* VexFlow - TickContext Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Formatter = (function() {
var run = VF.Test.runTests;
var Formatter = {
Start: function() {
QUnit.module('Formatter');
test('TickContext Building', Formatter.buildTickContexts);
run('StaveNote Formatting', Formatter.formatStaveNotes);
run('StaveNote Justification', Formatter.justifyStaveNotes);
run('Notes with Tab', Formatter.notesWithTab);
run('Multiple Staves - No Justification', Formatter.multiStaves, { justify: false, iterations: 0 });
run('Multiple Staves - Justified', Formatter.multiStaves, { justify: true, iterations: 0 });
run('Multiple Staves - Justified - 6 Iterations', Formatter.multiStaves, { justify: true, iterations: 6 });
run('Proportional Formatting - no tuning', Formatter.proportionalFormatting, { debug: false, iterations: 0 });
run('Proportional Formatting - 15 steps', Formatter.proportionalFormatting, { debug: false, iterations: 15 });
for (var i = 2; i < 15; i++) {
VF.Test.runSVGTest(
'Proportional Formatting (' + i + ' iterations)',
Formatter.proportionalFormatting,
{ debug: true, iterations: i }
);
}
},
buildTickContexts: function() {
function createTickable() {
return new VF.Test.MockTickable();
}
var R = VF.RESOLUTION;
var BEAT = 1 * R / 4;
var tickables1 = [
createTickable().setTicks(BEAT).setWidth(10),
createTickable().setTicks(BEAT * 2).setWidth(20),
createTickable().setTicks(BEAT).setWidth(30),
];
var tickables2 = [
createTickable().setTicks(BEAT * 2).setWidth(10),
createTickable().setTicks(BEAT).setWidth(20),
createTickable().setTicks(BEAT).setWidth(30),
];
var voice1 = new VF.Voice(VF.Test.TIME4_4);
var voice2 = new VF.Voice(VF.Test.TIME4_4);
voice1.addTickables(tickables1);
voice2.addTickables(tickables2);
var formatter = new VF.Formatter();
var tContexts = formatter.createTickContexts([voice1, voice2]);
equal(tContexts.list.length, 4, 'Voices should have four tick contexts');
// TODO: add this after pull request #68 is merged to master
// throws(
// function() { formatter.getMinTotalWidth(); },
// Vex.RERR,
// "Expected to throw exception"
// );
ok(formatter.preCalculateMinTotalWidth([voice1, voice2]), 'Successfully runs preCalculateMinTotalWidth');
equal(formatter.getMinTotalWidth(), 104, 'Get minimum total width without passing voices');
formatter.preFormat();
equal(formatter.getMinTotalWidth(), 104, 'Minimum total width');
equal(tickables1[0].getX(), tickables2[0].getX(), 'First notes of both voices have the same X');
equal(tickables1[2].getX(), tickables2[2].getX(), 'Last notes of both voices have the same X');
ok(tickables1[1].getX() < tickables2[1].getX(), 'Second note of voice 2 is to the right of the second note of voice 1');
},
formatStaveNotes: function(options) {
var vf = VF.Test.makeFactory(options, 500, 250);
var score = vf.EasyScore();
vf.Stave({ y: 40 });
var notes1 = score.notes(
'(cb4 e#4 a4)/2, (d4 e4 f4)/4, (cn4 f#4 a4)',
{ stem: 'down' }
);
var notes2 = score.notes(
'(cb5 e#5 a5)/2, (d5 e5 f5)/4, (cn5 f#5 a5)',
{ stem: 'up' }
);
var voices = [notes1, notes2].map(score.voice.bind(score));
vf.Formatter()
.joinVoices(voices)
.format(voices);
vf.draw();
var ctx = vf.getContext();
notes1.forEach(function(note) {
VF.Test.plotNoteWidth(ctx, note, 180);
});
notes2.forEach(function(note) {
VF.Test.plotNoteWidth(ctx, note, 15);
});
VF.Test.plotLegendForNoteWidth(ctx, 300, 180);
ok(true);
},
justifyStaveNotes: function(options) {
var vf = VF.Test.makeFactory(options, 420, 580);
var ctx = vf.getContext();
var score = vf.EasyScore();
var y = 30;
function justifyToWidth(width) {
vf.Stave({ y: y }).addTrebleGlyph();
var voices = [
score.voice(score.notes(
'(cbb4 en4 a4)/2, (d4 e4 f4)/8, (d4 f4 a4)/8, (cn4 f#4 a4)/4',
{ stem: 'down' }
)),
score.voice(score.notes(
'(bb4 e#5 a5)/4, (d5 e5 f5)/2, (c##5 fb5 a5)/4',
{ stem: 'up' }
)),
];
vf.Formatter()
.joinVoices(voices)
.format(voices, width);
voices[0].getTickables().forEach(function(note) {
VF.Test.plotNoteWidth(ctx, note, y + 140);
});
voices[1].getTickables().forEach(function(note) {
VF.Test.plotNoteWidth(ctx, note, y - 20);
});
y += 210;
}
justifyToWidth(0);
justifyToWidth(300);
justifyToWidth(400);
vf.draw();
ok(true);
},
notesWithTab: function(options) {
var vf = VF.Test.makeFactory(options, 420, 580);
var score = vf.EasyScore();
var y = 10;
function justifyToWidth(width) {
var stave = vf.Stave({ y: y }).addTrebleGlyph();
var voice = score.voice(score.notes(
'd#4/2, (c4 d4)/8, d4/8, (c#4 e4 a4)/4',
{ stem: 'up' }
));
y += 100;
vf.TabStave({ y: y })
.addTabGlyph()
.setNoteStartX(stave.getNoteStartX());
var tabVoice = score.voice([
vf.TabNote({ positions: [{ str: 3, fret: 6 }], duration: '2' }).addModifier(new VF.Bend('Full'), 0),
vf.TabNote({
positions: [{ str: 2, fret: 3 },
{ str: 3, fret: 5 }], duration: '8',
}).addModifier(new VF.Bend('Unison'), 1),
vf.TabNote({ positions: [{ str: 3, fret: 7 }], duration: '8' }),
vf.TabNote({
positions: [{ str: 3, fret: 6 },
{ str: 4, fret: 7 },
{ str: 2, fret: 5 }], duration: '4',
}),
]);
vf.Formatter()
.joinVoices([voice])
.joinVoices([tabVoice])
.format([voice, tabVoice], width);
y += 150;
}
justifyToWidth(0);
justifyToWidth(300);
vf.draw();
ok(true);
},
multiStaves: function(options) {
var vf = VF.Test.makeFactory(options, 600, 400);
var score = vf.EasyScore();
var stave11 = vf.Stave({ y: 20, width: 275 })
.addTrebleGlyph()
.addTimeSignature('6/8');
var notes11 = score.notes('f4/4, d4/8, g4/4, eb4/8');
var voice11 = score.voice(notes11, { time: '6/8' });
var stave21 = vf.Stave({ y: 130, width: 275 })
.addTrebleGlyph()
.addTimeSignature('6/8');
var notes21 = score.notes('d4/8, d4, d4, d4, eb4, eb4');
var voice21 = score.voice(notes21, { time: '6/8' });
var stave31 = vf.Stave({ y: 250, width: 275 })
.addClef('bass')
.addTimeSignature('6/8');
var notes31 = score.notes('a5/8, a5, a5, a5, a5, a5', { stem: 'down' });
var voice31 = score.voice(notes31, { time: '6/8' });
vf.StaveConnector({
top_stave: stave21,
bottom_stave: stave31,
type: 'brace',
});
vf.Beam({ notes: notes21.slice(0, 3) });
vf.Beam({ notes: notes21.slice(3, 6) });
vf.Beam({ notes: notes31.slice(0, 3) });
vf.Beam({ notes: notes31.slice(3, 6) });
var formatter = vf.Formatter()
.joinVoices([voice11])
.joinVoices([voice21])
.joinVoices([voice31]);
if (options.params.justify) {
formatter.formatToStave([voice11, voice21, voice31], stave11);
} else {
formatter.format([voice11, voice21, voice31], 0);
}
for (var i = 0; i < options.params.iterations; i++) {
formatter.tune();
}
var stave12 = vf.Stave({
x: stave11.width + stave11.x,
y: stave11.y,
width: stave11.width,
});
var notes12 = score.notes('ab4/4, bb4/8, (cb5 eb5)/4[stem="down"], d5/8[stem="down"]');
var voice12 = score.voice(notes12, { time: '6/8' });
vf.Stave({
x: stave21.width + stave21.x,
y: stave21.y,
width: stave21.width,
});
var notes22 = score.notes('(eb4 ab4)/4., (c4 eb4 ab4)/4, db5/8', { stem: 'up' });
var voice22 = score.voice(notes22, { time: '6/8' });
vf.Stave({
x: stave31.width + stave31.x,
y: stave31.y,
width: stave31.width,
});
var notes32 = score.notes('a5/8, a5, a5, a5, a5, a5', { stem: 'down' });
var voice32 = score.voice(notes32, { time: '6/8' });
formatter = vf.Formatter()
.joinVoices([voice12])
.joinVoices([voice22])
.joinVoices([voice32]);
if (options.params.justify) {
formatter.formatToStave([voice12, voice22, voice32], stave12);
} else {
formatter.format([voice12, voice22, voice32], 0);
}
for (var j = 0; j < options.params.iterations; j++) {
formatter.tune();
}
vf.Beam({ notes: notes32.slice(0, 3) });
vf.Beam({ notes: notes32.slice(3, 6) });
vf.draw();
ok(true);
},
proportionalFormatting: function(options) {
var debug = options.params.debug;
VF.Registry.enableDefaultRegistry(new VF.Registry());
var vf = VF.Test.makeFactory(options, 600, 750);
var system = vf.System({
x: 50,
width: 500,
debugFormatter: debug,
formatIterations: options.params.iterations,
});
var score = vf.EasyScore();
var newVoice = function(notes) {
return score.voice(notes, { time: '1/4' });
};
var newStave = function(voice) {
return system
.addStave({ voices: [voice], debugNoteMetrics: debug })
.addClef('treble')
.addTimeSignature('1/4');
};
var voices = [
score.notes('c5/8, c5'),
score.tuplet(score.notes('a4/8, a4, a4'), { notes_occupied: 2 }),
score.notes('c5/16, c5, c5, c5'),
score.tuplet(score.notes('a4/16, a4, a4, a4, a4'), { notes_occupied: 4 }),
score.tuplet(score.notes('a4/32, a4, a4, a4, a4, a4, a4'), { notes_occupied: 8 }),
];
voices.map(newVoice).forEach(newStave);
system.addConnector().setType(VF.StaveConnector.type.BRACKET);
vf.draw();
// var typeMap = VF.Registry.getDefaultRegistry().index.type;
// var table = Object.keys(typeMap).map(function(typeName) {
// return typeName + ': ' + Object.keys(typeMap[typeName]).length;
// });
// console.log(table);
VF.Registry.disableDefaultRegistry();
ok(true);
},
TIME6_8: {
num_beats: 6,
beat_value: 8,
resolution: VF.RESOLUTION,
},
};
return Formatter;
})();
/**
* VexFlow - Fraction Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Fraction = (function() {
var Fraction = {
Start: function() {
QUnit.module('Fraction');
test('Basic', VF.Test.Fraction.basic);
},
basic: function() {
var f_1_2 = new Vex.Flow.Fraction(1, 2);
ok(f_1_2.equals(0.5), 'Fraction: 1/2 equals 0.5');
ok(f_1_2.equals(new Vex.Flow.Fraction(1, 2)), 'Fraction: 1/2 equals 1/2');
ok(f_1_2.equals(new Vex.Flow.Fraction(2, 4)), 'Fraction: 1/2 equals 2/4');
notOk(f_1_2.greaterThan(1), 'Fraction: ! 1/2 > 1');
ok(f_1_2.greaterThan(0.2), 'Fraction: 1/2 > 0.2');
ok(f_1_2.greaterThanEquals(0.2), 'Fraction: 1/2 >= 0.2');
ok(f_1_2.greaterThanEquals(0.5), 'Fraction: 1/2 >= 0.5');
notOk(f_1_2.greaterThanEquals(1), 'Fraction: ! 1/2 >= 1');
notOk(f_1_2.lessThan(0.5), 'Fracion: ! 1/2 < 0.5');
ok(f_1_2.lessThan(1), 'Fraction: 1/2 < 1');
ok(f_1_2.lessThanEquals(0.6), 'Fraction: 1/2 <= 0.6');
ok(f_1_2.lessThanEquals(0.5), 'Fraction: 1/2 <= 0.5');
notOk(f_1_2.lessThanEquals(0.4), 'Fraction: ! 1/2 <= 0.4');
var f_05 = f_1_2.copy(0.5);
strictEqual(f_05, f_1_2, 'Fraction: f_05 === f_1_2');
strictEqual(f_05.toString(), '0.5/1', 'Fraction: f_05.toString() === "0.5/1"');
strictEqual(f_05.toSimplifiedString(), '1/2', 'Fraction: f_05.toSimplifiedString() === "1/2"');
var tF_n = f_05.clone();
notStrictEqual(tF_n, f_05, 'Fraction: tF_n !== f_05');
notEqual(tF_n, f_05, 'Fraction: tF_n != f_05');
deepEqual(tF_n, f_05, 'tF_n deepEqual f_05');
notDeepEqual(tF_n, {}, 'tF_n notDeepEqual {}');
tF_n.subtract(-0.5);
ok(tF_n.equals(1), 'Fraction: 0.5 -(-0.5) equals 1');
tF_n.add(1);
ok(tF_n.equals(2), 'Fraction: 1 + 1 equals 2');
tF_n.multiply(2);
ok(tF_n.equals(4), 'Fraction: 2 * 2 equals 4');
tF_n.divide(2);
ok(tF_n.equals(2), 'Fraction: 4 / 2 equals 2');
// TODO: Add more detailed tests.
},
};
return Fraction;
})();
/**
* VexFlow - Rest Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
function createTest(setup) {
return function(options) {
var vf = VF.Test.makeFactory(options, 550);
var stave = vf.Stave();
var score = vf.EasyScore();
setup(vf, score);
vf.Formatter()
.joinVoices(vf.getVoices())
.formatToStave(vf.getVoices(), stave);
vf.draw();
ok(true, 'all pass');
};
}
VF.Test.GhostNote = {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('GhostNote');
run('GhostNote Basic', createTest(function(vf, score) {
var voice1 = score.voice(score.notes(
'f#5/4, f5, db5, c5, c5/8, d5, fn5, e5, d5, c5',
{ stem: 'up' }
), { time: '7/4' });
score.voice([
vf.GhostNote({ duration: '2' }),
vf.StaveNote({ keys: ['f/4'], stem_direction: -1, duration: '4' }),
vf.GhostNote({ duration: '4' }),
vf.StaveNote({ keys: ['e/4'], stem_direction: -1, duration: '4' }),
vf.GhostNote({ duration: '8' }),
vf.StaveNote({ keys: ['d/4'], stem_direction: -1, duration: '8' })
.addAccidental(0, vf.Accidental({ type: '##' })),
vf.StaveNote({ keys: ['c/4'], stem_direction: -1, duration: '8' }),
vf.StaveNote({ keys: ['c/4'], stem_direction: -1, duration: '8' }),
], { time: '7/4' });
vf.Beam({ notes: voice1.getTickables().slice(4, 8) });
vf.Beam({ notes: voice1.getTickables().slice(8, 10) });
}));
run('GhostNote Dotted', createTest(function(vf, score) {
function addAccidental(note, type) {
note.addAccidental(0, vf.Accidental({ type: type }));
}
var voice1 = score.voice([
vf.GhostNote({ duration: '4d' }),
vf.StaveNote({ duration: '8', keys: ['f/5'], stem_direction: 1 }),
vf.StaveNote({ duration: '4', keys: ['d/5'], stem_direction: 1 }),
vf.StaveNote({ duration: '8', keys: ['c/5'], stem_direction: 1 }),
vf.StaveNote({ duration: '16', keys: ['c/5'], stem_direction: 1 }),
vf.StaveNote({ duration: '16', keys: ['d/5'], stem_direction: 1 }),
vf.GhostNote({ duration: '2dd' }),
vf.StaveNote({ duration: '8', keys: ['f/5'], stem_direction: 1 }),
], { time: '8/4' });
var voice2 = score.voice([
vf.StaveNote({ duration: '4', keys: ['f/4'], stem_direction: -1 }),
vf.StaveNote({ duration: '8', keys: ['e/4'], stem_direction: -1 }),
vf.StaveNote({ duration: '8', keys: ['d/4'], stem_direction: -1 }),
vf.GhostNote({ duration: '4dd' }),
vf.StaveNote({ duration: '16', keys: ['c/4'], stem_direction: -1 }),
vf.StaveNote({ duration: '2', keys: ['c/4'], stem_direction: -1 }),
vf.StaveNote({ duration: '4', keys: ['d/4'], stem_direction: -1 }),
vf.StaveNote({ duration: '8', keys: ['f/4'], stem_direction: -1 }),
vf.StaveNote({ duration: '8', keys: ['e/4'], stem_direction: -1 }),
], { time: '8/4' });
var notes1 = voice1.getTickables();
var notes2 = voice2.getTickables();
addAccidental(notes1[1], 'bb');
addAccidental(notes1[4], '#');
addAccidental(notes1[7], 'n');
addAccidental(notes2[0], '#');
addAccidental(notes2[4], 'b');
addAccidental(notes2[5], '#');
addAccidental(notes2[7], 'n');
vf.Beam({ notes: notes1.slice(3, 6) });
vf.Beam({ notes: notes2.slice(1, 3) });
vf.Beam({ notes: notes2.slice(7, 9) });
}));
},
};
/**
* VexFlow - GraceNote Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.GraceNote = (function() {
var stem_test_util = {
durations: ['8', '16', '32', '64', '128'],
createNote: function(d, noteT, keys, stem_direction, slash) {
var note_prop = {
duration: d,
};
note_prop.stem_direction = stem_direction;
note_prop.slash = slash;
note_prop.keys = keys;
return noteT(note_prop);
},
};
var GraceNote = {
Start: function() {
QUnit.module('Grace Notes');
VF.Test.runTests('Grace Note Basic', VF.Test.GraceNote.basic);
VF.Test.runTests('Grace Note Basic with Slurs', VF.Test.GraceNote.basicSlurred);
VF.Test.runTests('Grace Note Stem', VF.Test.GraceNote.stem);
VF.Test.runTests('Grace Note Stem with Beams', VF.Test.GraceNote.stemWithBeamed);
VF.Test.runTests('Grace Note Slash', VF.Test.GraceNote.slash);
VF.Test.runTests('Grace Note Slash with Beams', VF.Test.GraceNote.slashWithBeams);
VF.Test.runTests('Grace Notes Multiple Voices', VF.Test.GraceNote.multipleVoices);
VF.Test.runTests('Grace Notes Multiple Voices Multiple Draws', VF.Test.GraceNote.multipleVoicesMultipleDraws);
},
basic: function(options) {
const vf = VF.Test.makeFactory(options, 700, 130);
const stave = vf.Stave({ x: 10, y: 10, width: 650 });
var gracenotes = [
{ keys: ['e/4'], duration: '32' },
{ keys: ['f/4'], duration: '32' },
{ keys: ['g/4'], duration: '32' },
{ keys: ['a/4'], duration: '32' },
].map(vf.GraceNote.bind(vf));
var gracenotes1 = [
{ keys: ['b/4'], duration: '8', slash: false },
].map(vf.GraceNote.bind(vf));
var gracenotes2 = [
{ keys: ['b/4'], duration: '8', slash: true },
].map(vf.GraceNote.bind(vf));
var gracenotes3 = [
{ keys: ['e/4'], duration: '8' },
{ keys: ['f/4'], duration: '16' },
{ keys: ['e/4', 'g/4'], duration: '8' },
{ keys: ['a/4'], duration: '32' },
{ keys: ['b/4'], duration: '32' },
].map(vf.GraceNote.bind(vf));
var gracenotes4 = [
{ keys: ['g/4'], duration: '8' },
{ keys: ['g/4'], duration: '16' },
{ keys: ['g/4'], duration: '16' },
].map(vf.GraceNote.bind(vf));
gracenotes[1].addAccidental(0, vf.Accidental({ type: '##' }));
gracenotes3[3].addAccidental(0, vf.Accidental({ type: 'bb' }));
gracenotes4[0].addDotToAll();
var notes = [
vf.StaveNote({ keys: ['b/4'], duration: '4', auto_stem: true })
.addModifier(0, vf.GraceNoteGroup({ notes: gracenotes }).beamNotes()),
vf.StaveNote({ keys: ['c/5'], duration: '4', auto_stem: true })
.addAccidental(0, vf.Accidental({ type: '#' }))
.addModifier(0, vf.GraceNoteGroup({ notes: gracenotes1 }).beamNotes()),
vf.StaveNote({ keys: ['c/5', 'd/5'], duration: '4', auto_stem: true })
.addModifier(0, vf.GraceNoteGroup({ notes: gracenotes2 }).beamNotes()),
vf.StaveNote({ keys: ['a/4'], duration: '4', auto_stem: true })
.addModifier(0, vf.GraceNoteGroup({ notes: gracenotes3 }).beamNotes()),
vf.StaveNote({ keys: ['a/4'], duration: '4', auto_stem: true })
.addModifier(0, vf.GraceNoteGroup({ notes: gracenotes4 }).beamNotes()),
];
var voice = vf.Voice()
.setStrict(false)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'GraceNoteBasic');
},
basicSlurred: function(options) {
const vf = VF.Test.makeFactory(options, 700, 130);
const stave = vf.Stave({ x: 10, y: 10, width: 650 });
var gracenotes0 = [
{ keys: ['e/4'], duration: '32' },
{ keys: ['f/4'], duration: '32' },
{ keys: ['g/4'], duration: '32' },
{ keys: ['a/4'], duration: '32' },
].map(vf.GraceNote.bind(vf));
var gracenotes1 = [
{ keys: ['b/4'], duration: '8', slash: false },
].map(vf.GraceNote.bind(vf));
var gracenotes2 = [
{ keys: ['b/4'], duration: '8', slash: true },
].map(vf.GraceNote.bind(vf));
var gracenotes3 = [
{ keys: ['e/4'], duration: '8' },
{ keys: ['f/4'], duration: '16' },
{ keys: ['e/4', 'g/4'], duration: '8' },
{ keys: ['a/4'], duration: '32' },
{ keys: ['b/4'], duration: '32' },
].map(vf.GraceNote.bind(vf));
var gracenotes4 = [
{ keys: ['a/4'], duration: '8' },
{ keys: ['a/4'], duration: '16' },
{ keys: ['a/4'], duration: '16' },
].map(vf.GraceNote.bind(vf));
gracenotes0[1].addAccidental(0, vf.Accidental({ type: '#' }));
gracenotes3[3].addAccidental(0, vf.Accidental({ type: 'b' }));
gracenotes3[2].addAccidental(0, vf.Accidental({ type: 'n' }));
gracenotes4[0].addDotToAll();
const notes = [
vf.StaveNote({ keys: ['b/4'], duration: '4', auto_stem: true })
.addModifier(0, vf.GraceNoteGroup({ notes: gracenotes0, slur: true }).beamNotes()),
vf.StaveNote({ keys: ['c/5'], duration: '4', auto_stem: true })
.addAccidental(0, vf.Accidental({ type: '#' }))
.addModifier(0, vf.GraceNoteGroup({ notes: gracenotes1, slur: true }).beamNotes()),
vf.StaveNote({ keys: ['c/5', 'd/5'], duration: '4', auto_stem: true })
.addModifier(0, vf.GraceNoteGroup({ notes: gracenotes2, slur: true }).beamNotes()),
vf.StaveNote({ keys: ['a/4'], duration: '4', auto_stem: true })
.addModifier(0, vf.GraceNoteGroup({ notes: gracenotes3, slur: true }).beamNotes()),
vf.StaveNote({ keys: ['a/4'], duration: '4', auto_stem: true })
.addModifier(0, vf.GraceNoteGroup({ notes: gracenotes4, slur: true }).beamNotes()),
vf.StaveNote({ keys: ['a/4'], duration: '4', auto_stem: true }),
];
var voice = vf.Voice()
.setStrict(false)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'GraceNoteBasic');
},
stem: function(options) {
const vf = VF.Test.makeFactory(options, 700, 130);
const stave = vf.Stave({ x: 10, y: 10, width: 650 });
function createNotes(noteT, keys, stem_direction) {
return stem_test_util.durations.map(function(d) {
return stem_test_util.createNote(d, noteT, keys, stem_direction);
});
}
function createNoteBlock(keys, stem_direction) {
var notes = createNotes(vf.StaveNote.bind(vf), keys, stem_direction);
var gracenotes = createNotes(vf.GraceNote.bind(vf), keys, stem_direction);
notes[0].addModifier(0, vf.GraceNoteGroup({ notes: gracenotes }));
return notes;
}
var voice = vf.Voice().setStrict(false);
voice.addTickables(createNoteBlock(['g/4'], 1));
voice.addTickables(createNoteBlock(['d/5'], -1));
new vf.Formatter().joinVoices([voice]).formatToStave([voice], stave);
vf.draw();
ok(true, 'GraceNoteStem');
},
stemWithBeamed: function(options) {
const vf = VF.Test.makeFactory(options, 700, 130);
const stave = vf.Stave({ x: 10, y: 10, width: 650 });
function createBeamdNotes(noteT, keys, stem_direction, beams, isGrace, notesToBeam) {
var ret = [];
stem_test_util.durations.map(function(d) {
var n0 = stem_test_util.createNote(d, noteT, keys, stem_direction);
var n1 = stem_test_util.createNote(d, noteT, keys, stem_direction);
ret.push(n0);
ret.push(n1);
if (notesToBeam) {
notesToBeam.push([n0, n1]);
}
if (!isGrace) {
var tbeam = vf.Beam({ notes: [n0, n1] });
beams.push(tbeam);
}
return ret;
});
return ret;
}
function createBeamdNoteBlock(keys, stem_direction, beams) {
var bnotes = createBeamdNotes(vf.StaveNote.bind(vf), keys, stem_direction, beams);
var notesToBeam = [];
var gracenotes = createBeamdNotes(vf.GraceNote.bind(vf), keys, stem_direction, beams, true, notesToBeam);
var graceNoteGroup = vf.GraceNoteGroup({ notes: gracenotes });
notesToBeam.map(graceNoteGroup.beamNotes.bind(graceNoteGroup));
bnotes[0].addModifier(0, graceNoteGroup);
return bnotes;
}
var beams = [];
var voice = vf.Voice().setStrict(false);
voice.addTickables(createBeamdNoteBlock(['g/4'], 1, beams));
voice.addTickables(createBeamdNoteBlock(['d/5'], -1, beams));
new vf.Formatter().joinVoices([voice]).formatToStave([voice], stave);
vf.draw();
ok(true, 'GraceNoteStem');
},
slash: function(options) {
const vf = VF.Test.makeFactory(options, 700, 130);
const stave = vf.Stave({ x: 10, y: 10, width: 650 });
function createNotes(noteT, keys, stem_direction, slash) {
return stem_test_util.durations.map(function(d) {
return stem_test_util.createNote(d, noteT, keys, stem_direction, slash);
});
}
function createNoteBlock(keys, stem_direction) {
var notes = [vf.StaveNote({ keys: ['f/4'], stem_direction: stem_direction, duration: '16' })];
var gracenotes = createNotes(vf.GraceNote.bind(vf), keys, stem_direction, true);
var gnotesToBeam = [];
var duration = '8';
var gns = [
{ keys: ['d/4', 'a/4'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['d/4', 'a/4'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['d/4', 'a/4'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['e/4', 'a/4'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['e/4', 'a/4'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['b/4', 'f/5'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['b/4', 'f/5'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['b/4', 'f/5'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['e/4', 'a/4'], stem_direction: stem_direction, duration: duration, slash: true },
].map(vf.GraceNote.bind(vf));
gnotesToBeam.push([gns[0], gns[1], gns[2]]);
gnotesToBeam.push([gns[3], gns[4], gns[5]]);
gnotesToBeam.push([gns[6], gns[7], gns[8]]);
gracenotes = gracenotes.concat(gns);
var gracenoteGroup = vf.GraceNoteGroup({ notes: gracenotes });
gnotesToBeam.forEach(function(gnotes) {
gracenoteGroup.beamNotes(gnotes);
});
notes[0].addModifier(0, gracenoteGroup);
return notes;
}
var voice = vf.Voice().setStrict(false);
voice.addTickables(createNoteBlock(['d/4', 'a/4'], 1));
voice.addTickables(createNoteBlock(['d/4', 'a/4'], -1));
new vf.Formatter().joinVoices([voice]).formatToStave([voice], stave);
vf.draw();
ok(true, 'GraceNoteSlash');
},
slashWithBeams: function(options) {
const vf = VF.Test.makeFactory(options, 800, 130);
const stave = vf.Stave({ x: 10, y: 10, width: 750 });
function createNoteBlock(keys, stem_direction) {
var notes = [vf.StaveNote({ keys: ['f/4'], stem_direction: stem_direction, duration: '16' })];
var gracenotes = [];
var gnotesToBeam = [];
['8', '16', '32', '64'].forEach(function(duration) {
var gns = [
{ keys: ['d/4', 'a/4'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['d/4', 'a/4'], stem_direction: stem_direction, duration: duration, slash: false },
{ keys: ['e/4', 'a/4'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['b/4', 'f/5'], stem_direction: stem_direction, duration: duration, slash: false },
{ keys: ['b/4', 'f/5'], stem_direction: stem_direction, duration: duration, slash: true },
{ keys: ['e/4', 'a/4'], stem_direction: stem_direction, duration: duration, slash: false },
].map(vf.GraceNote.bind(vf));
gnotesToBeam.push([gns[0], gns[1]]);
gnotesToBeam.push([gns[2], gns[3]]);
gnotesToBeam.push([gns[4], gns[5]]);
gracenotes = gracenotes.concat(gns);
});
var gracenoteGroup = vf.GraceNoteGroup({ notes: gracenotes });
gnotesToBeam.forEach(function(gnotes) {
gracenoteGroup.beamNotes(gnotes);
});
notes[0].addModifier(0, gracenoteGroup);
return notes;
}
var voice = vf.Voice().setStrict(false);
voice.addTickables(createNoteBlock(['d/4', 'a/4'], 1));
voice.addTickables(createNoteBlock(['d/4', 'a/4'], -1));
new vf.Formatter().joinVoices([voice]).formatToStave([voice], stave);
vf.draw();
ok(true, 'GraceNoteSlashWithBeams');
},
multipleVoices: function(options) {
const vf = VF.Test.makeFactory(options, 450, 140);
const stave = vf.Stave({ x: 10, y: 10, width: 450 });
var notes = [
{ keys: ['f/5'], stem_direction: 1, duration: '16' },
{ keys: ['f/5'], stem_direction: 1, duration: '16' },
{ keys: ['d/5'], stem_direction: 1, duration: '16' },
{ keys: ['c/5'], stem_direction: 1, duration: '16' },
{ keys: ['c/5'], stem_direction: 1, duration: '16' },
{ keys: ['d/5'], stem_direction: 1, duration: '16' },
{ keys: ['f/5'], stem_direction: 1, duration: '16' },
{ keys: ['e/5'], stem_direction: 1, duration: '16' },
].map(vf.StaveNote.bind(vf));
var notes2 = [
{ keys: ['f/4'], stem_direction: -1, duration: '16' },
{ keys: ['e/4'], stem_direction: -1, duration: '16' },
{ keys: ['d/4'], stem_direction: -1, duration: '16' },
{ keys: ['c/4'], stem_direction: -1, duration: '16' },
{ keys: ['c/4'], stem_direction: -1, duration: '16' },
{ keys: ['d/4'], stem_direction: -1, duration: '16' },
{ keys: ['f/4'], stem_direction: -1, duration: '16' },
{ keys: ['e/4'], stem_direction: -1, duration: '16' },
].map(vf.StaveNote.bind(vf));
var gracenotes1 = [
{ keys: ['b/4'], stem_direction: 1, duration: '8', slash: true },
].map(vf.GraceNote.bind(vf));
var gracenotes2 = [
{ keys: ['f/4'], stem_direction: -1, duration: '8', slash: true },
].map(vf.GraceNote.bind(vf));
var gracenotes3 = [
{ keys: ['f/4'], duration: '32', stem_direction: -1 },
{ keys: ['e/4'], duration: '32', stem_direction: -1 },
].map(vf.GraceNote.bind(vf));
var gracenotes4 = [
{ keys: ['f/5'], duration: '32', stem_direction: 1 },
{ keys: ['e/5'], duration: '32', stem_direction: 1 },
{ keys: ['e/5'], duration: '8', stem_direction: 1 },
].map(vf.GraceNote.bind(vf));
gracenotes2[0].setStemDirection(-1);
gracenotes2[0].addAccidental(0, vf.Accidental({ type: '#' }));
notes[1].addModifier(0, vf.GraceNoteGroup({ notes: gracenotes4 }).beamNotes());
notes[3].addModifier(0, vf.GraceNoteGroup({ notes: gracenotes1 }));
notes2[1].addModifier(0, vf.GraceNoteGroup({ notes: gracenotes2 }).beamNotes());
notes2[5].addModifier(0, vf.GraceNoteGroup({ notes: gracenotes3 }).beamNotes());
var voice = vf.Voice()
.setStrict(false)
.addTickables(notes);
var voice2 = vf.Voice()
.setStrict(false)
.addTickables(notes2);
vf.Beam({ notes: notes.slice(0, 4) });
vf.Beam({ notes: notes.slice(4, 8) });
vf.Beam({ notes: notes2.slice(0, 4) });
vf.Beam({ notes: notes2.slice(4, 8) });
new VF.Formatter()
.joinVoices([voice, voice2])
.formatToStave([voice, voice2], stave);
vf.draw();
ok(true, 'Sixteenth Test');
},
multipleVoicesMultipleDraws: function(options) {
const vf = VF.Test.makeFactory(options, 450, 140);
const stave = vf.Stave({ x: 10, y: 10, width: 450 });
var notes = [
{ keys: ['f/5'], stem_direction: 1, duration: '16' },
{ keys: ['f/5'], stem_direction: 1, duration: '16' },
{ keys: ['d/5'], stem_direction: 1, duration: '16' },
{ keys: ['c/5'], stem_direction: 1, duration: '16' },
{ keys: ['c/5'], stem_direction: 1, duration: '16' },
{ keys: ['d/5'], stem_direction: 1, duration: '16' },
{ keys: ['f/5'], stem_direction: 1, duration: '16' },
{ keys: ['e/5'], stem_direction: 1, duration: '16' },
].map(vf.StaveNote.bind(vf));
var notes2 = [
{ keys: ['f/4'], stem_direction: -1, duration: '16' },
{ keys: ['e/4'], stem_direction: -1, duration: '16' },
{ keys: ['d/4'], stem_direction: -1, duration: '16' },
{ keys: ['c/4'], stem_direction: -1, duration: '16' },
{ keys: ['c/4'], stem_direction: -1, duration: '16' },
{ keys: ['d/4'], stem_direction: -1, duration: '16' },
{ keys: ['f/4'], stem_direction: -1, duration: '16' },
{ keys: ['e/4'], stem_direction: -1, duration: '16' },
].map(vf.StaveNote.bind(vf));
var gracenotes1 = [
{ keys: ['b/4'], stem_direction: 1, duration: '8', slash: true },
].map(vf.GraceNote.bind(vf));
var gracenotes2 = [
{ keys: ['f/4'], stem_direction: -1, duration: '8', slash: true },
].map(vf.GraceNote.bind(vf));
var gracenotes3 = [
{ keys: ['f/4'], duration: '32', stem_direction: -1 },
{ keys: ['e/4'], duration: '32', stem_direction: -1 },
].map(vf.GraceNote.bind(vf));
var gracenotes4 = [
{ keys: ['f/5'], duration: '32', stem_direction: 1 },
{ keys: ['e/5'], duration: '32', stem_direction: 1 },
{ keys: ['e/5'], duration: '8', stem_direction: 1 },
].map(vf.GraceNote.bind(vf));
gracenotes2[0].setStemDirection(-1);
gracenotes2[0].addAccidental(0, vf.Accidental({ type: '#' }));
notes[1].addModifier(0, vf.GraceNoteGroup({ notes: gracenotes4 }).beamNotes());
notes[3].addModifier(0, vf.GraceNoteGroup({ notes: gracenotes1 }));
notes2[1].addModifier(0, vf.GraceNoteGroup({ notes: gracenotes2 }).beamNotes());
notes2[5].addModifier(0, vf.GraceNoteGroup({ notes: gracenotes3 }).beamNotes());
var voice = vf.Voice()
.setStrict(false)
.addTickables(notes);
var voice2 = vf.Voice()
.setStrict(false)
.addTickables(notes2);
vf.Beam({ notes: notes.slice(0, 4) });
vf.Beam({ notes: notes.slice(4, 8) });
vf.Beam({ notes: notes2.slice(0, 4) });
vf.Beam({ notes: notes2.slice(4, 8) });
new VF.Formatter()
.joinVoices([voice, voice2])
.formatToStave([voice, voice2], stave);
vf.draw();
vf.draw();
ok(true, 'Seventeenth Test');
},
};
return GraceNote;
})();
/**
* VexFlow - GraceTabNote Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.GraceTabNote = (function() {
var GraceTabNote = {
Start: function() {
QUnit.module('Grace Tab Notes');
VF.Test.runTests('Grace Tab Note Simple', VF.Test.GraceTabNote.simple);
VF.Test.runTests('Grace Tab Note Slurred', VF.Test.GraceTabNote.slurred);
},
setupContext: function(options, x) {
var ctx = options.contextBuilder(options.elementId, 350, 140);
var stave = new VF.TabStave(10, 10, x || 350)
.addTabGlyph()
.setContext(ctx)
.draw();
return { context: ctx, stave: stave };
},
simple: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
var c = VF.Test.GraceTabNote.setupContext(options);
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
var note0 = newNote({ positions: [{ str: 4, fret: 6 }], duration: '4' });
var note1 = newNote({ positions: [{ str: 4, fret: 12 }], duration: '4' });
var note2 = newNote({ positions: [{ str: 4, fret: 10 }], duration: '4' });
var note3 = newNote({ positions: [{ str: 4, fret: 10 }], duration: '4' });
var gracenote_group0 = [
{ positions: [{ str: 4, fret: 'x' }], duration: '8' },
];
var gracenote_group1 = [
{ positions: [{ str: 4, fret: 9 }], duration: '16' },
{ positions: [{ str: 4, fret: 10 }], duration: '16' },
];
var gracenote_group2 = [
{ positions: [{ str: 4, fret: 9 }], duration: '8' },
];
var gracenote_group3 = [
{ positions: [{ str: 5, fret: 10 }], duration: '8' },
{ positions: [{ str: 4, fret: 9 }], duration: '8' },
];
function createNote(note_prop) {
return new VF.GraceTabNote(note_prop);
}
var gracenotes0 = gracenote_group0.map(createNote);
var gracenotes1 = gracenote_group1.map(createNote);
var gracenotes2 = gracenote_group2.map(createNote);
gracenotes2[0].setGhost(true);
var gracenotes3 = gracenote_group3.map(createNote);
note0.addModifier(new VF.GraceNoteGroup(gracenotes0));
note1.addModifier(new VF.GraceNoteGroup(gracenotes1));
note2.addModifier(new VF.GraceNoteGroup(gracenotes2));
note3.addModifier(new VF.GraceNoteGroup(gracenotes3));
var voice = new VF.Voice(VF.Test.TIME4_4);
voice.addTickables([note0, note1, note2, note3]);
new VF.Formatter().joinVoices([voice]).format([voice], 250);
voice.draw(c.context, c.stave);
ok(true, 'Simple Test');
},
slurred: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
var c = VF.Test.GraceTabNote.setupContext(options);
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
var note0 = newNote({ positions: [{ str: 4, fret: 12 }], duration: 'h' });
var note1 = newNote({ positions: [{ str: 4, fret: 10 }], duration: 'h' });
var gracenote_group0 = [
{ positions: [{ str: 4, fret: 9 }], duration: '8' },
{ positions: [{ str: 4, fret: 10 }], duration: '8' },
];
var gracenote_group1 = [
{ positions: [{ str: 4, fret: 7 }], duration: '16' },
{ positions: [{ str: 4, fret: 8 }], duration: '16' },
{ positions: [{ str: 4, fret: 9 }], duration: '16' },
];
function createNote(note_prop) {
return new VF.GraceTabNote(note_prop);
}
var gracenotes0 = gracenote_group0.map(createNote);
var gracenotes1 = gracenote_group1.map(createNote);
note0.addModifier(new VF.GraceNoteGroup(gracenotes0, true));
note1.addModifier(new VF.GraceNoteGroup(gracenotes1, true));
var voice = new VF.Voice(VF.Test.TIME4_4);
voice.addTickables([note0, note1]);
new VF.Formatter().joinVoices([voice]).format([voice], 200);
voice.draw(c.context, c.stave);
ok(true, 'Slurred Test');
},
};
return GraceTabNote;
})();
/**
* VexFlow - Clef-Key Signature Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.ClefKeySignature = (function() {
var ClefKeySignature = {
MAJOR_KEYS: [
'C',
'F',
'Bb',
'Eb',
'Ab',
'Db',
'Gb',
'Cb',
'G',
'D',
'A',
'E',
'B',
'F#',
'C#',
],
MINOR_KEYS: [
'Am',
'Dm',
'Gm',
'Cm',
'Fm',
'Bbm',
'Ebm',
'Abm',
'Em',
'Bm',
'F#m',
'C#m',
'G#m',
'D#m',
'A#m',
],
Start: function() {
QUnit.module('Clef Keys');
QUnit.test('Key Parser Test', VF.Test.ClefKeySignature.parser);
VF.Test.runTests('Major Key Clef Test', VF.Test.ClefKeySignature.keys, { majorKeys: true });
VF.Test.runTests('Minor Key Clef Test', VF.Test.ClefKeySignature.keys, { majorKeys: false });
VF.Test.runTests('Stave Helper', VF.Test.ClefKeySignature.staveHelper);
},
catchError: function(spec) {
try {
VF.keySignature(spec);
} catch (e) {
equal(e.code, 'BadKeySignature', e.message);
}
},
parser: function() {
expect(11);
VF.Test.ClefKeySignature.catchError('asdf');
VF.Test.ClefKeySignature.catchError('D!');
VF.Test.ClefKeySignature.catchError('E#');
VF.Test.ClefKeySignature.catchError('D#');
VF.Test.ClefKeySignature.catchError('#');
VF.Test.ClefKeySignature.catchError('b');
VF.Test.ClefKeySignature.catchError('Kb');
VF.Test.ClefKeySignature.catchError('Fb');
VF.Test.ClefKeySignature.catchError('Ab');
VF.Test.ClefKeySignature.catchError('Dbm');
VF.Test.ClefKeySignature.catchError('B#m');
VF.keySignature('B');
VF.keySignature('C');
VF.keySignature('Fm');
VF.keySignature('Ab');
VF.keySignature('Abm');
VF.keySignature('F#');
VF.keySignature('G#m');
ok(true, 'all pass');
},
keys: function(options, contextBuilder) {
var clefs = [
'treble',
'soprano',
'mezzo-soprano',
'alto',
'tenor',
'baritone-f',
'baritone-c',
'bass',
'french',
'subbass',
'percussion',
];
var ctx = new contextBuilder(options.elementId, 400, 20 + 80 * 2 * clefs.length);
var staves = [];
var keys = (options.params.majorKeys)
? VF.Test.ClefKeySignature.MAJOR_KEYS
: VF.Test.ClefKeySignature.MINOR_KEYS;
var i;
var flat;
var sharp;
var keySig;
var yOffsetForFlatStaves = 10 + 80 * clefs.length;
for (i = 0; i < clefs.length; i++) {
// Render all the sharps first, then all the flats:
staves[i] = new VF.Stave(10, 10 + 80 * i, 390);
staves[i].addClef(clefs[i]);
staves[i + clefs.length] = new VF.Stave(10, yOffsetForFlatStaves + 10 + 80 * i, 390);
staves[i + clefs.length].addClef(clefs[i]);
for (flat = 0; flat < 8; flat++) {
keySig = new VF.KeySignature(keys[flat]);
keySig.addToStave(staves[i]);
}
for (sharp = 8; sharp < keys.length; sharp++) {
keySig = new VF.KeySignature(keys[sharp]);
keySig.addToStave(staves[i + clefs.length]);
}
staves[i].setContext(ctx);
staves[i].draw();
staves[i + clefs.length].setContext(ctx);
staves[i + clefs.length].draw();
}
ok(true, 'all pass');
},
staveHelper: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 400);
var stave = new VF.Stave(10, 10, 370);
var stave2 = new VF.Stave(10, 90, 370);
var stave3 = new VF.Stave(10, 170, 370);
var stave4 = new VF.Stave(10, 260, 370);
var keys = VF.Test.ClefKeySignature.MAJOR_KEYS;
stave.addClef('treble');
stave2.addClef('bass');
stave3.addClef('alto');
stave4.addClef('tenor');
for (var n = 0; n < 8; ++n) {
stave.addKeySignature(keys[n]);
stave2.addKeySignature(keys[n]);
}
for (var i = 8; i < keys.length; ++i) {
stave3.addKeySignature(keys[i]);
stave4.addKeySignature(keys[i]);
}
stave.setContext(ctx);
stave.draw();
stave2.setContext(ctx);
stave2.draw();
stave3.setContext(ctx);
stave3.draw();
stave4.setContext(ctx);
stave4.draw();
ok(true, 'all pass');
},
};
return ClefKeySignature;
}());
/**
* VexFlow - Music Key Management Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.KeyManager = (function() {
var KeyManager = {
Start: function() {
QUnit.module('KeyManager');
test('Valid Notes', VF.Test.KeyManager.works);
test('Select Notes', VF.Test.KeyManager.selectNotes);
},
works: function() {
// expect(1);
var manager = new VF.KeyManager('g');
equal(manager.getAccidental('f').accidental, '#');
manager.setKey('a');
equal(manager.getAccidental('c').accidental, '#');
equal(manager.getAccidental('a').accidental, null);
equal(manager.getAccidental('f').accidental, '#');
manager.setKey('A');
equal(manager.getAccidental('c').accidental, '#');
equal(manager.getAccidental('a').accidental, null);
equal(manager.getAccidental('f').accidental, '#');
},
selectNotes: function() {
var manager = new VF.KeyManager('f');
equal(manager.selectNote('bb').note, 'bb');
equal(manager.selectNote('bb').accidental, 'b');
equal(manager.selectNote('g').note, 'g');
equal(manager.selectNote('g').accidental, null);
equal(manager.selectNote('b').note, 'b');
equal(manager.selectNote('b').accidental, null);
equal(manager.selectNote('a#').note, 'bb');
equal(manager.selectNote('g#').note, 'g#');
// Changes have no effect?
equal(manager.selectNote('g#').note, 'g#');
equal(manager.selectNote('bb').note, 'bb');
equal(manager.selectNote('bb').accidental, 'b');
equal(manager.selectNote('g').note, 'g');
equal(manager.selectNote('g').accidental, null);
equal(manager.selectNote('b').note, 'b');
equal(manager.selectNote('b').accidental, null);
equal(manager.selectNote('a#').note, 'bb');
equal(manager.selectNote('g#').note, 'g#');
// Changes should propagate
manager.reset();
equal(manager.selectNote('g#').change, true);
equal(manager.selectNote('g#').change, false);
equal(manager.selectNote('g').change, true);
equal(manager.selectNote('g').change, false);
equal(manager.selectNote('g#').change, true);
manager.reset();
var note = manager.selectNote('bb');
equal(note.change, false);
equal(note.accidental, 'b');
note = manager.selectNote('g');
equal(note.change, false);
equal(note.accidental, null);
note = manager.selectNote('g#');
equal(note.change, true);
equal(note.accidental, '#');
note = manager.selectNote('g');
equal(note.change, true);
equal(note.accidental, null);
note = manager.selectNote('g');
equal(note.change, false);
equal(note.accidental, null);
note = manager.selectNote('g#');
equal(note.change, true);
equal(note.accidental, '#');
},
};
return KeyManager;
})();
/**
* VexFlow - Key Signature Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.KeySignature = (function() {
function catchError(spec) {
try {
VF.keySignature(spec);
} catch (e) {
equal(e.code, 'BadKeySignature', e.message);
}
}
KeySignature = {
MAJOR_KEYS: [
'C',
'F',
'Bb',
'Eb',
'Ab',
'Db',
'Gb',
'Cb',
'G',
'D',
'A',
'E',
'B',
'F#',
'C#',
],
MINOR_KEYS: [
'Am',
'Dm',
'Gm',
'Cm',
'Fm',
'Bbm',
'Ebm',
'Abm',
'Em',
'Bm',
'F#m',
'C#m',
'G#m',
'D#m',
'A#m',
],
Start: function() {
QUnit.module('KeySignature');
test('Key Parser Test', VF.Test.KeySignature.parser);
VF.Test.runTests('Major Key Test', VF.Test.KeySignature.majorKeys);
VF.Test.runTests('Minor Key Test', VF.Test.KeySignature.minorKeys);
VF.Test.runTests('Stave Helper', VF.Test.KeySignature.staveHelper);
VF.Test.runTests('Cancelled key test', VF.Test.KeySignature.majorKeysCanceled);
VF.Test.runTests('Altered key test', VF.Test.KeySignature.majorKeysAltered);
VF.Test.runTests('Key Signature Change test', VF.Test.KeySignature.changeKey);
},
parser: function() {
expect(11);
catchError('asdf');
catchError('D!');
catchError('E#');
catchError('D#');
catchError('#');
catchError('b');
catchError('Kb');
catchError('Fb');
catchError('Ab');
catchError('Dbm');
catchError('B#m');
VF.keySignature('B');
VF.keySignature('C');
VF.keySignature('Fm');
VF.keySignature('Ab');
VF.keySignature('Abm');
VF.keySignature('F#');
VF.keySignature('G#m');
ok(true, 'all pass');
},
majorKeys: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 240);
var stave = new VF.Stave(10, 10, 350);
var stave2 = new VF.Stave(10, 90, 350);
var keys = VF.Test.KeySignature.MAJOR_KEYS;
var keySig = null;
for (var i = 0; i < 8; ++i) {
keySig = new VF.KeySignature(keys[i]);
keySig.addToStave(stave);
}
for (var n = 8; n < keys.length; ++n) {
keySig = new VF.KeySignature(keys[n]);
keySig.addToStave(stave2);
}
stave.setContext(ctx);
stave.draw();
stave2.setContext(ctx);
stave2.draw();
ok(true, 'all pass');
},
majorKeysCanceled: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 780, 500);
ctx.scale(0.9, 0.9);
var stave = new VF.Stave(10, 10, 750).addTrebleGlyph();
var stave2 = new VF.Stave(10, 90, 750).addTrebleGlyph();
var stave3 = new VF.Stave(10, 170, 750).addTrebleGlyph();
var stave4 = new VF.Stave(10, 250, 750).addTrebleGlyph();
var keys = VF.Test.KeySignature.MAJOR_KEYS;
var keySig = null;
var i;
var n;
for (i = 0; i < 8; ++i) {
keySig = new VF.KeySignature(keys[i]);
keySig.cancelKey('Cb');
keySig.padding = 18;
keySig.addToStave(stave);
}
for (n = 8; n < keys.length; ++n) {
keySig = new VF.KeySignature(keys[n]);
keySig.cancelKey('C#');
keySig.padding = 20;
keySig.addToStave(stave2);
}
for (i = 0; i < 8; ++i) {
keySig = new VF.KeySignature(keys[i]);
keySig.cancelKey('E');
keySig.padding = 18;
keySig.addToStave(stave3);
}
for (n = 8; n < keys.length; ++n) {
keySig = new VF.KeySignature(keys[n]);
keySig.cancelKey('Ab');
keySig.padding = 20;
keySig.addToStave(stave4);
}
stave.setContext(ctx);
stave.draw();
stave2.setContext(ctx);
stave2.draw();
stave3.setContext(ctx);
stave3.draw();
stave4.setContext(ctx);
stave4.draw();
ok(true, 'all pass');
},
majorKeysAltered: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 780, 500);
ctx.scale(0.9, 0.9);
var stave = new VF.Stave(10, 10, 750).addTrebleGlyph();
var stave2 = new VF.Stave(10, 90, 750).addTrebleGlyph();
var stave3 = new VF.Stave(10, 170, 750).addTrebleGlyph();
var stave4 = new VF.Stave(10, 250, 750).addTrebleGlyph();
var keys = VF.Test.KeySignature.MAJOR_KEYS;
var keySig = null;
var i;
var n;
for (i = 0; i < 8; ++i) {
keySig = new VF.KeySignature(keys[i]);
keySig.alterKey(['bs', 'bs']);
keySig.padding = 18;
keySig.addToStave(stave);
}
for (n = 8; n < keys.length; ++n) {
keySig = new VF.KeySignature(keys[n]);
keySig.alterKey(['+', '+', '+']);
keySig.padding = 20;
keySig.addToStave(stave2);
}
for (i = 0; i < 8; ++i) {
keySig = new VF.KeySignature(keys[i]);
keySig.alterKey(['n', 'bs', 'bb']);
keySig.padding = 18;
keySig.addToStave(stave3);
}
for (n = 8; n < keys.length; ++n) {
keySig = new VF.KeySignature(keys[n]);
keySig.alterKey(['++', '+', 'n', '+']);
keySig.padding = 20;
keySig.addToStave(stave4);
}
stave.setContext(ctx);
stave.draw();
stave2.setContext(ctx);
stave2.draw();
stave3.setContext(ctx);
stave3.draw();
stave4.setContext(ctx);
stave4.draw();
ok(true, 'all pass');
},
minorKeys: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 240);
var stave = new VF.Stave(10, 10, 350);
var stave2 = new VF.Stave(10, 90, 350);
var keys = VF.Test.KeySignature.MINOR_KEYS;
var keySig = null;
for (var i = 0; i < 8; ++i) {
keySig = new VF.KeySignature(keys[i]);
keySig.addToStave(stave);
}
for (var n = 8; n < keys.length; ++n) {
keySig = new VF.KeySignature(keys[n]);
keySig.addToStave(stave2);
}
stave.setContext(ctx);
stave.draw();
stave2.setContext(ctx);
stave2.draw();
ok(true, 'all pass');
},
staveHelper: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 240);
var stave = new VF.Stave(10, 10, 350);
var stave2 = new VF.Stave(10, 90, 350);
var keys = VF.Test.KeySignature.MAJOR_KEYS;
for (var i = 0; i < 8; ++i) {
stave.addKeySignature(keys[i]);
}
for (var n = 8; n < keys.length; ++n) {
stave2.addKeySignature(keys[n]);
}
stave.setContext(ctx);
stave.draw();
stave2.setContext(ctx);
stave2.draw();
ok(true, 'all pass');
},
changeKey: function(options) {
var vf = VF.Test.makeFactory(options, 900);
var stave = vf.Stave(10, 10, 800)
.addClef('treble')
.addTimeSignature('C|');
var voice = vf.Voice().setStrict(false).addTickables([
vf.KeySigNote({ key: 'Bb' }),
vf.StaveNote({ keys: ['c/4'], duration: '1' }),
vf.BarNote(),
vf.KeySigNote({ key: 'D', cancelKey: 'Bb' }),
vf.StaveNote({ keys: ['c/4'], duration: '1' }),
vf.BarNote(),
vf.KeySigNote({ key: 'Bb' }),
vf.StaveNote({ keys: ['c/4'], duration: '1' }),
vf.BarNote(),
vf.KeySigNote({ key: 'D', alterKey: ['b', 'n'] }),
vf.StaveNote({ keys: ['c/4'], duration: '1' }),
]);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'all pass');
}
};
return KeySignature;
}());
/**
* VexFlow - ModifierContext Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.ModifierContext = (function() {
var ModifierContext = {
Start: function() {
QUnit.module('ModifierContext');
test('Modifier Width Test', ModifierContext.width);
test('Modifier Management', ModifierContext.management);
},
width: function() {
var mc = new VF.ModifierContext();
equal(mc.getWidth(), 0, 'New modifier context has no width');
},
management: function() {
var mc = new VF.ModifierContext();
var modifier1 = new VF.Modifier();
var modifier2 = new VF.Modifier();
mc.addModifier(modifier1);
mc.addModifier(modifier2);
var accidentals = mc.getModifiers('none');
equal(accidentals.length, 2, 'Added two modifiers');
},
};
return ModifierContext;
})();
/**
* VexFlow - MultiMeasureRest Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.MultiMeasureRest = (function() {
return {
Start: function() {
QUnit.module('MultiMeasureRest');
VF.Test.runTests('Simple Test', VF.Test.MultiMeasureRest.simple0);
VF.Test.runTests('Stave with modifiers Test', VF.Test.MultiMeasureRest.staveWithModifiers);
},
simple0: function(options) {
const width = 910;
const vf = VF.Test.makeFactory(options, width, 300);
const params = [
{ number_of_measures: 2, show_number: false },
{ number_of_measures: 2 },
{ number_of_measures: 2, line_thickness: 8, serif_thickness: 3 },
{ number_of_measures: 1, use_symbols: true },
{ number_of_measures: 2, use_symbols: true },
{ number_of_measures: 3, use_symbols: true },
{ number_of_measures: 4, use_symbols: true },
{ number_of_measures: 5, use_symbols: true },
{ number_of_measures: 6, use_symbols: true },
{ number_of_measures: 7, use_symbols: true },
{ number_of_measures: 8, use_symbols: true },
{ number_of_measures: 9, use_symbols: true },
{ number_of_measures: 10, use_symbols: true },
{ number_of_measures: 11, use_symbols: true },
{ number_of_measures: 11, use_symbols: false, padding_left: 20, padding_right: 20 },
{ number_of_measures: 11, use_symbols: true, symbol_spacing: 5 },
{ number_of_measures: 11, use_symbols: false, line: 3, number_line: 2 },
{ number_of_measures: 11, use_symbols: true, line: 3, number_line: 2 },
[{ options: { spacing_between_lines_px: 15 } },
{ number_of_measures: 12 },
],
[{ options: { spacing_between_lines_px: 15 } },
{ number_of_measures: 9, use_symbols: true },
],
[{ options: { spacing_between_lines_px: 15 } },
{ number_of_measures: 12, spacing_between_lines_px: 15, number_glyph_point: 40 * 1.5 },
],
[{ options: { spacing_between_lines_px: 15 } },
{ number_of_measures: 9, spacing_between_lines_px: 15, use_symbols: true,
number_glyph_point: 40 * 1.5 },
],
[{ options: { spacing_between_lines_px: 15 } },
{ number_of_measures: 9, spacing_between_lines_px: 15, use_symbols: true,
number_glyph_point: 40 * 1.5,
semibrave_rest_glyph_scale: VF.DEFAULT_NOTATION_FONT_SCALE * 1.5 },
],
];
const staveWidth = 100;
var x = 0;
var y = 0;
const mmrests = params.map(function(param) {
if ((x + (staveWidth * 2)) > width) {
x = 0;
y += 80;
}
var staveParams = {};
var mmrestParams = param;
if (param.length) {
staveParams = param[0];
mmrestParams = param[1];
}
staveParams.x = x;
x += staveWidth;
staveParams.y = y;
staveParams.width = staveWidth;
const stave = vf.Stave(staveParams);
return vf.MultiMeasureRest(mmrestParams).setStave(stave);
});
vf.draw();
var xs = mmrests[0].getXs();
const strY = mmrests[0].getStave().getYForLine(-0.5);
const str = 'TACET';
const context = vf.getContext();
context.save();
context.setFont('Times', 16, 'bold');
const metrics = context.measureText('TACET');
context.fillText(str, xs.left + ((xs.right - xs.left) * 0.5) - (metrics.width * 0.5), strY);
context.restore();
ok(true, 'Simple Test');
},
staveWithModifiers: function(options) {
const width = 910;
const vf = VF.Test.makeFactory(options, width, 200);
// const stave = vf.Stave({ y: 20, width: 270 });
var x = 0;
var y = 0;
const params = [
[{ clef: 'treble', params: { width: 150 } },
{ number_of_measures: 5 },
],
[{ clef: 'treble', keySig: 'G', params: { width: 150 } },
{ number_of_measures: 5 },
],
[{ clef: 'treble', timeSig: '4/4', keySig: 'G', params: { width: 150 } },
{ number_of_measures: 5 },
],
[{ clef: 'treble', endClef: 'bass', params: { width: 150 } },
{ number_of_measures: 5 },
],
[{ clef: 'treble', endKeySig: 'F', params: { width: 150 } },
{ number_of_measures: 5 },
],
[{ clef: 'treble', endTimeSig: '2/4', params: { width: 150 } },
{ number_of_measures: 5 },
],
[{ clef: 'treble', endClef: 'bass', endTimeSig: '2/4', params: { width: 150 } },
{ number_of_measures: 5 },
],
[{ clef: 'treble', endClef: 'bass', endTimeSig: '2/4', params: { width: 150 } },
{ number_of_measures: 5, use_symbols: true },
],
];
params.map(function(param) {
const staveOptions = param[0];
const staveParams = staveOptions.params;
const mmrestParams = param[1];
if (x + staveParams.width > width) {
x = 0;
y += 80;
}
staveParams.x = x;
x += staveParams.width;
staveParams.y = y;
const stave = vf.Stave(staveParams);
if (staveOptions.clef) {
stave.addClef(staveOptions.clef);
}
if (staveOptions.timeSig) {
stave.addTimeSignature(staveOptions.timeSig);
}
if (staveOptions.keySig) {
stave.addKeySignature(staveOptions.keySig);
}
if (staveOptions.endClef) {
stave.addEndClef(staveOptions.endClef);
}
if (staveOptions.endKeySig) {
stave.setEndKeySignature(staveOptions.endKeySig);
}
if (staveOptions.endTimeSig) {
stave.setEndTimeSignature(staveOptions.endTimeSig);
}
return vf.MultiMeasureRest(mmrestParams).setStave(stave);
});
vf.draw();
ok(true, 'Stave with modifiers Test');
},
};
}());
/**
* VexFlow - Music API Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Music = (function() {
var Music = {
Start: function() {
QUnit.module('Music');
test('Valid Notes', Music.validNotes);
test('Valid Keys', Music.validKeys);
test('Note Values', Music.noteValue);
test('Interval Values', Music.intervalValue);
test('Relative Notes', Music.relativeNotes);
test('Relative Note Names', Music.relativeNoteNames);
test('Canonical Notes', Music.canonicalNotes);
test('Canonical Intervals', Music.canonicalNotes);
test('Scale Tones', Music.scaleTones);
test('Scale Intervals', Music.scaleIntervals);
},
validNotes: function() {
expect(10);
var music = new VF.Music();
var parts = music.getNoteParts('c');
equal(parts.root, 'c');
equal(parts.accidental, null);
parts = music.getNoteParts('C');
equal(parts.root, 'c');
equal(parts.accidental, null);
parts = music.getNoteParts('c#');
equal(parts.root, 'c');
equal(parts.accidental, '#');
parts = music.getNoteParts('c##');
equal(parts.root, 'c');
equal(parts.accidental, '##');
try {
music.getNoteParts('r');
} catch (e) {
equal(e.code, 'BadArguments', 'Invalid note: r');
}
try {
music.getNoteParts('');
} catch (e) {
equal(e.code, 'BadArguments', "Invalid note: ''");
}
},
validKeys: function() {
expect(18);
var music = new VF.Music();
var parts = music.getKeyParts('c');
equal(parts.root, 'c');
equal(parts.accidental, null);
equal(parts.type, 'M');
parts = music.getKeyParts('d#');
equal(parts.root, 'd');
equal(parts.accidental, '#');
equal(parts.type, 'M');
parts = music.getKeyParts('fbm');
equal(parts.root, 'f');
equal(parts.accidental, 'b');
equal(parts.type, 'm');
parts = music.getKeyParts('c#mel');
equal(parts.root, 'c');
equal(parts.accidental, '#');
equal(parts.type, 'mel');
parts = music.getKeyParts('g#harm');
equal(parts.root, 'g');
equal(parts.accidental, '#');
equal(parts.type, 'harm');
try {
music.getKeyParts('r');
} catch (e) {
equal(e.code, 'BadArguments', 'Invalid key: r');
}
try {
music.getKeyParts('');
} catch (e) {
equal(e.code, 'BadArguments', "Invalid key: ''");
}
try {
music.getKeyParts('#m');
} catch (e) {
equal(e.code, 'BadArguments', 'Invalid key: #m');
}
},
noteValue: function() {
expect(3);
var music = new VF.Music();
var note = music.getNoteValue('c');
equal(note, 0);
try {
music.getNoteValue('r');
} catch (e) {
ok(true, 'Invalid note');
}
note = music.getNoteValue('f#');
equal(note, 6);
},
intervalValue: function() {
expect(2);
var music = new VF.Music();
var value = music.getIntervalValue('b2');
equal(value, 1);
try {
music.getIntervalValue('7');
} catch (e) {
ok(true, 'Invalid note');
}
},
relativeNotes: function() {
expect(8);
var music = new VF.Music();
var value = music.getRelativeNoteValue(music.getNoteValue('c'),
music.getIntervalValue('b5'));
equal(value, 6);
try {
music.getRelativeNoteValue(music.getNoteValue('bc'),
music.getIntervalValue('b2'));
} catch (e) {
ok(true, 'Invalid note');
}
try {
music.getRelativeNoteValue(music.getNoteValue('b'),
music.getIntervalValue('p3'));
} catch (e) {
ok(true, 'Invalid interval');
}
// Direction
value = music.getRelativeNoteValue(music.getNoteValue('d'),
music.getIntervalValue('2'), -1);
equal(value, 0);
try {
music.getRelativeNoteValue(music.getNoteValue('b'),
music.getIntervalValue('p4'), 0);
} catch (e) {
ok(true, 'Invalid direction');
}
// Rollover
value = music.getRelativeNoteValue(music.getNoteValue('b'),
music.getIntervalValue('b5'));
equal(value, 5);
// Reverse rollover
value = music.getRelativeNoteValue(music.getNoteValue('c'),
music.getIntervalValue('b2'), -1);
equal(value, 11);
// Practical tests
value = music.getRelativeNoteValue(music.getNoteValue('g'),
music.getIntervalValue('p5'));
equal(value, 2);
},
relativeNoteNames: function() {
expect(9);
var music = new VF.Music();
equal(music.getRelativeNoteName('c', music.getNoteValue('c')), 'c');
equal(music.getRelativeNoteName('c', music.getNoteValue('db')), 'c#');
equal(music.getRelativeNoteName('c#', music.getNoteValue('db')), 'c#');
equal(music.getRelativeNoteName('e', music.getNoteValue('f#')), 'e##');
equal(music.getRelativeNoteName('e', music.getNoteValue('d#')), 'eb');
equal(music.getRelativeNoteName('e', music.getNoteValue('fb')), 'e');
try {
music.getRelativeNoteName('e', music.getNoteValue('g#'));
} catch (e) {
ok(true, 'Too far');
}
equal(music.getRelativeNoteName('b', music.getNoteValue('c#')), 'b##');
equal(music.getRelativeNoteName('c', music.getNoteValue('b')), 'cb');
},
canonicalNotes: function() {
expect(3);
var music = new VF.Music();
equal(music.getCanonicalNoteName(0), 'c');
equal(music.getCanonicalNoteName(2), 'd');
try {
music.getCanonicalNoteName(-1);
} catch (e) {
ok(true, 'Invalid note value');
}
},
canonicalIntervals: function() {
expect(3);
var music = new VF.Music();
equal(music.getCanonicalIntervalName(0), 'unison');
equal(music.getCanonicalIntervalName(2), 'M2');
try {
music.getCanonicalIntervalName(-1);
} catch (e) {
ok(true, 'Invalid interval value');
}
},
scaleTones: function() {
expect(24);
// C Major
var music = new VF.Music();
var manager = new VF.KeyManager('CM');
var c_major = music.getScaleTones(
music.getNoteValue('c'), VF.Music.scales.major);
var values = ['c', 'd', 'e', 'f', 'g', 'a', 'b'];
equal(c_major.length, 7);
for (var cm = 0; cm < c_major.length; ++cm) {
equal(music.getCanonicalNoteName(c_major[cm]), values[cm]);
}
// Dorian
var c_dorian = music.getScaleTones(
music.getNoteValue('c'), VF.Music.scales.dorian);
values = ['c', 'd', 'eb', 'f', 'g', 'a', 'bb'];
var note = null;
equal(c_dorian.length, 7);
for (var cd = 0; cd < c_dorian.length; ++cd) {
note = music.getCanonicalNoteName(c_dorian[cd]);
equal(manager.selectNote(note).note, values[cd]);
}
// Mixolydian
var c_mixolydian = music.getScaleTones(
music.getNoteValue('c'), VF.Music.scales.mixolydian);
values = ['c', 'd', 'e', 'f', 'g', 'a', 'bb'];
equal(c_mixolydian.length, 7);
for (var i = 0; i < c_mixolydian.length; ++i) {
note = music.getCanonicalNoteName(c_mixolydian[i]);
equal(manager.selectNote(note).note, values[i]);
}
},
scaleIntervals: function() {
expect(6);
var music = new VF.Music();
equal(music.getCanonicalIntervalName(music.getIntervalBetween(
music.getNoteValue('c'), music.getNoteValue('d'))), 'M2');
equal(music.getCanonicalIntervalName(music.getIntervalBetween(
music.getNoteValue('g'), music.getNoteValue('c'))), 'p4');
equal(music.getCanonicalIntervalName(music.getIntervalBetween(
music.getNoteValue('c'), music.getNoteValue('c'))), 'unison');
equal(music.getCanonicalIntervalName(music.getIntervalBetween(
music.getNoteValue('f'), music.getNoteValue('cb'))), 'dim5');
// Forwards and backwards
equal(music.getCanonicalIntervalName(music.getIntervalBetween(
music.getNoteValue('d'), music.getNoteValue('c'), 1)), 'b7');
equal(music.getCanonicalIntervalName(music.getIntervalBetween(
music.getNoteValue('d'), music.getNoteValue('c'), -1)), 'M2');
},
};
return Music;
})();
/**
* VexFlow - NoteHead Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.NoteHead = (function() {
var NoteHead = {
Start: function() {
QUnit.module('NoteHead');
VF.Test.runTests('Basic', VF.Test.NoteHead.basic);
VF.Test.runTests('Various Heads', VF.Test.NoteHead.variousHeads);
VF.Test.runTests('Bounding Boxes', VF.Test.NoteHead.basicBoundingBoxes);
},
setupContext: function(options, x, y) {
var ctx = new options.contextBuilder(options.elementId, x || 450, y || 140);
ctx.scale(0.9, 0.9); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
ctx.font = ' 10pt Arial';
var stave = new VF.Stave(10, 10, x || 450).addTrebleGlyph();
return { context: ctx, stave: stave };
},
showNote: function(note_struct, stave, ctx, x) {
var note = new VF.StaveNote(note_struct).setStave(stave);
new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(x);
note.setContext(ctx).draw();
return note;
},
basic: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
var c = VF.Test.NoteHead.setupContext(options, 450, 250);
c.stave = new VF.Stave(10, 0, 250).addTrebleGlyph();
c.context.scale(2.0, 2.0);
c.stave.setContext(c.context).draw();
var formatter = new VF.Formatter();
var voice = new VF.Voice(VF.TIME4_4).setStrict(false);
var note_head1 = new VF.NoteHead({
duration: '4',
line: 3,
});
var note_head2 = new VF.NoteHead({
duration: '1',
line: 2.5,
});
var note_head3 = new VF.NoteHead({
duration: '2',
line: 0,
});
voice.addTickables([note_head1, note_head2, note_head3]);
formatter.joinVoices([voice]).formatToStave([voice], c.stave);
voice.draw(c.context, c.stave);
ok('Basic NoteHead test');
},
variousHeads: function(options, contextBuilder) {
var notes = [
{ keys: ['g/5/d0'], duration: '4' },
{ keys: ['g/5/d1'], duration: '4' },
{ keys: ['g/5/d2'], duration: '4' },
{ keys: ['g/5/d3'], duration: '4' },
{ keys: ['x/'], duration: '1' },
{ keys: ['g/5/t0'], duration: '1' },
{ keys: ['g/5/t1'], duration: '4' },
{ keys: ['g/5/t2'], duration: '4' },
{ keys: ['g/5/t3'], duration: '4' },
{ keys: ['x/'], duration: '1' },
{ keys: ['g/5/x0'], duration: '1' },
{ keys: ['g/5/x1'], duration: '4' },
{ keys: ['g/5/x2'], duration: '4' },
{ keys: ['g/5/x3'], duration: '4' },
{ keys: ['x/'], duration: '1' },
{ keys: ['g/5/s1'], duration: '4' },
{ keys: ['g/5/s2'], duration: '4' },
{ keys: ['x/'], duration: '1' },
{ keys: ['g/5/r1'], duration: '4' },
{ keys: ['g/5/r2'], duration: '4' },
];
var ctx = new contextBuilder(options.elementId, notes.length * 25 + 100, 240);
// Draw two staves, one with up-stems and one with down-stems.
for (var h = 0; h < 2; ++h) {
var stave = new VF.Stave(10, 10 + h * 120, notes.length * 25 + 75)
.addClef('percussion')
.setContext(ctx)
.draw();
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
note.stem_direction = (h === 0 ? -1 : 1);
var staveNote = NoteHead.showNote(note, stave, ctx, (i + 1) * 25);
ok(staveNote.getX() > 0, 'Note ' + i + ' has X value');
ok(staveNote.getYs().length > 0, 'Note ' + i + ' has Y values');
}
}
},
basicBoundingBoxes: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
var c = VF.Test.NoteHead.setupContext(options, 350, 250);
c.stave = new VF.Stave(10, 0, 250).addTrebleGlyph();
c.context.scale(2.0, 2.0);
c.stave.setContext(c.context).draw();
var formatter = new VF.Formatter();
var voice = new VF.Voice(VF.TIME4_4).setStrict(false);
var note_head1 = new VF.NoteHead({
duration: '4',
line: 3,
});
var note_head2 = new VF.NoteHead({
duration: '2',
line: 2.5,
});
var note_head3 = new VF.NoteHead({
duration: '1',
line: 0,
});
voice.addTickables([note_head1, note_head2, note_head3]);
formatter.joinVoices([voice]).formatToStave([voice], c.stave);
voice.draw(c.context, c.stave);
note_head1.getBoundingBox().draw(c.context);
note_head2.getBoundingBox().draw(c.context);
note_head3.getBoundingBox().draw(c.context);
ok('NoteHead Bounding Boxes');
},
};
return NoteHead;
})();
/**
* VexFlow - NoteSubGroup Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*
* Author Taehoon Moon 2016
*/
VF.Test.NoteSubGroup = (function() {
var NoteSubGroup = {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('NoteSubGroup');
run('Basic - ClefNote, TimeSigNote and BarNote', VF.Test.NoteSubGroup.draw);
run('Multi Voice', VF.Test.NoteSubGroup.drawMultiVoice);
run('Multi Voice Multiple Draws', VF.Test.NoteSubGroup.drawMultiVoiceMultipleDraw);
run('Multi Staff', VF.Test.NoteSubGroup.drawMultiStaff);
},
draw: function(options) {
var vf = VF.Test.makeFactory(options, 750, 200);
var ctx = vf.getContext();
var stave = vf.Stave({ width: 600 }).addClef('treble');
var notes = [
{ keys: ['f/5'], stem_direction: -1, duration: '4' },
{ keys: ['d/4'], stem_direction: -1, duration: '4', clef: 'bass' },
{ keys: ['g/4'], stem_direction: -1, duration: '4', clef: 'alto' },
{ keys: ['a/4'], stem_direction: -1, duration: '4', clef: 'alto' },
{ keys: ['c/4'], stem_direction: -1, duration: '4', clef: 'tenor' },
{ keys: ['c/3'], stem_direction: +1, duration: '4', clef: 'tenor' },
{ keys: ['d/4'], stem_direction: -1, duration: '4', clef: 'tenor' },
{ keys: ['f/4'], stem_direction: -1, duration: '4', clef: 'tenor' },
].map(vf.StaveNote.bind(vf));
function addAccidental(note, acc) {
return note.addModifier(0, vf.Accidental({ type: acc }));
}
function addSubGroup(note, subNotes) {
return note.addModifier(0, vf.NoteSubGroup({ notes: subNotes }));
}
// {SubNotes} | {Accidental} | {StaveNote}
addAccidental(notes[1], '#');
addAccidental(notes[2], 'n');
addSubGroup(notes[1], [
vf.ClefNote({ type: 'bass', options: { size: 'small' } }),
]);
addSubGroup(notes[2], [
vf.ClefNote({ type: 'alto', options: { size: 'small' } }),
]);
addSubGroup(notes[4], [
vf.ClefNote({ type: 'tenor', options: { size: 'small' } }),
new VF.BarNote(),
]);
addSubGroup(notes[5], [
vf.TimeSigNote({ time: '6/8' }),
]);
addSubGroup(notes[6], [
new VF.BarNote(VF.Barline.type.REPEAT_BEGIN),
]);
addAccidental(notes[4], 'b');
addAccidental(notes[6], 'bb');
var voice = vf.Voice().setStrict(false).addTickables(notes);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
notes.forEach(function(note) {
Vex.Flow.Test.plotNoteWidth(ctx, note, 150);
});
Vex.Flow.Test.plotLegendForNoteWidth(ctx, 620, 120);
ok(true, 'all pass');
},
drawMultiVoice: function(options) {
var vf = VF.Test.makeFactory(options, 550, 200);
var ctx = vf.getContext();
var stave = vf.Stave().addClef('treble');
var notes1 = [
{ keys: ['f/5'], stem_direction: 1, duration: '4' },
{ keys: ['d/4'], stem_direction: 1, duration: '4', clef: 'bass' },
{ keys: ['c/5'], stem_direction: 1, duration: '4', clef: 'alto' },
{ keys: ['c/5'], stem_direction: 1, duration: '4', clef: 'soprano' },
].map(vf.StaveNote.bind(vf));
var notes2 = [
{ keys: ['c/4'], stem_direction: -1, duration: '4' },
{ keys: ['c/3'], stem_direction: -1, duration: '4', clef: 'bass' },
{ keys: ['d/4'], stem_direction: -1, duration: '4', clef: 'alto' },
{ keys: ['f/4'], stem_direction: -1, duration: '4', clef: 'soprano' },
].map(vf.StaveNote.bind(vf));
function addAccidental(note, accid) {
return note.addModifier(0, vf.Accidental({ type: accid }));
}
function addSubGroup(note, subNotes) {
return note.addModifier(0, vf.NoteSubGroup({ notes: subNotes }));
}
addAccidental(notes1[1], '#');
addSubGroup(notes1[1], [
vf.ClefNote({ type: 'bass', options: { size: 'small' } }),
new VF.BarNote(VF.Barline.type.REPEAT_BEGIN),
vf.TimeSigNote({ time: '3/4' }),
]);
addSubGroup(notes2[2], [
vf.ClefNote({ type: 'alto', options: { size: 'small' } }),
vf.TimeSigNote({ time: '9/8' }),
new VF.BarNote(VF.Barline.type.DOUBLE),
]);
addSubGroup(notes1[3], [
vf.ClefNote({ type: 'soprano', options: { size: 'small' } }),
]);
addAccidental(notes1[2], 'b');
addAccidental(notes2[3], '#');
var voices = [
vf.Voice().addTickables(notes1),
vf.Voice().addTickables(notes2),
];
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave);
vf.draw();
notes1.forEach(function(note) {
Vex.Flow.Test.plotNoteWidth(ctx, note, 150);
});
ok(true, 'all pass');
},
// draws multiple times. prevents incremental x-shift each draw.
drawMultiVoiceMultipleDraw: function(options) {
var vf = VF.Test.makeFactory(options, 550, 200);
var ctx = vf.getContext();
var stave = vf.Stave().addClef('treble');
var notes1 = [
{ keys: ['f/5'], stem_direction: 1, duration: '4' },
{ keys: ['d/4'], stem_direction: 1, duration: '4', clef: 'bass' },
{ keys: ['c/5'], stem_direction: 1, duration: '4', clef: 'alto' },
{ keys: ['c/5'], stem_direction: 1, duration: '4', clef: 'soprano' },
].map(vf.StaveNote.bind(vf));
var notes2 = [
{ keys: ['c/4'], stem_direction: -1, duration: '4' },
{ keys: ['c/3'], stem_direction: -1, duration: '4', clef: 'bass' },
{ keys: ['d/4'], stem_direction: -1, duration: '4', clef: 'alto' },
{ keys: ['f/4'], stem_direction: -1, duration: '4', clef: 'soprano' },
].map(vf.StaveNote.bind(vf));
function addAccidental(note, accid) {
return note.addModifier(0, vf.Accidental({ type: accid }));
}
function addSubGroup(note, subNotes) {
return note.addModifier(0, vf.NoteSubGroup({ notes: subNotes }));
}
addAccidental(notes1[1], '#');
addSubGroup(notes1[1], [
vf.ClefNote({ type: 'bass', options: { size: 'small' } }),
new VF.BarNote(VF.Barline.type.REPEAT_BEGIN),
vf.TimeSigNote({ time: '3/4' }),
]);
addSubGroup(notes2[2], [
vf.ClefNote({ type: 'alto', options: { size: 'small' } }),
vf.TimeSigNote({ time: '9/8' }),
new VF.BarNote(VF.Barline.type.DOUBLE),
]);
addSubGroup(notes1[3], [
vf.ClefNote({ type: 'soprano', options: { size: 'small' } }),
]);
addAccidental(notes1[2], 'b');
addAccidental(notes2[3], '#');
var voices = [
vf.Voice().addTickables(notes1),
vf.Voice().addTickables(notes2),
];
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave);
vf.draw();
vf.draw();
notes1.forEach(function(note) {
Vex.Flow.Test.plotNoteWidth(ctx, note, 150);
});
ok(true, 'all pass');
},
drawMultiStaff: function(options) {
var vf = VF.Test.makeFactory(options, 550, 400);
vf.StaveNote = vf.StaveNote.bind(vf);
var stave1 = vf.Stave({ x: 15, y: 30, width: 500 }).setClef('treble');
var notes1 = [
{ keys: ['f/5'], stem_direction: 1, duration: '4' },
{ keys: ['d/4'], stem_direction: 1, duration: '4', clef: 'bass' },
{ keys: ['c/5'], stem_direction: 1, duration: '4', clef: 'alto' },
{ keys: ['c/5'], stem_direction: 1, duration: '4', clef: 'soprano' },
].map(vf.StaveNote);
var notes2 = [
{ keys: ['c/4'], stem_direction: -1, duration: '4' },
{ keys: ['c/3'], stem_direction: -1, duration: '4', clef: 'bass' },
{ keys: ['d/4'], stem_direction: -1, duration: '4', clef: 'alto' },
{ keys: ['f/4'], stem_direction: -1, duration: '4', clef: 'soprano' },
].map(vf.StaveNote);
var stave2 = vf.Stave({ x: 15, y: 150, width: 500 }).setClef('bass');
var notes3 = [
{ keys: ['e/3'], duration: '8', stem_direction: -1, clef: 'bass' },
{ keys: ['g/4'], duration: '8', stem_direction: 1, clef: 'treble' },
{ keys: ['d/4'], duration: '8', stem_direction: 1, clef: 'treble' },
{ keys: ['f/4'], duration: '8', stem_direction: 1, clef: 'treble' },
{ keys: ['c/4'], duration: '8', stem_direction: 1, clef: 'treble' },
{ keys: ['g/3'], duration: '8', stem_direction: -1, clef: 'bass' },
{ keys: ['d/3'], duration: '8', stem_direction: -1, clef: 'bass' },
{ keys: ['f/3'], duration: '8', stem_direction: -1, clef: 'bass' },
].map(vf.StaveNote);
vf.StaveConnector({ top_stave: stave1, bottom_stave: stave2, type: 'brace' });
vf.StaveConnector({ top_stave: stave1, bottom_stave: stave2, type: 'singleLeft' });
vf.StaveConnector({ top_stave: stave1, bottom_stave: stave2, type: 'singleRight' });
function addAccidental(note, acc) {
return note.addModifier(0, vf.Accidental({ type: acc }));
}
function addSubGroup(note, subNotes) {
return note.addModifier(0, vf.NoteSubGroup({ notes: subNotes }));
}
vf.Beam({ notes: notes3.slice(1, 4) });
vf.Beam({ notes: notes3.slice(5) });
addAccidental(notes1[1], '#');
addSubGroup(notes1[1], [
vf.ClefNote({ type: 'bass', options: { size: 'small' } }),
vf.TimeSigNote({ time: '3/4' }),
]);
addSubGroup(notes2[2], [
vf.ClefNote({ type: 'alto', options: { size: 'small' } }),
vf.TimeSigNote({ time: '9/8' }),
]);
addSubGroup(notes1[3], [vf.ClefNote({ type: 'soprano', options: { size: 'small' } })]);
addSubGroup(notes3[1], [vf.ClefNote({ type: 'treble', options: { size: 'small' } })]);
addSubGroup(notes3[5], [vf.ClefNote({ type: 'bass', options: { size: 'small' } })]);
addAccidental(notes3[0], '#');
addAccidental(notes3[3], 'b');
addAccidental(notes3[5], '#');
addAccidental(notes1[2], 'b');
addAccidental(notes2[3], '#');
var voice = vf.Voice().addTickables(notes1);
var voice2 = vf.Voice().addTickables(notes2);
var voice3 = vf.Voice().addTickables(notes3);
vf.Formatter()
.joinVoices([voice, voice2])
.joinVoices([voice3])
.formatToStave([voice, voice2, voice3], stave1);
vf.draw();
ok(true, 'all pass');
},
};
return NoteSubGroup;
})();
/*
VexFlow - Ornament Tests
Copyright Mohit Cheppudira 2010 <mohit@muthanna.com>
Author: Cyril Silverman
*/
VF.Test.Ornament = (function() {
var Ornament = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('Ornament');
runTests('Ornaments', Ornament.drawOrnaments);
runTests('Ornaments Vertically Shifted', Ornament.drawOrnamentsDisplaced);
runTests('Ornaments - Delayed turns', Ornament.drawOrnamentsDelayed);
runTests('Ornaments - Delayed turns, Multiple Draws', Ornament.drawOrnamentsDelayedMultipleDraws);
runTests('Stacked', Ornament.drawOrnamentsStacked);
runTests('With Upper/Lower Accidentals', Ornament.drawOrnamentsWithAccidentals);
},
drawOrnaments: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 750, 195);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 700);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
];
notesBar1[0].addModifier(0, new VF.Ornament('mordent'));
notesBar1[1].addModifier(0, new VF.Ornament('mordent_inverted'));
notesBar1[2].addModifier(0, new VF.Ornament('turn'));
notesBar1[3].addModifier(0, new VF.Ornament('turn_inverted'));
notesBar1[4].addModifier(0, new VF.Ornament('tr'));
notesBar1[5].addModifier(0, new VF.Ornament('upprall'));
notesBar1[6].addModifier(0, new VF.Ornament('downprall'));
notesBar1[7].addModifier(0, new VF.Ornament('prallup'));
notesBar1[8].addModifier(0, new VF.Ornament('pralldown'));
notesBar1[9].addModifier(0, new VF.Ornament('upmordent'));
notesBar1[10].addModifier(0, new VF.Ornament('downmordent'));
notesBar1[11].addModifier(0, new VF.Ornament('lineprall'));
notesBar1[12].addModifier(0, new VF.Ornament('prallprall'));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
},
drawOrnamentsDisplaced: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 750, 195);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 700);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['a/5'], duration: '4', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: '4', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: '4', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: '4', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: '4', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: '4', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: '4', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
];
notesBar1[0].addModifier(0, new VF.Ornament('mordent'));
notesBar1[1].addModifier(0, new VF.Ornament('mordent_inverted'));
notesBar1[2].addModifier(0, new VF.Ornament('turn'));
notesBar1[3].addModifier(0, new VF.Ornament('turn_inverted'));
notesBar1[4].addModifier(0, new VF.Ornament('tr'));
notesBar1[5].addModifier(0, new VF.Ornament('upprall'));
notesBar1[6].addModifier(0, new VF.Ornament('downprall'));
notesBar1[7].addModifier(0, new VF.Ornament('prallup'));
notesBar1[8].addModifier(0, new VF.Ornament('pralldown'));
notesBar1[9].addModifier(0, new VF.Ornament('upmordent'));
notesBar1[10].addModifier(0, new VF.Ornament('downmordent'));
notesBar1[11].addModifier(0, new VF.Ornament('lineprall'));
notesBar1[12].addModifier(0, new VF.Ornament('prallprall'));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
},
drawOrnamentsDelayed: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 550, 195);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 500);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
];
notesBar1[0].addModifier(0, new VF.Ornament('turn').setDelayed(true));
notesBar1[1].addModifier(0, new VF.Ornament('turn_inverted').setDelayed(true));
notesBar1[2].addModifier(0, new VF.Ornament('turn_inverted').setDelayed(true));
notesBar1[3].addModifier(0, new VF.Ornament('turn').setDelayed(true));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
},
drawOrnamentsDelayedMultipleDraws: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 550, 195);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 500);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
];
notesBar1[0].addModifier(0, new VF.Ornament('turn').setDelayed(true));
notesBar1[1].addModifier(0, new VF.Ornament('turn_inverted').setDelayed(true));
notesBar1[2].addModifier(0, new VF.Ornament('turn_inverted').setDelayed(true));
notesBar1[3].addModifier(0, new VF.Ornament('turn').setDelayed(true));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
},
drawOrnamentsStacked: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 550, 195);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 500);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '4', stem_direction: 1 }),
];
notesBar1[0].addModifier(0, new VF.Ornament('mordent'));
notesBar1[1].addModifier(0, new VF.Ornament('turn_inverted'));
notesBar1[2].addModifier(0, new VF.Ornament('turn'));
notesBar1[3].addModifier(0, new VF.Ornament('turn_inverted'));
notesBar1[0].addModifier(0, new VF.Ornament('turn'));
notesBar1[1].addModifier(0, new VF.Ornament('prallup'));
notesBar1[2].addModifier(0, new VF.Ornament('upmordent'));
notesBar1[3].addModifier(0, new VF.Ornament('lineprall'));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
},
drawOrnamentsWithAccidentals: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 650, 250);
// bar 1
var staveBar1 = new VF.Stave(10, 60, 600);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }),
];
notesBar1[0].addModifier(0, new VF.Ornament('mordent').setUpperAccidental('#').setLowerAccidental('#'));
notesBar1[1].addModifier(0, new VF.Ornament('turn_inverted').setLowerAccidental('b').setUpperAccidental('b'));
notesBar1[2].addModifier(0, new VF.Ornament('turn').setUpperAccidental('##').setLowerAccidental('##'));
notesBar1[3].addModifier(0, new VF.Ornament('mordent_inverted').setLowerAccidental('db').setUpperAccidental('db'));
notesBar1[4].addModifier(0, new VF.Ornament('turn_inverted').setUpperAccidental('++').setLowerAccidental('++'));
notesBar1[5].addModifier(0, new VF.Ornament('tr').setUpperAccidental('n').setLowerAccidental('n'));
notesBar1[6].addModifier(0, new VF.Ornament('prallup').setUpperAccidental('d').setLowerAccidental('d'));
notesBar1[7].addModifier(0, new VF.Ornament('lineprall').setUpperAccidental('db').setLowerAccidental('db'));
notesBar1[8].addModifier(0, new VF.Ornament('upmordent').setUpperAccidental('bbs').setLowerAccidental('bbs'));
notesBar1[9].addModifier(0, new VF.Ornament('prallprall').setUpperAccidental('bb').setLowerAccidental('bb'));
notesBar1[10].addModifier(0, new VF.Ornament('turn_inverted').setUpperAccidental('+').setLowerAccidental('+'));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
},
};
return Ornament;
})();
/**
* VexFlow - Parser Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
Vex.Flow.Test.Parser = (function() {
var TestGrammar = function() {
return {
begin: function() { return this.BEGIN; },
BEGIN: function() { return { expect: [this.BIGORLITTLE, this.EOL] }; },
BIGORLITTLE: function() { return { expect: [this.BIGLINE, this.LITTLELINE], or: true }; },
BIGLINE: function() { return { expect: [this.LBRACE, this.WORD, this.WORDS, this.MAYBEEXCLAIM, this.RBRACE] }; },
LITTLELINE: function() { return { expect: [this.WORD, this.WORDS] }; },
WORDS: function() { return { expect: [this.COMMA, this.WORD], zeroOrMore: true }; },
MAYBEEXCLAIM: function() { return { expect: [this.EXCLAIM], maybe: true }; },
LBRACE: function() { return { token: '[{]' }; },
RBRACE: function() { return { token: '[}]' }; },
WORD: function() { return { token: '[a-zA-Z]+' }; },
COMMA: function() { return { token: '[,]' }; },
EXCLAIM: function() { return { token: '[!]' }; },
EOL: function() { return { token: '$' }; },
};
};
function assertParseFail(assert, result, expectedPos, msg) {
assert.notOk(result.success, msg);
assert.equal(result.errorPos, expectedPos, msg);
}
var Parser = {
Start: function() {
QUnit.module('Parser');
var VFT = Vex.Flow.Test;
QUnit.test('Basic', VFT.Parser.basic);
QUnit.test('Advanced', VFT.Parser.advanced);
QUnit.test('Mixed', VFT.Parser.mixed);
},
basic: function(assert) {
var grammar = new TestGrammar();
var parser = new VF.Parser(grammar);
grammar.BEGIN = function() { return { expect: [grammar.LITTLELINE, grammar.EOL] }; };
var mustPass = [
'first, second',
'first,second',
'first',
'first,second, third',
];
mustPass.forEach(function(line) { assert.equal(parser.parse(line).success, true, line); });
assertParseFail(assert, parser.parse(''), 0);
assertParseFail(assert, parser.parse('first second'), 6);
assertParseFail(assert, parser.parse('first,,'), 5);
assertParseFail(assert, parser.parse('first,'), 5);
assertParseFail(assert, parser.parse(',,'), 0);
},
advanced: function(assert) {
var grammar = new TestGrammar();
var parser = new VF.Parser(grammar);
grammar.BEGIN = function() { return { expect: [grammar.BIGLINE, grammar.EOL] }; };
var mustPass = [
'{first}',
'{first!}',
'{first,second}',
'{first,second!}',
'{first,second,third!}',
];
mustPass.forEach(function(line) { assert.equal(parser.parse(line).success, true, line); });
assertParseFail(assert, parser.parse('{first,second,third,}'), 19);
assertParseFail(assert, parser.parse('first,second,third'), 0);
assertParseFail(assert, parser.parse('{first,second,third'), 19);
assertParseFail(assert, parser.parse('{!}'), 1);
},
mixed: function(assert) {
var grammar = new TestGrammar();
var parser = new VF.Parser(grammar);
var mustPass = ['{first,second,third!}', 'first, second'];
mustPass.forEach(function(line) { assert.equal(parser.parse(line).success, true, line); });
assertParseFail(assert, parser.parse('first second'), 6);
},
};
return Parser;
})();
/**
* VexFlow - PedalMarking Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.PedalMarking = (function() {
var PedalMarking = {
test: function(makePedal) {
return function(options) {
var vf = VF.Test.makeFactory(options, 550, 200);
var score = vf.EasyScore();
var stave0 = vf.Stave({ width: 250 }).addTrebleGlyph();
var voice0 = score.voice(score.notes('b4/4, b4, b4, b4[stem="down"]', { stem: 'up' }));
vf.Formatter().joinVoices([voice0]).formatToStave([voice0], stave0);
var stave1 = vf.Stave({ width: 260, x: 250 });
var voice1 = score.voice(score.notes('c4/4, c4, c4, c4', { stem: 'up' }));
vf.Formatter().joinVoices([voice1]).formatToStave([voice1], stave1);
makePedal(vf, voice0.getTickables(), voice1.getTickables());
vf.draw();
ok(true, 'Must render');
};
},
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('PedalMarking');
var test = PedalMarking.test;
function makeSimplePedal(style) {
return function(factory, notes0, notes1) {
return factory.PedalMarking({
notes: [notes0[0], notes0[2], notes0[3], notes1[3]],
options: { style: style },
});
};
}
runTests('Simple Pedal 1', test(makeSimplePedal('text')));
runTests('Simple Pedal 2', test(makeSimplePedal('bracket')));
runTests('Simple Pedal 3', test(makeSimplePedal('mixed')));
function makeReleaseAndDepressedPedal(style) {
return function(factory, notes0, notes1) {
return factory.PedalMarking({
notes: [notes0[0], notes0[3], notes0[3], notes1[1], notes1[1], notes1[3]],
options: { style: style },
});
};
}
runTests('Release and Depress on Same Note 1', test(makeReleaseAndDepressedPedal('bracket')));
runTests('Release and Depress on Same Note 2', test(makeReleaseAndDepressedPedal('mixed')));
runTests('Custom Text 1', test(function(factory, notes0, notes1) {
var pedal = factory.PedalMarking({
notes: [notes0[0], notes1[3]],
options: { style: 'text' },
});
pedal.setCustomText('una corda', 'tre corda');
return pedal;
}));
runTests('Custom Text 2', test(function(factory, notes0, notes1) {
var pedal = factory.PedalMarking({
notes: [notes0[0], notes1[3]],
options: { style: 'mixed' },
});
pedal.setCustomText('Sost. Ped.');
return pedal;
}));
},
};
return PedalMarking;
})();
/**
* VexFlow - Percussion Tests
* Copyright Mike Corrigan 2012 <corrigan@gmail.com>
*/
function createSingleMeasureTest(setup) {
return function(options) {
var vf = VF.Test.makeFactory(options, 500);
var stave = vf.Stave().addClef('percussion');
setup(vf);
vf.Formatter()
.joinVoices(vf.getVoices())
.formatToStave(vf.getVoices(), stave);
vf.draw();
ok(true);
};
}
VF.Test.Percussion = (function() {
function showNote(note_struct, stave, ctx, x) {
var note = new VF.StaveNote(note_struct).setStave(stave);
new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(x);
note.setContext(ctx).draw();
return note;
}
var Percussion = {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('Percussion');
run('Percussion Clef', Percussion.draw);
run('Percussion Notes', Percussion.drawNotes);
run('Percussion Basic0', createSingleMeasureTest(function(vf) {
var voice0 = vf.Voice().addTickables([
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
]);
var voice1 = vf.Voice().addTickables([
vf.StaveNote({ keys: ['f/4'], duration: '8', stem_direction: -1 }),
vf.StaveNote({ keys: ['f/4'], duration: '8', stem_direction: -1 }),
vf.StaveNote({ keys: ['d/4/x2', 'c/5'], duration: '4', stem_direction: -1 }),
vf.StaveNote({ keys: ['f/4'], duration: '8', stem_direction: -1 }),
vf.StaveNote({ keys: ['f/4'], duration: '8', stem_direction: -1 }),
vf.StaveNote({ keys: ['d/4/x2', 'c/5'], duration: '4', stem_direction: -1 }),
]);
vf.Beam({ notes: voice0.getTickables() });
vf.Beam({ notes: voice1.getTickables().slice(0, 2) });
vf.Beam({ notes: voice1.getTickables().slice(3, 6) });
}));
run('Percussion Basic1', createSingleMeasureTest(function(vf) {
vf.Voice().addTickables([
vf.StaveNote({ keys: ['f/5/x2'], duration: '4' }),
vf.StaveNote({ keys: ['f/5/x2'], duration: '4' }),
vf.StaveNote({ keys: ['f/5/x2'], duration: '4' }),
vf.StaveNote({ keys: ['f/5/x2'], duration: '4' }),
]);
vf.Voice().addTickables([
vf.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: -1 }),
vf.StaveNote({ keys: ['d/4/x2', 'c/5'], duration: '4', stem_direction: -1 }),
vf.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: -1 }),
vf.StaveNote({ keys: ['d/4/x2', 'c/5'], duration: '4', stem_direction: -1 }),
]);
}));
run('Percussion Basic2', createSingleMeasureTest(function(vf) {
var voice0 = vf.Voice().addTickables([
vf.StaveNote({ keys: ['a/5/x3'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '8' }),
]);
vf.Beam({ notes: voice0.getTickables().slice(1, 8) });
var voice1 = vf.Voice().addTickables([
vf.StaveNote({ keys: ['f/4'], duration: '8', stem_direction: -1 }),
vf.StaveNote({ keys: ['f/4'], duration: '8', stem_direction: -1 }),
vf.StaveNote({ keys: ['d/4/x2', 'c/5'], duration: '4', stem_direction: -1 }),
vf.StaveNote({ keys: ['f/4'], duration: '4', stem_direction: -1 }),
vf.StaveNote({ keys: ['d/4/x2', 'c/5'], duration: '8d', stem_direction: -1 }).addDotToAll(),
vf.StaveNote({ keys: ['c/5'], duration: '16', stem_direction: -1 }),
]);
vf.Beam({ notes: voice1.getTickables().slice(0, 2) });
vf.Beam({ notes: voice1.getTickables().slice(4, 6) });
}));
run('Percussion Snare0', createSingleMeasureTest(function(vf) {
vf.Voice().addTickables([
vf.StaveNote({ keys: ['c/5'], duration: '4', stem_direction: -1 })
.addArticulation(0, vf.Articulation({ type: 'a>' }))
.addModifier(0, vf.Annotation({ text: 'L' })),
vf.StaveNote({ keys: ['c/5'], duration: '4', stem_direction: -1 })
.addModifier(0, vf.Annotation({ text: 'R' })),
vf.StaveNote({ keys: ['c/5'], duration: '4', stem_direction: -1 })
.addModifier(0, vf.Annotation({ text: 'L' })),
vf.StaveNote({ keys: ['c/5'], duration: '4', stem_direction: -1 })
.addModifier(0, vf.Annotation({ text: 'L' })),
]);
}));
run('Percussion Snare1', createSingleMeasureTest(function(vf) {
vf.Voice().addTickables([
vf.StaveNote({ keys: ['g/5/x2'], duration: '4', stem_direction: -1 })
.addArticulation(0, vf.Articulation({ type: 'ah' })),
vf.StaveNote({ keys: ['g/5/x2'], duration: '4', stem_direction: -1 }),
vf.StaveNote({ keys: ['g/5/x2'], duration: '4', stem_direction: -1 })
.addArticulation(0, vf.Articulation({ type: 'ah' })),
vf.StaveNote({ keys: ['a/5/x3'], duration: '4', stem_direction: -1 })
.addArticulation(0, vf.Articulation({ type: 'a,' })),
]);
}));
run('Percussion Snare2', createSingleMeasureTest(function(vf) {
vf.Voice().addTickables([
vf.StaveNote({ keys: ['c/5'], duration: '4', stem_direction: -1 })
.addArticulation(0, new VF.Tremolo(1)),
vf.GraceNote({ keys: ['c/5'], duration: '4', stem_direction: -1 })
.addArticulation(0, new VF.Tremolo(1)),
vf.StaveNote({ keys: ['c/5'], duration: '4', stem_direction: -1 })
.addArticulation(0, new VF.Tremolo(3)),
vf.StaveNote({ keys: ['c/5'], duration: '4', stem_direction: -1 })
.addArticulation(0, new VF.Tremolo(5)),
]);
}));
run('Percussion Snare3', createSingleMeasureTest(function(vf) {
vf.Voice().addTickables([
vf.StaveNote({ keys: ['c/5'], duration: '4', stem_direction: 1 })
.addArticulation(0, new VF.Tremolo(2)),
vf.GraceNote({ keys: ['c/5'], duration: '4', stem_direction: 1 })
.addArticulation(0, new VF.Tremolo(2)),
vf.GraceNote({ keys: ['c/5'], duration: '4', stem_direction: 1 })
.addArticulation(0, new VF.Tremolo(3)),
vf.StaveNote({ keys: ['c/5'], duration: '4', stem_direction: 1 })
.addArticulation(0, new VF.Tremolo(5)),
]);
}));
},
draw: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 120);
new VF.Stave(10, 10, 300)
.addClef('percussion')
.setContext(ctx)
.draw();
ok(true);
},
drawNotes: function(options, contextBuilder) {
var notes = [
{ keys: ['g/5/d0'], duration: '4' },
{ keys: ['g/5/d1'], duration: '4' },
{ keys: ['g/5/d2'], duration: '4' },
{ keys: ['g/5/d3'], duration: '4' },
{ keys: ['x/'], duration: '1' },
{ keys: ['g/5/t0'], duration: '1' },
{ keys: ['g/5/t1'], duration: '4' },
{ keys: ['g/5/t2'], duration: '4' },
{ keys: ['g/5/t3'], duration: '4' },
{ keys: ['x/'], duration: '1' },
{ keys: ['g/5/x0'], duration: '1' },
{ keys: ['g/5/x1'], duration: '4' },
{ keys: ['g/5/x2'], duration: '4' },
{ keys: ['g/5/x3'], duration: '4' },
];
var ctx = new contextBuilder(options.elementId, notes.length * 25 + 100, 240);
// Draw two staves, one with up-stems and one with down-stems.
for (var h = 0; h < 2; ++h) {
var stave = new VF.Stave(10, 10 + h * 120, notes.length * 25 + 75)
.addClef('percussion')
.setContext(ctx)
.draw();
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
note.stem_direction = (h === 0 ? -1 : 1);
var staveNote = showNote(note, stave, ctx, (i + 1) * 25);
ok(staveNote.getX() > 0, 'Note ' + i + ' has X value');
ok(staveNote.getYs().length > 0, 'Note ' + i + ' has Y values');
}
}
},
};
return Percussion;
})();
/**
* VexFlow - Registry Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
Vex.Flow.Test.Registry = (function() {
var Registry = {
Start: function() {
QUnit.module('Registry');
var VFT = Vex.Flow.Test;
QUnit.test('Register and Clear', VFT.Registry.registerAndClear);
QUnit.test('Default Registry', VFT.Registry.defaultRegistry);
QUnit.test('Multiple Classes', VFT.Registry.classes);
},
registerAndClear: function(assert) {
var registry = new VF.Registry();
var score = new VF.EasyScore({ factory: VF.Factory.newFromElementId(null) });
registry.register(score.notes('C4')[0], 'foobar');
var foobar = registry.getElementById('foobar');
assert.ok(foobar);
assert.equal(foobar.getAttribute('id'), 'foobar');
registry.clear();
assert.notOk(registry.getElementById('foobar'));
assert.throws(function() { registry.register(score.notes('C4')); });
registry.clear();
assert.ok(registry
.register(score.notes('C4[id="boobar"]')[0])
.getElementById('boobar'));
},
defaultRegistry: function(assert) {
var registry = new VF.Registry();
var score = new VF.EasyScore({ factory: VF.Factory.newFromElementId(null) });
VF.Registry.enableDefaultRegistry(registry);
score.notes('C4[id="foobar"]');
const note = registry.getElementById('foobar');
assert.ok(note);
note.setAttribute('id', 'boobar');
assert.ok(registry.getElementById('boobar'));
assert.notOk(registry.getElementById('foobar'));
registry.clear();
assert.equal(registry.getElementsByType('StaveNote').length, 0);
score.notes('C5');
var elements = registry.getElementsByType('StaveNote');
assert.equal(elements.length, 1);
},
classes: function(assert) {
var registry = new VF.Registry();
var score = new VF.EasyScore({ factory: VF.Factory.newFromElementId(null) });
VF.Registry.enableDefaultRegistry(registry);
score.notes('C4[id="foobar"]');
const note = registry.getElementById('foobar');
note.addClass('foo');
assert.ok(note.hasClass('foo'));
assert.notOk(note.hasClass('boo'));
assert.equal(registry.getElementsByClass('foo').length, 1);
assert.equal(registry.getElementsByClass('boo').length, 0);
note.addClass('boo');
assert.ok(note.hasClass('foo'));
assert.ok(note.hasClass('boo'));
assert.equal(registry.getElementsByClass('foo').length, 1);
assert.equal(registry.getElementsByClass('boo').length, 1);
note.removeClass('boo');
note.removeClass('foo');
assert.notOk(note.hasClass('foo'));
assert.notOk(note.hasClass('boo'));
assert.equal(registry.getElementsByClass('foo').length, 0);
assert.equal(registry.getElementsByClass('boo').length, 0);
},
};
return Registry;
}());
/**
* VexFlow - Rest Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*
*/
VF.Test.Rests = (function() {
var Rests = {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('Rests');
run('Rests - Dotted', Rests.basic);
run('Auto Align Rests - Beamed Notes Stems Up', Rests.beamsUp);
run('Auto Align Rests - Beamed Notes Stems Down', Rests.beamsDown);
run('Auto Align Rests - Tuplets Stems Up', Rests.tuplets);
run('Auto Align Rests - Tuplets Stems Down', Rests.tupletsdown);
run('Auto Align Rests - Single Voice (Default)', Rests.staveRests);
run('Auto Align Rests - Single Voice (Align All)', Rests.staveRestsAll);
run('Auto Align Rests - Multi Voice', Rests.multi);
},
setupContext: function(options, contextBuilder, x, y) {
var ctx = new contextBuilder(options.elementId, x || 350, y || 150);
ctx.scale(0.9, 0.9);
ctx.fillStyle = '#221';
ctx.strokeStyle = '#221';
ctx.font = ' 10pt Arial';
var stave = new VF.Stave(10, 30, x || 350)
.addTrebleGlyph()
.addTimeSignature('4/4')
.setContext(ctx)
.draw();
return {
context: ctx,
stave: stave,
};
},
basic: function(options, contextBuilder) {
var c = VF.Test.Rests.setupContext(options, contextBuilder, 700);
var notes = [
new VF.StaveNote({ keys: ['b/4'], stem_direction: 1, duration: 'wr' }).addDotToAll(),
new VF.StaveNote({ keys: ['b/4'], stem_direction: 1, duration: 'hr' }).addDotToAll(),
new VF.StaveNote({ keys: ['b/4'], stem_direction: 1, duration: '4r' }).addDotToAll(),
new VF.StaveNote({ keys: ['b/4'], stem_direction: 1, duration: '8r' }).addDotToAll(),
new VF.StaveNote({ keys: ['b/4'], stem_direction: 1, duration: '16r' }).addDotToAll(),
new VF.StaveNote({ keys: ['b/4'], stem_direction: 1, duration: '32r' }).addDotToAll(),
new VF.StaveNote({ keys: ['b/4'], stem_direction: 1, duration: '64r' }).addDotToAll(),
];
VF.Formatter.FormatAndDraw(c.context, c.stave, notes);
ok(true, 'Dotted Rest Test');
},
beamsUp: function(options, b) {
var c = VF.Test.Rests.setupContext(options, b, 600, 160);
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
var notes = [
newNote({ keys: ['e/5'], stem_direction: 1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '8r' }),
newNote({ keys: ['b/5'], stem_direction: 1, duration: '8' }),
newNote({ keys: ['c/5'], stem_direction: 1, duration: '8' }),
newNote({ keys: ['b/4', 'd/5', 'a/5'], stem_direction: 1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '8r' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '8r' }),
newNote({ keys: ['c/4'], stem_direction: 1, duration: '8' }),
newNote({ keys: ['b/4', 'd/5', 'a/5'], stem_direction: 1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '8r' }),
newNote({ keys: ['c/4'], stem_direction: 1, duration: '8' }),
];
var beam1 = new VF.Beam(notes.slice(0, 4));
var beam2 = new VF.Beam(notes.slice(4, 8));
var beam3 = new VF.Beam(notes.slice(8, 12));
VF.Formatter.FormatAndDraw(c.context, c.stave, notes);
beam1.setContext(c.context).draw();
beam2.setContext(c.context).draw();
beam3.setContext(c.context).draw();
ok(true, 'Auto Align Rests - Beams Up Test');
},
beamsDown: function(options, b) {
var c = VF.Test.Rests.setupContext(options, b, 600, 160);
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
var notes = [
newNote({ keys: ['a/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['b/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['c/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4', 'd/5', 'a/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['e/4'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4', 'd/5', 'a/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['e/4'], stem_direction: -1, duration: '8' }),
];
var beam1 = new VF.Beam(notes.slice(0, 4));
var beam2 = new VF.Beam(notes.slice(4, 8));
var beam3 = new VF.Beam(notes.slice(8, 12));
VF.Formatter.FormatAndDraw(c.context, c.stave, notes);
beam1.setContext(c.context).draw();
beam2.setContext(c.context).draw();
beam3.setContext(c.context).draw();
ok(true, 'Auto Align Rests - Beams Down Test');
},
tuplets: function(options, b) {
var c = VF.Test.Rests.setupContext(options, b, 600, 160);
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
var notes = [
newNote({ keys: ['b/4'], stem_direction: 1, duration: '4' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '4' }),
newNote({ keys: ['a/5'], stem_direction: 1, duration: '4r' }),
newNote({ keys: ['a/5'], stem_direction: 1, duration: '4r' }),
newNote({ keys: ['g/5'], stem_direction: 1, duration: '4r' }),
newNote({ keys: ['b/5'], stem_direction: 1, duration: '4' }),
newNote({ keys: ['a/5'], stem_direction: 1, duration: '4' }),
newNote({ keys: ['g/5'], stem_direction: 1, duration: '4r' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '4' }),
newNote({ keys: ['a/5'], stem_direction: 1, duration: '4' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '4r' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '4r' }),
];
var tuplet1 = new VF.Tuplet(notes.slice(0, 3)).setTupletLocation(VF.Tuplet.LOCATION_TOP);
var tuplet2 = new VF.Tuplet(notes.slice(3, 6)).setTupletLocation(VF.Tuplet.LOCATION_TOP);
var tuplet3 = new VF.Tuplet(notes.slice(6, 9)).setTupletLocation(VF.Tuplet.LOCATION_TOP);
var tuplet4 = new VF.Tuplet(notes.slice(9, 12)).setTupletLocation(VF.Tuplet.LOCATION_TOP);
VF.Formatter.FormatAndDraw(c.context, c.stave, notes);
tuplet1.setContext(c.context).draw();
tuplet2.setContext(c.context).draw();
tuplet3.setContext(c.context).draw();
tuplet4.setContext(c.context).draw();
ok(true, 'Auto Align Rests - Tuplets Stem Up Test');
},
tupletsdown: function(options, b) {
var c = VF.Test.Rests.setupContext(options, b, 600, 160);
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
var notes = [
newNote({ keys: ['a/5'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['g/5'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['a/5'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['g/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['a/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['g/5'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['a/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['g/5'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
];
var beam1 = new VF.Beam(notes.slice(0, 3));
var beam2 = new VF.Beam(notes.slice(3, 6));
var beam3 = new VF.Beam(notes.slice(6, 9));
var beam4 = new VF.Beam(notes.slice(9, 12));
var tuplet1 = new VF.Tuplet(notes.slice(0, 3))
.setTupletLocation(VF.Tuplet.LOCATION_BOTTOM);
var tuplet2 = new VF.Tuplet(notes.slice(3, 6))
.setTupletLocation(VF.Tuplet.LOCATION_BOTTOM);
var tuplet3 = new VF.Tuplet(notes.slice(6, 9))
.setTupletLocation(VF.Tuplet.LOCATION_BOTTOM);
var tuplet4 = new VF.Tuplet(notes.slice(9, 12))
.setTupletLocation(VF.Tuplet.LOCATION_BOTTOM);
VF.Formatter.FormatAndDraw(c.context, c.stave, notes);
tuplet1.setContext(c.context).draw();
tuplet2.setContext(c.context).draw();
tuplet3.setContext(c.context).draw();
tuplet4.setContext(c.context).draw();
beam1.setContext(c.context).draw();
beam2.setContext(c.context).draw();
beam3.setContext(c.context).draw();
beam4.setContext(c.context).draw();
ok(true, 'Auto Align Rests - Tuplets Stem Down Test');
},
staveRests: function(options, b) {
var c = VF.Test.Rests.setupContext(options, b, 600, 160);
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
var notes = [
newNote({ keys: ['b/4'], stem_direction: -1, duration: '4r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '4r' }),
newNote({ keys: ['f/4'], stem_direction: -1, duration: '4' }),
newNote({ keys: ['e/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['a/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['e/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['a/5'], stem_direction: 1, duration: '4' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '4r' }),
newNote({ keys: ['b/5'], stem_direction: 1, duration: '4' }),
newNote({ keys: ['d/5'], stem_direction: -1, duration: '4' }),
newNote({ keys: ['g/5'], stem_direction: -1, duration: '4' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '4r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '4r' }),
];
var beam1 = new VF.Beam(notes.slice(5, 9));
var tuplet = new VF.Tuplet(notes.slice(9, 12))
.setTupletLocation(VF.Tuplet.LOCATION_TOP);
VF.Formatter.FormatAndDraw(c.context, c.stave, notes);
tuplet.setContext(c.context).draw();
beam1.setContext(c.context).draw();
ok(true, 'Auto Align Rests - Default Test');
},
staveRestsAll: function(options, b) {
var c = VF.Test.Rests.setupContext(options, b, 600, 160);
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
var notes = [
newNote({ keys: ['b/4'], stem_direction: -1, duration: '4r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '4r' }),
newNote({ keys: ['f/4'], stem_direction: -1, duration: '4' }),
newNote({ keys: ['e/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['a/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['e/5'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['a/5'], stem_direction: 1, duration: '4' }),
newNote({ keys: ['b/4'], stem_direction: 1, duration: '4r' }),
newNote({ keys: ['b/5'], stem_direction: 1, duration: '4' }),
newNote({ keys: ['d/5'], stem_direction: -1, duration: '4' }),
newNote({ keys: ['g/5'], stem_direction: -1, duration: '4' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '4r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '4r' }),
];
var beam1 = new VF.Beam(notes.slice(5, 9));
var tuplet = new VF.Tuplet(notes.slice(9, 12))
.setTupletLocation(VF.Tuplet.LOCATION_TOP);
// Set option to position rests near the notes in the voice
VF.Formatter.FormatAndDraw(c.context, c.stave, notes, { align_rests: true });
tuplet.setContext(c.context).draw();
beam1.setContext(c.context).draw();
ok(true, 'Auto Align Rests - Align All Test');
},
multi: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 200);
var stave = new VF.Stave(50, 10, 500)
.addClef('treble')
.setContext(ctx)
.addTimeSignature('4/4')
.draw();
function newNote(note_struct) {
return new VF.StaveNote(note_struct).setStave(stave);
}
var notes1 = [
newNote({ keys: ['c/4', 'e/4', 'g/4'], duration: '4' }),
newNote({ keys: ['b/4'], duration: '4r' }),
newNote({ keys: ['c/4', 'd/4', 'a/4'], duration: '4' }),
newNote({ keys: ['b/4'], duration: '4r' }),
];
var notes2 = [
newNote({ keys: ['e/3'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['e/3'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['e/3'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['b/4'], stem_direction: -1, duration: '8r' }),
newNote({ keys: ['e/3'], stem_direction: -1, duration: '8' }),
newNote({ keys: ['e/3'], stem_direction: -1, duration: '8' }),
];
var voice = new VF.Voice(VF.Test.TIME4_4).addTickables(notes1);
var voice2 = new VF.Voice(VF.Test.TIME4_4).addTickables(notes2);
// Set option to position rests near the notes in each voice
new VF.Formatter()
.joinVoices([voice, voice2])
.formatToStave([voice, voice2], stave, { align_rests: true });
var beam2_1 = new VF.Beam(notes2.slice(0, 4));
var beam2_2 = new VF.Beam(notes2.slice(4, 8));
voice2.draw(ctx);
voice.draw(ctx);
beam2_1.setContext(ctx).draw();
beam2_2.setContext(ctx).draw();
ok(true, 'Strokes Test Multi Voice');
},
};
return Rests;
})();
/**
* VexFlow - Rhythm Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Rhythm = (function() {
var Rhythm = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('Rhythm');
runTests('Rhythm Draw - slash notes', Rhythm.drawBasic);
runTests('Rhythm Draw - beamed slash notes', Rhythm.drawBeamedSlashNotes);
runTests('Rhythm Draw - beamed slash notes, some rests', Rhythm.drawSlashAndBeamAndRests);
runTests('Rhythm Draw - 16th note rhythm with scratches', Rhythm.drawSixtenthWithScratches);
runTests('Rhythm Draw - 32nd note rhythm with scratches', Rhythm.drawThirtySecondWithScratches);
},
drawSlash: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 350, 180);
var stave = new VF.Stave(10, 10, 350);
stave.setContext(ctx);
stave.draw();
var showNote = VF.Test.StaveNote.showNote;
var notes = [
{ keys: ['b/4'], duration: 'ws', stem_direction: -1 },
{ keys: ['b/4'], duration: 'hs', stem_direction: -1 },
{ keys: ['b/4'], duration: 'qs', stem_direction: -1 },
{ keys: ['b/4'], duration: '8s', stem_direction: -1 },
{ keys: ['b/4'], duration: '16s', stem_direction: -1 },
{ keys: ['b/4'], duration: '32s', stem_direction: -1 },
{ keys: ['b/4'], duration: '64s', stem_direction: -1 },
];
expect(notes.length * 2);
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
var staveNote = showNote(note, stave, ctx, (i + 1) * 25);
ok(staveNote.getX() > 0, 'Note ' + i + ' has X value');
ok(staveNote.getYs().length > 0, 'Note ' + i + ' has Y values');
}
},
drawBasic: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 800, 150);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 150);
staveBar1.setBegBarType(VF.Barline.type.DOUBLE);
staveBar1.setEndBarType(VF.Barline.type.SINGLE);
staveBar1.addClef('treble');
staveBar1.addTimeSignature('4/4');
staveBar1.addKeySignature('C');
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote(
{ keys: ['b/4'], duration: '1s', stem_direction: -1 }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
// bar 2 - juxtaposing second bar next to first bar
var staveBar2 = new VF.Stave(staveBar1.width + staveBar1.x,
staveBar1.y, 120);
staveBar2.setBegBarType(VF.Barline.type.SINGLE);
staveBar2.setEndBarType(VF.Barline.type.SINGLE);
staveBar2.setContext(ctx).draw();
// bar 2
var notesBar2 = [
new VF.StaveNote(
{ keys: ['b/4'], duration: '2s', stem_direction: -1 }),
new VF.StaveNote(
{ keys: ['b/4'], duration: '2s', stem_direction: -1 }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar2, notesBar2);
// bar 3 - juxtaposing second bar next to first bar
var staveBar3 = new VF.Stave(staveBar2.width + staveBar2.x,
staveBar2.y, 170);
staveBar3.setContext(ctx).draw();
// bar 3
var notesBar3 = [
new VF.StaveNote({
keys: ['b/4'], duration: '4s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '4s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '4s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '4s',
stem_direction: -1,
}),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar3, notesBar3);
// bar 4 - juxtaposing second bar next to first bar
var staveBar4 = new VF.Stave(staveBar3.width + staveBar3.x,
staveBar3.y, 200);
staveBar4.setContext(ctx).draw();
// bar 4
var notesBar4 = [
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar4, notesBar4);
expect(0);
},
drawBeamedSlashNotes: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 800, 150);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 300);
staveBar1.setBegBarType(VF.Barline.type.DOUBLE);
staveBar1.setEndBarType(VF.Barline.type.SINGLE);
staveBar1.addClef('treble');
staveBar1.addTimeSignature('4/4');
staveBar1.addKeySignature('C');
staveBar1.setContext(ctx).draw();
// bar 4
var notesBar1_part1 = [
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
];
var notesBar1_part2 = [
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
];
// create the beams for 8th notes in 2nd measure
var beam1 = new VF.Beam(notesBar1_part1);
var beam2 = new VF.Beam(notesBar1_part2);
var notesBar1 = notesBar1_part1.concat(notesBar1_part2);
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
// Render beams
beam1.setContext(ctx).draw();
beam2.setContext(ctx).draw();
expect(0);
},
drawSlashAndBeamAndRests: function(options,
contextBuilder) {
var ctx = new contextBuilder(options.elementId, 800, 150);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 300);
staveBar1.setBegBarType(VF.Barline.type.DOUBLE);
staveBar1.setEndBarType(VF.Barline.type.SINGLE);
staveBar1.addClef('treble');
staveBar1.addTimeSignature('4/4');
staveBar1.addKeySignature('F');
staveBar1.setContext(ctx).draw();
// bar 1
var notesBar1_part1 = [
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({ keys: ['b/4'], duration: '8s', stem_direction: -1 }),
];
notesBar1_part1[0].addModifier(0, (new VF.Annotation('C7')).setFont(
'Times', VF.Test.Font.size + 2));
var notesBar1_part2 = [
new VF.StaveNote({
keys: ['b/4'], duration: '8r',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8r',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8r',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '8s',
stem_direction: -1,
}),
];
// create the beams for 8th notes in 2nd measure
var beam1 = new VF.Beam(notesBar1_part1);
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1,
notesBar1_part1.concat(notesBar1_part2));
// Render beams
beam1.setContext(ctx).draw();
// bar 2 - juxtaposing second bar next to first bar
var staveBar2 = new VF.Stave(staveBar1.width + staveBar1.x,
staveBar1.y, 220);
staveBar2.setContext(ctx).draw();
var notesBar2 = [
new VF.StaveNote({
keys: ['b/4'], duration: '1s',
stem_direction: -1,
}),
];
notesBar2[0].addModifier(0, (new VF.Annotation('F')).setFont('Times',
VF.Test.Font.size + 2));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar2, notesBar2);
expect(0);
},
drawSixtenthWithScratches: function(options,
contextBuilder) {
var ctx = new contextBuilder(options.elementId, 800, 150);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 300);
staveBar1.setBegBarType(VF.Barline.type.DOUBLE);
staveBar1.setEndBarType(VF.Barline.type.SINGLE);
staveBar1.addClef('treble');
staveBar1.addTimeSignature('4/4');
staveBar1.addKeySignature('F');
staveBar1.setContext(ctx).draw();
// bar 1
var notesBar1_part1 = [
new VF.StaveNote({
keys: ['b/4'], duration: '16s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '16s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '16m',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '16s',
stem_direction: -1,
}),
];
var notesBar1_part2 = [
new VF.StaveNote({
keys: ['b/4'], duration: '16m',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '16s',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '16r',
stem_direction: -1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '16s',
stem_direction: -1,
}),
];
notesBar1_part1[0].addModifier(0, (new VF.Annotation('C7')).setFont(
'Times', VF.Test.Font.size + 3));
// create the beams for 8th notes in 2nd measure
var beam1 = new VF.Beam(notesBar1_part1);
var beam2 = new VF.Beam(notesBar1_part2);
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1,
notesBar1_part1.concat(notesBar1_part2));
// Render beams
beam1.setContext(ctx).draw();
beam2.setContext(ctx).draw();
expect(0);
},
drawThirtySecondWithScratches: function(options,
contextBuilder) {
var ctx = new contextBuilder(options.elementId, 800, 150);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 300);
staveBar1.setBegBarType(VF.Barline.type.DOUBLE);
staveBar1.setEndBarType(VF.Barline.type.SINGLE);
staveBar1.addClef('treble');
staveBar1.addTimeSignature('4/4');
staveBar1.addKeySignature('F');
staveBar1.setContext(ctx).draw();
// bar 1
var notesBar1_part1 = [
new VF.StaveNote({
keys: ['b/4'], duration: '32s',
stem_direction: 1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '32s',
stem_direction: 1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '32m',
stem_direction: 1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '32s',
stem_direction: 1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '32m',
stem_direction: 1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '32s',
stem_direction: 1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '32r',
stem_direction: 1,
}),
new VF.StaveNote({
keys: ['b/4'], duration: '32s',
stem_direction: 1,
}),
];
notesBar1_part1[0].addModifier(0, (new VF.Annotation('C7')).setFont(
'Times', VF.Test.Font.size + 3));
// create the beams for 8th notes in 2nd measure
var beam1 = new VF.Beam(notesBar1_part1);
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1_part1);
// Render beams
beam1.setContext(ctx).draw();
expect(0);
},
};
return Rhythm;
})();
/**
* VexFlow - Basic Stave Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Stave = (function() {
var Stave = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('Stave');
test('StaveModifiers SortByCategory', Stave.sortByCategory);
runTests('Stave Draw Test', Stave.draw);
runTests('Open Stave Draw Test', Stave.drawOpenStave);
runTests('Vertical Bar Test', Stave.drawVerticalBar);
runTests('Multiple Stave Barline Test', Stave.drawMultipleMeasures);
runTests('Multiple Stave Repeats Test', Stave.drawRepeats);
runTests('Stave End Modifiers Test', Stave.drawEndModifiersTest);
runTests('Multiple Staves Volta Test', Stave.drawVoltaTest);
runTests('Tempo Test', Stave.drawTempo);
runTests('Single Line Configuration Test', Stave.configureSingleLine);
runTests('Batch Line Configuration Test', Stave.configureAllLines);
runTests('Stave Text Test', Stave.drawStaveText);
runTests('Multiple Line Stave Text Test', Stave.drawStaveTextMultiLine);
runTests('Factory API', Stave.factoryAPI);
},
sortByCategory: function() {
var stave = new VF.Stave(0, 0, 300);
var clef0 = new VF.Clef('treble');
var clef1 = new VF.Clef('alto');
var clef2 = new VF.Clef('bass');
var time0 = new VF.TimeSignature('C');
var time1 = new VF.TimeSignature('C|');
var time2 = new VF.TimeSignature('9/8');
var key0 = new VF.KeySignature('G');
var key1 = new VF.KeySignature('F');
var key2 = new VF.KeySignature('D');
var bar0 = new VF.Barline(VF.Barline.type.SINGLE);
var bar1 = new VF.Barline(VF.Barline.type.DOUBLE);
var bar2 = new VF.Barline(VF.Barline.type.NONE);
var order0 = { barlines: 0, clefs: 1, keysignatures: 2, timesignatures: 3 };
var order1 = { timesignatures: 0, keysignatures: 1, barlines: 2, clefs: 3 };
var sortAndCompare = function(title, arr, arr2, order) {
stave.sortByCategory(arr, order);
var isSame = true;
arr2.forEach(function(modifier, i) {
if (modifier !== arr[i]) isSame = false;
});
ok(isSame, title);
};
sortAndCompare(
'Keep the original order',
[bar0, bar1, clef0, clef1, key0, key1, time0, time1],
[bar0, bar1, clef0, clef1, key0, key1, time0, time1],
order0
);
sortAndCompare(
'Keep the original order 2',
[time0, time1, key0, key1, bar0, bar1, clef0, clef1],
[time0, time1, key0, key1, bar0, bar1, clef0, clef1],
order1
);
sortAndCompare(
'Sort and keep',
[bar0, bar1, clef0, clef1, key0, key1, time0, time1],
[time0, time1, key0, key1, bar0, bar1, clef0, clef1],
order1
);
sortAndCompare(
'Sort and keep 2',
[bar0, clef0, key0, time0, key1, time1, clef1, bar1, time2, clef2, bar2, key2],
[bar0, bar1, bar2, clef0, clef1, clef2, key0, key1, key2, time0, time1, time2],
order0
);
sortAndCompare(
'Sort and keep 3',
[bar2, clef2, key2, time0, key0, time2, clef1, bar1, time1, clef0, bar0, key1],
[time0, time2, time1, key2, key0, key1, bar2, bar1, bar0, clef2, clef1, clef0],
order1
);
},
draw: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 150);
var stave = new VF.Stave(10, 10, 300);
stave.setContext(ctx);
stave.draw();
equal(stave.getYForNote(0), 100, 'getYForNote(0)');
equal(stave.getYForLine(5), 100, 'getYForLine(5)');
equal(stave.getYForLine(0), 50, 'getYForLine(0) - Top Line');
equal(stave.getYForLine(4), 90, 'getYForLine(4) - Bottom Line');
ok(true, 'all pass');
},
drawOpenStave: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 350);
var stave = new VF.Stave(10, 10, 300, { left_bar: false });
stave.setContext(ctx);
stave.draw();
stave = new VF.Stave(10, 150, 300, { right_bar: false });
stave.setContext(ctx);
stave.draw();
ok(true, 'all pass');
},
drawVerticalBar: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 400, 120);
var stave = new VF.Stave(10, 10, 300);
stave.setContext(ctx);
stave.draw();
stave.drawVerticalBar(50, true);
stave.drawVerticalBar(150, false);
stave.drawVertical(250, true);
stave.drawVertical(300);
ok(true, 'all pass');
},
drawMultipleMeasures: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 550, 200);
// bar 1
var staveBar1 = new VF.Stave(10, 50, 200);
staveBar1.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
staveBar1.setEndBarType(VF.Barline.type.DOUBLE);
staveBar1.setSection('A', 0);
staveBar1.addClef('treble').setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['c/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['d/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['b/4'], duration: 'qr' }),
new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: 'q' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
// bar 2 - juxtaposing second bar next to first bar
var staveBar2 = new VF.Stave(staveBar1.width + staveBar1.x, staveBar1.y, 300);
staveBar2.setSection('B', 0);
staveBar2.setEndBarType(VF.Barline.type.END);
staveBar2.setContext(ctx).draw();
var notesBar2_part1 = [
new VF.StaveNote({ keys: ['c/4'], duration: '8' }),
new VF.StaveNote({ keys: ['d/4'], duration: '8' }),
new VF.StaveNote({ keys: ['g/4'], duration: '8' }),
new VF.StaveNote({ keys: ['e/4'], duration: '8' }),
];
var notesBar2_part2 = [
new VF.StaveNote({ keys: ['c/4'], duration: '8' }),
new VF.StaveNote({ keys: ['d/4'], duration: '8' }),
new VF.StaveNote({ keys: ['g/4'], duration: '8' }),
new VF.StaveNote({ keys: ['e/4'], duration: '8' }),
];
// create the beams for 8th notes in 2nd measure
var beam1 = new VF.Beam(notesBar2_part1);
var beam2 = new VF.Beam(notesBar2_part2);
var notesBar2 = notesBar2_part1.concat(notesBar2_part2);
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar2, notesBar2);
// Render beams
beam1.setContext(ctx).draw();
beam2.setContext(ctx).draw();
},
drawRepeats: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 750, 120);
// bar 1
var staveBar1 = new VF.Stave(10, 0, 250);
staveBar1.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
staveBar1.setEndBarType(VF.Barline.type.REPEAT_END);
staveBar1.addClef('treble');
staveBar1.addKeySignature('A');
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['c/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['d/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['b/4'], duration: 'qr' }),
new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: 'q' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
// bar 2 - juxtaposing second bar next to first bar
var staveBar2 = new VF.Stave(staveBar1.width + staveBar1.x,
staveBar1.y, 250);
staveBar2.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
staveBar2.setEndBarType(VF.Barline.type.REPEAT_END);
staveBar2.setContext(ctx).draw();
var notesBar2_part1 = [
new VF.StaveNote({ keys: ['c/4'], duration: '8' }),
new VF.StaveNote({ keys: ['d/4'], duration: '8' }),
new VF.StaveNote({ keys: ['g/4'], duration: '8' }),
new VF.StaveNote({ keys: ['e/4'], duration: '8' }),
];
var notesBar2_part2 = [
new VF.StaveNote({ keys: ['c/4'], duration: '8' }),
new VF.StaveNote({ keys: ['d/4'], duration: '8' }),
new VF.StaveNote({ keys: ['g/4'], duration: '8' }),
new VF.StaveNote({ keys: ['e/4'], duration: '8' }),
];
notesBar2_part2[0].addAccidental(0, new VF.Accidental('#'));
notesBar2_part2[1].addAccidental(0, new VF.Accidental('#'));
notesBar2_part2[3].addAccidental(0, new VF.Accidental('b'));
// create the beams for 8th notes in 2nd measure
var beam1 = new VF.Beam(notesBar2_part1);
var beam2 = new VF.Beam(notesBar2_part2);
var notesBar2 = notesBar2_part1.concat(notesBar2_part2);
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar2, notesBar2);
// Render beams
beam1.setContext(ctx).draw();
beam2.setContext(ctx).draw();
// bar 3 - juxtaposing third bar next to second bar
var staveBar3 = new VF.Stave(staveBar2.width + staveBar2.x,
staveBar2.y, 50);
staveBar3.setContext(ctx).draw();
var notesBar3 = [new VF.StaveNote({ keys: ['d/5'], duration: 'wr' })];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar3, notesBar3);
// bar 4 - juxtaposing third bar next to third bar
var staveBar4 = new VF.Stave(staveBar3.width + staveBar3.x,
staveBar3.y, 250 - staveBar1.getModifierXShift());
staveBar4.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
staveBar4.setEndBarType(VF.Barline.type.REPEAT_END);
staveBar4.setContext(ctx).draw();
var notesBar4 = [
new VF.StaveNote({ keys: ['c/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['d/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['b/4'], duration: 'qr' }),
new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: 'q' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar4, notesBar4);
},
drawEndModifiersTest: function(options, contextBuilder) {
expect(0);
var staveWidth = 230;
var blockHeight = 80;
var x = 10;
var y = 0;
function drawAStaves(endBarLine) {
function drawAStave(ctx, x, y, width, begMods, endMods) {
var staveBar = new VF.Stave(x, y, width - 10);
if (begMods) {
if (begMods.barLine !== undefined) {
staveBar.setBegBarType(begMods.barLine);
}
if (begMods.clef !== undefined) {
staveBar.addClef(begMods.clef);
}
if (begMods.keySig !== undefined) {
staveBar.addKeySignature(begMods.keySig);
}
if (begMods.timeSig !== undefined) {
staveBar.setTimeSignature(begMods.timeSig);
}
}
if (endMods) {
if (endMods.barLine !== undefined) {
staveBar.setEndBarType(endMods.barLine);
}
if (endMods.clef !== undefined) {
staveBar.addEndClef(endMods.clef);
}
if (endMods.keySig !== undefined) {
staveBar.setEndKeySignature(endMods.keySig);
}
if (endMods.timeSig !== undefined) {
staveBar.setEndTimeSignature(endMods.timeSig);
}
}
staveBar.setContext(ctx).draw();
var notesBar = [
new VF.StaveNote({ keys: ['c/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['d/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['b/4'], duration: 'qr' }),
new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: 'q' }),
];
VF.Formatter.FormatAndDraw(ctx, staveBar, notesBar);
}
drawAStave(ctx, x, y, staveWidth + 50, {
barLine: VF.Barline.type.REPEAT_BEGIN,
clef: 'treble',
keySig: 'A',
},
{
barLine: endBarLine,
clef: 'bass',
});
x += staveWidth + 50;
drawAStave(ctx, x, y, staveWidth, {
barLine: VF.Barline.type.REPEAT_BEGIN,
},
{
barLine: endBarLine,
keySig: 'E',
});
x += staveWidth;
drawAStave(ctx, x, y, staveWidth, {
barLine: VF.Barline.type.REPEAT_BEGIN,
},
{
barLine: endBarLine,
timeSig: '2/4',
});
x += staveWidth;
x = 10;
y += blockHeight;
drawAStave(ctx, x, y, staveWidth, {
barLine: VF.Barline.type.REPEAT_BEGIN,
},
{
barLine: endBarLine,
clef: 'bass',
timeSig: '2/4',
});
x += staveWidth;
drawAStave(ctx, x, y, staveWidth, {
barLine: VF.Barline.type.REPEAT_BEGIN,
},
{
barLine: endBarLine,
clef: 'treble',
keySig: 'Ab',
});
x += staveWidth;
drawAStave(ctx, x, y, staveWidth, {
barLine: VF.Barline.type.REPEAT_BEGIN,
},
{
barLine: endBarLine,
clef: 'bass',
keySig: 'Ab',
timeSig: '2/4',
});
x += staveWidth;
}
var ctx = contextBuilder(options.elementId, 800, 700);
y = 0;
x = 10;
drawAStaves(VF.Barline.type.SINGLE);
y += blockHeight + 10;
x = 10;
drawAStaves(VF.Barline.type.DOUBLE);
y += blockHeight + 10;
x = 10;
drawAStaves(VF.Barline.type.REPEAT_END);
y += blockHeight + 10;
x = 10;
drawAStaves(VF.Barline.type.REPEAT_BOTH);
},
drawVoltaTest: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 725, 200);
// bar 1
var mm1 = new VF.Stave(10, 50, 125);
mm1.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
mm1.setRepetitionTypeLeft(VF.Repetition.type.SEGNO_LEFT, -18);
mm1.addClef('treble');
mm1.addKeySignature('A');
mm1.setMeasure(1);
mm1.setSection('A', 0);
mm1.setContext(ctx).draw();
var notesmm1 = [
new VF.StaveNote({ keys: ['c/4'], duration: 'w' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, mm1, notesmm1);
// bar 2 - juxtapose second measure
var mm2 = new VF.Stave(mm1.width + mm1.x, mm1.y, 60);
mm2.setRepetitionTypeRight(VF.Repetition.type.CODA_RIGHT, 0);
mm2.setMeasure(2);
mm2.setContext(ctx).draw();
var notesmm2 = [
new VF.StaveNote({ keys: ['d/4'], duration: 'w' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, mm2, notesmm2);
// bar 3 - juxtapose third measure
var mm3 = new VF.Stave(mm2.width + mm2.x, mm1.y, 60);
mm3.setVoltaType(VF.Volta.type.BEGIN, '1.', -5);
mm3.setMeasure(3);
mm3.setContext(ctx).draw();
var notesmm3 = [
new VF.StaveNote({ keys: ['e/4'], duration: 'w' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, mm3, notesmm3);
// bar 4 - juxtapose fourth measure
var mm4 = new VF.Stave(mm3.width + mm3.x, mm1.y, 60);
mm4.setVoltaType(VF.Volta.type.MID, '', -5);
mm4.setMeasure(4);
mm4.setContext(ctx).draw();
var notesmm4 = [
new VF.StaveNote({ keys: ['f/4'], duration: 'w' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, mm4, notesmm4);
// bar 5 - juxtapose fifth measure
var mm5 = new VF.Stave(mm4.width + mm4.x, mm1.y, 60);
mm5.setEndBarType(VF.Barline.type.REPEAT_END);
mm5.setVoltaType(VF.Volta.type.END, '', -5);
mm5.setMeasure(5);
mm5.setContext(ctx).draw();
var notesmm5 = [
new VF.StaveNote({ keys: ['g/4'], duration: 'w' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, mm5, notesmm5);
// bar 6 - juxtapose sixth measure
var mm6 = new VF.Stave(mm5.width + mm5.x, mm1.y, 60);
mm6.setVoltaType(VF.Volta.type.BEGIN_END, '2.', -5);
mm6.setEndBarType(VF.Barline.type.DOUBLE);
mm6.setMeasure(6);
mm6.setContext(ctx).draw();
var notesmm6 = [
new VF.StaveNote({ keys: ['a/4'], duration: 'w' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, mm6, notesmm6);
// bar 7 - juxtapose seventh measure
var mm7 = new VF.Stave(mm6.width + mm6.x, mm1.y, 60);
mm7.setMeasure(7);
mm7.setSection('B', 0);
mm7.setContext(ctx).draw();
var notesmm7 = [
new VF.StaveNote({ keys: ['b/4'], duration: 'w' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, mm7, notesmm7);
// bar 8 - juxtapose eighth measure
var mm8 = new VF.Stave(mm7.width + mm7.x, mm1.y, 60);
mm8.setEndBarType(VF.Barline.type.DOUBLE);
mm8.setRepetitionTypeRight(VF.Repetition.type.DS_AL_CODA, 25);
mm8.setMeasure(8);
mm8.setContext(ctx).draw();
var notesmm8 = [
new VF.StaveNote({ keys: ['c/5'], duration: 'w' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, mm8, notesmm8);
// bar 9 - juxtapose ninth measure
var mm9 = new VF.Stave(mm8.width + mm8.x + 20, mm1.y, 125);
mm9.setEndBarType(VF.Barline.type.END);
mm9.setRepetitionTypeLeft(VF.Repetition.type.CODA_LEFT, 25);
mm9.addClef('treble');
mm9.addKeySignature('A');
mm9.setMeasure(9);
mm9.setContext(ctx).draw();
var notesmm9 = [
new VF.StaveNote({ keys: ['d/5'], duration: 'w' }),
];
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, mm9, notesmm9);
},
drawTempo: function(options, contextBuilder) {
expect(0);
var ctx = contextBuilder(options.elementId, 725, 350);
var padding = 10;
var x = 0;
var y = 50;
function drawTempoStaveBar(width, tempo, tempo_y, notes) {
var staveBar = new VF.Stave(padding + x, y, width);
if (x === 0) staveBar.addClef('treble');
staveBar.setTempo(tempo, tempo_y);
staveBar.setContext(ctx).draw();
var notesBar = notes || [
new VF.StaveNote({ keys: ['c/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['d/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['b/4'], duration: 'q' }),
new VF.StaveNote({ keys: ['c/4'], duration: 'q' }),
];
VF.Formatter.FormatAndDraw(ctx, staveBar, notesBar);
x += width;
}
drawTempoStaveBar(120, { duration: 'q', dots: 1, bpm: 80 }, 0);
drawTempoStaveBar(100, { duration: '8', dots: 2, bpm: 90 }, 0);
drawTempoStaveBar(100, { duration: '16', dots: 1, bpm: 96 }, 0);
drawTempoStaveBar(100, { duration: '32', bpm: 70 }, 0);
drawTempoStaveBar(250, { name: 'Andante', note: '8', bpm: 120 }, -20, [
new VF.StaveNote({ keys: ['c/4'], duration: '8' }),
new VF.StaveNote({ keys: ['d/4'], duration: '8' }),
new VF.StaveNote({ keys: ['g/4'], duration: '8' }),
new VF.StaveNote({ keys: ['e/5'], duration: '8' }),
new VF.StaveNote({ keys: ['c/4'], duration: '8' }),
new VF.StaveNote({ keys: ['d/4'], duration: '8' }),
new VF.StaveNote({ keys: ['g/4'], duration: '8' }),
new VF.StaveNote({ keys: ['e/4'], duration: '8' }),
]);
x = 0; y += 150;
drawTempoStaveBar(120, { duration: 'w', bpm: 80 }, 0);
drawTempoStaveBar(100, { duration: 'h', bpm: 90 }, 0);
drawTempoStaveBar(100, { duration: 'q', bpm: 96 }, 0);
drawTempoStaveBar(100, { duration: '8', bpm: 70 }, 0);
drawTempoStaveBar(250, { name: 'Andante grazioso' }, 0, [
new VF.StaveNote({ keys: ['c/4'], duration: '8' }),
new VF.StaveNote({ keys: ['d/4'], duration: '8' }),
new VF.StaveNote({ keys: ['g/4'], duration: '8' }),
new VF.StaveNote({ keys: ['e/4'], duration: '8' }),
new VF.StaveNote({ keys: ['c/4'], duration: '8' }),
new VF.StaveNote({ keys: ['d/4'], duration: '8' }),
new VF.StaveNote({ keys: ['g/4'], duration: '8' }),
new VF.StaveNote({ keys: ['e/4'], duration: '8' }),
]);
},
configureSingleLine: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 120);
var stave = new VF.Stave(10, 10, 300);
stave.setConfigForLine(0, { visible: true })
.setConfigForLine(1, { visible: false })
.setConfigForLine(2, { visible: true })
.setConfigForLine(3, { visible: false })
.setConfigForLine(4, { visible: true });
stave.setContext(ctx).draw();
var config = stave.getConfigForLines();
equal(config[0].visible, true, 'getLinesConfiguration() - Line 0');
equal(config[1].visible, false, 'getLinesConfiguration() - Line 1');
equal(config[2].visible, true, 'getLinesConfiguration() - Line 2');
equal(config[3].visible, false, 'getLinesConfiguration() - Line 3');
equal(config[4].visible, true, 'getLinesConfiguration() - Line 4');
ok(true, 'all pass');
},
configureAllLines: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 120);
var stave = new VF.Stave(10, 10, 300);
stave.setConfigForLines([
{ visible: false },
null,
{ visible: false },
{ visible: true },
{ visible: false },
]).setContext(ctx).draw();
var config = stave.getConfigForLines();
equal(config[0].visible, false, 'getLinesConfiguration() - Line 0');
equal(config[1].visible, true, 'getLinesConfiguration() - Line 1');
equal(config[2].visible, false, 'getLinesConfiguration() - Line 2');
equal(config[3].visible, true, 'getLinesConfiguration() - Line 3');
equal(config[4].visible, false, 'getLinesConfiguration() - Line 4');
ok(true, 'all pass');
},
drawStaveText: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 900, 140);
var stave = new VF.Stave(300, 10, 300);
stave.setText('Violin', VF.Modifier.Position.LEFT);
stave.setText('Right Text', VF.Modifier.Position.RIGHT);
stave.setText('Above Text', VF.Modifier.Position.ABOVE);
stave.setText('Below Text', VF.Modifier.Position.BELOW);
stave.setContext(ctx).draw();
ok(true, 'all pass');
},
drawStaveTextMultiLine: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 900, 200);
var stave = new VF.Stave(300, 40, 300);
stave.setText('Violin', VF.Modifier.Position.LEFT, { shift_y: -10 });
stave.setText('2nd line', VF.Modifier.Position.LEFT, { shift_y: 10 });
stave.setText('Right Text', VF.Modifier.Position.RIGHT, { shift_y: -10 });
stave.setText('2nd line', VF.Modifier.Position.RIGHT, { shift_y: 10 });
stave.setText('Above Text', VF.Modifier.Position.ABOVE, { shift_y: -10 });
stave.setText('2nd line', VF.Modifier.Position.ABOVE, { shift_y: 10 });
stave.setText('Left Below Text', VF.Modifier.Position.BELOW,
{ shift_y: -10, justification: VF.TextNote.Justification.LEFT });
stave.setText('Right Below Text', VF.Modifier.Position.BELOW,
{ shift_y: 10, justification: VF.TextNote.Justification.RIGHT });
stave.setContext(ctx).draw();
ok(true, 'all pass');
},
factoryAPI: function(options) {
var vf = VF.Test.makeFactory(options, 900, 200);
var stave = vf.Stave({ x: 300, y: 40, width: 300 });
stave.setText('Violin', VF.Modifier.Position.LEFT, { shift_y: -10 });
stave.setText('2nd line', VF.Modifier.Position.LEFT, { shift_y: 10 });
vf.draw();
ok(true, 'all pass');
},
};
return Stave;
})();
/**
* VexFlow - StaveConnector Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.StaveConnector = (function() {
var StaveConnector = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('StaveConnector');
runTests('Single Draw Test', StaveConnector.drawSingle);
runTests('Single Draw Test, 1px Stave Line Thickness', StaveConnector.drawSingle1pxBarlines);
runTests('Single Both Sides Test', StaveConnector.drawSingleBoth);
runTests('Double Draw Test', StaveConnector.drawDouble);
runTests('Bold Double Line Left Draw Test', StaveConnector.drawRepeatBegin);
runTests('Bold Double Line Right Draw Test', StaveConnector.drawRepeatEnd);
runTests('Thin Double Line Right Draw Test', StaveConnector.drawThinDouble);
runTests('Bold Double Lines Overlapping Draw Test', StaveConnector.drawRepeatAdjacent);
runTests('Bold Double Lines Offset Draw Test', StaveConnector.drawRepeatOffset);
runTests('Bold Double Lines Offset Draw Test 2', StaveConnector.drawRepeatOffset2);
runTests('Brace Draw Test', StaveConnector.drawBrace);
runTests('Brace Wide Draw Test', StaveConnector.drawBraceWide);
runTests('Bracket Draw Test', StaveConnector.drawBracket);
runTests('Combined Draw Test', StaveConnector.drawCombined);
},
drawSingle: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 300);
var stave2 = new VF.Stave(25, 120, 300);
stave.setContext(ctx);
stave2.setContext(ctx);
var connector = new VF.StaveConnector(stave, stave2);
connector.setType(VF.StaveConnector.type.SINGLE);
connector.setContext(ctx);
stave.draw();
stave2.draw();
connector.draw();
ok(true, 'all pass');
},
drawSingle1pxBarlines: function(options, contextBuilder) {
VF.STAVE_LINE_THICKNESS = 1;
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 300);
var stave2 = new VF.Stave(25, 120, 300);
stave.setContext(ctx);
stave2.setContext(ctx);
var connector = new VF.StaveConnector(stave, stave2);
connector.setType(VF.StaveConnector.type.SINGLE);
connector.setContext(ctx);
stave.draw();
stave2.draw();
connector.draw();
VF.STAVE_LINE_THICKNESS = 2;
ok(true, 'all pass');
},
drawSingleBoth: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 300);
var stave2 = new VF.Stave(25, 120, 300);
stave.setContext(ctx);
stave2.setContext(ctx);
var connector = new VF.StaveConnector(stave, stave2);
connector.setType(VF.StaveConnector.type.SINGLE_LEFT);
connector.setContext(ctx);
var connector2 = new VF.StaveConnector(stave, stave2);
connector2.setType(VF.StaveConnector.type.SINGLE_RIGHT);
connector2.setContext(ctx);
stave.draw();
stave2.draw();
connector.draw();
connector2.draw();
ok(true, 'all pass');
},
drawDouble: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 300);
var stave2 = new VF.Stave(25, 120, 300);
stave.setContext(ctx);
stave2.setContext(ctx);
var connector = new VF.StaveConnector(stave, stave2);
var line = new VF.StaveConnector(stave, stave2);
connector.setType(VF.StaveConnector.type.DOUBLE);
connector.setContext(ctx);
line.setType(VF.StaveConnector.type.SINGLE);
connector.setContext(ctx);
line.setContext(ctx);
stave.draw();
stave2.draw();
connector.draw();
line.draw();
ok(true, 'all pass');
},
drawBrace: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 450, 300);
var stave = new VF.Stave(100, 10, 300);
var stave2 = new VF.Stave(100, 120, 300);
stave.setContext(ctx);
stave2.setContext(ctx);
var connector = new VF.StaveConnector(stave, stave2);
var line = new VF.StaveConnector(stave, stave2);
connector.setType(VF.StaveConnector.type.BRACE);
connector.setContext(ctx);
connector.setText('Piano');
line.setType(VF.StaveConnector.type.SINGLE);
connector.setContext(ctx);
line.setContext(ctx);
stave.draw();
stave2.draw();
connector.draw();
line.draw();
ok(true, 'all pass');
},
drawBraceWide: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, -20, 300);
var stave2 = new VF.Stave(25, 200, 300);
stave.setContext(ctx);
stave2.setContext(ctx);
var connector = new VF.StaveConnector(stave, stave2);
var line = new VF.StaveConnector(stave, stave2);
connector.setType(VF.StaveConnector.type.BRACE);
connector.setContext(ctx);
line.setType(VF.StaveConnector.type.SINGLE);
connector.setContext(ctx);
line.setContext(ctx);
stave.draw();
stave2.draw();
connector.draw();
line.draw();
ok(true, 'all pass');
},
drawBracket: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 300);
var stave2 = new VF.Stave(25, 120, 300);
stave.setContext(ctx);
stave2.setContext(ctx);
var connector = new VF.StaveConnector(stave, stave2);
var line = new VF.StaveConnector(stave, stave2);
connector.setType(VF.StaveConnector.type.BRACKET);
connector.setContext(ctx);
line.setType(VF.StaveConnector.type.SINGLE);
connector.setContext(ctx);
line.setContext(ctx);
stave.draw();
stave2.draw();
connector.draw();
line.draw();
ok(true, 'all pass');
},
drawRepeatBegin: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 300);
var stave2 = new VF.Stave(25, 120, 300);
stave.setContext(ctx);
stave2.setContext(ctx);
stave.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave2.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
var line = new VF.StaveConnector(stave, stave2);
line.setType(VF.StaveConnector.type.BOLD_DOUBLE_LEFT);
line.setContext(ctx);
stave.draw();
stave2.draw();
line.draw();
ok(true, 'all pass');
},
drawRepeatEnd: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 300);
var stave2 = new VF.Stave(25, 120, 300);
stave.setContext(ctx);
stave2.setContext(ctx);
stave.setEndBarType(VF.Barline.type.REPEAT_END);
stave2.setEndBarType(VF.Barline.type.REPEAT_END);
var line = new VF.StaveConnector(stave, stave2);
line.setType(VF.StaveConnector.type.BOLD_DOUBLE_RIGHT);
line.setContext(ctx);
stave.draw();
stave2.draw();
line.draw();
ok(true, 'all pass');
},
drawThinDouble: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 300);
var stave2 = new VF.Stave(25, 120, 300);
stave.setContext(ctx);
stave2.setContext(ctx);
stave.setEndBarType(VF.Barline.type.DOUBLE);
stave2.setEndBarType(VF.Barline.type.DOUBLE);
var line = new VF.StaveConnector(stave, stave2);
line.setType(VF.StaveConnector.type.THIN_DOUBLE);
line.setContext(ctx);
stave.draw();
stave2.draw();
line.draw();
ok(true, 'all pass');
},
drawRepeatAdjacent: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 150);
var stave2 = new VF.Stave(25, 120, 150);
var stave3 = new VF.Stave(175, 10, 150);
var stave4 = new VF.Stave(175, 120, 150);
stave.setContext(ctx);
stave2.setContext(ctx);
stave3.setContext(ctx);
stave4.setContext(ctx);
stave.setEndBarType(VF.Barline.type.REPEAT_END);
stave2.setEndBarType(VF.Barline.type.REPEAT_END);
stave3.setEndBarType(VF.Barline.type.END);
stave4.setEndBarType(VF.Barline.type.END);
stave.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave2.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave3.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave4.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
var connector = new VF.StaveConnector(stave, stave2);
var connector2 = new VF.StaveConnector(stave, stave2);
var connector3 = new VF.StaveConnector(stave3, stave4);
var connector4 = new VF.StaveConnector(stave3, stave4);
connector.setContext(ctx);
connector2.setContext(ctx);
connector3.setContext(ctx);
connector4.setContext(ctx);
connector.setType(VF.StaveConnector.type.BOLD_DOUBLE_LEFT);
connector2.setType(VF.StaveConnector.type.BOLD_DOUBLE_RIGHT);
connector3.setType(VF.StaveConnector.type.BOLD_DOUBLE_LEFT);
connector4.setType(VF.StaveConnector.type.BOLD_DOUBLE_RIGHT);
stave.draw();
stave2.draw();
stave3.draw();
stave4.draw();
connector.draw();
connector2.draw();
connector3.draw();
connector4.draw();
ok(true, 'all pass');
},
drawRepeatOffset2: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 150);
var stave2 = new VF.Stave(25, 120, 150);
var stave3 = new VF.Stave(175, 10, 150);
var stave4 = new VF.Stave(175, 120, 150);
stave.setContext(ctx);
stave2.setContext(ctx);
stave3.setContext(ctx);
stave4.setContext(ctx);
stave.addClef('treble');
stave2.addClef('bass');
stave3.addClef('alto');
stave4.addClef('treble');
stave.addTimeSignature('4/4');
stave2.addTimeSignature('4/4');
stave3.addTimeSignature('6/8');
stave4.addTimeSignature('6/8');
stave.setEndBarType(VF.Barline.type.REPEAT_END);
stave2.setEndBarType(VF.Barline.type.REPEAT_END);
stave3.setEndBarType(VF.Barline.type.END);
stave4.setEndBarType(VF.Barline.type.END);
stave.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave2.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave3.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave4.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
var connector = new VF.StaveConnector(stave, stave2);
var connector2 = new VF.StaveConnector(stave, stave2);
var connector3 = new VF.StaveConnector(stave3, stave4);
var connector4 = new VF.StaveConnector(stave3, stave4);
var connector5 = new VF.StaveConnector(stave3, stave4);
connector.setContext(ctx);
connector2.setContext(ctx);
connector3.setContext(ctx);
connector4.setContext(ctx);
connector5.setContext(ctx);
connector.setType(VF.StaveConnector.type.BOLD_DOUBLE_LEFT);
connector2.setType(VF.StaveConnector.type.BOLD_DOUBLE_RIGHT);
connector3.setType(VF.StaveConnector.type.BOLD_DOUBLE_LEFT);
connector4.setType(VF.StaveConnector.type.BOLD_DOUBLE_RIGHT);
connector5.setType(VF.StaveConnector.type.SINGLE_LEFT);
connector.setXShift(stave.getModifierXShift());
connector3.setXShift(stave3.getModifierXShift());
stave.draw();
stave2.draw();
stave3.draw();
stave4.draw();
connector.draw();
connector2.draw();
connector3.draw();
connector4.draw();
connector5.draw();
ok(true, 'all pass');
},
drawRepeatOffset: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 300);
var stave = new VF.Stave(25, 10, 150);
var stave2 = new VF.Stave(25, 120, 150);
var stave3 = new VF.Stave(175, 10, 150);
var stave4 = new VF.Stave(175, 120, 150);
stave.setContext(ctx);
stave2.setContext(ctx);
stave3.setContext(ctx);
stave4.setContext(ctx);
stave.addClef('bass');
stave2.addClef('alto');
stave3.addClef('treble');
stave4.addClef('tenor');
stave3.addKeySignature('Ab');
stave4.addKeySignature('Ab');
stave.addTimeSignature('4/4');
stave2.addTimeSignature('4/4');
stave3.addTimeSignature('6/8');
stave4.addTimeSignature('6/8');
stave.setEndBarType(VF.Barline.type.REPEAT_END);
stave2.setEndBarType(VF.Barline.type.REPEAT_END);
stave3.setEndBarType(VF.Barline.type.END);
stave4.setEndBarType(VF.Barline.type.END);
stave.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave2.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave3.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave4.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
var connector = new VF.StaveConnector(stave, stave2);
var connector2 = new VF.StaveConnector(stave, stave2);
var connector3 = new VF.StaveConnector(stave3, stave4);
var connector4 = new VF.StaveConnector(stave3, stave4);
var connector5 = new VF.StaveConnector(stave3, stave4);
connector.setContext(ctx);
connector2.setContext(ctx);
connector3.setContext(ctx);
connector4.setContext(ctx);
connector5.setContext(ctx);
connector.setType(VF.StaveConnector.type.BOLD_DOUBLE_LEFT);
connector2.setType(VF.StaveConnector.type.BOLD_DOUBLE_RIGHT);
connector3.setType(VF.StaveConnector.type.BOLD_DOUBLE_LEFT);
connector4.setType(VF.StaveConnector.type.BOLD_DOUBLE_RIGHT);
connector5.setType(VF.StaveConnector.type.SINGLE_LEFT);
connector.setXShift(stave.getModifierXShift());
connector3.setXShift(stave3.getModifierXShift());
stave.draw();
stave2.draw();
stave3.draw();
stave4.draw();
connector.draw();
connector2.draw();
connector3.draw();
connector4.draw();
connector5.draw();
ok(true, 'all pass');
},
drawCombined: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 550, 700);
var stave = new VF.Stave(150, 10, 300);
var stave2 = new VF.Stave(150, 100, 300);
var stave3 = new VF.Stave(150, 190, 300);
var stave4 = new VF.Stave(150, 280, 300);
var stave5 = new VF.Stave(150, 370, 300);
var stave6 = new VF.Stave(150, 460, 300);
var stave7 = new VF.Stave(150, 560, 300);
stave.setText('Violin', VF.Modifier.Position.LEFT);
stave.setContext(ctx);
stave2.setContext(ctx);
stave3.setContext(ctx);
stave4.setContext(ctx);
stave5.setContext(ctx);
stave6.setContext(ctx);
stave7.setContext(ctx);
var conn_single = new VF.StaveConnector(stave, stave7);
var conn_double = new VF.StaveConnector(stave2, stave3);
var conn_bracket = new VF.StaveConnector(stave4, stave7);
var conn_none = new VF.StaveConnector(stave4, stave5);
var conn_brace = new VF.StaveConnector(stave6, stave7);
conn_single.setType(VF.StaveConnector.type.SINGLE);
conn_double.setType(VF.StaveConnector.type.DOUBLE);
conn_bracket.setType(VF.StaveConnector.type.BRACKET);
conn_brace.setType(VF.StaveConnector.type.BRACE);
conn_brace.setXShift(-5);
conn_double.setText('Piano');
conn_none.setText('Multiple', { shift_y: -15 });
conn_none.setText('Line Text', { shift_y: 15 });
conn_brace.setText('Harpsichord');
conn_single.setContext(ctx);
conn_double.setContext(ctx);
conn_bracket.setContext(ctx);
conn_none.setContext(ctx);
conn_brace.setContext(ctx);
stave.draw();
stave2.draw();
stave3.draw();
stave4.draw();
stave5.draw();
stave6.draw();
stave7.draw();
conn_single.draw();
conn_double.draw();
conn_bracket.draw();
conn_none.draw();
conn_brace.draw();
ok(true, 'all pass');
},
};
return StaveConnector;
})();
/**
* VexFlow - StaveHairpin Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
* Author: Raffaele Viglianti, 2012
*/
VF.Test.StaveHairpin = (function() {
function drawHairpin(from, to, stave, ctx, type, position, options) {
var hairpin = new VF.StaveHairpin({ first_note: from, last_note: to }, type);
hairpin.setContext(ctx);
hairpin.setPosition(position);
if (options) hairpin.setRenderOptions(options);
hairpin.draw();
}
function createTest(drawHairpins) {
return function(options) {
var vf = VF.Test.makeFactory(options);
var ctx = vf.getContext();
var stave = vf.Stave();
var notes = [
vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], stem_direction: 1, duration: '4' })
.addAccidental(0, vf.Accidental({ type: 'b' }))
.addAccidental(1, vf.Accidental({ type: '#' })),
vf.StaveNote({ keys: ['d/4'], stem_direction: 1, duration: '4' }),
vf.StaveNote({ keys: ['e/4'], stem_direction: 1, duration: '4' }),
vf.StaveNote({ keys: ['f/4'], stem_direction: 1, duration: '4' }),
];
var voice = vf.Voice().addTickables(notes);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
drawHairpins(ctx, stave, notes);
ok(true, 'Simple Test');
};
}
return {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('StaveHairpin');
run('Simple StaveHairpin', createTest(function(ctx, stave, notes) {
drawHairpin(notes[0], notes[2], stave, ctx, 1, 4);
drawHairpin(notes[1], notes[3], stave, ctx, 2, 3);
}));
run('Horizontal Offset StaveHairpin', createTest(function(ctx, stave, notes) {
drawHairpin(notes[0], notes[2], stave, ctx, 1, 3, {
height: 10,
vo: 20, // vertical offset
left_ho: 20, // left horizontal offset
right_ho: -20, // right horizontal offset
});
drawHairpin(notes[3], notes[3], stave, ctx, 2, 4, {
height: 10,
y_shift: 0, // vertical offset
left_shift_px: 0, // left horizontal offset
right_shift_px: 120, // right horizontal offset
});
}));
run('Vertical Offset StaveHairpin', createTest(function(ctx, stave, notes) {
drawHairpin(notes[0], notes[2], stave, ctx, 1, 4, {
height: 10,
y_shift: 0, // vertical offset
left_shift_px: 0, // left horizontal offset
right_shift_px: 0, // right horizontal offset
});
drawHairpin(notes[2], notes[3], stave, ctx, 2, 4, {
height: 10,
y_shift: -15, // vertical offset
left_shift_px: 2, // left horizontal offset
right_shift_px: 0, // right horizontal offset
});
}));
run('Height StaveHairpin', createTest(function(ctx, stave, notes) {
drawHairpin(notes[0], notes[2], stave, ctx, 1, 4, {
height: 10,
y_shift: 0, // vertical offset
left_shift_px: 0, // left horizontal offset
right_shift_px: 0, // right horizontal offset
});
drawHairpin(notes[2], notes[3], stave, ctx, 2, 4, {
height: 15,
y_shift: 0, // vertical offset
left_shift_px: 2, // left horizontal offset
right_shift_px: 0, // right horizontal offset
});
}));
},
};
}());
/**
* VexFlow - StaveLine Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.StaveLine = (function() {
var StaveLine = {
Start: function() {
QUnit.module('StaveLine');
VF.Test.runTests('Simple StaveLine', VF.Test.StaveLine.simple0);
VF.Test.runTests('StaveLine Arrow Options', VF.Test.StaveLine.simple1);
},
simple0: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave().addTrebleGlyph();
var notes = [
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'treble' }),
vf.StaveNote({ keys: ['c/5'], duration: '4', clef: 'treble' }),
vf.StaveNote({ keys: ['c/4', 'g/4', 'b/4'], duration: '4', clef: 'treble' }),
vf.StaveNote({ keys: ['f/4', 'a/4', 'f/5'], duration: '4', clef: 'treble' }),
];
var voice = vf.Voice().addTickables(notes);
vf.StaveLine({
from: notes[0],
to: notes[1],
first_indices: [0],
last_indices: [0],
options: {
font: { family: 'serif', size: 12, weight: 'italic' },
text: 'gliss.',
},
});
var staveLine2 = vf.StaveLine({
from: notes[2],
to: notes[3],
first_indices: [2, 1, 0],
last_indices: [0, 1, 2],
});
staveLine2.render_options.line_dash = [10, 10];
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
simple1: function(options) {
var vf = VF.Test.makeFactory(options, 770);
var stave = vf.Stave().addTrebleGlyph();
var notes = [
vf.StaveNote({ keys: ['c#/5', 'd/5'], duration: '4', clef: 'treble', stem_direction: -1 })
.addDotToAll(),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'treble' })
.addAccidental(0, vf.Accidental({ type: '#' })),
vf.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: '4', clef: 'treble' }),
vf.StaveNote({ keys: ['f/4', 'a/4', 'c/5'], duration: '4', clef: 'treble' })
.addAccidental(2, vf.Accidental({ type: '#' })),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'treble' })
.addAccidental(0, vf.Accidental({ type: '#' })),
vf.StaveNote({ keys: ['c#/5', 'd/5'], duration: '4', clef: 'treble', stem_direction: -1 }),
vf.StaveNote({ keys: ['c/4', 'd/4', 'g/4'], duration: '4', clef: 'treble' }),
vf.StaveNote({ keys: ['f/4', 'a/4', 'c/5'], duration: '4', clef: 'treble' })
.addAccidental(2, vf.Accidental({ type: '#' })),
];
var voice = vf.Voice().setStrict(false).addTickables(notes);
var staveLine0 = vf.StaveLine({
from: notes[0],
to: notes[1],
first_indices: [0],
last_indices: [0],
options: {
text: 'Left',
},
});
var staveLine4 = vf.StaveLine({
from: notes[2],
to: notes[3],
first_indices: [1],
last_indices: [1],
options: {
text: 'Right',
},
});
var staveLine1 = vf.StaveLine({
from: notes[4],
to: notes[5],
first_indices: [0],
last_indices: [0],
options: {
text: 'Center',
},
});
var staveLine2 = vf.StaveLine({
from: notes[6],
to: notes[7],
first_indices: [1],
last_indices: [0],
});
var staveLine3 = vf.StaveLine({
from: notes[6],
to: notes[7],
first_indices: [2],
last_indices: [2],
options: {
text: 'Top',
},
});
staveLine0.render_options.draw_end_arrow = true;
staveLine0.render_options.text_justification = 1;
staveLine0.render_options.text_position_vertical = 2;
staveLine1.render_options.draw_end_arrow = true;
staveLine1.render_options.arrowhead_length = 30;
staveLine1.render_options.line_width = 5;
staveLine1.render_options.text_justification = 2;
staveLine1.render_options.text_position_vertical = 2;
staveLine4.render_options.line_width = 2;
staveLine4.render_options.draw_end_arrow = true;
staveLine4.render_options.draw_start_arrow = true;
staveLine4.render_options.arrowhead_angle = 0.5;
staveLine4.render_options.arrowhead_length = 20;
staveLine4.render_options.text_justification = 3;
staveLine4.render_options.text_position_vertical = 2;
staveLine2.render_options.draw_start_arrow = true;
staveLine2.render_options.line_dash = [5, 4];
staveLine3.render_options.draw_end_arrow = true;
staveLine3.render_options.draw_start_arrow = true;
staveLine3.render_options.color = 'red';
staveLine3.render_options.text_position_vertical = 1;
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
};
return StaveLine;
}());
/**
* VexFlow - StaveModifier Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.StaveModifier = (function() {
var StaveModifier = {
Start: function() {
QUnit.module('StaveModifier');
VF.Test.runTests('Stave Draw Test', VF.Test.Stave.draw);
VF.Test.runTests('Vertical Bar Test',
VF.Test.Stave.drawVerticalBar);
VF.Test.runTests('Begin & End StaveModifier Test',
StaveModifier.drawBeginAndEnd);
},
draw: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 120);
var stave = new VF.Stave(10, 10, 300);
stave.setContext(ctx);
stave.draw();
equal(stave.getYForNote(0), 100, 'getYForNote(0)');
equal(stave.getYForLine(5), 100, 'getYForLine(5)');
equal(stave.getYForLine(0), 50, 'getYForLine(0) - Top Line');
equal(stave.getYForLine(4), 90, 'getYForLine(4) - Bottom Line');
ok(true, 'all pass');
},
drawVerticalBar: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 400, 120);
var stave = new VF.Stave(10, 10, 300);
stave.setContext(ctx);
stave.draw();
stave.drawVerticalBar(100);
stave.drawVerticalBar(150);
stave.drawVerticalBar(300);
ok(true, 'all pass');
},
drawBeginAndEnd: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 500, 240);
var stave = new VF.Stave(10, 10, 400);
stave.setContext(ctx);
stave.setTimeSignature('C|');
stave.setKeySignature('Db');
stave.setClef('treble');
stave.setBegBarType(VF.Barline.type.REPEAT_BEGIN);
stave.setEndClef('alto');
stave.setEndTimeSignature('9/8');
stave.setEndKeySignature('G', 'C#');
stave.setEndBarType(VF.Barline.type.DOUBLE);
stave.draw();
// change
var END = VF.StaveModifier.Position.END;
stave.setY(100);
stave.setTimeSignature('3/4');
stave.setKeySignature('G', 'C#');
stave.setClef('bass');
stave.setBegBarType(VF.Barline.type.SINGLE);
stave.setClef('treble', undefined, undefined, END);
stave.setTimeSignature('C', undefined, END);
stave.setKeySignature('F', undefined, END);
stave.setEndBarType(VF.Barline.type.SINGLE);
stave.draw();
ok(true, 'all pass');
},
};
return StaveModifier;
})();
/**
* VexFlow - StaveNote Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.StaveNote = (function() {
var StaveNote = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('StaveNote');
test('Tick', StaveNote.ticks);
test('Tick - New API', StaveNote.ticksNewApi);
test('Stem', StaveNote.stem);
test('Automatic Stem Direction', StaveNote.autoStem);
test('Displacement after calling setStemDirection', StaveNote.setStemDirectionDisplacement);
test('StaveLine', StaveNote.staveLine);
test('Width', StaveNote.width);
test('TickContext', StaveNote.tickContext);
VF.Test.runUITests('Interactive Mouseover StaveNote', StaveNote.draw, { clef: 'treble', octaveShift: 0, restKey: 'r/4', ui: true });
runTests('StaveNote Draw - Treble', StaveNote.draw, { clef: 'treble', octaveShift: 0, restKey: 'r/4' });
runTests('StaveNote BoundingBoxes - Treble', StaveNote.drawBoundingBoxes, { clef: 'treble', octaveShift: 0, restKey: 'r/4' });
runTests('StaveNote Draw - Alto', StaveNote.draw, { clef: 'alto', octaveShift: -1, restKey: 'r/4' });
runTests('StaveNote Draw - Tenor', StaveNote.draw, { clef: 'tenor', octaveShift: -1, restKey: 'r/3' });
runTests('StaveNote Draw - Bass', StaveNote.draw, { clef: 'bass', octaveShift: -2, restKey: 'r/3' });
runTests('StaveNote Draw - Harmonic And Muted', StaveNote.drawHarmonicAndMuted);
runTests('StaveNote Draw - Slash', StaveNote.drawSlash);
runTests('Displacements', StaveNote.displacements);
runTests('StaveNote Draw - Bass 2', StaveNote.drawBass);
runTests('StaveNote Draw - Key Styles', StaveNote.drawKeyStyles);
runTests('StaveNote Draw - StaveNote Stem Styles', StaveNote.drawNoteStemStyles);
runTests('StaveNote Draw - StaveNote Flag Styles', StaveNote.drawNoteStylesWithFlag);
runTests('StaveNote Draw - StaveNote Styles', StaveNote.drawNoteStyles);
runTests('Stave, Ledger Line, Beam, Stem and Flag Styles', StaveNote.drawBeamStyles);
runTests('Flag and Dot Placement - Stem Up', StaveNote.dotsAndFlagsStemUp);
runTests('Flag and Dots Placement - Stem Down', StaveNote.dotsAndFlagsStemDown);
runTests('Beam and Dot Placement - Stem Up', StaveNote.dotsAndBeamsUp);
runTests('Beam and Dot Placement - Stem Down', StaveNote.dotsAndBeamsDown);
runTests('Center Aligned Note', StaveNote.centerAlignedRest);
runTests('Center Aligned Note with Articulation', StaveNote.centerAlignedRestFermata);
runTests('Center Aligned Note with Annotation', StaveNote.centerAlignedRestAnnotation);
runTests('Center Aligned Note - Multi Voice', StaveNote.centerAlignedMultiVoice);
runTests('Center Aligned Note with Multiple Modifiers', StaveNote.centerAlignedNoteMultiModifiers);
},
ticks: function() {
var BEAT = 1 * VF.RESOLUTION / 4;
var tickTests = {
// Key value pairs of `testName: [durationString, expectedBeats, expectedNoteType]`
'Breve note': ['1/2', 8.0, 'n'],
'Whole note': ['w', 4.0, 'n'],
'Quarter note': ['q', 1.0, 'n'],
'Dotted half note': ['hd', 3.0, 'n'],
'Doubled-dotted half note': ['hdd', 3.5, 'n'],
'Triple-dotted half note': ['hddd', 3.75, 'n'],
'Dotted half rest': ['hdr', 3.0, 'r'],
'Double-dotted half rest': ['hddr', 3.5, 'r'],
'Triple-dotted half rest': ['hdddr', 3.75, 'r'],
'Dotted harmonic quarter note': ['qdh', 1.5, 'h'],
'Double-dotted harmonic quarter note': ['qddh', 1.75, 'h'],
'Triple-dotted harmonic quarter note': ['qdddh', 1.875, 'h'],
'Dotted muted 8th note': ['8dm', 0.75, 'm'],
'Double-dotted muted 8th note': ['8ddm', 0.875, 'm'],
'Triple-dotted muted 8th note': ['8dddm', 0.9375, 'm'],
};
Object.keys(tickTests).forEach(function(testName) {
var testData = tickTests[testName];
var durationString = testData[0];
var expectedBeats = testData[1];
var expectedNoteType = testData[2];
var note = new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: durationString });
equal(note.getTicks().value(), BEAT * expectedBeats, testName + ' must have ' + expectedBeats + ' beats');
equal(note.getNoteType(), expectedNoteType, 'Note type must be ' + expectedNoteType);
});
throws(function() {
return new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: '8.7dddm' });
}, /BadArguments/, "Invalid note duration '8.7' throws BadArguments exception");
throws(function() {
return new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: '2Z' });
}, /BadArguments/, "Invalid note type 'Z' throws BadArguments exception");
throws(function() {
return new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: '2dddZ' });
}, /BadArguments/, "Invalid note type 'Z' throws BadArguments exception");
},
ticksNewApi: function() {
var BEAT = 1 * VF.RESOLUTION / 4;
// Key value pairs of `testName: [noteData, expectedBeats, expectedNoteType]`
var tickTests = {
'Breve note': [{ duration: '1/2' }, 8.0, 'n'],
'Whole note': [{ duration: 'w' }, 4.0, 'n'],
'Quarter note': [{ duration: 'q' }, 1.0, 'n'],
'Dotted half note': [{ duration: 'h', dots: 1 }, 3.0, 'n'],
'Doubled-dotted half note': [{ duration: 'h', dots: 2 }, 3.5, 'n'],
'Triple-dotted half note': [{ duration: 'h', dots: 3 }, 3.75, 'n'],
'Dotted half rest': [{ duration: 'h', dots: 1, type: 'r' }, 3.0, 'r'],
'Double-dotted half rest': [{ duration: 'h', dots: 2, type: 'r' }, 3.5, 'r'],
'Triple-dotted half rest': [{ duration: 'h', dots: 3, type: 'r' }, 3.75, 'r'],
'Dotted harmonic quarter note': [{ duration: 'q', dots: 1, type: 'h' }, 1.5, 'h'],
'Double-dotted harmonic quarter note': [{ duration: 'q', dots: 2, type: 'h' }, 1.75, 'h'],
'Triple-dotted harmonic quarter note': [{ duration: 'q', dots: 3, type: 'h' }, 1.875, 'h'],
'Dotted muted 8th note': [{ duration: '8', dots: 1, type: 'm' }, 0.75, 'm'],
'Double-dotted muted 8th note': [{ duration: '8', dots: 2, type: 'm' }, 0.875, 'm'],
'Triple-dotted muted 8th note': [{ duration: '8', dots: 3, type: 'm' }, 0.9375, 'm'],
};
Object.keys(tickTests).forEach(function(testName) {
var testData = tickTests[testName];
var noteData = testData[0];
var expectedBeats = testData[1];
var expectedNoteType = testData[2];
noteData.keys = ['c/4', 'e/4', 'g/4'];
var note = new VF.StaveNote(noteData);
equal(note.getTicks().value(), BEAT * expectedBeats, testName + ' must have ' + expectedBeats + ' beats');
equal(note.getNoteType(), expectedNoteType, 'Note type must be ' + expectedNoteType);
});
throws(function() {
return new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: '8.7dddm' });
}, /BadArguments/, "Invalid note duration '8.7' throws BadArguments exception");
throws(function() {
return new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: '2Z' });
}, /BadArguments/, "Invalid note type 'Z' throws BadArguments exception");
throws(function() {
return new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: '2dddZ' });
}, /BadArguments/, "Invalid note type 'Z' throws BadArguments exception");
},
stem: function() {
var note = new VF.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: 'w' });
equal(note.getStemDirection(), VF.StaveNote.STEM_UP, 'Default note has UP stem');
},
autoStem: function() {
[
// [keys, expectedStemDirection]
[['c/5', 'e/5', 'g/5'], VF.StaveNote.STEM_DOWN],
[['e/4', 'g/4', 'c/5'], VF.StaveNote.STEM_UP],
[['c/5'], VF.StaveNote.STEM_DOWN],
[['a/4', 'e/5', 'g/5'], VF.StaveNote.STEM_DOWN],
[['b/4'], VF.StaveNote.STEM_DOWN],
]
.forEach(function(testData) {
var keys = testData[0];
var expectedStemDirection = testData[1];
var note = new VF.StaveNote({ keys: keys, auto_stem: true, duration: '8' });
equal(note.getStemDirection(), expectedStemDirection, 'Stem must be' + (expectedStemDirection === VF.StaveNote.STEM_UP ? 'up' : 'down'));
});
},
setStemDirectionDisplacement: function() {
function getDisplacements(note) {
return note.note_heads.map(function(notehead) {
return notehead.isDisplaced();
});
}
var stemUpDisplacements = [false, true, false];
var stemDownDisplacements = [true, false, false];
var note = new VF.StaveNote({ keys: ['c/5', 'd/5', 'g/5'], stem_direction: VF.Stem.UP, duration: '4' });
deepEqual(getDisplacements(note), stemUpDisplacements);
note.setStemDirection(VF.Stem.DOWN);
deepEqual(getDisplacements(note), stemDownDisplacements);
note.setStemDirection(VF.Stem.UP);
deepEqual(getDisplacements(note), stemUpDisplacements);
},
staveLine: function() {
var stave = new VF.Stave(10, 10, 300);
var note = new VF.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], duration: 'w' });
note.setStave(stave);
var props = note.getKeyProps();
equal(props[0].line, 0, 'C/4 on line 0');
equal(props[1].line, 1, 'E/4 on line 1');
equal(props[2].line, 2.5, 'A/4 on line 2.5');
var ys = note.getYs();
equal(ys.length, 3, 'Chord should be rendered on three lines');
equal(ys[0], 100, 'Line for C/4');
equal(ys[1], 90, 'Line for E/4');
equal(ys[2], 75, 'Line for A/4');
},
width: function() {
var note = new VF.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], duration: 'w' });
throws(function() {
note.getWidth();
}, /UnformattedNote/, 'Unformatted note should have no width');
},
tickContext: function() {
var stave = new VF.Stave(10, 10, 400);
var note = new VF.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], duration: 'w' }).setStave(stave);
var tickContext = new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(10)
.setPadding(0);
VF.Test.almostEqual(tickContext.getWidth(), 17.3815, 0.0001);
},
showNote: function(note_struct, stave, ctx, x, drawBoundingBox) {
var note = new VF.StaveNote(note_struct).setStave(stave);
new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(x);
note.setContext(ctx).draw();
if (drawBoundingBox) note.getBoundingBox().draw(ctx);
return note;
},
draw: function(options, contextBuilder) {
var clef = options.params.clef;
var octaveShift = options.params.octaveShift;
var restKey = options.params.restKey;
var ctx = new contextBuilder(options.elementId, 700, 180);
var stave = new VF.Stave(10, 30, 750);
stave.setContext(ctx);
stave.addClef(clef);
stave.draw();
var lowerKeys = ['c/', 'e/', 'a/'];
var higherKeys = ['c/', 'e/', 'a/'];
for (var k = 0; k < lowerKeys.length; k++) {
lowerKeys[k] = lowerKeys[k] + (4 + octaveShift);
higherKeys[k] = higherKeys[k] + (5 + octaveShift);
}
var restKeys = [restKey];
var showNote = VF.Test.StaveNote.showNote;
var notes = [
{ clef: clef, keys: higherKeys, duration: '1/2' },
{ clef: clef, keys: lowerKeys, duration: 'w' },
{ clef: clef, keys: higherKeys, duration: 'h' },
{ clef: clef, keys: lowerKeys, duration: 'q' },
{ clef: clef, keys: higherKeys, duration: '8' },
{ clef: clef, keys: lowerKeys, duration: '16' },
{ clef: clef, keys: higherKeys, duration: '32' },
{ clef: clef, keys: higherKeys, duration: '64' },
{ clef: clef, keys: higherKeys, duration: '128' },
{ clef: clef, keys: lowerKeys, duration: '1/2', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: 'w', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: 'h', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: 'q', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: '8', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: '16', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: '32', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: '64', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: '128', stem_direction: -1 },
{ clef: clef, keys: restKeys, duration: '1/2r' },
{ clef: clef, keys: restKeys, duration: 'wr' },
{ clef: clef, keys: restKeys, duration: 'hr' },
{ clef: clef, keys: restKeys, duration: 'qr' },
{ clef: clef, keys: restKeys, duration: '8r' },
{ clef: clef, keys: restKeys, duration: '16r' },
{ clef: clef, keys: restKeys, duration: '32r' },
{ clef: clef, keys: restKeys, duration: '64r' },
{ clef: clef, keys: restKeys, duration: '128r' },
{ keys: ['x/4'], duration: 'h' },
];
expect(notes.length * 2);
function colorDescendants(color) {
return function() {
Vex.forEach($(this).find('*'), function(child) {
child.setAttribute('fill', color);
child.setAttribute('stroke', color);
});
};
}
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
var staveNote = showNote(note, stave, ctx, (i + 1) * 25);
// If this is an interactivity test, then attempt to attach mouseover
// and mouseout handlers to the notes.
if (options.params.ui) {
var item = staveNote.getAttribute('el');
item.addEventListener('mouseover', colorDescendants('green'), false);
item.addEventListener('mouseout', colorDescendants('black'), false);
}
ok(staveNote.getX() > 0, 'Note ' + i + ' has X value');
ok(staveNote.getYs().length > 0, 'Note ' + i + ' has Y values');
}
},
drawBoundingBoxes: function(options, contextBuilder) {
var clef = options.params.clef;
var octaveShift = options.params.octaveShift;
var restKey = options.params.restKey;
var ctx = new contextBuilder(options.elementId, 700, 180);
var stave = new VF.Stave(10, 30, 750);
stave.setContext(ctx);
stave.addClef(clef);
stave.draw();
var lowerKeys = ['c/', 'e/', 'a/'];
var higherKeys = ['c/', 'e/', 'a/'];
for (var k = 0; k < lowerKeys.length; k++) {
lowerKeys[k] = lowerKeys[k] + (4 + octaveShift);
higherKeys[k] = higherKeys[k] + (5 + octaveShift);
}
var restKeys = [restKey];
var showNote = VF.Test.StaveNote.showNote;
var notes = [
{ clef: clef, keys: higherKeys, duration: '1/2' },
{ clef: clef, keys: lowerKeys, duration: 'w' },
{ clef: clef, keys: higherKeys, duration: 'h' },
{ clef: clef, keys: lowerKeys, duration: 'q' },
{ clef: clef, keys: higherKeys, duration: '8' },
{ clef: clef, keys: lowerKeys, duration: '16' },
{ clef: clef, keys: higherKeys, duration: '32' },
{ clef: clef, keys: higherKeys, duration: '64' },
{ clef: clef, keys: higherKeys, duration: '128' },
{ clef: clef, keys: lowerKeys, duration: '1/2', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: 'w', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: 'h', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: 'q', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: '8', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: '16', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: '32', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: '64', stem_direction: -1 },
{ clef: clef, keys: lowerKeys, duration: '128' },
{ clef: clef, keys: restKeys, duration: '1/2r' },
{ clef: clef, keys: restKeys, duration: 'wr' },
{ clef: clef, keys: restKeys, duration: 'hr' },
{ clef: clef, keys: restKeys, duration: 'qr' },
{ clef: clef, keys: restKeys, duration: '8r' },
{ clef: clef, keys: restKeys, duration: '16r' },
{ clef: clef, keys: restKeys, duration: '32r' },
{ clef: clef, keys: restKeys, duration: '64r' },
{ clef: clef, keys: restKeys, duration: '128r' },
{ keys: ['x/4'], duration: 'h' },
];
expect(notes.length * 2);
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
var staveNote = showNote(note, stave, ctx, (i + 1) * 25, true);
ok(staveNote.getX() > 0, 'Note ' + i + ' has X value');
ok(staveNote.getYs().length > 0, 'Note ' + i + ' has Y values');
}
},
drawBass: function(options, contextBuilder) {
expect(40);
var ctx = new contextBuilder(options.elementId, 600, 280);
var stave = new VF.Stave(10, 10, 650);
stave.setContext(ctx);
stave.addClef('bass');
stave.draw();
var showNote = VF.Test.StaveNote.showNote;
var notes = [
{ clef: 'bass', keys: ['c/3', 'e/3', 'a/3'], duration: '1/2' },
{ clef: 'bass', keys: ['c/2', 'e/2', 'a/2'], duration: 'w' },
{ clef: 'bass', keys: ['c/3', 'e/3', 'a/3'], duration: 'h' },
{ clef: 'bass', keys: ['c/2', 'e/2', 'a/2'], duration: 'q' },
{ clef: 'bass', keys: ['c/3', 'e/3', 'a/3'], duration: '8' },
{ clef: 'bass', keys: ['c/2', 'e/2', 'a/2'], duration: '16' },
{ clef: 'bass', keys: ['c/3', 'e/3', 'a/3'], duration: '32' },
{ clef: 'bass', keys: ['c/2', 'e/2', 'a/2'], duration: 'h', stem_direction: -1 },
{ clef: 'bass', keys: ['c/2', 'e/2', 'a/2'], duration: 'q', stem_direction: -1 },
{ clef: 'bass', keys: ['c/2', 'e/2', 'a/2'], duration: '8', stem_direction: -1 },
{ clef: 'bass', keys: ['c/2', 'e/2', 'a/2'], duration: '16', stem_direction: -1 },
{ clef: 'bass', keys: ['c/2', 'e/2', 'a/2'], duration: '32', stem_direction: -1 },
{ keys: ['r/4'], duration: '1/2r' },
{ keys: ['r/4'], duration: 'wr' },
{ keys: ['r/4'], duration: 'hr' },
{ keys: ['r/4'], duration: 'qr' },
{ keys: ['r/4'], duration: '8r' },
{ keys: ['r/4'], duration: '16r' },
{ keys: ['r/4'], duration: '32r' },
{ keys: ['x/4'], duration: 'h' },
];
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
var staveNote = showNote(note, stave, ctx, (i + 1) * 25);
ok(staveNote.getX() > 0, 'Note ' + i + ' has X value');
ok(staveNote.getYs().length > 0, 'Note ' + i + ' has Y values');
}
},
displacements: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 700, 140);
ctx.scale(0.9, 0.9);
ctx.fillStyle = '#221';
ctx.strokeStyle = '#221';
var stave = new VF.Stave(10, 10, 650);
stave.setContext(ctx);
stave.draw();
var showNote = VF.Test.StaveNote.showNote;
var notes = [
{ keys: ['g/3', 'a/3', 'c/4', 'd/4', 'e/4'], duration: '1/2' },
{ keys: ['g/3', 'a/3', 'c/4', 'd/4', 'e/4'], duration: 'w' },
{ keys: ['d/4', 'e/4', 'f/4'], duration: 'h' },
{ keys: ['f/4', 'g/4', 'a/4', 'b/4'], duration: 'q' },
{ keys: ['e/3', 'b/3', 'c/4', 'e/4', 'f/4', 'g/5', 'a/5'], duration: '8' },
{ keys: ['a/3', 'c/4', 'e/4', 'g/4', 'a/4', 'b/4'], duration: '16' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '32' },
{ keys: ['c/4', 'e/4', 'a/4', 'a/4'], duration: '64' },
{ keys: ['g/3', 'c/4', 'd/4', 'e/4'], duration: 'h', stem_direction: -1 },
{ keys: ['d/4', 'e/4', 'f/4'], duration: 'q', stem_direction: -1 },
{ keys: ['f/4', 'g/4', 'a/4', 'b/4'], duration: '8', stem_direction: -1 },
{ keys: ['c/4', 'd/4', 'e/4', 'f/4', 'g/4', 'a/4'], duration: '16', stem_direction: -1 },
{ keys: ['b/3', 'c/4', 'e/4', 'a/4', 'b/5', 'c/6', 'e/6'], duration: '32', stem_direction: -1 },
{ keys: ['b/3', 'c/4', 'e/4', 'a/4', 'b/5', 'c/6', 'e/6', 'e/6'], duration: '64', stem_direction: -1 },
];
expect(notes.length * 2);
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
var staveNote = showNote(note, stave, ctx, (i + 1) * 45);
ok(staveNote.getX() > 0, 'Note ' + i + ' has X value');
ok(staveNote.getYs().length > 0, 'Note ' + i + ' has Y values');
}
},
drawHarmonicAndMuted: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 300, 180);
var stave = new VF.Stave(10, 10, 280);
stave.setContext(ctx);
stave.draw();
var showNote = VF.Test.StaveNote.showNote;
var notes = [
{ keys: ['c/4', 'e/4', 'a/4'], duration: '1/2h' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'wh' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'hh' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'qh' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '8h' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '16h' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '32h' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '64h' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '128h' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '1/2h', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'wh', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'hh', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'qh', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '8h', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '16h', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '32h', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '64h', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '128h', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '1/2m' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'wm' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'hm' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'qm' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '8m' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '16m' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '32m' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '64m' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '128m' },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '1/2m', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'wm', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'hm', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: 'qm', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '8m', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '16m', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '32m', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '64m', stem_direction: -1 },
{ keys: ['c/4', 'e/4', 'a/4'], duration: '128m', stem_direction: -1 },
];
expect(notes.length * 2);
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
var staveNote = showNote(note, stave, ctx, (i + 1) * 25);
ok(staveNote.getX() > 0, 'Note ' + i + ' has X value');
ok(staveNote.getYs().length > 0, 'Note ' + i + ' has Y values');
}
},
drawSlash: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 700, 180);
var stave = new VF.Stave(10, 10, 650);
stave.setContext(ctx);
stave.draw();
var notes = [
{ keys: ['b/4'], duration: '1/2s', stem_direction: -1 },
{ keys: ['b/4'], duration: 'ws', stem_direction: -1 },
{ keys: ['b/4'], duration: 'hs', stem_direction: -1 },
{ keys: ['b/4'], duration: 'qs', stem_direction: -1 },
{ keys: ['b/4'], duration: '8s', stem_direction: -1 },
{ keys: ['b/4'], duration: '16s', stem_direction: -1 },
{ keys: ['b/4'], duration: '32s', stem_direction: -1 },
{ keys: ['b/4'], duration: '64s', stem_direction: -1 },
{ keys: ['b/4'], duration: '128s', stem_direction: -1 },
{ keys: ['b/4'], duration: '1/2s', stem_direction: 1 },
{ keys: ['b/4'], duration: 'ws', stem_direction: 1 },
{ keys: ['b/4'], duration: 'hs', stem_direction: 1 },
{ keys: ['b/4'], duration: 'qs', stem_direction: 1 },
{ keys: ['b/4'], duration: '8s', stem_direction: 1 },
{ keys: ['b/4'], duration: '16s', stem_direction: 1 },
{ keys: ['b/4'], duration: '32s', stem_direction: 1 },
{ keys: ['b/4'], duration: '64s', stem_direction: 1 },
{ keys: ['b/4'], duration: '128s', stem_direction: 1 },
// Beam
{ keys: ['b/4'], duration: '8s', stem_direction: -1 },
{ keys: ['b/4'], duration: '8s', stem_direction: -1 },
{ keys: ['b/4'], duration: '8s', stem_direction: 1 },
{ keys: ['b/4'], duration: '8s', stem_direction: 1 },
];
var stave_notes = notes.map(function(note) { return new VF.StaveNote(note); });
var beam1 = new VF.Beam([stave_notes[16], stave_notes[17]]);
var beam2 = new VF.Beam([stave_notes[18], stave_notes[19]]);
VF.Formatter.FormatAndDraw(ctx, stave, stave_notes, false);
beam1.setContext(ctx).draw();
beam2.setContext(ctx).draw();
ok('Slash Note Heads');
},
drawKeyStyles: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 300, 280);
ctx.scale(3, 3);
var stave = new VF.Stave(10, 0, 100);
var note = new VF.StaveNote({ keys: ['g/4', 'bb/4', 'd/5'], duration: 'q' })
.setStave(stave)
.addAccidental(1, new VF.Accidental('b'))
.setKeyStyle(1, { shadowBlur: 15, shadowColor: 'blue', fillStyle: 'blue' });
new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(25);
stave.setContext(ctx).draw();
note.setContext(ctx).draw();
ok(note.getX() > 0, 'Note has X value');
ok(note.getYs().length > 0, 'Note has Y values');
},
drawNoteStyles: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 300, 280);
var stave = new VF.Stave(10, 0, 100);
ctx.scale(3, 3);
var note = new VF.StaveNote({ keys: ['g/4', 'bb/4', 'd/5'], duration: '8' })
.setStave(stave)
.addAccidental(1, new VF.Accidental('b'));
note.setStyle({ shadowBlur: 15, shadowColor: 'blue', fillStyle: 'blue', strokeStyle: 'blue' });
new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(25);
stave.setContext(ctx).draw();
note.setContext(ctx).draw();
ok(note.getX() > 0, 'Note has X value');
ok(note.getYs().length > 0, 'Note has Y values');
},
drawNoteStemStyles: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 300, 280);
var stave = new VF.Stave(10, 0, 100);
ctx.scale(3, 3);
var note = new VF.StaveNote({ keys: ['g/4', 'bb/4', 'd/5'], duration: 'q' })
.setStave(stave)
.addAccidental(1, new VF.Accidental('b'));
note.setStemStyle({ shadowBlur: 15, shadowColor: 'blue', fillStyle: 'blue', strokeStyle: 'blue' });
new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(25);
stave.setContext(ctx).draw();
note.setContext(ctx).draw();
ok('Note Stem Style');
},
drawNoteStylesWithFlag: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 300, 280);
var stave = new VF.Stave(10, 0, 100);
ctx.scale(3, 3);
var note = new VF.StaveNote({ keys: ['g/4', 'bb/4', 'd/5'], duration: '8' })
.setStave(stave)
.addAccidental(1, new VF.Accidental('b'));
note.setFlagStyle({ shadowBlur: 15, shadowColor: 'blue', fillStyle: 'blue', strokeStyle: 'blue' });
new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(25);
stave.setContext(ctx).draw();
note.setContext(ctx).draw();
ok(note.getX() > 0, 'Note has X value');
ok(note.getYs().length > 0, 'Note has Y values');
},
drawBeamStyles: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 160);
var stave = new VF.Stave(10, 10, 380);
stave.setStyle({
strokeStyle: '#EEAAEE',
lineWidth: '3',
});
stave.setContext(ctx);
stave.draw();
var notes = [
// beam1
{ keys: ['b/4'], duration: '8', stem_direction: -1 },
{ keys: ['b/4'], duration: '8', stem_direction: -1 },
// should be unstyled...
{ keys: ['b/4'], duration: '8', stem_direction: -1 },
// beam2 should also be unstyled
{ keys: ['b/4'], duration: '8', stem_direction: -1 },
{ keys: ['b/4'], duration: '8', stem_direction: -1 },
// beam3
{ keys: ['b/4'], duration: '8', stem_direction: 1 },
{ keys: ['b/4'], duration: '8', stem_direction: 1 },
// beam4
{ keys: ['d/6'], duration: '8', stem_direction: -1 },
{ keys: ['c/6', 'd/6'], duration: '8', stem_direction: -1 },
// unbeamed
{ keys: ['d/6', 'e/6'], duration: '8', stem_direction: -1 },
// unbeamed, unstyled
{ keys: ['e/6', 'f/6'], duration: '8', stem_direction: -1 },
];
var staveNotes = notes.map(function(note) { return new VF.StaveNote(note); });
var beam1 = new VF.Beam(staveNotes.slice(0, 2));
var beam2 = new VF.Beam(staveNotes.slice(3, 5));
var beam3 = new VF.Beam(staveNotes.slice(5, 7));
var beam4 = new VF.Beam(staveNotes.slice(7, 9));
// stem, key, ledger, flag; beam.setStyle
beam1.setStyle({
fillStyle: 'blue',
strokeStyle: 'blue',
});
staveNotes[0].setKeyStyle(0, { fillStyle: 'purple' });
staveNotes[0].setStemStyle({ strokeStyle: 'green' });
staveNotes[1].setStemStyle({ strokeStyle: 'orange' });
staveNotes[1].setKeyStyle(0, { fillStyle: 'darkturquoise' });
staveNotes[5].setStyle({ fillStyle: 'tomato', strokeStyle: 'tomato' });
beam3.setStyle({
shadowBlur: 20,
shadowColor: 'blue',
});
staveNotes[9].setLedgerLineStyle({ fillStyle: 'lawngreen', strokeStyle: 'lawngreen', lineWidth: 1 });
staveNotes[9].setFlagStyle({ fillStyle: 'orange', strokeStyle: 'orange' });
VF.Formatter.FormatAndDraw(ctx, stave, staveNotes, false);
beam1.setContext(ctx).draw();
beam2.setContext(ctx).draw();
beam3.setContext(ctx).draw();
beam4.setContext(ctx).draw();
ok('draw beam styles');
},
renderNote: function(note, stave, ctx, x) {
note.setStave(stave);
var mc = new VF.ModifierContext();
note.addToModifierContext(mc);
new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(x);
note.setContext(ctx).draw();
ctx.save();
return note;
},
dotsAndFlagsStemUp: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 800, 150);
ctx.scale(1.0, 1.0);
ctx.setFillStyle('#221');
ctx.setStrokeStyle('#221');
var stave = new VF.Stave(10, 10, 975);
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
var notes = [
newNote({ keys: ['f/4'], duration: '4', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['f/4'], duration: '8', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['f/4'], duration: '16', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['f/4'], duration: '32', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['f/4'], duration: '64', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['f/4'], duration: '128', stem_direction: 1 }).addDotToAll().addDotToAll(),
newNote({ keys: ['g/4'], duration: '4', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['g/4'], duration: '8', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['g/4'], duration: '16', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['g/4'], duration: '32' }).addDotToAll(),
newNote({ keys: ['g/4'], duration: '64', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['g/4'], duration: '128', stem_direction: 1 }).addDotToAll().addDotToAll(),
];
stave.setContext(ctx).draw();
for (var i = 0; i < notes.length; ++i) {
VF.Test.StaveNote.renderNote(notes[i], stave, ctx, (i * 65));
}
ok(true, 'Full Dot');
},
dotsAndFlagsStemDown: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 800, 160);
ctx.scale(1.0, 1.0);
ctx.setFillStyle('#221');
ctx.setStrokeStyle('#221');
var stave = new VF.Stave(10, 10, 975);
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
var notes = [
newNote({ keys: ['e/5'], duration: '4', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['e/5'], duration: '8', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['e/5'], duration: '16', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['e/5'], duration: '32', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['e/5'], duration: '64', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['e/5'], duration: '128', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '4', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '8', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '16', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '32', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '64', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '128', stem_direction: -1 }).addDotToAll(),
];
stave.setContext(ctx).draw();
for (var i = 0; i < notes.length; ++i) {
VF.Test.StaveNote.renderNote(notes[i], stave, ctx, (i * 65));
}
ok(true, 'Full Dot');
},
dotsAndBeamsUp: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 800, 150);
ctx.scale(1.0, 1.0);
ctx.setFillStyle('#221');
ctx.setStrokeStyle('#221');
var stave = new VF.Stave(10, 10, 975);
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
var notes = [
newNote({ keys: ['f/4'], duration: '8', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['f/4'], duration: '16', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['f/4'], duration: '32', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['f/4'], duration: '64', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['f/4'], duration: '128', stem_direction: 1 }).addDotToAll().addDotToAll(),
newNote({ keys: ['g/4'], duration: '8', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['g/4'], duration: '16', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['g/4'], duration: '32' }).addDotToAll(),
newNote({ keys: ['g/4'], duration: '64', stem_direction: 1 }).addDotToAll(),
newNote({ keys: ['g/4'], duration: '128', stem_direction: 1 }).addDotToAll().addDotToAll(),
];
var beam = new VF.Beam(notes);
stave.setContext(ctx).draw();
for (var i = 0; i < notes.length; ++i) {
VF.Test.StaveNote.renderNote(notes[i], stave, ctx, (i * 65));
}
beam.setContext(ctx).draw();
ok(true, 'Full Dot');
},
dotsAndBeamsDown: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 800, 160);
ctx.scale(1.0, 1.0);
ctx.setFillStyle('#221');
ctx.setStrokeStyle('#221');
var stave = new VF.Stave(10, 10, 975);
function newNote(note_struct) { return new VF.StaveNote(note_struct); }
var notes = [
newNote({ keys: ['e/5'], duration: '8', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['e/5'], duration: '16', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['e/5'], duration: '32', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['e/5'], duration: '64', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['e/5'], duration: '128', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '8', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '16', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '32', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '64', stem_direction: -1 }).addDotToAll(),
newNote({ keys: ['d/5'], duration: '128', stem_direction: -1 }).addDotToAll(),
];
var beam = new VF.Beam(notes);
stave.setContext(ctx).draw();
for (var i = 0; i < notes.length; ++i) {
VF.Test.StaveNote.renderNote(notes[i], stave, ctx, (i * 65));
}
beam.setContext(ctx).draw();
ok(true, 'Full Dot');
},
centerAlignedRest: function(options) {
var vf = VF.Test.makeFactory(options, 400, 160);
var stave = vf.Stave({ x: 10, y: 10, width: 350 })
.addClef('treble')
.addTimeSignature('4/4');
var note = vf.StaveNote({ keys: ['b/4'], duration: '1r', align_center: true });
var voice = vf.Voice()
.setStrict(false)
.addTickables([note]);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
centerAlignedRestFermata: function(options) {
var vf = VF.Test.makeFactory(options, 400, 160);
var stave = vf.Stave({ x: 10, y: 10, width: 350 })
.addClef('treble')
.addTimeSignature('4/4');
var note = vf.StaveNote({ keys: ['b/4'], duration: '1r', align_center: true })
.addArticulation(0, new VF.Articulation('a@a').setPosition(3));
var voice = vf.Voice()
.setStrict(false)
.addTickables([note]);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
centerAlignedRestAnnotation: function(options) {
var vf = VF.Test.makeFactory(options, 400, 160);
var stave = vf.Stave({ x: 10, y: 10, width: 350 })
.addClef('treble')
.addTimeSignature('4/4');
var note = vf.StaveNote({ keys: ['b/4'], duration: '1r', align_center: true })
.addAnnotation(0, new VF.Annotation('Whole measure rest').setPosition(3));
var voice = vf.Voice()
.setStrict(false)
.addTickables([note]);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
centerAlignedNoteMultiModifiers: function(options) {
var vf = VF.Test.makeFactory(options, 400, 160);
var stave = vf.Stave({ x: 10, y: 10, width: 350 })
.addClef('treble')
.addTimeSignature('4/4');
function newFinger(num, pos) { return new VF.FretHandFinger(num).setPosition(pos); }
function newStringNumber(num, pos) { return new VF.StringNumber(num).setPosition(pos); }
var note = vf.StaveNote({ keys: ['c/4', 'e/4', 'g/4'], duration: '4', align_center: true })
.addAnnotation(0, new VF.Annotation('Test').setPosition(3))
.addStroke(0, new VF.Stroke(2))
.addAccidental(1, new VF.Accidental('#'))
.addModifier(0, newFinger('3', VF.Modifier.Position.LEFT))
.addModifier(2, newFinger('2', VF.Modifier.Position.LEFT))
.addModifier(1, newFinger('1', VF.Modifier.Position.RIGHT))
.addModifier(2, newStringNumber('4', VF.Modifier.Position.BELOW))
.addDotToAll();
var voice = vf.Voice()
.setStrict(false)
.addTickables([note]);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
centerAlignedMultiVoice: function(options) {
var vf = VF.Test.makeFactory(options, 400, 160);
var stave = vf.Stave({ x: 10, y: 10, width: 350 })
.addClef('treble')
.addTimeSignature('3/8');
// Create custom duration
var custom_duration = new VF.Fraction(3, 8);
var notes0 = [
{ keys: ['c/4'], duration: '1r', align_center: true, duration_override: custom_duration },
].map(vf.StaveNote.bind(vf));
var notes1 = [
{ keys: ['b/4'], duration: '8' },
{ keys: ['b/4'], duration: '8' },
{ keys: ['b/4'], duration: '8' },
].map(vf.StaveNote.bind(vf));
notes1[1].addAccidental(0, vf.Accidental({ type: '#' }));
vf.Beam({ notes: notes1 });
var voice0 = vf.Voice({ time: '3/8' })
.setStrict(false)
.addTickables(notes0);
var voice1 = vf.Voice({ time: '3/8' })
.setStrict(false)
.addTickables(notes1);
vf.Formatter()
.joinVoices([voice0, voice1])
.formatToStave([voice0, voice1], stave);
vf.draw();
ok(true);
},
};
return StaveNote;
})();
/**
* VexFlow - StaveTie Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.StaveTie = (function() {
function createTest(notesData, setupTies) {
return function(options) {
var vf = VF.Test.makeFactory(options, 300);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes.apply(score, notesData));
var notes = voice.getTickables();
setupTies(vf, notes, stave);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
};
}
return {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('StaveTie');
run('Simple StaveTie', createTest(
['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }],
function(vf, notes) {
vf.StaveTie({
from: notes[0],
to: notes[1],
first_indices: [0, 1],
last_indices: [0, 1],
});
}
));
run('Chord StaveTie', createTest(
['(d4 e4 f4)/2, (cn4 f#4 a4)', { stem: 'down' }],
function(vf, notes) {
vf.StaveTie({
from: notes[0],
to: notes[1],
first_indices: [0, 1, 2],
last_indices: [0, 1, 2],
});
}
));
run('Stem Up StaveTie', createTest(
['(d4 e4 f4)/2, (cn4 f#4 a4)', { stem: 'up' }],
function(vf, notes) {
vf.StaveTie({
from: notes[0],
to: notes[1],
first_indices: [0, 1, 2],
last_indices: [0, 1, 2],
});
}
));
run('No End Note', createTest(
['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }],
function(vf, notes, stave) {
stave.addEndClef('treble');
vf.StaveTie({
from: notes[1],
to: null,
first_indices: [2],
last_indices: [2],
text: 'slow.',
});
}
));
run('No Start Note', createTest(
['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }],
function(vf, notes, stave) {
stave.addClef('treble');
vf.StaveTie({
from: null,
to: notes[0],
first_indices: [2],
last_indices: [2],
text: 'H',
});
}
));
run('Set Direction Down', createTest(
['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }],
function(vf, notes) {
vf.StaveTie({
from: notes[0],
to: notes[1],
first_indices: [0, 1],
last_indices: [0, 1],
options: {
direction: VF.Stem.DOWN,
},
});
}
));
run('Set Direction Up', createTest(
['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }],
function(vf, notes) {
vf.StaveTie({
from: notes[0],
to: notes[1],
first_indices: [0, 1],
last_indices: [0, 1],
options: {
direction: VF.Stem.UP,
},
});
}
));
},
};
}());
/**
* VexFlow - StringNumber Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.StringNumber = (function() {
var StringNumber = {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('StringNumber');
run('String Number In Notation', StringNumber.drawMultipleMeasures);
run('Fret Hand Finger In Notation', StringNumber.drawFretHandFingers);
run('Multi Voice With Strokes, String & Finger Numbers', StringNumber.multi);
run('Complex Measure With String & Finger Numbers', StringNumber.drawAccidentals);
},
drawMultipleMeasures: function(options) {
var vf = VF.Test.makeFactory(options, 775, 200);
var score = vf.EasyScore();
// bar 1
var stave1 = vf.Stave({ width: 300 })
.setEndBarType(VF.Barline.type.DOUBLE)
.addClef('treble');
var notes1 = score.notes(
'(c4 e4 g4)/4., (c5 e5 g5)/8, (c4 f4 g4)/4, (c4 f4 g4)/4',
{ stem: 'down' }
);
notes1[0]
.addModifier(0, vf.StringNumber({ number: '5', position: 'right' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'left' }))
.addModifier(2, vf.StringNumber({ number: '3', position: 'right' }));
notes1[1]
.addAccidental(0, vf.Accidental({ type: '#' }))
.addModifier(0, vf.StringNumber({ number: '5', position: 'below' }))
.addAccidental(1, vf.Accidental({ type: '#' }).setAsCautionary())
.addModifier(2, vf.StringNumber({ number: '3', position: 'above' })
.setLastNote(notes1[3])
.setLineEndType(VF.Renderer.LineEndType.DOWN));
notes1[2]
.addModifier(0, vf.StringNumber({ number: '5', position: 'left' }))
.addModifier(2, vf.StringNumber({ number: '3', position: 'left' }))
.addAccidental(1, vf.Accidental({ type: '#' }));
notes1[3]
.addModifier(0, vf.StringNumber({ number: '5', position: 'right' }).setOffsetY(7))
.addModifier(1, vf.StringNumber({ number: '4', position: 'right' }).setOffsetY(6))
.addModifier(2, vf.StringNumber({ number: '3', position: 'right' }).setOffsetY(-6));
var voice1 = score.voice(notes1);
vf.Formatter()
.joinVoices([voice1])
.formatToStave([voice1], stave1);
// bar 2 - juxtaposing second bar next to first bar
var stave2 = vf.Stave({ x: stave1.width + stave1.x, y: stave1.y, width: 300 })
.setEndBarType(VF.Barline.type.DOUBLE);
var notes2 = score.notes(
'(c4 e4 g4)/4, (c5 e5 g5), (c4 f4 g4), (c4 f4 g4)',
{ stem: 'up' }
);
notes2[0]
.addModifier(0, vf.StringNumber({ number: '5', position: 'right' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'left' }))
.addModifier(2, vf.StringNumber({ number: '3', position: 'right' }));
notes2[1]
.addAccidental(0, vf.Accidental({ type: '#' }))
.addModifier(0, vf.StringNumber({ number: '5', position: 'below' }))
.addAccidental(1, vf.Accidental({ type: '#' }))
.addModifier(2, vf.StringNumber({ number: '3', position: 'above' }).setLastNote(notes2[3]).setDashed(false));
notes2[2]
.addModifier(2, vf.StringNumber({ number: '3', position: 'left' }))
.addAccidental(1, vf.Accidental({ type: '#' }));
notes2[3]
.addModifier(0, vf.StringNumber({ number: '5', position: 'right' }).setOffsetY(7))
.addModifier(1, vf.StringNumber({ number: '4', position: 'right' }).setOffsetY(6))
.addModifier(2, vf.StringNumber({ number: '3', position: 'right' }).setOffsetY(-6));
var voice2 = score.voice(notes2);
vf.Formatter()
.joinVoices([voice2])
.formatToStave([voice2], stave2);
// bar 3 - juxtaposing third bar next to second bar
var stave3 = vf.Stave({ x: stave2.width + stave2.x, y: stave2.y, width: 150 })
.setEndBarType(VF.Barline.type.END);
var notesBar3 = score.notes('(c4 e4 g4 a4)/1.');
notesBar3[0]
.addModifier(0, vf.StringNumber({ number: '5', position: 'below' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'right' }))
.addModifier(2, vf.StringNumber({ number: '3', position: 'left' }))
.addModifier(3, vf.StringNumber({ number: '2', position: 'above' }));
var voice3 = score.voice(notesBar3, { time: '6/4' });
vf.Formatter()
.joinVoices([voice3])
.formatToStave([voice3], stave3);
vf.draw();
ok(true, 'String Number');
},
drawFretHandFingers: function(options) {
var vf = VF.Test.makeFactory(options, 725, 200);
var score = vf.EasyScore();
// bar 1
var stave1 = vf.Stave({ width: 350 })
.setEndBarType(VF.Barline.type.DOUBLE)
.addClef('treble');
var notes1 = score.notes(
'(c4 e4 g4)/4, (c5 e5 g5), (c4 f4 g4), (c4 f4 g4)',
{ stem: 'down' }
);
notes1[0]
.addModifier(0, vf.Fingering({ number: '3', position: 'left' }))
.addModifier(1, vf.Fingering({ number: '2', position: 'left' }))
.addModifier(2, vf.Fingering({ number: '0', position: 'left' }));
notes1[1]
.addAccidental(0, vf.Accidental({ type: '#' }))
.addModifier(0, vf.Fingering({ number: '3', position: 'left' }))
.addModifier(1, vf.Fingering({ number: '2', position: 'left' }))
.addAccidental(1, vf.Accidental({ type: '#' }))
.addModifier(2, vf.Fingering({ number: '0', position: 'left' }));
notes1[2]
.addModifier(0, vf.Fingering({ number: '3', position: 'below' }))
.addModifier(1, vf.Fingering({ number: '4', position: 'left' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'left' }))
.addModifier(2, vf.Fingering({ number: '0', position: 'above' }))
.addAccidental(1, vf.Accidental({ type: '#' }));
notes1[3]
.addModifier(0, vf.Fingering({ number: '3', position: 'right' }))
.addModifier(0, vf.StringNumber({ number: '5', position: 'right' }).setOffsetY(7))
.addModifier(1, vf.Fingering({ number: '4', position: 'right' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'right' }).setOffsetY(6))
.addModifier(2, vf.Fingering({ number: '0', position: 'right' }).setOffsetY(-5))
.addModifier(2, vf.StringNumber({ number: '3', position: 'right' }).setOffsetY(-6));
var voice1 = score.voice(notes1);
vf.Formatter()
.joinVoices([voice1])
.formatToStave([voice1], stave1);
// bar 2 - juxtaposing second bar next to first bar
var stave2 = vf.Stave({ x: stave1.width + stave1.x, y: stave1.y, width: 350 })
.setEndBarType(VF.Barline.type.END);
var notes2 = score.notes(
'(c4 e4 g4)/4., (c5 e5 g5)/8, (c4 f4 g4)/8, (c4 f4 g4)/4.[stem="down"]',
{ stem: 'up' }
);
notes2[0]
.addModifier(0, vf.Fingering({ number: '3', position: 'right' }))
.addModifier(1, vf.Fingering({ number: '2', position: 'left' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'right' }))
.addModifier(2, vf.Fingering({ number: '0', position: 'above' }));
notes2[1]
.addAccidental(0, vf.Accidental({ type: '#' }))
.addModifier(0, vf.Fingering({ number: '3', position: 'right' }))
.addModifier(1, vf.Fingering({ number: '2', position: 'left' }))
.addAccidental(1, vf.Accidental({ type: '#' }))
.addModifier(2, vf.Fingering({ number: '0', position: 'left' }));
notes2[2]
.addModifier(0, vf.Fingering({ number: '3', position: 'below' }))
.addModifier(1, vf.Fingering({ number: '2', position: 'left' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'left' }))
.addModifier(2, vf.Fingering({ number: '1', position: 'right' }))
.addAccidental(2, vf.Accidental({ type: '#' }));
notes2[3]
.addModifier(0, vf.Fingering({ number: '3', position: 'right' }))
.addModifier(0, vf.StringNumber({ number: '5', position: 'right' }).setOffsetY(7))
.addModifier(1, vf.Fingering({ number: '4', position: 'right' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'right' }).setOffsetY(6))
.addModifier(2, vf.Fingering({ number: '1', position: 'right' }).setOffsetY(-6))
.addModifier(2, vf.StringNumber({ number: '3', position: 'right' }).setOffsetY(-6));
var voice2 = score.voice(notes2);
vf.Formatter()
.joinVoices([voice2])
.formatToStave([voice2], stave2);
vf.draw();
ok(true, 'String Number');
},
multi: function(options) {
var vf = VF.Test.makeFactory(options, 700, 200);
var score = vf.EasyScore();
var stave = vf.Stave();
var notes1 = score.notes(
'(c4 e4 g4)/4, (a3 e4 g4), (c4 d4 a4), (c4 d4 a4)',
{ stem: 'up' }
);
notes1[0]
.addStroke(0, new VF.Stroke(5))
.addModifier(0, vf.Fingering({ number: '3', position: 'left' }))
.addModifier(1, vf.Fingering({ number: '2', position: 'left' }))
.addModifier(2, vf.Fingering({ number: '0', position: 'left' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'left' }))
.addModifier(2, vf.StringNumber({ number: '3', position: 'above' }));
notes1[1]
.addStroke(0, new VF.Stroke(6))
.addModifier(1, vf.StringNumber({ number: '4', position: 'right' }))
.addModifier(2, vf.StringNumber({ number: '3', position: 'above' }))
.addAccidental(0, vf.Accidental({ type: '#' }))
.addAccidental(1, vf.Accidental({ type: '#' }))
.addAccidental(2, vf.Accidental({ type: '#' }));
notes1[2]
.addStroke(0, new VF.Stroke(2))
.addModifier(0, vf.Fingering({ number: '3', position: 'left' }))
.addModifier(1, vf.Fingering({ number: '0', position: 'right' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'right' }))
.addModifier(2, vf.Fingering({ number: '1', position: 'left' }))
.addModifier(2, vf.StringNumber({ number: '3', position: 'right' }));
notes1[3]
.addStroke(0, new VF.Stroke(1))
.addModifier(2, vf.StringNumber({ number: '3', position: 'left' }))
.addModifier(1, vf.StringNumber({ number: '4', position: 'right' }));
var notes2 = score.notes('e3/8, e3, e3, e3, e3, e3, e3, e3', { stem: 'down' });
notes2[0]
.addModifier(0, vf.Fingering({ number: '0', position: 'left' }))
.addModifier(0, vf.StringNumber({ number: '6', position: 'below' }));
notes2[2]
.addAccidental(0, vf.Accidental({ type: '#' }));
notes2[4]
.addModifier(0, vf.Fingering({ number: '0', position: 'left' }));
// Position string number 6 beneath the strum arrow: left (15) and down (18)
notes2[4]
.addModifier(0, vf.StringNumber({ number: '6', position: 'left' }).setOffsetX(15).setOffsetY(18));
var voices = [notes1, notes2].map(score.voice.bind(score));
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave);
vf.Beam({ notes: notes2.slice(0, 4) });
vf.Beam({ notes: notes2.slice(4, 8) });
vf.draw();
ok(true, 'Strokes Test Multi Voice');
},
drawAccidentals: function(options) {
var vf = VF.Test.makeFactory(options, 500);
var stave = vf.Stave()
.setEndBarType(VF.Barline.type.DOUBLE)
.addClef('treble');
var notes = [
vf.StaveNote({ keys: ['c/4', 'e/4', 'g/4', 'c/5', 'e/5', 'g/5'], stem_direction: 1, duration: '4' }),
vf.StaveNote({ keys: ['c/4', 'e/4', 'g/4', 'd/5', 'e/5', 'g/5'], stem_direction: 1, duration: '4' }),
vf.StaveNote({ keys: ['c/4', 'e/4', 'g/4', 'd/5', 'e/5', 'g/5'], stem_direction: -1, duration: '4' }),
vf.StaveNote({ keys: ['c/4', 'e/4', 'g/4', 'd/5', 'e/5', 'g/5'], stem_direction: -1, duration: '4' }),
];
notes[0]
.addModifier(0, vf.Fingering({ number: '3', position: 'left' }))
.addAccidental(0, vf.Accidental({ type: '#' }))
.addModifier(1, vf.Fingering({ number: '2', position: 'left' }))
.addModifier(1, vf.StringNumber({ number: '2', position: 'left' }))
.addAccidental(1, vf.Accidental({ type: '#' }))
.addModifier(2, vf.Fingering({ number: '0', position: 'left' }))
.addAccidental(2, vf.Accidental({ type: '#' }))
.addModifier(3, vf.Fingering({ number: '3', position: 'left' }))
.addAccidental(3, vf.Accidental({ type: '#' }))
.addModifier(4, vf.Fingering({ number: '2', position: 'right' }))
.addModifier(4, vf.StringNumber({ number: '3', position: 'right' }))
.addAccidental(4, vf.Accidental({ type: '#' }))
.addModifier(5, vf.Fingering({ number: '0', position: 'left' }))
.addAccidental(5, vf.Accidental({ type: '#' }));
notes[1]
.addAccidental(0, vf.Accidental({ type: '#' }))
.addAccidental(1, vf.Accidental({ type: '#' }))
.addAccidental(2, vf.Accidental({ type: '#' }))
.addAccidental(3, vf.Accidental({ type: '#' }))
.addAccidental(4, vf.Accidental({ type: '#' }))
.addAccidental(5, vf.Accidental({ type: '#' }));
notes[2]
.addModifier(0, vf.Fingering({ number: '3', position: 'left' }))
.addAccidental(0, vf.Accidental({ type: '#' }))
.addModifier(1, vf.Fingering({ number: '2', position: 'left' }))
.addModifier(1, vf.StringNumber({ number: '2', position: 'left' }))
.addAccidental(1, vf.Accidental({ type: '#' }))
.addModifier(2, vf.Fingering({ number: '0', position: 'left' }))
.addAccidental(2, vf.Accidental({ type: '#' }))
.addModifier(3, vf.Fingering({ number: '3', position: 'left' }))
.addAccidental(3, vf.Accidental({ type: '#' }))
.addModifier(4, vf.Fingering({ number: '2', position: 'right' }))
.addModifier(4, vf.StringNumber({ number: '3', position: 'right' }))
.addAccidental(4, vf.Accidental({ type: '#' }))
.addModifier(5, vf.Fingering({ number: '0', position: 'left' }))
.addAccidental(5, vf.Accidental({ type: '#' }));
notes[3]
.addAccidental(0, vf.Accidental({ type: '#' }))
.addAccidental(1, vf.Accidental({ type: '#' }))
.addAccidental(2, vf.Accidental({ type: '#' }))
.addAccidental(3, vf.Accidental({ type: '#' }))
.addAccidental(4, vf.Accidental({ type: '#' }))
.addAccidental(5, vf.Accidental({ type: '#' }));
var voice = vf.Voice().addTickables(notes);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'String Number');
},
};
return StringNumber;
})();
/**
* VexFlow - Stroke Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Strokes = (function() {
var Strokes = {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('Strokes');
run('Strokes - Brush/Roll/Rasquedo', Strokes.brushRollRasquedo);
run('Strokes - Arpeggio directionless (without arrows)', Strokes.arpeggioDirectionless);
run('Strokes - Multi Voice', Strokes.multiVoice);
run('Strokes - Notation and Tab', Strokes.notesWithTab);
run('Strokes - Multi-Voice Notation and Tab', Strokes.multiNotationAndTab);
},
brushRollRasquedo: function(options) {
var vf = VF.Test.makeFactory(options, 600, 200);
var score = vf.EasyScore();
// bar 1
var stave1 = vf.Stave({ width: 250 }).setEndBarType(VF.Barline.type.DOUBLE);
var notes1 = score.notes(
'(a3 e4 a4)/4, (c4 e4 g4), (c4 e4 g4), (c4 e4 g4)',
{ stem: 'up' }
);
notes1[0]
.addStroke(0, new VF.Stroke(1));
notes1[1]
.addStroke(0, new VF.Stroke(2))
.addAccidental(1, vf.Accidental({ type: '#' }))
.addAccidental(2, vf.Accidental({ type: '#' }))
.addAccidental(0, vf.Accidental({ type: '#' }));
notes1[2]
.addStroke(0, new VF.Stroke(1));
notes1[3]
.addStroke(0, new VF.Stroke(2));
var voice1 = score.voice(notes1);
vf.Formatter()
.joinVoices([voice1])
.formatToStave([voice1], stave1);
// bar 2
var stave2 = vf.Stave({ x: stave1.width + stave1.x, y: stave1.y, width: 300 })
.setEndBarType(VF.Barline.type.DOUBLE);
var notes2 = score.notes(
'(c4 d4 g4)/4, (c4 d4 g4), (c4 d4 g4), (c4 d4 a4)',
{ stem: 'up' }
);
notes2[0]
.addStroke(0, new VF.Stroke(3));
notes2[1]
.addStroke(0, new VF.Stroke(4));
notes2[2]
.addStroke(0, new VF.Stroke(5));
notes2[3]
.addStroke(0, new VF.Stroke(6))
.addAccidental(0, vf.Accidental({ type: 'bb' }))
.addAccidental(1, vf.Accidental({ type: 'bb' }))
.addAccidental(2, vf.Accidental({ type: 'bb' }));
var voice2 = score.voice(notes2);
vf.Formatter()
.joinVoices([voice2])
.formatToStave([voice2], stave2);
vf.draw();
ok(true, 'Brush/Roll/Rasquedo');
},
arpeggioDirectionless: function(options) {
var vf = VF.Test.makeFactory(options, 700, 200);
var score = vf.EasyScore();
// bar 1
var stave1 = vf.Stave({ x: 100, width: 500 }).setEndBarType(VF.Barline.type.DOUBLE);
var notes1 = score.notes(
'(g4 b4 d5)/4, (g4 b4 d5 g5), (g4 b4 d5 g5), (g4 b4 d5)',
{ stem: 'up' }
);
var graceNotes = [
{ keys: ['e/4'], duration: '32' },
{ keys: ['f/4'], duration: '32' },
{ keys: ['g/4'], duration: '32' },
].map(vf.GraceNote.bind(vf));
var graceNoteGroup = vf.GraceNoteGroup({ notes: graceNotes, slur: false });
graceNoteGroup.beamNotes();
notes1[0]
.addStroke(0, new VF.Stroke(7));
notes1[1]
.addStroke(0, new VF.Stroke(7))
.addAccidental(0, vf.Accidental({ type: '#' }))
.addAccidental(1, vf.Accidental({ type: '#' }))
.addAccidental(2, vf.Accidental({ type: '#' }))
.addAccidental(3, vf.Accidental({ type: '#' }));
notes1[2]
.addStroke(0, new VF.Stroke(7))
.addAccidental(1, vf.Accidental({ type: 'b' }))
.addModifier(0, graceNoteGroup);
notes1[3]
.addStroke(0, new VF.Stroke(7))
.addModifier(0, vf.NoteSubGroup({ notes: [
vf.ClefNote({ type: 'treble', options: { size: 'default', annotation: '8va' } }),
] }));
var voice1 = score.voice(notes1);
vf.Formatter()
.joinVoices([voice1])
.formatToStave([voice1], stave1);
vf.draw();
ok(true, 'Arpeggio directionless (without arrows)');
},
multiVoice: function(options) {
var vf = VF.Test.makeFactory(options, 500, 200);
var score = vf.EasyScore();
var stave = vf.Stave();
var notes1 = score.notes(
'(c4 e4 g4)/4, (c4 e4 g4), (c4 d4 a4), (c4 d4 a4)',
{ stem: 'up' }
);
notes1[0]
.addStroke(0, new VF.Stroke(5));
notes1[1]
.addStroke(0, new VF.Stroke(6))
.addAccidental(0, vf.Accidental({ type: '#' }))
.addAccidental(2, vf.Accidental({ type: '#' }));
notes1[2]
.addStroke(0, new VF.Stroke(2));
notes1[3]
.addStroke(0, new VF.Stroke(1));
var notes2 = score.notes(
'e3/8, e3, e3, e3, e3, e3, e3, e3',
{ stem: 'down' }
);
vf.Beam({ notes: notes2.slice(0, 4) });
vf.Beam({ notes: notes2.slice(4, 8) });
var voices = [notes1, notes2].map(score.voice.bind(score));
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave);
vf.draw();
ok(true, 'Strokes Test Multi Voice');
},
multiNotationAndTab: function(options) {
var vf = VF.Test.makeFactory(options, 400, 275);
var score = vf.EasyScore();
var stave = vf.Stave().addClef('treble');
// notation upper voice notes
var notes1 = score.notes(
'(g4 b4 e5)/4, (g4 b4 e5), (g4 b4 e5), (g4 b4 e5)',
{ stem: 'up' }
);
notes1[0].addStroke(0, new VF.Stroke(3, { all_voices: false }));
notes1[1].addStroke(0, new VF.Stroke(6));
notes1[2].addStroke(0, new VF.Stroke(2, { all_voices: false }));
notes1[3].addStroke(0, new VF.Stroke(1));
var notes2 = score.notes(
'g3/4, g3, g3, g3',
{ stem: 'down' }
);
vf.TabStave({ y: 100 })
.addClef('tab')
.setNoteStartX(stave.getNoteStartX());
// tablature upper voice notes
var tabNotes1 = [
vf.TabNote({
positions: [{ str: 3, fret: 0 },
{ str: 2, fret: 0 },
{ str: 1, fret: 1 }], duration: '4',
}),
vf.TabNote({
positions: [{ str: 3, fret: 0 },
{ str: 2, fret: 0 },
{ str: 1, fret: 1 }], duration: '4',
}),
vf.TabNote({
positions: [{ str: 3, fret: 0 },
{ str: 2, fret: 0 },
{ str: 1, fret: 1 }], duration: '4',
}),
vf.TabNote({
positions: [{ str: 3, fret: 0 },
{ str: 2, fret: 0 },
{ str: 1, fret: 1 }], duration: '4',
}),
];
tabNotes1[0].addStroke(0, new VF.Stroke(3, { all_voices: false }));
tabNotes1[1].addStroke(0, new VF.Stroke(6));
tabNotes1[2].addStroke(0, new VF.Stroke(2, { all_voices: false }));
tabNotes1[3].addStroke(0, new VF.Stroke(1));
var tabNotes2 = [
vf.TabNote({ positions: [{ str: 6, fret: 3 }], duration: '4' }),
vf.TabNote({ positions: [{ str: 6, fret: 3 }], duration: '4' }),
vf.TabNote({ positions: [{ str: 6, fret: 3 }], duration: '4' }),
vf.TabNote({ positions: [{ str: 6, fret: 3 }], duration: '4' }),
];
var voices = [notes1, notes2, tabNotes1, tabNotes2].map(score.voice.bind(score));
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave);
vf.draw();
ok(true, 'Strokes Test Notation & Tab Multi Voice');
},
drawTabStrokes: function(options) {
var vf = VF.Test.makeFactory(options, 600, 200);
var stave1 = vf.TabStave({ width: 250 }).setEndBarType(VF.Barline.type.DOUBLE);
var tabNotes1 = [
vf.TabNote({
positions: [{ str: 2, fret: 8 },
{ str: 3, fret: 9 },
{ str: 4, fret: 10 }], duration: '4',
}),
vf.TabNote({
positions: [{ str: 3, fret: 7 },
{ str: 4, fret: 8 },
{ str: 5, fret: 9 }], duration: '4',
}),
vf.TabNote({
positions: [{ str: 1, fret: 5 },
{ str: 2, fret: 6 },
{ str: 3, fret: 7 },
{ str: 4, fret: 7 },
{ str: 5, fret: 5 },
{ str: 6, fret: 5 }], duration: '4',
}),
vf.TabNote({
positions: [{ str: 4, fret: 3 },
{ str: 5, fret: 4 },
{ str: 6, fret: 5 }], duration: '4',
}),
];
tabNotes1[0].addStroke(0, new VF.Stroke(1));
tabNotes1[1].addStroke(0, new VF.Stroke(2));
tabNotes1[2].addStroke(0, new VF.Stroke(3));
tabNotes1[3].addStroke(0, new VF.Stroke(4));
var tabVoice1 = vf.Voice().addTickables(tabNotes1);
vf.Formatter()
.joinVoices([tabVoice1])
.formatToStave([tabVoice1], stave1);
// bar 2
var stave2 = vf.TabStave({ x: stave1.width + stave1.x, width: 300 })
.setEndBarType(VF.Barline.type.DOUBLE);
var tabNotes2 = [
vf.TabNote({
positions: [{ str: 2, fret: 7 },
{ str: 3, fret: 8 },
{ str: 4, fret: 9 }], duration: '2',
}),
vf.TabNote({
positions: [{ str: 1, fret: 5 },
{ str: 2, fret: 6 },
{ str: 3, fret: 7 },
{ str: 4, fret: 7 },
{ str: 5, fret: 5 },
{ str: 6, fret: 5 }], duration: '2',
}),
];
tabNotes2[0].addStroke(0, new VF.Stroke(6));
tabNotes2[1].addStroke(0, new VF.Stroke(5));
var tabVoice2 = vf.Voice().addTickables(tabNotes2);
vf.Formatter()
.joinVoices([tabVoice2])
.formatToStave([tabVoice2], stave2);
vf.draw();
ok(true, 'Strokes Tab test');
},
notesWithTab: function(options) {
var vf = VF.Test.makeFactory(options, 500, 300);
var stave = vf.Stave({ x: 15, y: 40, width: 450 }).addClef('treble');
var notes = [
vf.StaveNote({ keys: ['b/4', 'd/5', 'g/5'], stem_direction: -1, duration: '4' })
.addAccidental(1, vf.Accidental({ type: 'b' }))
.addAccidental(0, vf.Accidental({ type: 'b' })),
vf.StaveNote({ keys: ['c/5', 'd/5'], stem_direction: -1, duration: '4' }),
vf.StaveNote({ keys: ['b/3', 'e/4', 'a/4', 'd/5'], stem_direction: 1, duration: '8' }),
vf.StaveNote({ keys: ['a/3', 'e/4', 'a/4', 'c/5', 'e/5', 'a/5'], stem_direction: 1, duration: '8' })
.addAccidental(3, vf.Accidental({ type: '#' })),
vf.StaveNote({ keys: ['b/3', 'e/4', 'a/4', 'd/5'], stem_direction: 1, duration: '8' }),
vf.StaveNote({ keys: ['a/3', 'e/4', 'a/4', 'c/5', 'f/5', 'a/5'], stem_direction: 1, duration: '8' })
.addAccidental(3, vf.Accidental({ type: '#' }))
.addAccidental(4, vf.Accidental({ type: '#' })),
];
var tabstave = vf.TabStave({ x: stave.x, y: 140, width: 450 })
.addClef('tab')
.setNoteStartX(stave.getNoteStartX());
var tabNotes = [
vf.TabNote({
positions: [{ str: 1, fret: 3 },
{ str: 2, fret: 2 },
{ str: 3, fret: 3 }], duration: '4',
}).addModifier(new VF.Bend('Full'), 0),
vf.TabNote({
positions: [{ str: 2, fret: 3 },
{ str: 3, fret: 5 }], duration: '4',
}).addModifier(new VF.Bend('Unison'), 1),
vf.TabNote({
positions: [{ str: 3, fret: 7 },
{ str: 4, fret: 7 },
{ str: 5, fret: 7 },
{ str: 6, fret: 7 }], duration: '8',
}),
vf.TabNote({
positions: [{ str: 1, fret: 5 },
{ str: 2, fret: 5 },
{ str: 3, fret: 6 },
{ str: 4, fret: 7 },
{ str: 5, fret: 7 },
{ str: 6, fret: 5 }], duration: '8',
}),
vf.TabNote({
positions: [{ str: 3, fret: 7 },
{ str: 4, fret: 7 },
{ str: 5, fret: 7 },
{ str: 6, fret: 7 }], duration: '8',
}),
vf.TabNote({
positions: [{ str: 1, fret: 5 },
{ str: 2, fret: 5 },
{ str: 3, fret: 6 },
{ str: 4, fret: 7 },
{ str: 5, fret: 7 },
{ str: 6, fret: 5 }], duration: '8',
}),
];
notes[0].addStroke(0, new VF.Stroke(1));
notes[1].addStroke(0, new VF.Stroke(2));
notes[2].addStroke(0, new VF.Stroke(3));
notes[3].addStroke(0, new VF.Stroke(4));
notes[4].addStroke(0, new VF.Stroke(5));
notes[5].addStroke(0, new VF.Stroke(6));
tabNotes[0].addStroke(0, new VF.Stroke(1));
tabNotes[1].addStroke(0, new VF.Stroke(2));
tabNotes[2].addStroke(0, new VF.Stroke(3));
tabNotes[3].addStroke(0, new VF.Stroke(4));
tabNotes[4].addStroke(0, new VF.Stroke(5));
tabNotes[5].addStroke(0, new VF.Stroke(6));
vf.StaveConnector({
top_stave: stave,
bottom_stave: tabstave,
type: 'bracket',
});
vf.StaveConnector({
top_stave: stave,
bottom_stave: tabstave,
type: 'single',
});
var voice = vf.Voice().addTickables(notes);
var tabVoice = vf.Voice().addTickables(tabNotes);
var beams = VF.Beam.applyAndGetBeams(voice);
vf.Formatter()
.joinVoices([voice])
.joinVoices([tabVoice])
.formatToStave([voice, tabVoice], stave);
vf.draw();
beams.forEach(function(beam) {
beam.setContext(vf.getContext()).draw();
});
ok(true);
},
};
return Strokes;
}());
/**
* VexFlow - TabNote Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.TabNote = (function() {
var TabNote = {
Start: function() {
QUnit.module('TabNote');
test('Tick', VF.Test.TabNote.ticks);
test('TabStave Line', VF.Test.TabNote.tabStaveLine);
test('Width', VF.Test.TabNote.width);
test('TickContext', VF.Test.TabNote.tickContext);
var run = VF.Test.runTests;
run('TabNote Draw', TabNote.draw);
run('TabNote Stems Up', TabNote.drawStemsUp);
run('TabNote Stems Down', TabNote.drawStemsDown);
run('TabNote Stems Up Through Stave', TabNote.drawStemsUpThrough);
run('TabNote Stems Down Through Stave', TabNote.drawStemsDownThrough);
run('TabNote Stems with Dots', TabNote.drawStemsDotted);
},
ticks: function() {
var BEAT = 1 * VF.RESOLUTION / 4;
var note = new VF.TabNote({ positions: [{ str: 6, fret: 6 }], duration: '1' });
equal(note.getTicks().value(), BEAT * 4, 'Whole note has 4 beats');
note = new VF.TabNote({ positions: [{ str: 3, fret: 4 }], duration: '4' });
equal(note.getTicks().value(), BEAT, 'Quarter note has 1 beat');
},
tabStaveLine: function() {
var note = new VF.TabNote({
positions: [{ str: 6, fret: 6 }, { str: 4, fret: 5 }],
duration: '1',
});
var positions = note.getPositions();
equal(positions[0].str, 6, 'String 6, Fret 6');
equal(positions[0].fret, 6, 'String 6, Fret 6');
equal(positions[1].str, 4, 'String 4, Fret 5');
equal(positions[1].fret, 5, 'String 4, Fret 5');
var stave = new VF.Stave(10, 10, 300);
note.setStave(stave);
var ys = note.getYs();
equal(ys.length, 2, 'Chord should be rendered on two lines');
equal(ys[0], 100, 'Line for String 6, Fret 6');
equal(ys[1], 80, 'Line for String 4, Fret 5');
},
width: function() {
expect(1);
var note = new VF.TabNote({
positions: [{ str: 6, fret: 6 }, { str: 4, fret: 5 }],
duration: '1',
});
try {
note.getWidth();
} catch (e) {
equal(e.code, 'UnformattedNote', 'Unformatted note should have no width');
}
},
tickContext: function() {
var note = new VF.TabNote({
positions: [{ str: 6, fret: 6 }, { str: 4, fret: 5 }],
duration: '1',
});
var tickContext = new VF.TickContext()
.addTickable(note)
.preFormat()
.setX(10)
.setPadding(0);
equal(tickContext.getWidth(), 7);
},
showNote: function(tab_struct, stave, ctx, x) {
var note = new VF.TabNote(tab_struct);
var tickContext = new VF.TickContext();
tickContext.addTickable(note).preFormat().setX(x);
note.setContext(ctx).setStave(stave);
note.draw();
return note;
},
draw: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 140);
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 10, 550);
stave.setContext(ctx);
stave.draw();
var showNote = VF.Test.TabNote.showNote;
var notes = [
{ positions: [{ str: 6, fret: 6 }], duration: '4' },
{ positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '4' },
{ positions: [{ str: 2, fret: 'x' }, { str: 5, fret: 15 }], duration: '4' },
{ positions: [{ str: 2, fret: 'x' }, { str: 5, fret: 5 }], duration: '4' },
{ positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '4' },
{
positions: [{ str: 6, fret: 0 },
{ str: 5, fret: 5 },
{ str: 4, fret: 5 },
{ str: 3, fret: 4 },
{ str: 2, fret: 3 },
{ str: 1, fret: 0 }],
duration: '4',
},
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '4' },
];
for (var i = 0; i < notes.length; ++i) {
var note = notes[i];
var staveNote = showNote(note, stave, ctx, (i + 1) * 25);
ok(staveNote.getX() > 0, 'Note ' + i + ' has X value');
ok(staveNote.getYs().length > 0, 'Note ' + i + ' has Y values');
}
},
drawStemsUp: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 200);
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 30, 550);
stave.setContext(ctx);
stave.draw();
var specs = [
{ positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '4' },
{ positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '32' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '64' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '128' },
];
var notes = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
return tabNote;
});
var voice = new VF.Voice(VF.Test.TIME4_4).setMode(VF.Voice.Mode.SOFT);
voice.addTickables(notes);
new VF.Formatter().joinVoices([voice]).formatToStave([voice], stave);
voice.draw(ctx, stave);
ok(true, 'TabNotes successfully drawn');
},
drawStemsDown: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 200);
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 10, 550);
stave.setContext(ctx);
stave.draw();
var specs = [
{ positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '4' },
{ positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '32' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '64' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '128' },
];
var notes = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
tabNote.setStemDirection(-1);
return tabNote;
});
var voice = new VF.Voice(VF.Test.TIME4_4).setMode(VF.Voice.Mode.SOFT);
voice.addTickables(notes);
new VF.Formatter().joinVoices([voice]).formatToStave([voice], stave);
voice.draw(ctx, stave);
ok(true, 'All objects have been drawn');
},
drawStemsUpThrough: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 200);
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 30, 550);
stave.setContext(ctx);
stave.draw();
var specs = [
{ positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '4' },
{ positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '32' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '64' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '128' },
];
var notes = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
tabNote.render_options.draw_stem_through_stave = true;
return tabNote;
});
ctx.setFont('sans-serif', 10, 'bold');
var voice = new VF.Voice(VF.Test.TIME4_4).setMode(VF.Voice.Mode.SOFT);
voice.addTickables(notes);
new VF.Formatter().joinVoices([voice]).formatToStave([voice], stave);
voice.draw(ctx, stave);
ok(true, 'TabNotes successfully drawn');
},
drawStemsDownThrough: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 250);
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 10, 550, { num_lines: 8 });
stave.setContext(ctx);
stave.draw();
var specs = [
{ positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '4' },
{ positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }, { str: 6, fret: 10 }], duration: '32' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '64' },
{ positions: [{ str: 1, fret: 6 }, { str: 3, fret: 5 }, { str: 5, fret: 5 }, { str: 7, fret: 5 }], duration: '128' },
];
var notes = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
tabNote.render_options.draw_stem_through_stave = true;
tabNote.setStemDirection(-1);
return tabNote;
});
ctx.setFont('Arial', 10, 'bold');
var voice = new VF.Voice(VF.Test.TIME4_4).setMode(VF.Voice.Mode.SOFT);
voice.addTickables(notes);
new VF.Formatter().joinVoices([voice]).formatToStave([voice], stave);
voice.draw(ctx, stave);
ok(true, 'All objects have been drawn');
},
drawStemsDotted: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 200);
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 10, 550);
stave.setContext(ctx);
stave.draw();
var specs = [
{ positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '4d' },
{ positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '4dd', stem_direction: -1 },
{ positions: [{ str: 1, fret: 6 }, { str: 4, fret: 5 }], duration: '16', stem_direction: -1 },
];
var notes = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec, true);
return tabNote;
});
notes[0].addDot();
notes[2].addDot();
notes[2].addDot();
var voice = new VF.Voice(VF.Test.TIME4_4).setMode(VF.Voice.Mode.SOFT);
voice.addTickables(notes);
new VF.Formatter().joinVoices([voice]).formatToStave([voice], stave);
voice.draw(ctx, stave);
ok(true, 'TabNotes successfully drawn');
},
};
return TabNote;
})();
/**
* VexFlow - TabSlide Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.TabSlide = (function() {
var TabSlide = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('TabSlide');
runTests('Simple TabSlide', TabSlide.simple);
runTests('Slide Up', TabSlide.slideUp);
runTests('Slide Down', TabSlide.slideDown);
},
tieNotes: function(notes, indices, stave, ctx) {
var voice = new VF.Voice(VF.Test.TIME4_4);
voice.addTickables(notes);
new VF.Formatter().joinVoices([voice]).format([voice], 100);
voice.draw(ctx, stave);
var tie = new VF.TabSlide({
first_note: notes[0],
last_note: notes[1],
first_indices: indices,
last_indices: indices,
}, VF.TabSlide.SLIDE_UP);
tie.setContext(ctx);
tie.draw();
},
setupContext: function(options, x) {
var ctx = options.contextBuilder(options.elementId, 350, 140);
ctx.scale(0.9, 0.9);
ctx.fillStyle = '#221';
ctx.strokeStyle = '#221';
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 10, x || 350)
.addTabGlyph()
.setContext(ctx)
.draw();
return { context: ctx, stave: stave };
},
simple: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
var c = VF.Test.TabSlide.setupContext(options);
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
VF.Test.TabSlide.tieNotes([
newNote({ positions: [{ str: 4, fret: 4 }], duration: 'h' }),
newNote({ positions: [{ str: 4, fret: 6 }], duration: 'h' }),
], [0], c.stave, c.context);
ok(true, 'Simple Test');
},
multiTest: function(options, factory) {
var c = VF.Test.TabSlide.setupContext(options, 440, 100);
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
var notes = [
newNote({ positions: [{ str: 4, fret: 4 }], duration: '8' }),
newNote({ positions: [{ str: 4, fret: 4 }], duration: '8' }),
newNote({ positions: [{ str: 4, fret: 4 }, { str: 5, fret: 4 }], duration: '8' }),
newNote({ positions: [{ str: 4, fret: 6 }, { str: 5, fret: 6 }], duration: '8' }),
newNote({ positions: [{ str: 2, fret: 14 }], duration: '8' }),
newNote({ positions: [{ str: 2, fret: 16 }], duration: '8' }),
newNote({ positions: [{ str: 2, fret: 14 }, { str: 3, fret: 14 }], duration: '8' }),
newNote({ positions: [{ str: 2, fret: 16 }, { str: 3, fret: 16 }], duration: '8' }),
];
var voice = new VF.Voice(VF.Test.TIME4_4).addTickables(notes);
new VF.Formatter().joinVoices([voice]).format([voice], 300);
voice.draw(c.context, c.stave);
factory({
first_note: notes[0],
last_note: notes[1],
first_indices: [0],
last_indices: [0],
}).setContext(c.context).draw();
ok(true, 'Single note');
factory({
first_note: notes[2],
last_note: notes[3],
first_indices: [0, 1],
last_indices: [0, 1],
}).setContext(c.context).draw();
ok(true, 'Chord');
factory({
first_note: notes[4],
last_note: notes[5],
first_indices: [0],
last_indices: [0],
}).setContext(c.context).draw();
ok(true, 'Single note high-fret');
factory({
first_note: notes[6],
last_note: notes[7],
first_indices: [0, 1],
last_indices: [0, 1],
}).setContext(c.context).draw();
ok(true, 'Chord high-fret');
},
slideUp: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
VF.Test.TabSlide.multiTest(options, VF.TabSlide.createSlideUp);
},
slideDown: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
VF.Test.TabSlide.multiTest(options, VF.TabSlide.createSlideDown);
},
};
return TabSlide;
}());
/**
* VexFlow - TabStave Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.TabStave = (function() {
var TabStave = {
Start: function() {
QUnit.module('TabStave');
VF.Test.runTests('TabStave Draw Test', VF.Test.TabStave.draw);
VF.Test.runTests('Vertical Bar Test', VF.Test.TabStave.drawVerticalBar);
},
draw: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 160);
var stave = new VF.TabStave(10, 10, 300);
stave.setNumLines(6);
stave.setContext(ctx);
stave.draw();
equal(stave.getYForNote(0), 127, 'getYForNote(0)');
equal(stave.getYForLine(5), 127, 'getYForLine(5)');
equal(stave.getYForLine(0), 62, 'getYForLine(0) - Top Line');
equal(stave.getYForLine(4), 114, 'getYForLine(4) - Bottom Line');
ok(true, 'all pass');
},
drawVerticalBar: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 160);
var stave = new VF.TabStave(10, 10, 300);
stave.setNumLines(6);
stave.setContext(ctx);
stave.drawVerticalBar(50, true);
stave.drawVerticalBar(100, true);
stave.drawVerticalBar(150, false);
stave.setEndBarType(VF.Barline.type.END);
stave.draw();
ok(true, 'all pass');
},
};
return TabStave;
})();
module.exports = VF.Test.TabStave;
/**
* VexFlow - TabTie Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.TabTie = (function() {
var TabTie = {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('TabTie');
run('Simple TabTie', TabTie.simple);
run('Hammerons', TabTie.simpleHammeron);
run('Pulloffs', TabTie.simplePulloff);
run('Tapping', TabTie.tap);
run('Continuous', TabTie.continuous);
},
tieNotes: function(notes, indices, stave, ctx, text) {
var voice = new VF.Voice(VF.Test.TIME4_4);
voice.addTickables(notes);
new VF.Formatter().joinVoices([voice]).format([voice], 100);
voice.draw(ctx, stave);
var tie = new VF.TabTie({
first_note: notes[0],
last_note: notes[1],
first_indices: indices,
last_indices: indices,
}, text || 'Annotation');
tie.setContext(ctx);
tie.draw();
},
setupContext: function(options, x, y) {
var ctx = options.contextBuilder(options.elementId, x || 350, y || 160);
ctx.fillStyle = '#221';
ctx.strokeStyle = '#221';
ctx.setFont('Arial', VF.Test.Font.size, '');
var stave = new VF.TabStave(10, 10, x || 350)
.addTabGlyph()
.setContext(ctx)
.draw();
return { context: ctx, stave: stave };
},
drawTie: function(notes, indices, options, text) {
var c = VF.Test.TabTie.setupContext(options);
VF.Test.TabTie.tieNotes(notes, indices, c.stave, c.context, text);
},
simple: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
VF.Test.TabTie.drawTie([
newNote({ positions: [{ str: 4, fret: 4 }], duration: 'h' }),
newNote({ positions: [{ str: 4, fret: 6 }], duration: 'h' }),
], [0], options);
ok(true, 'Simple Test');
},
tap: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
VF.Test.TabTie.drawTie([
newNote({ positions: [{ str: 4, fret: 12 }], duration: 'h' })
.addModifier(new VF.Annotation('T'), 0),
newNote({ positions: [{ str: 4, fret: 10 }], duration: 'h' }),
], [0], options, 'P');
ok(true, 'Tapping Test');
},
multiTest: function(options, factory) {
var c = VF.Test.TabTie.setupContext(options, 440, 140);
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
var notes = [
newNote({ positions: [{ str: 4, fret: 4 }], duration: '8' }),
newNote({ positions: [{ str: 4, fret: 4 }], duration: '8' }),
newNote({ positions: [{ str: 4, fret: 4 }, { str: 5, fret: 4 }], duration: '8' }),
newNote({ positions: [{ str: 4, fret: 6 }, { str: 5, fret: 6 }], duration: '8' }),
newNote({ positions: [{ str: 2, fret: 14 }], duration: '8' }),
newNote({ positions: [{ str: 2, fret: 16 }], duration: '8' }),
newNote({ positions: [{ str: 2, fret: 14 }, { str: 3, fret: 14 }], duration: '8' }),
newNote({ positions: [{ str: 2, fret: 16 }, { str: 3, fret: 16 }], duration: '8' }),
];
var voice = new VF.Voice(VF.Test.TIME4_4).addTickables(notes);
new VF.Formatter().joinVoices([voice]).format([voice], 300);
voice.draw(c.context, c.stave);
factory({
first_note: notes[0],
last_note: notes[1],
first_indices: [0],
last_indices: [0],
}).setContext(c.context).draw();
ok(true, 'Single note');
factory({
first_note: notes[2],
last_note: notes[3],
first_indices: [0, 1],
last_indices: [0, 1],
}).setContext(c.context).draw();
ok(true, 'Chord');
factory({
first_note: notes[4],
last_note: notes[5],
first_indices: [0],
last_indices: [0],
}).setContext(c.context).draw();
ok(true, 'Single note high-fret');
factory({
first_note: notes[6],
last_note: notes[7],
first_indices: [0, 1],
last_indices: [0, 1],
}).setContext(c.context).draw();
ok(true, 'Chord high-fret');
},
simpleHammeron: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
VF.Test.TabTie.multiTest(options, VF.TabTie.createHammeron);
},
simplePulloff: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
VF.Test.TabTie.multiTest(options, VF.TabTie.createPulloff);
},
continuous: function(options, contextBuilder) {
options.contextBuilder = contextBuilder;
var c = VF.Test.TabTie.setupContext(options, 440, 140);
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
var notes = [
newNote({ positions: [{ str: 4, fret: 4 }], duration: 'q' }),
newNote({ positions: [{ str: 4, fret: 5 }], duration: 'q' }),
newNote({ positions: [{ str: 4, fret: 6 }], duration: 'h' }),
];
var voice = new VF.Voice(VF.Test.TIME4_4).addTickables(notes);
new VF.Formatter().joinVoices([voice]).format([voice], 300);
voice.draw(c.context, c.stave);
VF.TabTie.createHammeron({
first_note: notes[0],
last_note: notes[1],
first_indices: [0],
last_indices: [0],
}).setContext(c.context).draw();
VF.TabTie.createPulloff({
first_note: notes[1],
last_note: notes[2],
first_indices: [0],
last_indices: [0],
}).setContext(c.context).draw();
ok(true, 'Continuous Hammeron');
},
};
return TabTie;
}());
/**
* VexFlow - TextBracket Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.TextBracket = (function() {
var TextBracket = {
Start: function() {
QUnit.module('TextBracket');
VF.Test.runTests('Simple TextBracket', VF.Test.TextBracket.simple0);
VF.Test.runTests('TextBracket Styles', VF.Test.TextBracket.simple1);
},
simple0: function(options) {
var vf = VF.Test.makeFactory(options, 550);
var stave = vf.Stave();
var score = vf.EasyScore();
var notes = score.notes('c4/4, c4, c4, c4, c4', { stem: 'up' });
var voice = score.voice(notes, { time: '5/4' });
vf.TextBracket({
from: notes[0],
to: notes[4],
text: '15',
options: {
superscript: 'va',
position: 'top',
},
});
vf.TextBracket({
from: notes[0],
to: notes[4],
text: '8',
options: {
superscript: 'vb',
position: 'bottom',
line: 3,
},
});
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
simple1: function(options) {
var vf = VF.Test.makeFactory(options, 550);
var stave = vf.Stave();
var score = vf.EasyScore();
var notes = score.notes('c4/4, c4, c4, c4, c4', { stem: 'up' });
var voice = score.voice(notes, { time: '5/4' });
const topOctaves = [
vf.TextBracket({
from: notes[0],
to: notes[1],
text: 'Cool notes',
options: {
superscript: '',
position: 'top',
},
}),
vf.TextBracket({
from: notes[2],
to: notes[4],
text: 'Testing',
options: {
position: 'top',
superscript: 'superscript',
font: { family: 'Arial', size: 15, weight: '' },
},
}),
];
const bottomOctaves = [
vf.TextBracket({
from: notes[0],
to: notes[1],
text: '8',
options: {
superscript: 'vb',
position: 'bottom',
line: 3,
font: { size: 30 },
},
}),
vf.TextBracket({
from: notes[2],
to: notes[4],
text: 'Not cool notes',
options: {
superscript: ' super uncool',
position: 'bottom',
line: 4,
},
}),
];
topOctaves[1].render_options.line_width = 2;
topOctaves[1].render_options.show_bracket = false;
bottomOctaves[0].render_options.underline_superscript = false;
bottomOctaves[0].setDashed(false);
bottomOctaves[1].render_options.bracket_height = 40;
bottomOctaves[1].setDashed(true, [2, 2]);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
};
return TextBracket;
})();
/**
* VexFlow - Text Note Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.TextNote = (function() {
var TextNote = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('TextNote');
runTests('TextNote Formatting', TextNote.formatTextNotes);
runTests('TextNote Superscript and Subscript', TextNote.superscriptAndSubscript);
runTests('TextNote Formatting With Glyphs 0', TextNote.formatTextGlyphs0);
runTests('TextNote Formatting With Glyphs 1', TextNote.formatTextGlyphs1);
runTests('Crescendo', TextNote.crescendo);
runTests('Text Dynamics', TextNote.textDynamics);
},
formatTextNotes: function(options) {
var vf = VF.Test.makeFactory(options, 400, 200);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var voice1 = score.voice([
vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], stem_direction: -1, duration: 'h' })
.addAccidental(0, vf.Accidental({ type: 'b' }))
.addAccidental(1, vf.Accidental({ type: '#' })),
vf.StaveNote({ keys: ['d/4', 'e/4', 'f/4'], stem_direction: -1, duration: 'q' }),
vf.StaveNote({ keys: ['c/4', 'f/4', 'a/4'], stem_direction: -1, duration: 'q' })
.addAccidental(0, vf.Accidental({ type: 'n' }))
.addAccidental(1, vf.Accidental({ type: '#' })),
]);
var voice2 = score.voice([
vf.TextNote({ text: 'Center Justification', duration: 'h' })
.setJustification(VF.TextNote.Justification.CENTER),
vf.TextNote({ text: 'Left Line 1', duration: 'q' })
.setLine(1),
vf.TextNote({ text: 'Right', duration: 'q' })
.setJustification(VF.TextNote.Justification.RIGHT),
]);
vf.Formatter()
.joinVoices([voice1, voice2])
.formatToStave([voice1, voice2], stave);
vf.draw();
ok(true);
},
superscriptAndSubscript: function(options) {
var vf = VF.Test.makeFactory(options, 600, 230);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var voice1 = score.voice([
vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], stem_direction: 1, duration: 'h' })
.addAccidental(0, vf.Accidental({ type: 'b' }))
.addAccidental(1, vf.Accidental({ type: '#' })),
vf.StaveNote({ keys: ['d/4', 'e/4', 'f/4'], stem_direction: 1, duration: 'q' }),
vf.StaveNote({ keys: ['c/4', 'f/4', 'a/4'], stem_direction: 1, duration: 'q' })
.addAccidental(0, vf.Accidental({ type: 'n' }))
.addAccidental(1, vf.Accidental({ type: '#' })),
]);
var voice2 = score.voice([
vf.TextNote({ text: VF.unicode.flat + 'I', superscript: '+5', duration: '8' }),
vf.TextNote({ text: 'D' + VF.unicode.sharp + '/F', duration: '4d', superscript: 'sus2' }),
vf.TextNote({ text: 'ii', superscript: '6', subscript: '4', duration: '8' }),
vf.TextNote({ text: 'C', superscript: VF.unicode.triangle + '7', subscript: '', duration: '8' }),
vf.TextNote({ text: 'vii', superscript: VF.unicode['o-with-slash'] + '7', duration: '8' }),
vf.TextNote({ text: 'V', superscript: '7', duration: '8' }),
]);
voice2.getTickables().forEach(function(note) {
note.font = { family: 'Serif', size: 15, weight: '' };
note.setLine(13);
note.setJustification(VF.TextNote.Justification.LEFT);
});
vf.Formatter()
.joinVoices([voice1, voice2])
.formatToStave([voice1, voice2], stave);
vf.draw();
ok(true);
},
formatTextGlyphs0: function(options) {
var vf = VF.Test.makeFactory(options, 600, 230);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var voice1 = score.voice([
vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], stem_direction: -1, duration: 'h' })
.addAccidental(0, vf.Accidental({ type: 'b' }))
.addAccidental(1, vf.Accidental({ type: '#' })),
vf.StaveNote({ keys: ['d/4', 'e/4', 'f/4'], stem_direction: -1, duration: '8' }),
vf.StaveNote({ keys: ['c/4', 'f/4', 'a/4'], stem_direction: -1, duration: '8' }),
vf.StaveNote({ keys: ['c/4', 'f/4', 'a/4'], stem_direction: -1, duration: '8' }),
vf.StaveNote({ keys: ['c/4', 'f/4', 'a/4'], stem_direction: -1, duration: '8' }),
]);
var voice2 = score.voice([
vf.TextNote({ text: 'Center', duration: '8' })
.setJustification(VF.TextNote.Justification.CENTER),
vf.TextNote({ glyph: 'f', duration: '8' }),
vf.TextNote({ glyph: 'p', duration: '8' }),
vf.TextNote({ glyph: 'm', duration: '8' }),
vf.TextNote({ glyph: 'z', duration: '8' }),
vf.TextNote({ glyph: 'mordent_upper', duration: '16' }),
vf.TextNote({ glyph: 'mordent_lower', duration: '16' }),
vf.TextNote({ glyph: 'segno', duration: '8' }),
vf.TextNote({ glyph: 'coda', duration: '8' }),
]);
vf.Formatter()
.joinVoices([voice1, voice2])
.formatToStave([voice1, voice2], stave);
vf.draw();
ok(true);
},
formatTextGlyphs1: function(options) {
var vf = VF.Test.makeFactory(options, 600, 230);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var voice1 = score.voice([
vf.StaveNote({ keys: ['c/4', 'e/4', 'a/4'], stem_direction: -1, duration: 'h' })
.addAccidental(0, vf.Accidental({ type: 'b' }))
.addAccidental(1, vf.Accidental({ type: '#' })),
vf.StaveNote({ keys: ['d/4', 'e/4', 'f/4'], stem_direction: -1, duration: '8' }),
vf.StaveNote({ keys: ['c/4', 'f/4', 'a/4'], stem_direction: -1, duration: '8' }),
vf.StaveNote({ keys: ['c/4', 'f/4', 'a/4'], stem_direction: -1, duration: '8' }),
vf.StaveNote({ keys: ['c/4', 'f/4', 'a/4'], stem_direction: -1, duration: '8' }),
]);
var voice2 = score.voice([
vf.TextNote({ glyph: 'turn', duration: '16' }),
vf.TextNote({ glyph: 'turn_inverted', duration: '16' }),
vf.TextNote({ glyph: 'pedal_open', duration: '8' }).setLine(10),
vf.TextNote({ glyph: 'pedal_close', duration: '8' }).setLine(10),
vf.TextNote({ glyph: 'caesura_curved', duration: '8' }).setLine(3),
vf.TextNote({ glyph: 'caesura_straight', duration: '8' }).setLine(3),
vf.TextNote({ glyph: 'breath', duration: '8' }).setLine(2),
vf.TextNote({ glyph: 'tick', duration: '8' }).setLine(3),
vf.TextNote({ glyph: 'tr', duration: '8', smooth: true })
.setJustification(VF.TextNote.Justification.CENTER),
]);
vf.Formatter()
.joinVoices([voice1, voice2])
.formatToStave([voice1, voice2], stave);
vf.draw();
ok(true);
},
crescendo: function(options) {
var vf = VF.Test.makeFactory(options, 600, 230);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var voice = score.voice([
vf.TextNote({ glyph: 'p', duration: '16' }),
new VF.Crescendo({ duration: '4d' })
.setLine(0)
.setHeight(25)
.setStave(stave),
vf.TextNote({ glyph: 'f', duration: '16' }),
new VF.Crescendo({ duration: '4' })
.setLine(5)
.setStave(stave),
new VF.Crescendo({ duration: '4' })
.setLine(10)
.setDecrescendo(true)
.setHeight(5)
.setStave(stave),
]);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
textDynamics: function(options) {
var vf = VF.Test.makeFactory(options, 600, 230);
var stave = vf.Stave({ y: 40 });
var score = vf.EasyScore();
var voice = score.voice([
vf.TextDynamics({ text: 'sfz', duration: '4' }),
vf.TextDynamics({ text: 'rfz', duration: '4' }),
vf.TextDynamics({ text: 'mp', duration: '4' }),
vf.TextDynamics({ text: 'ppp', duration: '4' }),
vf.TextDynamics({ text: 'fff', duration: '4' }),
vf.TextDynamics({ text: 'mf', duration: '4' }),
vf.TextDynamics({ text: 'sff', duration: '4' }),
], { time: '7/4' });
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
},
};
return TextNote;
})();
/**
* VexFlow - Three Voices in single staff tests.
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.ThreeVoices = (function() {
function concat(a, b) { return a.concat(b); }
function createThreeVoicesTest(noteGroup1, noteGroup2, noteGroup3, setup) {
return function(options) {
var vf = VF.Test.makeFactory(options, 600, 200);
var stave = vf.Stave().addTrebleGlyph().addTimeSignature('4/4');
var score = vf.EasyScore();
var noteGroups = [noteGroup1, noteGroup2, noteGroup3].map(function(noteGroup) {
return score.notes.apply(score, noteGroup);
});
var voices = noteGroups.map(score.voice.bind(score));
setup(vf, voices);
var beams = [
VF.Beam.applyAndGetBeams(voices[0], +1),
VF.Beam.applyAndGetBeams(voices[1], -1),
VF.Beam.applyAndGetBeams(voices[2], -1),
].reduce(concat);
// Set option to position rests near the notes in each voice
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave);
vf.draw();
for (var i = 0; i < beams.length; i++) {
beams[i].setContext(vf.getContext()).draw();
}
ok(true);
};
}
var ThreeVoices = {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('Three Voice Rests');
run('Three Voices - #1', createThreeVoicesTest(
['e5/2, e5', { stem: 'up' }],
['(d4 a4 d#5)/8, b4, (d4 a4 c5), b4, (d4 a4 c5), b4, (d4 a4 c5), b4', { stem: 'down' }],
['b3/4, e3, f3, a3', { stem: 'down' }],
function(vf, voices) {
voices[0]
.getTickables()[0]
.addModifier(0, vf.Fingering({ number: '0', position: 'left' }));
voices[1]
.getTickables()[0]
.addModifier(0, vf.Fingering({ number: '0', position: 'left' }))
.addModifier(1, vf.Fingering({ number: '4', position: 'left' }));
}
));
run('Three Voices - #2 Complex', createThreeVoicesTest(
['(a4 e5)/16, e5, e5, e5, e5/8, e5, e5/2', { stem: 'up' }],
['(d4 d#5)/16, (b4 c5), d5, e5, (d4 a4 c5)/8, b4, (d4 a4 c5), b4, (d4 a4 c5), b4', { stem: 'down' }],
['b3/8, b3, e3/4, f3, a3', { stem: 'down' }],
function(vf, voices) {
voices[0]
.getTickables()[0]
.addModifier(0, vf.Fingering({ number: '2', position: 'left' }))
.addModifier(1, vf.Fingering({ number: '0', position: 'above' }));
voices[1]
.getTickables()[0]
.addModifier(0, vf.Fingering({ number: '0', position: 'left' }))
.addModifier(1, vf.Fingering({ number: '4', position: 'left' }));
}
));
run('Three Voices - #3', createThreeVoicesTest(
['(g4 e5)/4, e5, (g4 e5)/2', { stem: 'up' }],
['c#5/4, b4/8, b4/8/r, a4/4., g4/8', { stem: 'down' }],
['c4/4, b3, a3, g3', { stem: 'down' }],
function(vf, voices) {
voices[0]
.getTickables()[0]
.addModifier(0, vf.Fingering({ number: '0', position: 'left' }))
.addModifier(1, vf.Fingering({ number: '0', position: 'left' }));
voices[1]
.getTickables()[0]
.addModifier(0, vf.Fingering({ number: '1', position: 'left' }));
voices[2]
.getTickables()[0]
.addModifier(0, vf.Fingering({ number: '3', position: 'left' }));
}
));
run('Auto Adjust Rest Positions - Two Voices', ThreeVoices.autoRestTwoVoices);
run('Auto Adjust Rest Positions - Three Voices #1', ThreeVoices.autorestthreevoices);
run('Auto Adjust Rest Positions - Three Voices #2', ThreeVoices.autorestthreevoices2);
},
autoRestTwoVoices: function(options) {
var vf = VF.Test.makeFactory(options, 900, 200);
var score = vf.EasyScore();
var x = 10;
var beams = [];
function createMeasure(measureTitle, width, alignRests) {
var stave = vf.Stave({ x: x, y: 50, width: width }).setBegBarType(1);
x += width;
var voices = [
score.notes(
'b4/8/r, e5/16, b4/r, b4/8/r, e5/16, b4/r, b4/8/r, d5/16, b4/r, e5/4',
{ stem: 'up' }
),
score.notes(
'c5/16, c4, b4/r, d4, e4, f4, b4/r, g4, g4[stem="up"], a4[stem="up"], b4/r, b4[stem="up"], e4/4',
{ stem: 'down' }
),
[vf.TextNote({ text: measureTitle, line: -1, duration: '1', smooth: true })],
].map(score.voice.bind(score));
beams = beams
.concat(VF.Beam.applyAndGetBeams(voices[0], 1))
.concat(VF.Beam.applyAndGetBeams(voices[1], -1));
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave, { align_rests: alignRests });
}
createMeasure('Default Rest Positions', 400, false);
createMeasure('Rests Repositioned To Avoid Collisions', 400, true);
vf.draw();
for (var i = 0; i < beams.length; i++) {
beams[i].setContext(vf.getContext()).draw();
}
ok(true, 'Auto Adjust Rests - Two Voices');
},
autorestthreevoices: function(options) {
var vf = VF.Test.makeFactory(options, 850, 200);
var score = vf.EasyScore();
var x = 10;
function createMeasure(measureTitle, width, alignRests) {
var stave = vf.Stave({ x: x, y: 50, width: width }).setBegBarType(1);
var voices = [
score.voice(score.notes(
'b4/4/r, e5, e5/r, e5/r, e5, e5, e5, e5/r',
{ stem: 'up' }
), { time: '8/4' }),
score.voice(score.notes(
'b4/4/r, b4/r, b4/r, b4, b4/r, b4/r, b4, b4',
{ stem: 'down' }
), { time: '8/4' }),
score.voice(score.notes(
'e4/4/r, e4/r, f4, b4/r, g4, c4, e4/r, c4',
{ stem: 'down' }
), { time: '8/4' }),
score.voice([
vf.TextNote({ text: measureTitle, duration: '1', line: -1, smooth: true }),
vf.TextNote({ text: '', duration: '1', line: -1, smooth: true }),
], { time: '8/4' }),
];
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave, { align_rests: alignRests });
x += width;
}
createMeasure('Default Rest Positions', 400, false);
createMeasure('Rests Repositioned To Avoid Collisions', 400, true);
vf.draw();
ok(true);
},
autorestthreevoices2: function(options) {
var vf = VF.Test.makeFactory(options, 850, 200);
var score = vf.EasyScore();
var x = 10;
function createMeasure(measureTitle, width, alignRests) {
var stave = vf.Stave({ x: x, y: 50, width: width }).setBegBarType(1);
var voices = [
score.voice(score.notes(
'b4/16/r, e5, e5/r, e5/r, e5, e5, e5, e5/r'
), { time: '2/4' }),
score.voice(score.notes(
'b4/16/r, b4/r, b4/r, b4, b4/r, b4/r, b4, b4'
), { time: '2/4' }),
score.voice(score.notes(
'e4/16/r, e4/r, f4, b4/r, g4, c4, e4/r, c4'
), { time: '2/4' }),
score.voice([
vf.TextNote({ text: measureTitle, duration: 'h', line: -1, smooth: true }),
], { time: '2/4' }),
];
vf.Formatter()
.joinVoices(voices)
.formatToStave(voices, stave, { align_rests: alignRests });
x += width;
}
createMeasure('Default Rest Positions', 400, false);
createMeasure('Rests Repositioned To Avoid Collisions', 400, true);
vf.draw();
ok(true);
},
};
return ThreeVoices;
}());
/**
* VexFlow - TickContext Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.TickContext = (function() {
var TickContext = {
Start: function() {
QUnit.module('TickContext');
test('Current Tick Test', VF.Test.TickContext.currentTick);
test('Tracking Test', VF.Test.TickContext.tracking);
},
currentTick: function() {
var tc = new VF.TickContext();
equal(tc.getCurrentTick().value(), 0, 'New tick context has no ticks');
},
tracking: function() {
function createTickable() {
return new VF.Test.MockTickable(VF.Test.TIME4_4);
}
var R = VF.RESOLUTION;
var BEAT = 1 * R / 4;
var tickables = [
createTickable().setTicks(BEAT).setWidth(10),
createTickable().setTicks(BEAT * 2).setWidth(20),
createTickable().setTicks(BEAT).setWidth(30),
];
var tc = new VF.TickContext();
tc.setPadding(0);
tc.addTickable(tickables[0]);
equal(tc.getMaxTicks().value(), BEAT);
tc.addTickable(tickables[1]);
equal(tc.getMaxTicks().value(), BEAT * 2);
tc.addTickable(tickables[2]);
equal(tc.getMaxTicks().value(), BEAT * 2);
equal(tc.getWidth(), 0);
tc.preFormat();
equal(tc.getWidth(), 30);
},
};
return TickContext;
})();
/**
* VexFlow - TimeSignature Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.TimeSignature = (function() {
return {
Start: function() {
QUnit.module('TimeSignature');
test('Time Signature Parser', function() {
var mustFail = ['asdf', '123/', '/10', '/', '4567', 'C+'];
var mustPass = ['4/4', '10/12', '1/8', '1234567890/1234567890', 'C', 'C|'];
var timeSig = new VF.TimeSignature();
mustFail.forEach(function(invalidString) {
throws(function() { timeSig.parseTimeSpec(invalidString); }, /BadTimeSignature/);
});
mustPass.forEach(function(validString) {
timeSig.parseTimeSpec(validString);
});
ok(true, 'all pass');
});
var run = VF.Test.runTests;
run('Basic Time Signatures', function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 120);
new VF.Stave(10, 10, 500)
.addTimeSignature('2/2')
.addTimeSignature('3/4')
.addTimeSignature('4/4')
.addTimeSignature('6/8')
.addTimeSignature('C')
.addTimeSignature('C|')
.addEndTimeSignature('2/2')
.addEndTimeSignature('3/4')
.addEndTimeSignature('4/4')
.addEndClef('treble')
.addEndTimeSignature('6/8')
.addEndTimeSignature('C')
.addEndTimeSignature('C|')
.setContext(ctx)
.draw();
ok(true, 'all pass');
});
run('Big Signature Test', function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 120);
new VF.Stave(10, 10, 300)
.addTimeSignature('12/8')
.addTimeSignature('7/16')
.addTimeSignature('1234567/890')
.addTimeSignature('987/654321')
.setContext(ctx)
.draw();
ok(true, 'all pass');
});
run('Time Signature multiple staves alignment test', function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 400, 350);
var stave = new VF.Stave(15, 0, 300)
.setConfigForLines(
[false, false, true, false, false].map(function(visible) {
return { visible: visible };
}))
.addClef('percussion')
.addTimeSignature('4/4', 25) // passing the custom padding in pixels
.setContext(ctx)
.draw();
var stave2 = new VF.Stave(15, 110, 300)
.addClef('treble')
.addTimeSignature('4/4')
.setContext(ctx)
.draw();
new VF.StaveConnector(stave, stave2)
.setType('single')
.setContext(ctx)
.draw();
var stave3 = new VF.Stave(15, 220, 300)
.addClef('bass')
.addTimeSignature('4/4')
.setContext(ctx)
.draw();
new VF.StaveConnector(stave2, stave3)
.setType('single')
.setContext(ctx)
.draw();
new VF.StaveConnector(stave2, stave3)
.setType('brace')
.setContext(ctx)
.draw();
ok(true, 'all pass');
});
run('Time Signature Change Test', function(options) {
var vf = VF.Test.makeFactory(options, 900);
var stave = vf.Stave(10, 10, 800)
.addClef('treble')
.addTimeSignature('C|');
var voice = vf.Voice().setStrict(false).addTickables([
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'treble' }),
vf.TimeSigNote({ time: '3/4' }),
vf.StaveNote({ keys: ['d/4'], duration: '4', clef: 'alto' }),
vf.StaveNote({ keys: ['b/3'], duration: '4r', clef: 'alto' }),
vf.TimeSigNote({ time: 'C' }),
vf.StaveNote({ keys: ['c/3', 'e/3', 'g/3'], duration: '4', clef: 'bass' }),
vf.TimeSigNote({ time: '9/8' }),
vf.StaveNote({ keys: ['c/4'], duration: '4', clef: 'treble' }),
]);
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'all pass');
});
},
};
}());
/**
* VexFlow - Tuning Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Tuning = (function() {
var Tuning = {
Start: function() {
QUnit.module('Tuning');
test('Standard Tuning', VF.Test.Tuning.standard);
test('Standard Banjo Tuning', VF.Test.Tuning.banjo);
test('Return note for fret', VF.Test.Tuning.noteForFret);
},
checkStandard: function(tuning) {
try {
tuning.getValueForString(0);
} catch (e) {
equal(e.code, 'BadArguments', 'String 0');
}
try {
tuning.getValueForString(9);
} catch (e) {
equal(e.code, 'BadArguments', 'String 7');
}
equal(tuning.getValueForString(6), 40, 'Low E string');
equal(tuning.getValueForString(5), 45, 'A string');
equal(tuning.getValueForString(4), 50, 'D string');
equal(tuning.getValueForString(3), 55, 'G string');
equal(tuning.getValueForString(2), 59, 'B string');
equal(tuning.getValueForString(1), 64, 'High E string');
},
checkStandardBanjo: function(tuning) {
try {
tuning.getValueForString(0);
} catch (e) {
equal(e.code, 'BadArguments', 'String 0');
}
try {
tuning.getValueForString(6);
} catch (e) {
equal(e.code, 'BadArguments', 'String 6');
}
equal(tuning.getValueForString(5), 67, 'High G string');
equal(tuning.getValueForString(4), 50, 'D string');
equal(tuning.getValueForString(3), 55, 'G string');
equal(tuning.getValueForString(2), 59, 'B string');
equal(tuning.getValueForString(1), 62, 'High D string');
},
banjo: function() {
expect(7);
var tuning = new VF.Tuning();
tuning.setTuning('standardBanjo');
VF.Test.Tuning.checkStandardBanjo(tuning);
},
standard: function() {
expect(16);
var tuning = new VF.Tuning();
VF.Test.Tuning.checkStandard(tuning);
// Test named tuning
tuning.setTuning('standard');
VF.Test.Tuning.checkStandard(tuning);
},
noteForFret: function() {
expect(8);
var tuning = new VF.Tuning('E/5,B/4,G/4,D/4,A/3,E/3');
try {
tuning.getNoteForFret(-1, 1);
} catch (e) {
equal(e.code, 'BadArguments', 'Fret -1');
}
try {
tuning.getNoteForFret(1, -1);
} catch (e) {
equal(e.code, 'BadArguments', 'String -1');
}
equal(tuning.getNoteForFret(0, 1), 'E/5', 'High E string');
equal(tuning.getNoteForFret(5, 1), 'A/5', 'High E string, fret 5');
equal(tuning.getNoteForFret(0, 2), 'B/4', 'B string');
equal(tuning.getNoteForFret(0, 3), 'G/4', 'G string');
equal(tuning.getNoteForFret(12, 2), 'B/5', 'B string, fret 12');
equal(tuning.getNoteForFret(0, 6), 'E/3', 'Low E string');
},
};
return Tuning;
})();
/**
* VexFlow - Tuplet Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Tuplet = (function() {
// Ideally this would be using arrow syntax...
var set = function(key) {
return function(value) {
return function(object) {
object[key] = value;
return object;
};
};
};
var setStemDirection = set('stem_direction');
var setDuration = set('duration');
var stemUp = setStemDirection(VF.Stem.UP);
var stemDown = setStemDirection(VF.Stem.DOWN);
var quarterNote = setDuration('4');
var Tuplet = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('Tuplet');
runTests('Simple Tuplet', Tuplet.simple);
runTests('Beamed Tuplet', Tuplet.beamed);
runTests('Ratioed Tuplet', Tuplet.ratio);
runTests('Bottom Tuplet', Tuplet.bottom);
runTests('Bottom Ratioed Tuplet', Tuplet.bottom_ratio);
runTests('Awkward Tuplet', Tuplet.awkward);
runTests('Complex Tuplet', Tuplet.complex);
runTests('Mixed Stem Direction Tuplet', Tuplet.mixedTop);
runTests('Mixed Stem Direction Bottom Tuplet', Tuplet.mixedBottom);
runTests('Nested Tuplets', Tuplet.nested);
runTests('Single Tuplets', Tuplet.single);
},
simple: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave({ x: 10, y: 10, width: 350 }).addTimeSignature('3/4');
var notes = [
{ keys: ['g/4'], duration: '4' },
{ keys: ['a/4'], duration: '4' },
{ keys: ['b/4'], duration: '4' },
{ keys: ['b/4'], duration: '8' },
{ keys: ['a/4'], duration: '8' },
{ keys: ['g/4'], duration: '8' },
].map(stemUp).map(vf.StaveNote.bind(vf));
vf.Tuplet({ notes: notes.slice(0, 3) });
vf.Tuplet({ notes: notes.slice(3, 6) });
// 3/4 time
var voice = vf.Voice({ time: { num_beats: 3, beat_value: 4 } })
.setStrict(true)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Simple Test');
},
beamed: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave({ x: 10, y: 10, width: 350 }).addTimeSignature('3/8');
var notes = [
{ keys: ['b/4'], duration: '16' },
{ keys: ['a/4'], duration: '16' },
{ keys: ['g/4'], duration: '16' },
{ keys: ['a/4'], duration: '8' },
{ keys: ['f/4'], duration: '8' },
{ keys: ['a/4'], duration: '8' },
{ keys: ['f/4'], duration: '8' },
{ keys: ['a/4'], duration: '8' },
{ keys: ['f/4'], duration: '8' },
{ keys: ['g/4'], duration: '8' },
].map(stemUp).map(vf.StaveNote.bind(vf));
vf.Beam({ notes: notes.slice(0, 3) });
vf.Beam({ notes: notes.slice(3, 10) });
vf.Tuplet({ notes: notes.slice(0, 3) });
vf.Tuplet({ notes: notes.slice(3, 10) });
// 3/8 time
var voice = vf.Voice({ time: { num_beats: 3, beat_value: 8 } })
.setStrict(true)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Beamed Test');
},
ratio: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave({ x: 10, y: 10, width: 350 }).addTimeSignature('4/4');
var notes = [
{ keys: ['f/4'], duration: '4' },
{ keys: ['a/4'], duration: '4' },
{ keys: ['b/4'], duration: '4' },
{ keys: ['g/4'], duration: '8' },
{ keys: ['e/4'], duration: '8' },
{ keys: ['g/4'], duration: '8' },
].map(stemUp).map(vf.StaveNote.bind(vf));
vf.Beam({
notes: notes.slice(3, 6),
});
vf.Tuplet({
notes: notes.slice(0, 3),
options: {
ratioed: true,
},
});
vf.Tuplet({
notes: notes.slice(3, 6),
options: {
ratioed: true,
notes_occupied: 4,
},
});
var voice = vf.Voice()
.setStrict(true)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Ratioed Test');
},
bottom: function(options) {
var vf = VF.Test.makeFactory(options, 350, 160);
var stave = vf.Stave({ x: 10, y: 10 }).addTimeSignature('3/4');
var notes = [
{ keys: ['f/4'], duration: '4' },
{ keys: ['c/4'], duration: '4' },
{ keys: ['g/4'], duration: '4' },
{ keys: ['d/5'], duration: '8' },
{ keys: ['g/3'], duration: '8' },
{ keys: ['b/4'], duration: '8' },
].map(stemDown).map(vf.StaveNote.bind(vf));
vf.Beam({
notes: notes.slice(3, 6),
});
vf.Tuplet({
notes: notes.slice(0, 3),
options: { location: VF.Tuplet.LOCATION_BOTTOM },
});
vf.Tuplet({
notes: notes.slice(3, 6),
options: { location: VF.Tuplet.LOCATION_BOTTOM },
});
var voice = vf.Voice({ time: { num_beats: 3, beat_value: 4 } })
.setStrict(true)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Bottom Test');
},
bottom_ratio: function(options) {
var vf = VF.Test.makeFactory(options, 350, 160);
var stave = vf.Stave({ x: 10, y: 10 }).addTimeSignature('5/8');
var notes = [
{ keys: ['f/4'], duration: '4' },
{ keys: ['c/4'], duration: '4' },
{ keys: ['d/4'], duration: '4' },
{ keys: ['d/5'], duration: '8' },
{ keys: ['g/5'], duration: '8' },
{ keys: ['b/4'], duration: '8' },
].map(stemDown).map(vf.StaveNote.bind(vf));
vf.Beam({
notes: notes.slice(3, 6),
});
vf.Tuplet({
notes: notes.slice(0, 3),
options: {
location: VF.Tuplet.LOCATION_BOTTOM,
ratioed: true,
},
});
vf.Tuplet({
notes: notes.slice(3, 6),
options: {
location: VF.Tuplet.LOCATION_BOTTOM,
notes_occupied: 1,
},
});
var voice = vf.Voice({ time: { num_beats: 5, beat_value: 8 } })
.setStrict(true)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Bottom Ratioed Test');
},
awkward: function(options) {
var vf = VF.Test.makeFactory(options, 350, 160);
var stave = vf.Stave({ x: 10, y: 10 });
var notes = [
{ keys: ['g/4'], duration: '16' },
{ keys: ['b/4'], duration: '16' },
{ keys: ['a/4'], duration: '16' },
{ keys: ['a/4'], duration: '16' },
{ keys: ['g/4'], duration: '16' },
{ keys: ['f/4'], duration: '16' },
{ keys: ['e/4'], duration: '16' },
{ keys: ['c/4'], duration: '16' },
{ keys: ['g/4'], duration: '16' },
{ keys: ['a/4'], duration: '16' },
{ keys: ['f/4'], duration: '16' },
{ keys: ['c/4'], duration: '8' },
{ keys: ['d/4'], duration: '8' },
{ keys: ['e/4'], duration: '8' },
].map(stemUp).map(vf.StaveNote.bind(vf));
vf.Beam({ notes: notes.slice(0, 11) });
vf.Tuplet({
notes: notes.slice(0, 11),
options: {
notes_occupied: 142,
ratioed: true,
},
});
vf.Tuplet({
notes: notes.slice(11, 14),
options: {
ratioed: true,
},
}).setBracketed(true);
var voice = vf.Voice()
.setStrict(false)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Awkward Test');
},
complex: function(options) {
var vf = VF.Test.makeFactory(options, 600);
var stave = vf.Stave({ x: 10, y: 10 }).addTimeSignature('4/4');
var notes1 = [
{ keys: ['b/4'], duration: '8d' },
{ keys: ['a/4'], duration: '16' },
{ keys: ['g/4'], duration: '8' },
{ keys: ['a/4'], duration: '16' },
{ keys: ['b/4'], duration: '16r' },
{ keys: ['g/4'], duration: '32' },
{ keys: ['f/4'], duration: '32' },
{ keys: ['g/4'], duration: '32' },
{ keys: ['f/4'], duration: '32' },
{ keys: ['a/4'], duration: '16' },
{ keys: ['f/4'], duration: '8' },
{ keys: ['b/4'], duration: '8' },
{ keys: ['a/4'], duration: '8' },
{ keys: ['g/4'], duration: '8' },
{ keys: ['b/4'], duration: '8' },
{ keys: ['a/4'], duration: '8' },
].map(stemUp).map(vf.StaveNote.bind(vf));
notes1[0].addDotToAll();
var notes2 = [
{ keys: ['c/4'] },
{ keys: ['c/4'] },
{ keys: ['c/4'] },
{ keys: ['c/4'] },
].map(quarterNote).map(stemDown).map(vf.StaveNote.bind(vf));
vf.Beam({ notes: notes1.slice(0, 3) });
vf.Beam({ notes: notes1.slice(5, 9) });
vf.Beam({ notes: notes1.slice(11, 16) });
vf.Tuplet({
notes: notes1.slice(0, 3),
});
vf.Tuplet({
notes: notes1.slice(3, 11),
options: {
num_notes: 7,
notes_occupied: 4,
ratioed: false,
},
});
vf.Tuplet({
notes: notes1.slice(11, 16),
options: {
notes_occupied: 4,
},
});
var voice1 = vf.Voice()
.setStrict(true)
.addTickables(notes1);
var voice2 = vf.Voice()
.setStrict(true)
.addTickables(notes2);
new VF.Formatter()
.joinVoices([voice1, voice2])
.formatToStave([voice1, voice2], stave);
vf.draw();
ok(true, 'Complex Test');
},
mixedTop: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave({ x: 10, y: 10 });
var notes = [
{ keys: ['a/4'], stem_direction: 1 },
{ keys: ['c/6'], stem_direction: -1 },
{ keys: ['a/4'], stem_direction: 1 },
{ keys: ['f/5'], stem_direction: 1 },
{ keys: ['a/4'], stem_direction: -1 },
{ keys: ['c/6'], stem_direction: -1 },
].map(quarterNote).map(vf.StaveNote.bind(vf));
vf.Tuplet({
notes: notes.slice(0, 2),
options: {
notes_occupied: 3,
},
});
vf.Tuplet({
notes: notes.slice(2, 4),
options: {
notes_occupied: 3,
},
});
vf.Tuplet({
notes: notes.slice(4, 6),
options: {
notes_occupied: 3,
},
});
var voice = vf.Voice()
.setStrict(false)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Mixed Stem Direction Tuplet');
},
mixedBottom: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave({ x: 10, y: 10 });
var notes = [
{ keys: ['f/3'], stem_direction: 1 },
{ keys: ['a/5'], stem_direction: -1 },
{ keys: ['a/4'], stem_direction: 1 },
{ keys: ['f/3'], stem_direction: 1 },
{ keys: ['a/4'], stem_direction: -1 },
{ keys: ['c/4'], stem_direction: -1 },
].map(quarterNote).map(vf.StaveNote.bind(vf));
vf.Tuplet({
notes: notes.slice(0, 2),
options: {
notes_occupied: 3,
},
});
vf.Tuplet({
notes: notes.slice(2, 4),
options: {
notes_occupied: 3,
},
});
vf.Tuplet({
notes: notes.slice(4, 6),
options: {
notes_occupied: 3,
},
});
var voice = vf.Voice()
.setStrict(false)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Mixed Stem Direction Bottom Tuplet');
},
nested: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave({ x: 10, y: 10 }).addTimeSignature('4/4');
var notes = [
// Big triplet 1:
{ keys: ['b/4'], duration: '4' },
{ keys: ['a/4'], duration: '4' },
{ keys: ['g/4'], duration: '16' },
{ keys: ['a/4'], duration: '16' },
{ keys: ['f/4'], duration: '16' },
{ keys: ['a/4'], duration: '16' },
{ keys: ['g/4'], duration: '16' },
{ keys: ['b/4'], duration: '2' },
].map(stemUp).map(vf.StaveNote.bind(vf));
vf.Beam({
notes: notes.slice(2, 7),
});
vf.Tuplet({
notes: notes.slice(0, 7),
options: {
notes_occupied: 2,
num_notes: 3,
},
});
vf.Tuplet({
notes: notes.slice(2, 7),
options: {
notes_occupied: 4,
num_notes: 5,
},
});
// 4/4 time
var voice = vf.Voice()
.setStrict(true)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Nested Tuplets');
},
single: function(options) {
var vf = VF.Test.makeFactory(options);
var stave = vf.Stave({ x: 10, y: 10 }).addTimeSignature('4/4');
var notes = [
// Big triplet 1:
{ keys: ['c/4'], duration: '4' },
{ keys: ['d/4'], duration: '8' },
{ keys: ['e/4'], duration: '8' },
{ keys: ['f/4'], duration: '8' },
{ keys: ['g/4'], duration: '8' },
{ keys: ['a/4'], duration: '2' },
{ keys: ['b/4'], duration: '4' },
].map(stemUp).map(vf.StaveNote.bind(vf));
vf.Beam({
notes: notes.slice(1, 4),
});
// big quartuplet
vf.Tuplet({
notes: notes.slice(0, -1),
options: {
num_notes: 4,
notes_occupied: 3,
ratioed: true,
bracketed: true,
},
});
// first singleton
vf.Tuplet({
notes: notes.slice(0, 1),
options: {
num_notes: 3,
notes_occupied: 2,
ratioed: true,
},
});
// eighth note triplet
vf.Tuplet({
notes: notes.slice(1, 4),
options: {
num_notes: 3,
notes_occupied: 2,
},
});
// second singleton
vf.Tuplet({
notes: notes.slice(4, 5),
options: {
num_notes: 3,
notes_occupied: 2,
ratioed: true,
bracketed: true,
},
});
// 4/4 time
var voice = vf.Voice({ time: { num_beats: 4, beat_value: 4 } })
.setStrict(true)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true, 'Nested Tuplets');
},
};
return Tuplet;
})();
/**
* VexFlow - Vibrato Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Vibrato = (function() {
var Vibrato = {
Start: function() {
var runTests = VF.Test.runTests;
QUnit.module('Vibrato');
runTests('Simple Vibrato', Vibrato.simple);
runTests('Harsh Vibrato', Vibrato.harsh);
runTests('Vibrato with Bend', Vibrato.withBend);
},
simple: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 500, 140);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 10, 450)
.addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newVibrato() { return new VF.Vibrato(); }
var notes = [
newNote({
positions: [{ str: 2, fret: 10 }, { str: 4, fret: 9 }], duration: 'h' })
.addModifier(newVibrato(), 0),
newNote({
positions: [{ str: 2, fret: 10 }], duration: 'h' })
.addModifier(newVibrato(), 0),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes);
ok(true, 'Simple Vibrato');
},
harsh: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5); ctx.fillStyle = '#221'; ctx.strokeStyle = '#221';
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 10, 450)
.addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newVibrato() { return new VF.Vibrato(); }
var notes = [
newNote({
positions: [{ str: 2, fret: 10 }, { str: 4, fret: 9 }], duration: 'h' })
.addModifier(newVibrato().setHarsh(true), 0),
newNote({
positions: [{ str: 2, fret: 10 }], duration: 'h' })
.addModifier(newVibrato().setHarsh(true), 0),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes);
ok(true, 'Harsh Vibrato');
},
withBend: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 500, 240);
ctx.scale(1.3, 1.3); ctx.setFillStyle('#221'); ctx.setStrokeStyle('#221');
ctx.setFont('Arial', VF.Test.Font.size, '');
var stave = new VF.TabStave(10, 10, 450)
.addTabGlyph().setContext(ctx).draw();
function newNote(tab_struct) { return new VF.TabNote(tab_struct); }
function newBend(text, release) { return new VF.Bend(text, release); }
function newVibrato() { return new VF.Vibrato(); }
var notes = [
newNote({
positions: [{ str: 2, fret: 9 }, { str: 3, fret: 9 }], duration: 'q' })
.addModifier(newBend('1/2', true), 0)
.addModifier(newBend('1/2', true), 1)
.addModifier(newVibrato(), 0),
newNote({
positions: [{ str: 2, fret: 10 }], duration: 'q' })
.addModifier(newBend('Full', false), 0)
.addModifier(newVibrato().setVibratoWidth(60), 0),
newNote({
positions: [{ str: 2, fret: 10 }], duration: 'h' })
.addModifier(newVibrato().setVibratoWidth(120).setHarsh(true), 0),
];
VF.Formatter.FormatAndDraw(ctx, stave, notes);
ok(true, 'Vibrato with Bend');
},
};
return Vibrato;
})();
/**
* VexFlow - VibratoBracket Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*
* Author: Balazs Forian-Szabo
*/
VF.Test.VibratoBracket = (function() {
function createTest(noteGroup1, setupVibratoBracket) {
return function(options) {
var vf = VF.Test.makeFactory(options, 650, 200);
var stave = vf.Stave();
var score = vf.EasyScore();
var voice = score.voice(score.notes.apply(score, noteGroup1));
setupVibratoBracket(vf, voice.getTickables());
vf.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
vf.draw();
ok(true);
};
}
return {
Start: function() {
var run = VF.Test.runTests;
QUnit.module('VibratoBracket');
run('Simple VibratoBracket', createTest(
['c4/4, c4, c4, c4'],
function(vf, notes) {
vf.VibratoBracket({
from: notes[0],
to: notes[3],
options: {
line: 2,
},
});
}
));
run('Harsh VibratoBracket Without End Note', createTest(
['c4/4, c4, c4, c4'],
function(vf, notes) {
vf.VibratoBracket({
from: notes[2],
to: null,
options: {
line: 2,
harsh: true,
},
});
}
));
run('Harsh VibratoBracket Without Start Note', createTest(
['c4/4, c4, c4, c4'],
function(vf, notes) {
vf.VibratoBracket({
from: null,
to: notes[2],
options: {
line: 2,
harsh: true,
},
});
}
));
},
};
})();
/**
* VexFlow - Voice Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
VF.Test.Voice = (function() {
var Voice = {
Start: function() {
QUnit.module('Voice');
test('Strict Test', VF.Test.Voice.strict);
test('Ignore Test', VF.Test.Voice.ignore);
VF.Test.runTests('Full Voice Mode Test', VF.Test.Voice.full);
},
strict: function() {
expect(8);
function createTickable() {
return new VF.Test.MockTickable(VF.Test.TIME4_4);
}
var R = VF.RESOLUTION;
var BEAT = 1 * R / 4;
var tickables = [
createTickable().setTicks(BEAT),
createTickable().setTicks(BEAT),
createTickable().setTicks(BEAT),
];
var voice = new VF.Voice(VF.Test.TIME4_4);
equal(voice.totalTicks.value(), BEAT * 4, '4/4 Voice has 4 beats');
equal(voice.ticksUsed.value(), BEAT * 0, 'No beats in voice');
voice.addTickables(tickables);
equal(voice.ticksUsed.value(), BEAT * 3, 'Three beats in voice');
voice.addTickable(createTickable().setTicks(BEAT));
equal(voice.ticksUsed.value(), BEAT * 4, 'Four beats in voice');
equal(voice.isComplete(), true, 'Voice is complete');
var beforeNumerator = voice.ticksUsed.numerator;
try {
voice.addTickable(createTickable().setTicks(BEAT));
} catch (e) {
equal(e.code, 'BadArgument', 'Too many ticks exception');
equal(voice.ticksUsed.numerator, beforeNumerator, 'Revert "ticksUsed" when it occurred "Too many ticks" exception');
}
equal(voice.getSmallestTickCount().value(), BEAT, 'Smallest tick count is BEAT');
},
ignore: function() {
function createTickable() {
return new VF.Test.MockTickable(VF.Test.TIME4_4);
}
var R = VF.RESOLUTION;
var BEAT = 1 * R / 4;
var tickables = [
createTickable().setTicks(BEAT),
createTickable().setTicks(BEAT),
createTickable().setTicks(BEAT).setIgnoreTicks(true),
createTickable().setTicks(BEAT),
createTickable().setTicks(BEAT).setIgnoreTicks(true),
createTickable().setTicks(BEAT),
];
var voice = new VF.Voice(VF.Test.TIME4_4);
voice.addTickables(tickables);
ok(true, 'all pass');
},
full: function(options, contextBuilder) {
var ctx = contextBuilder(options.elementId, 550, 200);
var stave = new VF.Stave(10, 50, 500)
.addClef('treble')
.addTimeSignature('4/4')
.setEndBarType(VF.Barline.type.END);
var notes = [
new VF.StaveNote({ keys: ['c/4'], duration: '4' }),
new VF.StaveNote({ keys: ['d/4'], duration: '4' }),
new VF.StaveNote({ keys: ['r/4'], duration: '4r' }),
];
notes.forEach(function(note) { note.setStave(stave); });
var voice = new VF.Voice(VF.Test.TIME4_4)
.setMode(VF.Voice.Mode.FULL)
.addTickables(notes);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
stave.setContext(ctx).draw();
voice.draw(ctx);
voice.getBoundingBox().draw(ctx);
throws(function() {
voice.addTickable(new VF.StaveNote({ keys: ['c/4'], duration: '2' }));
}, /BadArgument/, 'Voice cannot exceed full amount of ticks');
},
};
return Voice;
})();
VF.Test.run = function() {
VF.Test.Accidental.Start();
VF.Test.StaveNote.Start();
VF.Test.Voice.Start();
VF.Test.NoteHead.Start();
VF.Test.TabNote.Start();
VF.Test.TickContext.Start();
VF.Test.ModifierContext.Start();
VF.Test.Dot.Start();
VF.Test.Bend.Start();
VF.Test.Formatter.Start();
VF.Test.Fraction.Start();
VF.Test.Clef.Start();
VF.Test.KeySignature.Start();
VF.Test.TimeSignature.Start();
VF.Test.StaveTie.Start();
VF.Test.TabTie.Start();
VF.Test.Stave.Start();
VF.Test.TabStave.Start();
VF.Test.TabSlide.Start();
VF.Test.Beam.Start();
VF.Test.Barline.Start();
VF.Test.AutoBeamFormatting.Start();
VF.Test.GraceNote.Start();
VF.Test.GraceTabNote.Start();
VF.Test.Vibrato.Start();
VF.Test.VibratoBracket.Start();
VF.Test.Annotation.Start();
VF.Test.Tuning.Start();
VF.Test.Music.Start();
VF.Test.KeyManager.Start();
VF.Test.Articulation.Start();
VF.Test.StaveConnector.Start();
VF.Test.MultiMeasureRest.Start();
VF.Test.Percussion.Start();
VF.Test.NoteSubGroup.Start();
VF.Test.ClefKeySignature.Start();
VF.Test.StaveHairpin.Start();
VF.Test.Rhythm.Start();
VF.Test.Tuplet.Start();
VF.Test.BoundingBox.Start();
VF.Test.Strokes.Start();
VF.Test.StringNumber.Start();
VF.Test.Rests.Start();
VF.Test.ThreeVoices.Start();
VF.Test.Curve.Start();
VF.Test.TextNote.Start();
VF.Test.StaveLine.Start();
VF.Test.Ornament.Start();
VF.Test.PedalMarking.Start();
VF.Test.TextBracket.Start();
VF.Test.StaveModifier.Start();
VF.Test.GhostNote.Start();
VF.Test.Factory.Start();
VF.Test.Parser.Start();
VF.Test.EasyScore.Start();
VF.Test.Registry.Start();
VF.Test.BachDemo.Start();
};
module.exports = VF.Test;
//# sourceMappingURL=vexflow-tests.js.map