|
|
var layoutVoice = require('./voice'); |
|
|
var setUpperAndLowerElements = require('./set-upper-and-lower-elements'); |
|
|
var layoutStaffGroup = require('./staff-group'); |
|
|
var getLeftEdgeOfStaff = require('./get-left-edge-of-staff'); |
|
|
var layoutInGrid = require('./layout-in-grid'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var layout = function (renderer, abctune, width, space, expandToWidest, timeBasedLayout) { |
|
|
var i; |
|
|
var abcLine; |
|
|
|
|
|
var maxWidth = width; |
|
|
for (i = 0; i < abctune.lines.length; i++) { |
|
|
abcLine = abctune.lines[i]; |
|
|
if (abcLine.staff) { |
|
|
|
|
|
var thisWidth; |
|
|
if (timeBasedLayout !== undefined) |
|
|
thisWidth = layoutInGrid(renderer, abcLine.staffGroup, timeBasedLayout); |
|
|
else |
|
|
thisWidth = setXSpacing(renderer, maxWidth, space, abcLine.staffGroup, abctune.formatting, i === abctune.lines.length - 1, false); |
|
|
|
|
|
if (Math.round(thisWidth) > Math.round(maxWidth)) { |
|
|
maxWidth = thisWidth |
|
|
if (expandToWidest) |
|
|
i = -1 |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (i = 0; i < abctune.lines.length; i++) { |
|
|
abcLine = abctune.lines[i]; |
|
|
if (abcLine.staffGroup && abcLine.staffGroup.voices) { |
|
|
for (var j = 0; j < abcLine.staffGroup.voices.length; j++) |
|
|
layoutVoice(abcLine.staffGroup.voices[j]); |
|
|
setUpperAndLowerElements(renderer, abcLine.staffGroup); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < abctune.lines.length; i++) { |
|
|
abcLine = abctune.lines[i]; |
|
|
if (abcLine.staffGroup) { |
|
|
abcLine.staffGroup.setHeight(); |
|
|
} |
|
|
} |
|
|
return maxWidth; |
|
|
} |
|
|
|
|
|
var setXSpacing = function (renderer, width, space, staffGroup, formatting, isLastLine, debug) { |
|
|
var leftEdge = getLeftEdgeOfStaff(renderer, staffGroup.getTextSize, staffGroup.voices, staffGroup.brace, staffGroup.bracket); |
|
|
var newspace = space; |
|
|
|
|
|
for (var it = 0; it < 8; it++) { |
|
|
|
|
|
var ret = layoutStaffGroup(newspace, renderer.minPadding, debug, staffGroup, leftEdge); |
|
|
newspace = calcHorizontalSpacing(isLastLine, formatting.stretchlast, width + renderer.padding.left, staffGroup.w, newspace, ret.spacingUnits, ret.minSpace, renderer.padding.left + renderer.padding.right); |
|
|
if (debug) |
|
|
console.log("setXSpace", it, staffGroup.w, newspace, staffGroup.minspace); |
|
|
if (newspace === null) break; |
|
|
} |
|
|
|
|
|
centerWholeRests(staffGroup.voices); |
|
|
return staffGroup.w - leftEdge |
|
|
}; |
|
|
|
|
|
function replacer(key, value) { |
|
|
|
|
|
if (key === 'parent') { |
|
|
return 'parent'; |
|
|
} |
|
|
if (key === 'beam') { |
|
|
return 'beam'; |
|
|
} |
|
|
return value; |
|
|
} |
|
|
|
|
|
function dumpGroup(label, staffGroup) { |
|
|
console.log("=================== " + label + " =========================") |
|
|
console.log(staffGroup) |
|
|
console.log(JSON.stringify(staffGroup, replacer, "\t")) |
|
|
} |
|
|
|
|
|
function calcHorizontalSpacing(isLastLine, stretchLast, targetWidth, lineWidth, spacing, spacingUnits, minSpace, padding) { |
|
|
if (isLastLine) { |
|
|
if (stretchLast === undefined) { |
|
|
if (lineWidth / targetWidth < 0.66) return null; |
|
|
} else { |
|
|
|
|
|
var lack = 1 - (lineWidth + padding) / targetWidth; |
|
|
var stretch = lack < stretchLast; |
|
|
if (!stretch) return null; |
|
|
} |
|
|
} |
|
|
if (Math.abs(targetWidth - lineWidth) < 2) return null; |
|
|
var relSpace = spacingUnits * spacing; |
|
|
var constSpace = lineWidth - relSpace; |
|
|
if (spacingUnits > 0) { |
|
|
spacing = (targetWidth - constSpace) / spacingUnits; |
|
|
if (spacing * minSpace > 50) { |
|
|
spacing = 50 / minSpace; |
|
|
} |
|
|
return spacing; |
|
|
} |
|
|
return null; |
|
|
} |
|
|
|
|
|
function centerWholeRests(voices) { |
|
|
|
|
|
|
|
|
for (var i = 0; i < voices.length; i++) { |
|
|
var voice = voices[i]; |
|
|
|
|
|
for (var j = 1; j < voice.children.length - 1; j++) { |
|
|
var absElem = voice.children[j]; |
|
|
if (absElem.abcelem.rest && (absElem.abcelem.rest.type === 'whole' || absElem.abcelem.rest.type === 'multimeasure')) { |
|
|
var before = voice.children[j - 1]; |
|
|
var after = voice.children[j + 1]; |
|
|
absElem.center(before, after); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
module.exports = layout; |
|
|
|