App-Music-ChordPro
view release on metacpan or search on metacpan
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
out_sxsy(x1, ' ', y1);
output += 'c' +
((xx1 - x1) / stv_g.scale).toFixed(1) + ' ' +
((y1 - yy1) / scale_y).toFixed(1) + ' ' +
((xx2 - x1) / stv_g.scale).toFixed(1) + ' ' +
((y1 - yy2) / scale_y).toFixed(1) + ' ' +
((x2 - x1) / stv_g.scale).toFixed(1) + ' ' +
((y1 - y2) / scale_y).toFixed(1)
if (!dotted)
output += '\n\tv' +
(-dz).toFixed(1) + 'c' +
((xx2 - dx - x2) / stv_g.scale).toFixed(1) + ' ' +
((y2 + dz - yy2 - dy) / scale_y).toFixed(1) + ' ' +
((xx1 + dx - x2) / stv_g.scale).toFixed(1) + ' ' +
((y2 + dz - yy1 - dy) / scale_y).toFixed(1) + ' ' +
((x1 - x2) / stv_g.scale).toFixed(1) + ' ' +
((y2 - y1) / scale_y).toFixed(1)
output += '"/>\n'
}
// draw a slur between two chords / notes
/* (the staves are not yet defined) */
/* (delayed output) */
/* (not a pretty routine, this) */
function draw_slur(path, // list of symbols under the slur
sl, // slur variables: type, end symbol, note
recurr) { // recurrent call when slur on two staves
var i,
k, g, x1, y1, x2, y2, height, addy, s_st2,
a, y, z, h, dx, dy,
ty = sl.ty,
dir = (ty & 0x07) == C.SL_ABOVE ? 1 : -1,
n = path.length,
i1 = 0,
i2 = n - 1,
not1 = sl.nts, // if the slur starts on a note
k1 = path[0],
k2 = path[i2],
nn = 1
set_dscale(k1.st)
for (i = 1; i < n; i++) {
k = path[i]
if (k.type == C.NOTE || k.type == C.REST) {
nn++
if (k.st != k1.st
&& !s_st2)
s_st2 = k
}
}
// if slur on 2 staves, define it, but don't output it now
// this will be done in draw_sl2()
if (s_st2 && !recurr) { // if not 2nd call to draw_slur()
if (!gene.a_sl)
gene.a_sl = []
// replace the symbols of the other staff
// by symbols in the current staff but with updated y offsets
h = 24 + k1.fmt.sysstaffsep // delta y
if (s_st2.st > k1.st)
h = -h
for (i = 0; i < n; i++) {
k = path[i]
if (k.st == k1.st) {
if (k.dur)
a = k // (used for types // and \\)
continue
}
k = clone(k)
if (path[i] == s_st2)
s_st2 = k
path[i] = k
if (k.dur) {
k.notes = clone(k.notes)
k.notes[0] = clone(k.notes[0])
if (sl.ty & C.SL_CENTER) {
if (k.st != a.st) {
sl.ty = (sl.ty & ~0x07)
| (a.st < k.st
? C.SL_BELOW
: C.SL_ABOVE)
z = k1.ymn
h = k2.ymx
if (k.st < a.st) {
for (i1 = 1; i1 < i; i1++) {
a = path[i1]
if (a.ymn < z)
z = a.ymn
}
for (i1 = i; i1 < i2; i1++) {
a = path[i1]
if (a.ymx > h)
h = a.ymx
}
} else {
for (i1 = 1; i1 < i; i1++) {
a = path[i1]
if (a.ymx > h)
h = a.ymx
}
for (i1 = i; i1 < i2; i1++) {
a = path[i1]
if (a.ymn < z)
z = a.ymn
}
}
h += z
a = k
}
k.y = h - k.y
k.notes[0].pit = (k.y / 3 | 0) + 18
k.ys = h - k.ys
y = k.ymx
k.ymx = h - k.ymn
k.ymn = h - y
k.stem = -k.stem
} else {
k.notes[0].pit += h / 3 | 0
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
&& s2.st == st
&& s2.type == C.NOTE
&& s2.notes[0].pit <= 13) /* G, */
continue
s2 = s.ts_next
if (s2
&& s2.st == st
&& s2.time == time
&& s2.type == C.NOTE
&& s2.notes[0].pit <= 13) /* G, */
continue
}
/* if first change, change the starting clef */
if (!s_last_chg) {
clef_type = clef_type_start =
clef_type == 't' ? 'b' : 't';
s_last_chg = s
continue
}
/* go backwards and search where to insert a clef change */
s3 = s
for (s2 = s.ts_prev; s2 != s_last_chg; s2 = s2.ts_prev) {
if (s2.st != st)
continue
if (s2.type == C.BAR) {
s3 = s2.bar_type[0] != ':' ? s2 : s2.next
break
}
if (s2.type != C.NOTE)
continue
/* have a 2nd choice on beam start */
if (s2.beam_st
&& !s2.p_v.second)
s3 = s2
}
/* no change possible if no insert point */
if (s3.time == s_last_chg.time) {
s_last_chg = s
continue
}
s_last_chg = s;
/* insert a clef change */
clef_type = clef_type == 't' ? 'b' : 't';
s2 = insert_clef(s3, clef_type, clef_type == "t" ? 2 : 4);
s2.clef_auto = true
// s3.prev.st = st
}
return clef_type_start
}
/* set the clefs */
/* this function is called once at start of tune generation */
/*
* global variables:
* - staff_tb[st].clef = clefs at start of line (here, start of tune)
* (created here, updated on clef draw)
* - voice_tb[v].clef = clefs at end of generation
* (created on voice creation, updated here)
*/
function set_clefs() {
var s, s2, st, v, p_voice, g, new_type, new_line, p_staff, pit,
staff_clef = new Array(nstaff + 1), // st -> { clef, autoclef }
sy = cur_sy,
mid = []
// create the staff table
staff_tb = new Array(nstaff + 1)
for (st = 0; st <= nstaff; st++) {
staff_clef[st] = {
autoclef: true
}
staff_tb[st] = {
output: "",
sc_out: ""
}
}
for (st = 0; st <= sy.nstaff; st++)
mid[st] = (sy.staves[st].stafflines.length - 1) * 3
for (s = tsfirst; s; s = s.ts_next) {
if (s.repeat_n)
set_repeat(s)
switch (s.type) {
case C.STAVES:
sy = s.sy // new system
for (st = 0; st <= nstaff; st++)
staff_clef[st].autoclef = true
for (v = 0; v < voice_tb.length; v++) {
if (!sy.voices[v])
continue
p_voice = voice_tb[v];
st = sy.voices[v].st
if (!sy.voices[v].second) {
sy.staves[st].staffnonote = p_voice.staffnonote
if (p_voice.staffscale)
sy.staves[st].staffscale = p_voice.staffscale
if (sy.voices[v].sep)
sy.staves[st].sep = sy.voices[v].sep
if (sy.voices[v].maxsep)
sy.staves[st].maxsep = sy.voices[v].maxsep
}
s2 = p_voice.clef
if (!s2.clef_auto)
staff_clef[st].autoclef = false
}
for (st = 0; st <= sy.nstaff; st++)
mid[st] = (sy.staves[st].stafflines.length - 1) * 3
for (v = 0; v < voice_tb.length; v++) {
if (!sy.voices[v]
|| sy.voices[v].second) // main voices
continue
p_voice = voice_tb[v];
st = sy.voices[v].st;
s2 = p_voice.clef
if (s2.clef_auto) {
//fixme: the staff may have other voices with explicit clefs...
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
staff_tb[stv_g.st].output += output
} else {
staff_tb[stv_g.st].sc_out += output
}
output = ""
}
if (st < 0)
stv_g.scale = 1
else
stv_g.scale = no_scale ? 1 : staff_tb[st].staffscale;
stv_g.st = st;
stv_g.dy = 0
}
// update the y offsets of delayed output
function delayed_update() {
var st, new_out, text
for (st = 0; st <= nstaff; st++) {
if (staff_tb[st].sc_out) {
output += '<g ' + staff_tb[st].scale_str + '>\n' +
staff_tb[st].sc_out + '</g>\n';
staff_tb[st].sc_out = ""
}
if (!staff_tb[st].output)
continue
output += '<g transform="translate(0,' +
(-staff_tb[st].y).toFixed(1) +
')">\n' +
staff_tb[st].output +
'</g>\n';
staff_tb[st].output = ""
}
}
// output the annotations
function anno_out(s, t, f) {
if (s.istart == undefined)
return
var type = s.type,
h = s.ymx - s.ymn + 4,
wl = s.wl || 2,
wr = s.wr || 2
if (s.grace)
type = C.GRACE
f(t || abc2svg.sym_name[type], s.istart, s.iend,
s.x - wl - 2, staff_tb[s.st].y + s.ymn + h - 2,
wl + wr + 4, h, s);
}
function a_start(s, t) {
anno_out(s, t, user.anno_start)
}
function a_stop(s, t) {
anno_out(s, t, user.anno_stop)
}
function empty_function() {
}
// the values are updated on generate()
var anno_start = empty_function,
anno_stop = empty_function
// output the stop user annotations
function anno_put() {
var s
while (1) {
s = anno_a.shift()
if (!s)
break
switch (s.type) {
case C.CLEF:
case C.METER:
case C.KEY:
case C.REST:
if (s.type != C.REST || s.rep_nb) {
set_sscale(s.st)
break
}
// fall thru
case C.GRACE:
case C.NOTE:
case C.MREST:
set_scale(s)
break
// default:
// continue
}
anno_stop(s)
}
} // anno_put()
// output a string with x, y, a and b
// In the string,
// X and Y are replaced by scaled x and y
// A and B are replaced by a and b as string
// F and G are replaced by a and b as float
function out_XYAB(str, x, y, a, b) {
x = sx(x);
y = sy(y);
output += str.replace(/X|Y|A|B|F|G/g, function(c) {
switch (c) {
case 'X': return x.toFixed(1)
case 'Y': return y.toFixed(1)
case 'A': return a
case 'B': return b
case 'F': return a.toFixed(1)
// case 'G':
default: return b.toFixed(1)
}
})
}
// open / close containers
function g_open(x, y, rot, sx, sy) {
glout()
out_XYAB('<g transform="translate(X,Y', x, y);
if (rot)
output += ') rotate(' + rot.toFixed(2)
if (sx) {
( run in 1.621 second using v1.01-cache-2.11-cpan-d7f47b0818f )