|
|
var layoutVoiceElements = require('./voice-elements'); |
|
|
|
|
|
function checkLastBarX(voices) { |
|
|
var maxX = 0; |
|
|
for (var i = 0; i < voices.length; i++) { |
|
|
var curVoice = voices[i]; |
|
|
if (curVoice.children.length > 0) { |
|
|
var lastChild = curVoice.children.length - 1; |
|
|
var maxChild = curVoice.children[lastChild]; |
|
|
if (maxChild.abcelem.el_type === 'bar') { |
|
|
var barX = maxChild.children[0].x; |
|
|
if (barX > maxX) { |
|
|
maxX = barX; |
|
|
} else { |
|
|
maxChild.children[0].x = maxX; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
var layoutStaffGroup = function (spacing, minPadding, debug, staffGroup, leftEdge) { |
|
|
var epsilon = 0.0000001; |
|
|
var spacingunits = 0; |
|
|
var minspace = 1000; |
|
|
|
|
|
var x = leftEdge; |
|
|
staffGroup.startx = x; |
|
|
var i; |
|
|
|
|
|
var currentduration = 0; |
|
|
if (debug) console.log("init layout", spacing); |
|
|
for (i = 0; i < staffGroup.voices.length; i++) { |
|
|
layoutVoiceElements.beginLayout(x, staffGroup.voices[i]); |
|
|
} |
|
|
|
|
|
var spacingunit = 0; |
|
|
while (!finished(staffGroup.voices)) { |
|
|
|
|
|
currentduration = null; |
|
|
for (i = 0; i < staffGroup.voices.length; i++) { |
|
|
if (!layoutVoiceElements.layoutEnded(staffGroup.voices[i]) && (!currentduration || getDurationIndex(staffGroup.voices[i]) < currentduration)) |
|
|
currentduration = getDurationIndex(staffGroup.voices[i]); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var currentvoices = []; |
|
|
var othervoices = []; |
|
|
for (i = 0; i < staffGroup.voices.length; i++) { |
|
|
var durationIndex = getDurationIndex(staffGroup.voices[i]); |
|
|
|
|
|
if (durationIndex - currentduration > epsilon) { |
|
|
othervoices.push(staffGroup.voices[i]); |
|
|
|
|
|
} else { |
|
|
currentvoices.push(staffGroup.voices[i]); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
spacingunit = 0; |
|
|
var spacingduration = 0; |
|
|
for (i = 0; i < currentvoices.length; i++) { |
|
|
|
|
|
if (layoutVoiceElements.getNextX(currentvoices[i]) > x) { |
|
|
x = layoutVoiceElements.getNextX(currentvoices[i]); |
|
|
spacingunit = layoutVoiceElements.getSpacingUnits(currentvoices[i]); |
|
|
spacingduration = currentvoices[i].spacingduration; |
|
|
} |
|
|
} |
|
|
spacingunits += spacingunit; |
|
|
minspace = Math.min(minspace, spacingunit); |
|
|
if (debug) console.log("currentduration: ", currentduration, spacingunits, minspace); |
|
|
|
|
|
var lastTopVoice = undefined; |
|
|
for (i = 0; i < currentvoices.length; i++) { |
|
|
var v = currentvoices[i]; |
|
|
if (v.voicenumber === 0) |
|
|
lastTopVoice = i; |
|
|
var topVoice = (lastTopVoice !== undefined && currentvoices[lastTopVoice].voicenumber !== v.voicenumber) ? currentvoices[lastTopVoice] : undefined; |
|
|
if (!isSameStaff(v, topVoice)) |
|
|
topVoice = undefined; |
|
|
var voicechildx = layoutVoiceElements.layoutOneItem(x, spacing, v, minPadding, topVoice); |
|
|
var dx = voicechildx - x; |
|
|
if (dx > 0) { |
|
|
x = voicechildx; |
|
|
for (var j = 0; j < i; j++) { |
|
|
layoutVoiceElements.shiftRight(dx, currentvoices[j]); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (i = 0; i < othervoices.length; i++) { |
|
|
othervoices[i].spacingduration -= spacingduration; |
|
|
layoutVoiceElements.updateNextX(x, spacing, othervoices[i]); |
|
|
} |
|
|
|
|
|
|
|
|
for (i = 0; i < currentvoices.length; i++) { |
|
|
var voice = currentvoices[i]; |
|
|
layoutVoiceElements.updateIndices(voice); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < staffGroup.voices.length; i++) { |
|
|
if (layoutVoiceElements.getNextX(staffGroup.voices[i]) > x) { |
|
|
x = layoutVoiceElements.getNextX(staffGroup.voices[i]); |
|
|
spacingunit = layoutVoiceElements.getSpacingUnits(staffGroup.voices[i]); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
checkLastBarX(staffGroup.voices); |
|
|
|
|
|
spacingunits += spacingunit; |
|
|
staffGroup.setWidth(x); |
|
|
|
|
|
return { spacingUnits: spacingunits, minSpace: minspace }; |
|
|
}; |
|
|
|
|
|
|
|
|
function finished(voices) { |
|
|
for (var i = 0; i < voices.length; i++) { |
|
|
if (!layoutVoiceElements.layoutEnded(voices[i])) return false; |
|
|
} |
|
|
return true; |
|
|
} |
|
|
|
|
|
function getDurationIndex(element) { |
|
|
return element.durationindex - (element.children[element.i] && (element.children[element.i].duration > 0) ? 0 : 0.0000005); |
|
|
} |
|
|
|
|
|
function isSameStaff(voice1, voice2) { |
|
|
if (!voice1 || !voice1.staff || !voice1.staff.voices || voice1.staff.voices.length === 0) |
|
|
return false; |
|
|
if (!voice2 || !voice2.staff || !voice2.staff.voices || voice2.staff.voices.length === 0) |
|
|
return false; |
|
|
return (voice1.staff.voices[0] === voice2.staff.voices[0]); |
|
|
} |
|
|
|
|
|
module.exports = layoutStaffGroup; |
|
|
|