Skip to content

Commit

Permalink
Issue 969
Browse files Browse the repository at this point in the history
Fix issue with long measures that don't take up full space
  • Loading branch information
AaronDavidNewman committed May 8, 2021
1 parent 423ed7f commit 6c18e85
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
5 changes: 3 additions & 2 deletions src/formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -617,13 +617,14 @@ export class Formatter {
firstContext.getMetrics().totalLeftPx;
let targetWidth = adjustedJustifyWidth;
let actualWidth = shiftToIdealDistances(calculateIdealDistances(targetWidth));
const maxX = adjustedJustifyWidth + lastContext.getMetrics().notePx;

let iterations = this.options.maxIterations;
while (actualWidth > adjustedJustifyWidth + lastContext.getMetrics().notePx && iterations > 0) {
while (actualWidth > maxX && iterations > 0) {
// If we couldn't fit all the notes into the jusification width, it's because the softmax-scaled
// widths between different durations differ across stave (e.g., 1 quarter note is not the same pixel-width
// as 4 16th-notes). Run another pass, now that we know how much to justify.
targetWidth -= actualWidth - targetWidth;
targetWidth -= actualWidth - maxX;
actualWidth = shiftToIdealDistances(calculateIdealDistances(targetWidth));
iterations--;
}
Expand Down
43 changes: 43 additions & 0 deletions tests/formatter_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ VF.Test.Formatter = (function () {
QUnit.module('Formatter');
test('TickContext Building', Formatter.buildTickContexts);
runSVG('Justification and alignment with accidentals', Formatter.accidentalJustification);
runSVG('Long measure taking full space', Formatter.longMeasureProblems);
runSVG('Vertical alignment - few unaligned beats', Formatter.unalignedNoteDurations);
runSVG('Vertical alignment - many unaligned beats', Formatter.unalignedNoteDurations2, { globalSoftmax: false });
runSVG('Vertical alignment - many unaligned beats (global softmax)', Formatter.unalignedNoteDurations2, {
Expand Down Expand Up @@ -94,6 +95,48 @@ VF.Test.Formatter = (function () {
'Second note of voice 2 is to the right of the second note of voice 1'
);
},
longMeasureProblems: (options) => {
var registry = new VF.Registry();
VF.Registry.enableDefaultRegistry(registry);
var vf = VF.Test.makeFactory(options, 1500, 300);
var score = vf.EasyScore();
score.set({
time: '4/4',
});
const notes1 = score.notes(
'b4/4,b4/8,b4/8,b4/4,b4/4,b4/2,b4/2,b4/4,b4/8,b4/8,b4/4,b4/4,b4/2,b4/2,b4/4,b4/8,b4/8,b4/4,b4/4,b4/2,b4/2,b4/4,b4/2,b4/8,b4/8'
);
const voice1 = new VF.Voice().setMode(VF.Voice.Mode.Soft);
const notes2 = score.notes(
'd3/4,(ab3 f4)/2,d3/4,ab3/4,d3/2,ab3/4,d3/4,ab3/2,d3/4,ab3/4,d3/2,ab3/4,d3/4,ab3/2,d3/4,ab3/4,d3/2,ab3/4,d4/4,d4/2,d4/4',
{
clef: 'bass',
}
);
const voice2 = new VF.Voice().setMode(VF.Voice.Mode.Soft);
voice2.addTickables(notes2);
voice1.addTickables(notes1);
const stave1 = vf.Stave({
y: 50,
width: 1500,
});
const stave2 = vf.Stave({
y: 200,
width: 1500,
});
vf.StaveConnector({
top_stave: stave1,
bottom_stave: stave2,
type: 'brace',
});
var formatter = vf.Formatter().joinVoices([voice1]).joinVoices([voice2]);
formatter.format([voice1, voice2], 1500);
stave1.draw();
stave2.draw();
voice1.draw(vf.context, stave1);
voice2.draw(vf.context, stave2);
ok(true);
},

accidentalJustification: (options) => {
var vf = VF.Test.makeFactory(options, 600, 300);
Expand Down

0 comments on commit 6c18e85

Please sign in to comment.