File size: 2,991 Bytes
af6912c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
var getLeftEdgeOfStaff = require('./get-left-edge-of-staff');

function layoutInGrid(renderer, staffGroup, timeBasedLayout) {
	var leftEdge = getLeftEdgeOfStaff(renderer, staffGroup.getTextSize, staffGroup.voices, staffGroup.brace, staffGroup.bracket);
	var ret = getTotalDuration(staffGroup, timeBasedLayout.minPadding)
	var totalDuration = ret.totalDuration
	var minSpacing = ret.minSpacing
	var totalWidth = minSpacing * totalDuration
	if (timeBasedLayout.minWidth)
		totalWidth = Math.max(totalWidth, timeBasedLayout.minWidth)
	var leftAlignPadding = timeBasedLayout.minPadding ? timeBasedLayout.minPadding/2 : 2 // If the padding isn't specified still give it some

	staffGroup.startx = leftEdge
	staffGroup.w = totalWidth + leftEdge
	for (var i = 0; i < staffGroup.voices.length; i++) {
		var voice = staffGroup.voices[i]
		voice.startx = leftEdge
		voice.w = totalWidth + leftEdge

		var x = leftEdge
		var afterFixedLeft = false
		var durationUnit = 0
		for (var j = 0; j < voice.children.length; j++) {
			var child = voice.children[j]
			if (!afterFixedLeft) {
				if (child.duration !== 0) {
					// We got to the first music element on the line
					afterFixedLeft = true
					durationUnit = (totalWidth + leftEdge - x) / totalDuration
					staffGroup.gridStart = x
				} else {
					// We are still doing the preliminary stuff - clef, time sig, etc.
					child.x = x
					x += child.w + child.minspacing
				}
			}
			if (afterFixedLeft) {
				if (timeBasedLayout.align === 'center')
					child.x = x + (child.duration * durationUnit) / 2 - child.w / 2
				else {
					// left align with padding - but no padding for barlines, they should be right aligned.
					// TODO-PER: it looks better to move bar lines one pixel to right. Not sure why.
					if (child.duration === 0) {
						child.x = x + 1 - child.w
					} else {
						// child.extraw has the width of the accidentals - push the note to the right to take that into consideration. It will be 0 if there is nothing to the left.
						child.x = x + leftAlignPadding - child.extraw
					}
				}
				x += child.duration * durationUnit
			}
			for (var k = 0; k < child.children.length; k++) {
				var grandchild = child.children[k]
				// some elements don't have a dx - Tempo, for instance
				var dx = grandchild.dx ? grandchild.dx : 0
				grandchild.x = child.x + dx
			}
		}
		staffGroup.gridEnd = x
	}
	return totalWidth
}

function getTotalDuration(staffGroup, timeBasedLayout) {
	var maxSpacing = 0
	var maxCount = 0
	for (var i = 0; i < staffGroup.voices.length; i++) {
		var count = 0
		var voice = staffGroup.voices[i]
		for (var j = 0; j < voice.children.length; j++) {
			var element = voice.children[j]
			count += element.duration
			if (element.duration) {
				var width = (element.w+timeBasedLayout) / element.duration
				maxSpacing = Math.max(maxSpacing, width)
			}
		}
		maxCount = Math.max(maxCount, count)
	}
	return { totalDuration: maxCount, minSpacing: maxSpacing}
}

module.exports = layoutInGrid;