File size: 4,348 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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
var sprintf = require('./sprintf');
var roundNumber = require("./round-number");

function drawTie(renderer, params, linestartx, lineendx, selectables) {
	layout(params, linestartx, lineendx);

	var klass = '';
	if (params.anchor1) {
		klass += 'abcjs-start-m' + params.anchor1.parent.counters.measure + '-n' + params.anchor1.parent.counters.note;
	} else
		klass += 'abcjs-start-edge';
	if (params.anchor2) {
		klass += ' abcjs-end-m' + params.anchor2.parent.counters.measure + '-n' + params.anchor2.parent.counters.note;
	} else
		klass += ' abcjs-end-edge';
	if (params.hint)
		klass = "abcjs-hint";
	var fudgeY = params.fixedY ? 1.5 : 0; // TODO-PER: This just compensates for drawArc, which contains too much knowledge of ties and slurs.
	var el = drawArc(renderer, params.startX, params.endX, params.startY + fudgeY, params.endY + fudgeY, params.above, klass, params.isTie, params.dotted);
	var startChar = -1
	// This gets the start and end points of the contents of the slur. We assume that the parenthesis are just to the outside of that.
	if (params.anchor1 && !params.isTie)
		startChar = params.anchor1.parent.abcelem.startChar - 1
	var endChar = -1
	if (params.anchor2 && !params.isTie)
		endChar = params.anchor2.parent.abcelem.endChar + 1

	selectables.wrapSvgEl({ el_type: "slur", startChar: startChar, endChar: endChar }, el);
	return [el];
}

// TODO-PER: I think params part should have been done earlier in the layout pass.
var layout = function (params, lineStartX, lineEndX) {
	// We now have all of the input variables set, so we can figure out the start and ending x,y coordinates, and finalize the direction of the arc.

	// Ties and slurs are handled a little differently, so do calculations for them separately.
	if (!params.anchor1 || !params.anchor2)
		params.isTie = true; // if the slur goes off the end of the line, then draw it like a tie
	else if (params.anchor1.pitch === params.anchor2.pitch && params.internalNotes.length === 0)
		params.isTie = true;
	else
		params.isTie = false;

	if (params.isTie) {
		params.calcTieDirection();
		params.calcX(lineStartX, lineEndX);
		params.calcTieY();

	} else {
		params.calcSlurDirection();
		params.calcX(lineStartX, lineEndX);
		params.calcSlurY();
	}
	params.avoidCollisionAbove();
};

var drawArc = function (renderer, x1, x2, pitch1, pitch2, above, klass, isTie, dotted) {
	// If it is a tie vs. a slur, draw it shallower.
	var spacing = isTie ? 1.2 : 1.5;

	x1 = roundNumber(x1 + 6);
	x2 = roundNumber(x2 + 4);
	pitch1 = pitch1 + ((above) ? spacing : -spacing);
	pitch2 = pitch2 + ((above) ? spacing : -spacing);
	var y1 = roundNumber(renderer.calcY(pitch1));
	var y2 = roundNumber(renderer.calcY(pitch2));

	//unit direction vector
	var dx = x2 - x1;
	var dy = y2 - y1;
	var norm = Math.sqrt(dx * dx + dy * dy);
	var ux = dx / norm;
	var uy = dy / norm;

	var flatten = norm / 3.5;
	var maxFlatten = isTie ? 10 : 25;  // If it is a tie vs. a slur, draw it shallower.
	var curve = ((above) ? -1 : 1) * Math.min(maxFlatten, Math.max(4, flatten));

	var controlx1 = roundNumber(x1 + flatten * ux - curve * uy);
	var controly1 = roundNumber(y1 + flatten * uy + curve * ux);
	var controlx2 = roundNumber(x2 - flatten * ux - curve * uy);
	var controly2 = roundNumber(y2 - flatten * uy + curve * ux);
	var thickness = 2;
	if (klass)
		klass += ' slur';
	else
		klass = 'slur';
	klass += isTie ? ' tie' : ' legato';
	var ret;
	if (dotted) {
		klass += ' dotted';
		var pathString2 = sprintf("M %f %f C %f %f %f %f %f %f", x1, y1,
			controlx1, controly1, controlx2, controly2, x2, y2);
		ret = renderer.paper.path({ path: pathString2, stroke: renderer.foregroundColor, fill: "none", 'stroke-dasharray': "5 5", 'class': renderer.controller.classes.generate(klass), "data-name": isTie ? "tie" : "slur" });
	} else {
		var pathString = sprintf("M %f %f C %f %f %f %f %f %f C %f %f %f %f %f %f z", x1, y1,
			controlx1, controly1, controlx2, controly2, x2, y2,
			roundNumber(controlx2 - thickness * uy), roundNumber(controly2 + thickness * ux), roundNumber(controlx1 - thickness * uy), roundNumber(controly1 + thickness * ux), x1, y1);
		ret = renderer.paper.path({ path: pathString, stroke: "none", fill: renderer.foregroundColor, 'class': renderer.controller.classes.generate(klass), "data-name": isTie ? "tie" : "slur" });
	}

	return ret;
};

module.exports = drawTie;