App-Music-ChordPro
view release on metacpan or search on metacpan
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
de.x = x = realwidth - dd.wr
// if (dd.func == 6
// && ((de.pos & C.SL_ALI_MSK) == C.SL_ALIGN
// || ((de.pos & C.SL_ALI_MSK) == 0
// && de.s.fmt.dynalign > 0))) // if align
// ;
// else
if (up)
y_set(s.st, 1, x - dd.wl, w, y + dd.h)
else
y_set(s.st, 0, x - dd.wl, w, y - dd.hd)
de.y = y
}
// add a decoration
/* syntax:
* %%deco <name> <c_func> <glyph> <h> <wl> <wr> [<str>]
* "<h>" may be followed by ",<hd>" (descent)
*/
function deco_add(param) {
var dv = param.match(/(\S*)\s+(.*)/);
decos[dv[1]] = dv[2]
}
// define a decoration
// nm is the name of the decoration
// nmd is the name of the definition in the table 'decos'
function deco_def(nm, nmd) {
if (!nmd)
nmd = nm
var a, dd, dd2, nm2, c, i, elts, str, hd,
text = decos[nmd]
// check if a long decoration with number
if (!text) {
if (/\d[()]$/.test(nmd))
text = decos[nmd.replace(/\d/, '')]
else if (/^\d$/.test(nmd)) // or some fingering/string number
text = "3 fng 5,5 3 3 " + nmd
}
if (!text) {
if (cfmt.decoerr)
error(1, null, "Unknown decoration '$1'", nm)
return //undefined
}
// extract the values
a = text.match(/(\d+)\s+(.+?)\s+([0-9.,]+)\s+([0-9.]+)\s+([0-9.]+)/)
if (!a) {
error(1, null, "Invalid decoration '$1'", nm)
return //undefined
}
var c_func = Number(a[1]),
// glyph = a[2],
h = a[3],
wl = parseFloat(a[4]),
wr = parseFloat(a[5])
if (isNaN(c_func)) {
error(1, null, "%%deco: bad C function value '$1'", a[1])
return //undefined
}
if (c_func > 10
&& (c_func < 32 || c_func > 45)) {
error(1, null, "%%deco: bad C function index '$1'", c_func)
return //undefined
}
// if (c_func == 5) // old !trill(!
// c_func = 3
// if (c_func == 7) // old !cresc(!
// c_func = 6
if (h.indexOf(',') > 0) {
h = h.split(',')
hd = h[1]
h = h[0]
} else {
hd = 0
}
if (h > 50 || wl > 80 || wr > 80) {
error(1, null, "%%deco: abnormal h/wl/wr value '$1'", text)
return //undefined
}
// create/redefine the decoration
dd = dd_tb[nm]
if (!dd) {
dd = {
name: nm
}
dd_tb[nm] = dd
}
/* set the values */
dd.func = nm.indexOf("head-") == 0 ? 9 : c_func;
dd.glyph = a[2];
dd.h = Number(h)
dd.hd = Number(hd)
dd.wl = wl;
dd.wr = wr;
str = text.replace(a[0], '').trim()
if (str) { // optional string
if (str[0] == '"')
str = str.slice(1, -1);
if (str[0] == '@') {
c = str.match(/^@([0-9.-]+),([0-9.-]+);?/)
if (!c) {
error(1, null, "%%deco: bad position '$1'", str)
return
}
dd.dx = +c[1] // x and y offsets
dd.dy = +c[2]
str = str.replace(c[0], '')
}
dd.str = str
}
/* compatibility */
if (dd.func == 6 && dd.str == undefined)
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
// transp: 0, // global transpose
// topmargin: .7 * IN,
topspace: 22,
tuplets: [0, 0, 0, 0],
tupletfont: {name: txt_ff, style: "italic", size: 10},
vocalfont: {name: txt_ff, weight: "bold", size: 13},
vocalspace: 10,
voicefont: {name: txt_ff, weight: "bold", size: 13},
// voicescale: 1,
writefields: "CMOPQsTWw",
wordsfont: {name: txt_ff, size: 16},
wordsspace: 5,
"writeout-accidentals": "n"
}
// parameters that are used in the symbols
var sfmt = {
bardef: true,
barsperstaff: true,
beamslope: true,
breaklimit: true,
bstemdown: true,
cancelkey: true,
dynalign: true,
flatbeams: true,
gracespace: true,
hyphencont: true,
keywarn: true,
maxshrink: true,
maxstaffsep: true,
measrepnb: true,
rbmax: true,
rbmin: true,
shiftunison: true,
slurheight: true,
squarebreve: true,
staffsep: true,
systvoices: 1, //true
stemheight: true,
stretchlast: true,
stretchstaff: true,
tieheight: true,
timewarn: true,
trimsvg: 1, //true
vocalspace: true
} // sfmt
function get_bool(param) {
return !param || !/^(0|n|f)/i.test(param) // accept void as true !
}
// %%font <font> [<encoding>] [<scale>]
function get_font_scale(param) {
var i, font,
a = info_split(param) // a[0] = font name
if (a.length <= 1)
return
var scale = +a[a.length - 1]
if (isNaN(scale) || scale <= 0.5) {
syntax(1, "Bad scale value in %%font")
return
}
font_scale_tb[a[0]] = scale
}
// set the width factor of a font
function set_font_fac(font) {
var scale = font_scale_tb[font.fname || font.name]
if (!scale)
scale = 1.1;
font.swfac = font.size * scale
}
// %%xxxfont fontname|* [encoding] [size|*]
function param_set_font(xxxfont, p) {
var font, n, a, ft2, k
// "setfont-<n>" goes to "u<n>font"
if (xxxfont[xxxfont.length - 2] == '-') {
n = xxxfont[xxxfont.length - 1]
if (n < '1' || n > '9')
return
xxxfont = "u" + n + "font"
}
// fill the values
font = {}
a = p.match(/\s+(no)?box(\s|$)/)
if (a) { // if box
if (a[1]) {
font.box = false // nobox
font.pad = 0
} else {
font.box = true
font.pad = 2.5
}
p = p.replace(a[0], a[2])
}
a = p.match(/\s+padding=([\d.]+)(\s|$)/)
if (a) { // if padding
font.pad = a[1] ? +a[1] : 0
p = p.replace(a[0], a[2])
}
a = p.match(/\s+class=(.*?)(\s|$)/)
if (a) {
font.class = a[1];
p = p.replace(a[0], a[2])
}
a = p.match(/\s+wadj=(.*?)(\s|$)/)
if (a) {
if (typeof document == "undefined") // useless if in browser
switch (a[1]) {
case 'none':
font.wadj = ''
break
case 'space':
font.wadj = 'spacing'
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
if (!font.src) { // if no url(...)
// here is the font family
p = p.trim()
if (p == '*')
p = ''
p = p.replace(/Times-Roman|Times/, "serif")
.replace("Helvetica", "sans-serif")
.replace("Courier", "monospace")
.replace("music", cfmt.musicfont.name)
//hack: the font "Figurato" is used for figured bass
if (p.indexOf("Fig") > 0)
font.figb = true
}
if (p && !font.name)
font.name = p
if (font.size)
set_font_fac(font)
// keep the previous attributes if no font name or no size
if (!font.name || !font.size) {
ft2 = cfmt[xxxfont]
for (k in ft2) {
if (!ft2.hasOwnProperty(k)
|| font[k] != undefined)
continue
switch (k) {
case "fid":
case "used":
case "src":
break
case "style":
case "weight":
if (font.normal)
break
// fall thru
default:
font[k] = ft2[k]
break
}
}
if (!font.swfac)
set_font_fac(font)
}
if (font.pad == undefined)
font.pad = 0
font.fname = font.name
if (font.weight >= 700)
font.fname += 'Bold'
cfmt[xxxfont] = font
}
// get a length with a unit - return the number of pixels
function get_unit(param) {
var v = param.toLowerCase().match(/(-?[\d.]+)(.*)/)
if (!v)
return NaN
v[1] = +v[1]
switch (v[2]) {
case "cm":
return v[1] * CM
case "in":
return v[1] * IN
case "pt": // paper point in 1/72 inch
return v[1] / .75
case "px": // screen pixel in 1/96 inch
case "":
return v[1]
}
return NaN
}
// set the name of an info or a part
function set_infoname(cmd, param) {
//fixme: check syntax: '<letter> ["string"]'
var tmp = cfmt[cmd] ? cfmt[cmd].split("\n") : "",
letter = param[0]
for (var i = 0; i < tmp.length; i++) {
var infoname = tmp[i]
if (infoname[0] != letter)
continue
if (param.length == 1)
tmp.splice(i, 1)
else
tmp[i] = param
cfmt[cmd] = tmp.join('\n')
return
}
if (cfmt[cmd])
cfmt[cmd] += "\n" + param
else
cfmt[cmd] = param
}
// get the text option
var textopt = {
align: 'j',
center: 'c',
fill: 'f',
justify: 'j',
obeylines: 'l',
ragged: 'f',
right: 'r',
skip: 's',
// abcm2ps compatibility
"0": 'l',
"1": 'j',
"2": 'f',
"3": 'c',
"4": 's',
"5": 'r'
}
function get_textopt(v) {
var i = v.indexOf(' ')
if (i > 0)
v = v.slice(0, i)
return textopt[v]
}
/* -- position of a voice element -- */
var posval = {
above: C.SL_ABOVE,
auto: 0, // !! not C.SL_AUTO !!
below: C.SL_BELOW,
down: C.SL_BELOW,
hidden: C.SL_HIDDEN,
opposite: C.SL_HIDDEN,
under: C.SL_BELOW,
up: C.SL_ABOVE
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
function set_v_param(k, v) {
k = [k + '=', v]
if (parse.state < 3)
memo_kv_parm(curvoice ? curvoice.id : '*', k)
else if (curvoice)
set_kv_parm(k)
else
memo_kv_parm('*', k)
}
function set_page() {
if (!img.chg)
return
img.chg = false;
img.lm = cfmt.leftmargin - cfmt.printmargin
if (img.lm < 0)
img.lm = 0;
img.rm = cfmt.rightmargin - cfmt.printmargin
if (img.rm < 0)
img.rm = 0;
img.width = cfmt.pagewidth - 2 * cfmt.printmargin
// must have 100pt at least as the staff width
if (img.width - img.lm - img.rm < 100) {
error(0, undefined, "Bad staff width");
img.width = img.lm + img.rm + 150
}
set_posx()
} // set_page()
// set a format parameter
// (possible hook)
Abc.prototype.set_format = function(cmd, param) {
var f, f2, v, i
//fixme: should check the type and limits of the parameter values
if (/.+font(-[\d])?$/.test(cmd)) {
if (cmd == "soundfont")
cfmt.soundfont = param
else
param_set_font(cmd, param)
return
}
// duplicate the global parameters if already used by symbols
if (sfmt[cmd] && parse.ufmt)
cfmt = Object.create(cfmt)
switch (cmd) {
case "aligncomposer":
case "barsperstaff":
case "infoline":
case "measurenb":
case "rbmax":
case "rbmin":
case "measrepnb":
case "shiftunison":
case "systnames":
case "systvoices":
v = parseInt(param)
if (isNaN(v)) {
syntax(1, "Bad integer value");
break
}
if (cmd == "systnames") { // compatibility
switch (v) {
case -1: v = 3; break
case 1: v = 2; break
case 2: v = 1; break
}
cmd = "systvoices"
}
cfmt[cmd] = v
break
case "abc-version":
case "bgcolor":
case "fgcolor":
case "propagate-accidentals":
case "writeout-accidentals":
cfmt[cmd] = param
break
case "beamslope":
case "breaklimit": // float values
case "lineskipfac":
case "maxshrink":
case "pagescale":
case "parskipfac":
case "scale":
case "slurheight":
case "stemheight":
case "tieheight":
f = +param
if (isNaN(f) || !param || f < 0) {
syntax(1, errs.bad_val, '%%' + cmd)
break
}
switch (cmd) {
case "scale": // old scale
f /= .75
case "pagescale":
if (f < .1)
f = .1 // smallest scale
cmd = "scale";
img.chg = true
break
}
cfmt[cmd] = f
break
case "annotationbox":
case "gchordbox":
case "measurebox":
case "partsbox":
param_set_font(cmd.replace("box", "font"), // font
"* * " + (get_bool(param) ? "box" : "nobox"))
break
case "altchord":
case "bstemdown":
case "breakoneoln":
case "cancelkey":
case "checkbars":
case "contbarnb":
case "custos":
case "decoerr":
case "flatbeams":
case "graceslurs":
case "graceword":
case "hyphencont":
case "keywarn":
case "linewarn":
case "squarebreve":
case "splittune":
case "straightflags":
case "stretchstaff":
case "timewarn":
case "titlecaps":
case "titleleft":
case "trimsvg":
cfmt[cmd] = get_bool(param)
break
case "dblrepbar":
param = ":: " + param
// fall thru
case "bardef": // %%bardef oldbar newbar
v = param.split(/\s+/)
if (v.length != 2) {
syntax(1, errs.bad_val, "%%bardef")
} else {
if (parse.ufmt)
cfmt.bardef = Object.create(cfmt.bardef) // new object
cfmt.bardef[v[0]] = v[1]
}
break
case "chordalias":
v = param.split(/\s+/)
if (!v.length)
syntax(1, errs.bad_val, "%%chordalias")
else
abc2svg.ch_alias[v[0]] = v[1] || ""
break
case "composerspace":
case "indent":
case "infospace":
case "maxstaffsep":
case "maxsysstaffsep":
case "musicspace":
case "partsspace":
case "staffsep":
case "subtitlespace":
case "sysstaffsep":
case "textspace":
case "titlespace":
case "topspace":
case "vocalspace":
case "wordsspace":
f = get_unit(param) // normally, unit in points - 72 DPI accepted
if (isNaN(f) || f < 0)
syntax(1, errs.bad_val, '%%' + cmd)
else
cfmt[cmd] = f
break
case "page-format":
user.page_format = get_bool(param)
break
case "print-leftmargin": // to remove
syntax(0, "$1 is deprecated - use %%printmargin instead", '%%' + cmd)
cmd = "printmargin"
// fall thru
case "printmargin":
// case "botmargin":
case "leftmargin":
// case "pageheight":
case "pagewidth":
case "rightmargin":
// case "topmargin":
f = get_unit(param) // normally unit in cm or in - 96 DPI
if (isNaN(f)) {
syntax(1, errs.bad_val, '%%' + cmd)
break
}
cfmt[cmd] = f;
img.chg = true
break
case "concert-score":
if (cfmt.sound != "play")
cfmt.sound = "concert"
break
case "writefields":
set_writefields(param)
break
case "volume":
cmd = "dynamic"
// fall thru
case "dynamic":
case "gchord":
case "gstemdir":
case "ornament":
case "stemdir":
case "vocal":
set_pos(cmd, param)
break
case "font":
get_font_scale(param)
break
case "fullsvg":
if (parse.state != 0) {
syntax(1, errs.not_in_tune, "%%fullsvg")
break
}
//fixme: should check only alpha, num and '_' characters
cfmt[cmd] = param
break
case "gracespace":
v = param.split(/\s+/)
for (i = 0; i < 3; i++)
if (isNaN(+v[i])) {
syntax(1, errs.bad_val, "%%gracespace")
break
}
if (parse.ufmt)
cfmt[cmd] = new Float32Array(3)
for (i = 0; i < 3; i++)
cfmt[cmd][i] = +v[i]
break
case "tuplets":
v = param.split(/\s+/)
f = v[3]
if (f) // if 'where'
f = posval[f] // translate the keyword
if (f)
v[3] = f
if (curvoice)
curvoice.tup = v
else
cfmt[cmd] = v
break
case "infoname":
case "partname":
set_infoname(cmd, param)
break
case "notespacingfactor":
v = param.match(/([.\d]+)[,\s]*(\d+)?/)
if (v) {
f = +v[1]
if (isNaN(f) || f < 1 || f > 2) {
f = 0
} else if (v[2]) {
f2 = +v[2]
if (isNaN(f))
f = 0
} else {
f2 = cfmt.spatab[5]
}
}
if (!f) {
syntax(1, errs.bad_val, "%%" + cmd)
break
}
cfmt[cmd] = param // (for dump)
// in the table 'spatab',
// the width of notes is indexed by log2(note_length)
cfmt.spatab = new Float32Array(10)
i = 5; // index of crotchet
do {
cfmt.spatab[i] = f2
f2 /= f
} while (--i >= 0)
i = 5;
f2 = cfmt.spatab[i]
for ( ; ++i < cfmt.spatab.length; ) {
f2 *= f;
cfmt.spatab[i] = f2
}
break
case "play":
cfmt.sound = "play" // without clef
break
case "pos":
cmd = param.match(/(\w*)\s+(.*)/)
if (!cmd || !cmd[2]) {
syntax(1, "Error in %%pos")
break
}
if (cmd[1].slice(0, 3) == 'tup' // special case for %%pos tuplet
&& curvoice) { // inside tune
if (!curvoice.tup)
curvoice.tup = cfmt.tuplets
else
curvoice.tup = Object.create(curvoice.tup)
v = posval[cmd[2]]
switch (v) {
case C.SL_ABOVE:
curvoice.tup[3] = 1
break
case C.SL_BELOW:
curvoice.tup[3] = 2
break
case C.SL_HIDDEN:
curvoice.tup[2] = 1
break
}
break
}
if (cmd[1].slice(0, 3) == "vol")
cmd[1] = "dyn" // compatibility
set_pos(cmd[1], cmd[2])
break
case "sounding-score":
if (cfmt.sound != "play")
cfmt.sound = "sounding"
break
case "staffwidth":
v = get_unit(param)
if (isNaN(v)) {
syntax(1, errs.bad_val, '%%' + cmd)
break
}
if (v < 100) {
syntax(1, "%%staffwidth too small")
break
}
v = cfmt.pagewidth - v - cfmt.leftmargin
if (v < 2) {
syntax(1, "%%staffwidth too big")
break
}
cfmt.rightmargin = v;
img.chg = true
break
case "textoption":
cfmt[cmd] = get_textopt(param)
break
case "dynalign":
case "quiet":
case "singleline":
case "stretchlast":
case "titletrim":
v = param == '' ? 1 : +param
if (isNaN(v))
v = +get_bool(param)
if (cmd[1] == 't') { // stretchlast
if (v < 0 || v > 1) {
syntax(1, errs.bad_val, '%%' + cmd)
break
}
}
cfmt[cmd] = v
break
case "combinevoices":
syntax(1, "%%combinevoices is deprecated - use %%voicecombine instead")
break
case "voicemap":
set_v_param("map", param)
break
case "voicescale":
set_v_param("scale", param)
break
case "unsizedsvg":
if (get_bool(param))
user.imagesize = ""
else
delete user.imagesize
break
// deprecated
case "rbdbstop":
v = get_bool(param)
if (v && cfmt["abc-version"] >= "2.2")
cfmt["abc-version"] = "1"
else if (!v && cfmt["abc-version"] < "2.2")
cfmt["abc-version"] = "2.2"
break
default: // memorize all global commands
if (!parse.state) // (needed for modules)
cfmt[cmd] = param
break
}
// check if already a same format
if (sfmt[cmd] && parse.ufmt) {
// to do...
parse.ufmt = false
}
}
// font stuff
// build a font style
function st_font(font) {
var n = font.name,
r = ""
if (font.weight)
r += font.weight + " "
if (font.style)
r += font.style + " "
if (n.indexOf('"') < 0 && n.indexOf(' ') > 0)
n = '"' + n + '"'
return r + font.size.toFixed(1) + 'px ' + n
}
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
"/o": "ø",
// "/D": "Ä",
// "/d": "Ä",
"/L": "Å",
"/l": "Å",
"vL": "Ľ",
"vl": "ľ",
"vd": "Ä",
".i": "ı",
"AA": "Ã
",
"aa": "Ã¥",
"AE": "Ã",
"ae": "æ",
"DH": "Ã",
"dh": "ð",
// "ng": "Å",
"OE": "Å",
"oe": "Å",
"ss": "Ã",
"TH": "Ã",
"th": "þ"
}
// accidentals as octal values (abcm2ps compatibility)
var oct_acc = {
"1": "\u266f",
"2": "\u266d",
"3": "\u266e",
"4": "𝄪",
"5": "𝄫"
}
// convert the escape sequences to utf-8
function cnv_escape(src, flag) {
var c, c2,
dst = "",
i, j = 0
while (1) {
i = src.indexOf('\\', j)
if (i < 0)
break
dst += src.slice(j, i);
c = src[++i]
if (!c)
return dst + '\\'
switch (c) {
case '0':
case '2':
if (src[i + 1] != '0')
break
c2 = oct_acc[src[i + 2]]
if (c2) {
dst += c2;
j = i + 3
continue
}
break
case 'u':
j = Number("0x" + src.slice(i + 1, i + 5));
if (isNaN(j) || j < 0x20) {
dst += src[++i] + "\u0306" // breve accent
j = i + 1
continue
}
c = String.fromCharCode(j)
if (c == '\\') {
i += 4
break
}
dst += c
j = i + 5
continue
case 't': // TAB
dst += '\t';
j = i + 1
continue
case 'n': // new line (voice name)
dst += '\n';
j = i + 1
continue
default:
c2 = abc_utf[src.slice(i, i + 2)]
if (c2) {
dst += c2;
j = i + 2
continue
}
// try unicode combine characters
c2 = src[i + 1]
if (!c2)
break // !! the next test is true if c2 is undefined !!
if (!/[A-Za-z]/.test(c2))
break
switch (c) {
case '`':
dst += c2 + "\u0300" // grave
j = i + 2
continue
case "'":
dst += c2 + "\u0301" // acute
j = i + 2
continue
case '^':
dst += c2 + "\u0302" // circumflex
j = i + 2
continue
case '~':
dst += c2 + "\u0303" // tilde
j = i + 2
continue
case '=':
dst += c2 + "\u0304" // macron
j = i + 2
continue
case '_':
dst += c2 + "\u0305" // overline
j = i + 2
continue
case '.':
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
}
c = a[1];
v = a[2]
if (c[0] == '\\') {
if (c[1] == 't')
c = '\t'
else if (!c[1])
c = ' '
}
k = c.charCodeAt(0)
if (k >= 128) {
syntax(1, errs.not_ascii)
return
}
switch (char_tb[k][0]) {
case '0': // nil
case 'd':
case 'i':
case ' ':
break
case '"':
case '!':
case '[':
if (char_tb[k].length > 1)
break
// fall thru
default:
syntax(1, "Bad user character '$1'", c)
return
}
switch (v) {
case "!beambreak!":
v = " "
break
case "!ignore!":
v = "i"
break
case "!nil!":
case "!none!":
v = "d"
break
}
char_tb[k] = v
}
// get a stafflines value
function get_st_lines(param) {
if (!param)
return
if (/^[\]\[|.':-]+$/.test(param)) // '
return param.replace(/\]/g, '[')
var n = +param
switch (n) {
case 0: return "..."
case 1: return "..|"
case 2: return ".||"
case 3: return ".|||"
}
if (isNaN(n) || n < 0 || n > 16)
return //undefined
return "||||||||||||||||".slice(0, n)
}
// create a block symbol in the tune body
function new_block(subtype) {
var s = {
type: C.BLOCK,
subtype: subtype,
dur: 0
}
sym_link(s)
return s
}
// set the voice parameters
// (possible hook)
Abc.prototype.set_vp = function(a) {
var s, item, pos, val, clefpit,
tr_p = 0
while (1) {
item = a.shift()
if (!item)
break
if (item.slice(-1) == '='
&& !a.length) {
syntax(1, errs.bad_val, item)
break
}
switch (item) {
case "clef=":
s = a.shift() // keep last clef
break
case "clefpitch=":
item = a.shift() // (<note><octave>)
if (item) {
val = ntb.indexOf(item[0])
if (val >= 0) {
switch (item[1]) {
case "'":
val += 7
break
case ',':
val -= 7
if (item[2] == ',')
val -= 7
break
}
clefpit = 4 - val // 4 = 'G'
break
}
}
syntax(1, errs.bad_val, item)
break
case "octave=":
val = +a.shift()
if (isNaN(val))
syntax(1, errs.bad_val, item)
else
curvoice.octave = val
break
case "cue=":
// (ignore cue=off)
// curvoice.scale = a.shift() == 'on' ? .7 : 1
if (a.shift() == 'on')
curvoice.scale = .7
break
case "instrument=":
// instrument=M/N => score=MN and sound=cN
// (instrument=M == instrument=M/M)
item = a.shift()
val = item.indexOf('/')
if (val < 0) {
val = get_interval('c' + item)
if (val == undefined)
break
curvoice.sound = val
tr_p |= 2
val = 0
} else {
val = get_interval('c' + item.slice(val + 1))
if (val == undefined)
break
curvoice.sound = val
tr_p |= 2
val = get_interval(item.replace('/', ''))
if (val == undefined)
break
}
curvoice.score = cfmt.sound ? curvoice.sound : val
tr_p |= 1
break
case "map=": // %%voicemap
curvoice.map = a.shift()
break
case "name=":
case "nm=":
curvoice.nm = a.shift()
if (curvoice.nm[0] == '"')
curvoice.nm = cnv_escape(curvoice.nm.slice(1, -1))
curvoice.new_name = true
break
case "stem=": // compatibility
case "pos=": // from %%pos only
if (item == "pos=")
item = a.shift()
.slice(1, -1) // always inside dble quotes
.split(' ')
else
item = ["stm", a.shift()];
val = posval[item[1]]
if (val == undefined) {
syntax(1, errs.bad_val, "%%pos")
break
}
switch (item[2]) {
case "align": val |= C.SL_ALIGN; break
case "center": val |= C.SL_CENTER; break
case "close": val |= C.SL_CLOSE; break
}
if (!pos)
pos = {}
pos[item[0]] = val
break
case "scale=": // %%voicescale
val = +a.shift()
if (isNaN(val) || val < .5 || val > 2)
syntax(1, errs.bad_val, "%%voicescale")
else
curvoice.scale = val
break
case "score=":
if (cfmt.nedo) {
syntax(1, errs.notransp)
break
}
// score=MN
// (score=M == score=Mc)
item = a.shift()
if (cfmt.sound)
break
val = get_interval(item, true)
if (val != undefined) {
curvoice.score = val
tr_p |= 1
}
break
case "shift=":
if (cfmt.nedo) {
syntax(1, errs.notransp)
break
}
val = get_interval(a.shift())
if (val != undefined) {
curvoice.shift = val
tr_p = 3
}
break
case "sound=":
if (cfmt.nedo) {
syntax(1, errs.notransp)
break
}
// concert-score display: apply sound=
// sounding-score display: apply sound= only if M != c/C
// sound: apply sound=
val = get_interval(a.shift())
if (val == undefined)
break
curvoice.sound = val
if (cfmt.sound)
curvoice.score = val
tr_p |= 2
break
case "subname=":
case "sname=":
case "snm=":
curvoice.snm = a.shift()
if (curvoice.snm[0] == '"')
curvoice.snm = curvoice.snm.slice(1, -1);
break
case "stafflines=":
val = get_st_lines(a.shift())
if (val == undefined) {
syntax(1, "Bad %%stafflines value")
break
}
if (curvoice.st != undefined)
par_sy.staves[curvoice.st].stafflines = val
curvoice.stafflines = val
break
case "staffnonote=":
val = +a.shift()
if (isNaN(val))
syntax(1, "Bad %%staffnonote value")
else
curvoice.staffnonote = val
break
case "staffscale=":
val = +a.shift()
if (isNaN(val) || val < .3 || val > 2)
syntax(1, "Bad %%staffscale value")
else
curvoice.staffscale = val
break
case "tacet=":
val = a.shift()
curvoice.tacet = val || undefined
break
case "transpose=": // (abcMIDI compatibility)
val = get_transp(a.shift())
if (val == undefined) {
syntax(1, errs.bad_transp)
} else {
curvoice.sound = val
if (cfmt.sound)
curvoice.score = val
tr_p = 2
}
break
default:
switch (item.slice(0, 4)) {
case "treb":
case "bass":
case "alto":
case "teno":
case "perc":
s = item
break
default:
if ("GFC".indexOf(item[0]) >= 0)
s = item
else if (item.slice(-1) == '=')
a.shift()
break
}
break
}
}
if (pos) {
curvoice.pos = clone(curvoice.pos)
for (item in pos)
if (pos.hasOwnProperty(item))
curvoice.pos[item] = pos[item]
}
if (s) {
s = new_clef(s)
if (s) {
if (clefpit)
s.clefpit = clefpit
get_clef(s)
}
}
// if transposition
if (tr_p & 2) { // curvoice.tr_sco is set in key_trans()
tr_p = (curvoice.sound | 0) + (curvoice.shift | 0)
if (tr_p)
curvoice.tr_snd = abc2svg.b40m(tr_p + 122) - 36
// semi-tone interval
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
}
// link P: or Q:
function link_pq(s, text) {
var p_v, s2
if (curvoice.v == par_sy.top_voice) {
sym_link(s)
} else if (voice_tb[par_sy.top_voice].time == s.time) {
p_v = curvoice
curvoice = voice_tb[par_sy.top_voice]
sym_link(s)
curvoice = p_v
} else if (voice_tb[par_sy.top_voice].time > s.time) {
p_v = voice_tb[par_sy.top_voice]
for (s2 = p_v.sym; ; s2 = s2.next) {
if (s2.time >= s.time) {
set_ref(s)
s.fmt = cfmt
s.next = s2
s.prev = s2.prev
if (s2.prev)
s.prev.next = s
else
p_v.sym = s
s2.prev = s
s.v = s2.v
s.p_v = p_v
s.st = p_v.st
break
}
}
} else {
set_ref(s)
s.fmt = cfmt
if (!parse.pq_d)
parse.pq_d = []
parse.pq_d.push(s) // delayed insertion
}
if (!parse.pq)
parse.pq = {}
parse.pq[text] = s.time
} // link_pq()
/* Q: tempo */
function new_tempo(text) {
var i, c, d, nd,
txt = text, // (for info.Q)
s = {
type: C.TEMPO,
dur: 0
}
// get a note duration
function get_nd(p) {
var n, d,
nd = p.match(/(\d+)\/(\d+)/)
if (nd) {
d = +nd[2]
if (d && !isNaN(d) && !(d & (d - 1))) {
n = +nd[1]
if (!isNaN(n))
return C.BLEN * n / d
}
}
syntax(1, "Invalid note duration $1", c)
} // get_nd()
set_ref(s)
if (cfmt.writefields.indexOf('Q') < 0)
s.invis = true // don't display
/* string before */
if (text[0] == '"') {
c = text.match(/"([^"]*)"/) // "
if (!c) {
syntax(1, "Unterminated string in Q:")
return
}
s.tempo_str1 = c[1]
text = text.slice(c[0].length).replace(/^\s+/,'')
}
// string after
if (text.slice(-1) == '"') {
i = text.indexOf('"')
s.tempo_str2 = text.slice(i + 1, -1)
text = text.slice(0, i).replace(/\s+$/,'')
}
/* beat */
i = text.indexOf('=')
if (i > 0) {
d = text.slice(0, i).split(/\s+/)
text = text.slice(i + 1).replace(/^\s+/,'')
while (1) {
c = d.shift()
if (!c)
break
nd = get_nd(c)
if (!nd)
return
if (!s.tempo_notes)
s.tempo_notes = []
s.tempo_notes.push(nd)
}
// tempo value
if (text.slice(0, 4) == "ca. ") {
s.tempo_ca = 'ca. '
text = text.slice(4)
}
i = text.indexOf('/')
if (i > 0) {
nd = get_nd(text)
if (!nd)
return
s.new_beat = nd
} else {
s.tempo = +text
if (!s.tempo || isNaN(s.tempo)) {
syntax(1, "Bad tempo value")
return
}
}
}
if (parse.state < 2 // if in tune header
|| (!curvoice.time && !glovar.tempo)) {
info.Q = txt
glovar.tempo = s
return
}
if (!glovar.tempo)
syntax(0, "No previous tempo")
s.time = curvoice.time
text = 'Q' + (s.tempo_str1 ? 'S' : '') + s.time
// accept [Q:"text"][Q:1/4=60]
if (parse.pq
&& parse.pq[text] == s.time)
return // already seen
link_pq(s, text)
}
// treat the information fields which may embedded
function do_info(info_type, text) {
var s, d1, d2, a, vid, tim, v, p_v
// skip this line if the current voice is ignored
// but keep the time related definitions
if (curvoice && curvoice.ignore) {
switch (info_type) {
default:
return
case 'P':
case 'Q':
case 'V':
break
}
}
switch (info_type) {
// info fields in any state
case 'I':
self.do_pscom(text)
break
case 'L':
a = text.match(/^1\/(\d+)(=(\d+)\/(\d+))?$/)
if (a) {
d1 = +a[1]
if (!d1 || (d1 & (d1 - 1)) != 0)
break
d1 = C.BLEN / d1
if (a[2]) { // if '='
d2 = +a[4]
d2 = d2 ? +a[3] / d2 * C.BLEN : 0
} else {
d2 = d1
}
lib/ChordPro/res/abc/abc2svg/abc2svg-1.js view on Meta::CPAN
if (a[0][0] != '*') {
tmp = new scanBuf; // print
tmp.buffer = a[0];
map[1] = parse_acc_pit(tmp)
}
if (!a[1])
return
i++
if (a[1].indexOf('=') < 0) {
map[0] = a[1].split(',') // heads
i++
}
}
for (; i < a.length; i++) {
switch (a[i]) {
case "heads=":
if (!a[++i]) {
syntax(1, errs.not_enough_p)
break
}
map[0] = a[i].split(',')
break
case "print=":
case "play=":
case "print_notrp=":
if (!a[++i]) {
syntax(1, errs.not_enough_p)
break
}
tmp = new scanBuf;
tmp.buffer = a[i];
note = parse_acc_pit(tmp)
if (a[i - 1][5] == '_') // if print no transpose
note.notrp = 1 //true
if (a[i - 1][1] == 'r')
map[1] = note
else
map[3] = note
break
case "color=":
if (!a[++i]) {
syntax(1, errs.not_enough_p)
break
}
map[2] = a[i]
break
}
}
}
// get a abcm2ps/abcMIDI compatible transposition value as a base-40 interval
// The value may be
// - [+|-]<number of semitones>[s|f]
// - <note1>[<note2>] % <note2> default is 'c'
function get_transp(param) {
if (param[0] == '0')
return 0
if ("123456789-+".indexOf(param[0]) >= 0) { // by semi-tone
var val = parseInt(param)
if (isNaN(val) || val < -36 || val > 36) {
//fixme: no source reference...
syntax(1, errs.bad_transp)
return
}
val += 36
val = ((val / 12 | 0) - 3) * 40 + abc2svg.isb40[val % 12]
if (param.slice(-1) == 'b')
val += 4
return val
}
// return undefined
} // get_transp()
/* -- process a pseudo-comment (%% or I:) -- */
// (possible hook)
Abc.prototype.do_pscom = function(text) {
var h1, val, s, cmd, param, n, k, b
cmd = text.match(/[^\s]+/)
if (!cmd)
return
cmd = cmd[0];
// ignore the command if the voice is ignored,
// but not if %%score/%%staves!
if (curvoice && curvoice.ignore) {
switch (cmd) {
case "staves":
case "score":
break
default:
return
}
}
param = text.replace(cmd, '').trim()
if (param.slice(-5) == ' lock') {
fmt_lock[cmd] = true;
param = param.slice(0, -5).trim()
} else if (fmt_lock[cmd]) {
return
}
switch (cmd) {
case "clef":
if (parse.state >= 2) {
s = new_clef(param)
if (s)
get_clef(s)
}
return
case "deco":
deco_add(param)
return
case "linebreak":
set_linebreak(param)
return
case "map":
get_map(param)
return
case "maxsysstaffsep":
case "sysstaffsep":
if (parse.state == 3) {
val = get_unit(param)
if (isNaN(val)) {
syntax(1, errs.bad_val, "%%" + cmd)
return
}
par_sy.voices[curvoice.v][cmd[0] == 'm' ? "maxsep" : "sep"] =
val
return
}
break
case "multicol":
switch (param) {
case "start":
case "new":
case "end":
break
default:
syntax(1, "Unknown keyword '$1' in %%multicol", param)
return
}
s = {
type: C.BLOCK,
subtype: "mc_" + param,
dur: 0
}
if (parse.state >= 2) {
if (curvoice.clone)
do_cloning()
curvoice = voice_tb[0]
curvoice.eoln = 1 //true
sym_link(s)
return
}
set_ref(s)
self.block_gen(s)
return
case "ottava":
if (parse.state != 3)
return
n = parseInt(param)
if (isNaN(n) || n < -2 || n > 2
|| (!n && !curvoice.ottava)) {
syntax(1, errs.bad_val, "%%ottava")
return
}
k = n
if (n) {
curvoice.ottava = n
} else {
n = curvoice.ottava
curvoice.ottava = 0
}
a_dcn.push(["15mb", "8vb", "", "8va", "15ma"][n + 2]
+ (k ? '(' : ')'))
return
case "repbra":
if (curvoice)
curvoice.norepbra = !get_bool(param)
return
case "repeat":
if (parse.state != 3)
return
if (!curvoice.last_sym) {
syntax(1, "%%repeat cannot start a tune")
return
}
if (!param.length) {
n = 1;
k = 1
} else {
b = param.split(/\s+/);
n = parseInt(b[0]);
k = parseInt(b[1])
if (isNaN(n) || n < 1
|| (curvoice.last_sym.type == C.BAR
&& n > 2)) {
syntax(1, "Incorrect 1st value in %%repeat")
return
}
if (isNaN(k)) {
k = 1
} else {
if (k < 1) {
syntax(1, "Incorrect 2nd value in %%repeat")
return
}
}
}
parse.repeat_n = curvoice.last_sym.type == C.BAR ? n : -n;
parse.repeat_k = k
return
case "sep":
var h2, len, values, lwidth;
set_page();
lwidth = img.width - img.lm - img.rm;
h1 = h2 = len = 0
if (param) {
values = param.split(/\s+/);
h1 = get_unit(values[0])
if (values[1]) {
h2 = get_unit(values[1])
if (values[2])
len = get_unit(values[2])
}
if (isNaN(h1) || isNaN(h2) || isNaN(len)) {
syntax(1, errs.bad_val, "%%sep")
return
}
}
if (h1 < 1)
h1 = 14
if (h2 < 1)
h2 = h1
if (len < 1)
len = 90
if (parse.state >= 2) {
if (curvoice.clone)
do_cloning()
s = new_block(cmd);
s.x = (lwidth - len) / 2 / cfmt.scale;
s.l = len / cfmt.scale;
s.sk1 = h1;
s.sk2 = h2
return
}
vskip(h1);
output += '<path class="stroke"\n\td="M';
out_sxsy((lwidth - len) / 2 / cfmt.scale, ' ', 0);
output += 'h' + (len / cfmt.scale).toFixed(1) + '"/>\n';
vskip(h2);
blk_flush()
return
case "setbarnb":
val = parseInt(param)
if (isNaN(val) || val < 1) {
syntax(1, "Bad %%setbarnb value")
break
}
glovar.new_nbar = val
return
case "staff":
if (parse.state != 3)
return
if (curvoice.clone)
do_cloning()
val = parseInt(param)
if (isNaN(val)) {
syntax(1, "Bad %%staff value '$1'", param)
return
}
var st
if (param[0] == '+' || param[0] == '-')
st = curvoice.cst + val
else
st = val - 1
if (st < 0 || st > nstaff) {
syntax(1, "Bad %%staff number $1 (cur $2, max $3)",
st, curvoice.cst, nstaff)
return
}
delete curvoice.floating;
curvoice.cst = st
return
case "staffbreak":
if (parse.state != 3)
return
if (curvoice.clone)
do_cloning()
s = {
type: C.STBRK,
dur:0
}
if (param.slice(-1) == 'f') {
s.stbrk_forced = true
param = param.replace(/\sf$/, '')
}
if (param) {
val = get_unit(param)
if (isNaN(val)) {
syntax(1, errs.bad_val, "%%staffbreak")
return
}
s.xmx = val
} else {
s.xmx = 14
}
sym_link(s)
return
case "tacet":
if (param[0] == '"')
param = param.slice(1, -1)
// fall thru
case "stafflines":
case "staffscale":
case "staffnonote":
set_v_param(cmd, param)
return
case "staves":
case "score":
if (!parse.state)
return
if (parse.scores && parse.scores.length > 0) {
text = parse.scores.shift();
cmd = text.match(/([^\s]+)\s*(.*)/);
param = cmd[2]
cmd = cmd[1]
}
get_staves(cmd, param)
return
case "center":
case "text":
k = cmd[0] == 'c' ? 'c' : cfmt.textoption
set_font("text")
if (parse.state >= 2) {
if (curvoice.clone)
do_cloning()
s = new_block("text")
s.text = param
s.opt = k
s.font = cfmt.textfont
return
}
write_text(param, k)
return
case "transpose": // (abcm2ps compatibility)
if (cfmt.sound)
return
val = get_transp(param)
if (val == undefined) { // accept note interval
val = get_interval(param)
if (val == undefined)
return
}
switch (parse.state) {
case 0:
cfmt.transp = 0
// fall thru
case 1:
cfmt.transp = (cfmt.transp || 0) + val
return
}
curvoice.shift = val
key_trans()
return
case "tune":
//fixme: to do
return
case "user":
set_user(param)
return
case "voicecolor":
if (curvoice)
curvoice.color = param
return
case "vskip":
val = get_unit(param)
if (isNaN(val)) {
syntax(1, errs.bad_val, "%%vskip")
return
}
if (val < 0) {
syntax(1, "%%vskip cannot be negative")
return
}
if (parse.state >= 2) {
if (curvoice.clone)
do_cloning()
s = new_block(cmd);
s.sk = val
return
}
vskip(val);
return
case "newpage":
case "leftmargin":
case "rightmargin":
case "pagescale":
case "pagewidth":
case "printmargin":
case "scale":
case "staffwidth":
if (parse.state >= 2) {
if (curvoice.clone)
do_cloning()
s = new_block(cmd);
s.param = param
return
}
if (cmd == "newpage") {
blk_flush()
if (user.page_format)
blkdiv = 2 // start the next SVG in a new page
return
}
break
}
self.set_format(cmd, param)
}
// treat the %%beginxxx / %%endxxx sequences
// (possible hook)
Abc.prototype.do_begin_end = function(type,
opt,
text) {
var i, j, action, s
if (curvoice && curvoice.clone)
do_cloning()
switch (type) {
case "js":
js_inject(text)
break
case "ml":
if (cfmt.pageheight) {
syntax(1, "Cannot have %%beginml with %%pageheight")
break
}
( run in 0.702 second using v1.01-cache-2.11-cpan-4e7a2411597 )