Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From 433944c7887548a5 To af5bcae7ac2b432e
|
2020-01-01
| ||
| 16:36 | core: fix: bad transposition with score=<note1> (without <note2>) ... (check-in: dc98412a6d user: jef tags: trunk) | |
| 14:18 | New release v1.20.7 ... (check-in: af5bcae7ac user: jef tags: trunk, v1.20.7) | |
| 14:06 | core: fix: bad display when m: and '%%writefields m 0' ... (check-in: 2bcf730e67 user: jef tags: trunk) | |
|
2019-02-06
| ||
| 14:25 | batch: add 'abctopdf' ... (check-in: 2c9cf4bafe user: jef tags: trunk) | |
|
2019-02-01
| ||
| 15:55 | New release v1.19.1 ... (check-in: 433944c788 user: jef tags: trunk, v1.19.1) | |
| 14:01 | copyright update to 2019 ... (check-in: 83a7d2efe0 user: jef tags: trunk) | |
Changes to README.md.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 | - `abc2svg-1.js` This script is the **abc2svg** core. It contains the ABC parser and the SVG generation engine. It must be included in the (X)HTML header of the pages where ABC rendering is needed (in `<script src=` tags). - `abcemb-1.js` | < | | > > > > > > > > > > > > | > | > > > > > > > > | | | > | < > > | | < > > | < | < < < < | < < < | < < | | < < | < < | < < | < > > > | | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
- `abc2svg-1.js`
This script is the **abc2svg** core.
It contains the ABC parser and the SVG generation engine.
It must be included in the (X)HTML header of the pages
where ABC rendering is needed (in `<script src=` tags).
- `abcemb-1.js`
This script replaces the ABC or MEI sequences by SVG images of the music
(the ABC sequences start on `X:` or `%abc` at start of line,
and stop on any ML tag - see below for MEI).
See the
[%%beginml documentation](http://moinejf.free.fr/abcm2ps-doc/beginml.xhtml)
for an example.
When the URL of the (X)HTML file ends with '#' followed by a string,
only the first tune containing this string is displayed.
Note that, if the ABC sequence contains the characters '<', '>' or '&',
it must be enclosed in a XML comment (starting after the first `X:` or `%abc`).
- `abcemb1-1.js`
This script is to be used with the core in (X)HTML files.
It works quite the same as the previous script, but replaces the whole
page by the selected tune.
When there is no selection ('#' + string at the end of the URL),
a list of the tunes is displayed.
When a tune is displayed, a menu offers the edition of the ABC source and
the automatic scroll of the music (this is done according to the tempo -
repeats and parts are not handled).
See [this tune](http://moinejf.free.fr/abc/boyvin-2-2.html)
for an example.
- `abcemb2-1.js`
This script is also to be used with the core in (X)HTML files.
The differences with the script `abcemb-1.js` are:
- the ABC sequences are replaced in HTML elements with the class `abc`,
- the string after '#' in the URL does a real %%select (i.e. this may
select many tunes),
- there is no menu nor list of tunes
- if the ABC sequences contain the characters '<', '>' or '&',
either these sequences must be enclosed in a XML comment, or the characters
must be replaced by their XML counterparts ('&lt;', '&gt;' or '&amp;').
- `abcdoc-1.js`
This script is also to be used in (X)HTML pages with the core.
Mainly used for ABC documentation, it lets the ABC source sequences
in the page before the SVG images.
See the source of
[abcm2ps/abc2svg features](http://moinejf.free.fr/abcm2ps-doc/features.xhtml)
for an example.
- `play-1.js`
This script may be used with `abcemb{,1,2}-1.js` for playing the
rendered ABC music.
See [this page](http://moinejf.free.fr/abcm2ps-doc/au_clair.xhtml)
for an example.
- `abcweb2-1.js`
This script works the same as `abcemb2-1.js` but it must use `snd-1.js`
for playing.
- `snd-1.js`
This script contains a other way for playing. It is used in the editor
and it may be used with `abcweb2-1.js`.
- `follow-1.js`
This script may be used after `play-1.js` or `snd-1.js` for highlighting
the notes while playing.
See [this page](http://moinejf.free.fr/abcm2ps-doc/tabac.xhtml)
for an example.
- `edit-1.xhtml`
This is a simple web
[ABC editor/player](http://moinejf.free.fr/js/edit-1.xhtml).
When looking at a ABC file in a web browser, you may also use a
<a href="https://en.wikipedia.org/wiki/Bookmarklet">bookmarklet</a>
as
<a href="javascript:(function(){var%20s,n=3,d=document,b=d.body;b.innerHTML='\n%25abc-2.2\n%25%3c!--\n'+b.textContent+'%25--%3e\n';function%20f(u){s=d.createElement('script');s.src='http://moinejf.free.fr/js/'+u;s.onload=function(){if(--n==0)dom_loaded()};d.head.appendChild(s)};f('play-1.js');f('follow-1.js');f('abcemb-1.js')})();void(0)">this one</a>
for rendering all tunes, or
<a href="javascript:(function(){var%20s,n=3,d=document,b=d.body;b.innerHTML='\n%25abc-2.2\n%25%3c!--\n'+b.textContent+'%25--%3e\n';function%20f(u){s=d.createElement('script');s.src='http://moinejf.free.fr/js/'+u;s.onload=function(){if(--n==0)dom_loaded()};d.head.appendChild(s)};f('play-1.js');f('follow-1.js');f('abcemb1-1.js')})();void(0)">this one</a>
for rendering the tunes one by one.
##### Notes:
- The music is rendered as SVG images. There is one image per
music line / text block.
If you want to move these images to some other files,
each one must contain the full CSS and defs. For that, insert
` %%fullsvg x`
in the ABC file before rendering (see the
[fullsvg documentation](http://moinejf.free.fr/abcm2ps-doc/fullsvg.xhtml)
for more information).
- Playing uses the HTML5 audio and/or midi APIs.
- With the editor, if you want to render ABC files
which contain `%%abc-include`, you must:
- load the ABC file from the browse button
- click in the include file name
- load the include file by the same browse button
Then, you may edit and save both files.
There may be only one included file.
- The editor comes with different ways to enter the music from the keyboard.
If you have a US keyboard, you may try these bookmarklets:
<a href="javascript:(function(){if(typeof%20loadjs=='function'){loadjs('abckbd-1.js')}else{alert('use%20with%20abc2svg%20editor')}})();void(0)">keyboard 1</a>
and
<a href="javascript:(function(){if(typeof%20loadjs=='function'){loadjs('abckbd2-1.js')}else{alert('use%20with%20abc2svg%20editor')}})();void(0)">keyboard 2</a>
- The .js and .xhtml file names have a suffix which is the version of
the core interface (actually '`-1`').
### nodeJS usage
Installed via **npm**, the **abc2svg** package comes with the
command line (batch) programs `abc2svg` and `abc2odt`.
These ones may be used as **abcm2ps** to generate XHTML or ODT files.
`abc2svg` writes to standard output:
` abc2svg mytunes.abc > Out.xhtml`
`abc2odt` output is `abc.odt` or the file specified
by the command line argument `-o`:
` abc2odt my_file.abc -o my_file.odt`
### Build
If you want to build the **abc2svg** scripts in your machine,
you must first get the files from
[chisel](https://chiselapp.com/user/moinejf/repository/abc2svg),
either as a tarball or a Zip archive
(click `Timeline` and then in the top commit),
or by cloning the repository in some directory:
> `fossil clone https://chiselapp.com/user/moinejf/repository/abc2svg abc2svg.fossil`
> `fossil open abc2svg.fossil`
Then, building is done using the tool [ninja](https://ninja-build.org/)
or [samurai](https://github.com/michaelforney/samurai).
You may do it:
- without minification
This is interesting for debug purpose, the scripts being more human friendly.
` NOMIN=1 samu -v`
- in a standard way with minification
In this case, you need the tool `uglifyjs` which comes with nodeJS.
` samu -v`
If you also want to change or add music glyphs, you may edit the source
file `font/abc2svg.sfd`. In this case, you will need both `base64` and `fontforge`,
and run
` samu -v font.js`
If you cannot or don't want to install `ninja` or `samurai`, you may build
the abc2svg files by `./build` which is a shell script.
### Batch
After building the **abc2svg** scripts, you will be able to generate music
sheets from the command line as you did with `abcm2ps`, thanks to the
following shell scripts (the result goes to stdout):
- `abcqjs` with `qjs`
([QuickJS by Fabrice Bellard and Charlie Gordon](https://bellard.org/quickjs/))
- `abcjs24` with `js24` (Mozilla JavaScript shell - Spidermonkey)
- `abcjs52` with `js52` (Mozilla JavaScript shell - Spidermonkey)
- `abcjs60` with `js60` (Mozilla JavaScript shell - Spidermonkey)
- `abcjsc` with `jsc-1` (webkitgtk2)
- `abcnode` with `node` (nodeJS)
- `abcv8` with `d8` (Google libv8)
#### backend scripts
By default, the batch scripts generate (XHTML+SVG) files.
This output may be modified by backend scripts. These ones must appear
just after the command.
There are:
- `toabc.js`
This script outputs back the (selected) ABC tunes of the ABC source file.
Transposition is applied.
The resulting file does not contain the formatting parameters.
Example:
` abcqjs toabc.js my_file.abc --select X:2 > tune_2.abc`
- `toabw.js`
This script outputs a Abiword file (ABW+SVG) which may be read by some
word processors (abiword, libreoffice...) and converted to many other
formats by the batch function of abiword.
The abc2svg music font (`abc2svf.woff` or `abc2svg.ttf`) must be installed
in the local system for displaying and/or converting the .abw file.
Example:
` abcv8 toabw.js my_file.abc > my_file.abw`
- `tomei.js`
This script outputs the music as a [MEI](https://music-encoding.org/) file.
Indeed, only one tune may be translated from ABC to MEI (multi-tunes ABC
generates bad MEI).
- `toodt.js`
This script creates an Open Document (ODT+SVG) which may be read by most
word processors (abiword, libreoffice...).
It runs only with the npm script `abc2svg` and asks for the npm module
`jszip` to be installed.
The output ODT document may be specified by the command line argument `-o`
(default `abc.odt`).
Example:
` abc2svg toodt.js my_file.abc -o my_file.odt`
- `toparam.js`
This script just outputs the abc2svg parameters.
#### PDF generation
`abctopdf` is a shell script which converts ABC to PDF using one of the
previous shell scripts and the program `rsvg-convert`.
As a constraint, the used music font must be installed and defined by
`%%musicfont <fontname>`.
Example:
` abctopdf my_file.abc -o my_file.pdf`
### MEI support
As an experimental feature, an extented core `mei2svg-1.js` may be generated.
This one may handle both the ABC and [MEI](https://music-encoding.org/) notations.
In browser mode, the script `abcemb-1.js` loads either abc2svg-1.js or
mei2svg-1.js after checking the music notation type (`%abc` or `X:` is ABC,
`<mei` is MEI - see
[this tune](http://moinejf.free.fr/abc/Czerny_op603_6.html) for an example).
In batch mode, the script `abcqjs` also loads the right abc2svg core
according to the source file extension (`.abc` or `.mei`).
|
Changes to abc2odt.
| ︙ | ︙ | |||
34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
process.exit(1)
}
abc2svg.readFile = function(fname) {
var fs = require("fs")
return fs.readFileSync(fname).toString()
}
abc2svg.loadjs = function(fn, relay, onerror) {
try {
var geval = eval;
geval(abc2svg.readFile(__dirname + sep + fn))
if (relay)
relay()
| > > > > > > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
process.exit(1)
}
abc2svg.readFile = function(fname) {
var fs = require("fs")
return fs.readFileSync(fname).toString()
}
abc2svg.get_mtime = function(fn) {
var fs = require("fs")
return fs.statSync(fn).mtime
}
abc2svg.loadjs = function(fn, relay, onerror) {
try {
var geval = eval;
geval(abc2svg.readFile(__dirname + sep + fn))
if (relay)
relay()
|
| ︙ | ︙ |
Changes to abc2svg.
| ︙ | ︙ | |||
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
process.exit(1)
}
abc2svg.readFile = function(fname) {
var fs = require("fs")
return fs.readFileSync(fname).toString()
}
abc2svg.loadjs = function(fn, relay, onerror) {
try {
var geval = eval;
geval(abc2svg.readFile(__dirname + sep + fn))
if (relay)
relay()
} catch(e) {
if (onerror)
onerror()
else
printErr('Cannot read file ' + fn)
}
}
// load the command line
m = require("abc2svg/cmdline");
| > > > > > > < | 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 |
process.exit(1)
}
abc2svg.readFile = function(fname) {
var fs = require("fs")
return fs.readFileSync(fname).toString()
}
abc2svg.get_mtime = function(fn) {
var fs = require("fs")
return fs.statSync(fn).mtime
}
abc2svg.loadjs = function(fn, relay, onerror) {
try {
var geval = eval;
geval(abc2svg.readFile(__dirname + sep + fn))
if (relay)
relay()
} catch(e) {
if (onerror)
onerror()
else
printErr('Cannot read file ' + fn)
}
}
// load the command line
m = require("abc2svg/cmdline");
global.user = m.user;
global.abc_cmd = m.abc_cmd
// main
var args = process.argv
if (!args[2])
usage();
|
| ︙ | ︙ |
Changes to abc2svg.ttf.
cannot compute difference between binary files
Added abcjs60.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
#!/usr/bin/env js60
// abc2svg with js60 (Mozilla JavaScript shell - Spidermonkey
// packages: debian: libmozjs-60-dev, voidlinux: mozjs60)
loadRelativeToScript("abc2svg-1.js")
// interpreter specific functions
abc2svg.print = function(str) {
print(str)
}
abc2svg.printErr = function(str) {
printErr(str)
}
abc2svg.quit = function() {
quit(1)
}
abc2svg.readFile = function(fname) {
return read(fname)
}
abc2svg.loadjs = function(fn, relay, onerror) {
try {
loadRelativeToScript(fn)
if (relay)
relay()
} catch(e) {
if (onerror)
onerror()
else
printErr('Cannot read file ' + fn)
}
} // loadjs()
loadRelativeToScript("cmdline.js")
// main
var args = scriptArgs
if (/\.js$/.test(args[0])) {
load(args[0])
args.shift()
}
if (typeof abc2svg.abc_init != 'function')
loadRelativeToScript("toxhtml.js")
if (!args[0]) {
printErr('ABC translator with js60 (SpiderMonkey)\
and abc2svg-' + abc2svg.version + ' ' + abc2svg.vdate + '\n\
Usage:\n\
abcjs60 [script.js] [g_options] ABC_file [f_options] [ABC_file [f_options]]*\n\
Arguments:\n\
script.js generation script to load - default: toxhtml.js (XHTML+SVG)\n\
g_options global ABC options\n\
ABC_file ABC file\n\
f_options file options')
quit()
}
abc_cmd("abcjs60", args)
|
Changes to abcjsc.
1 2 3 4 5 6 7 8 9 |
#!/bin/sh
# abc2svg with jsc (webkit2gtk)
progdir=`dirname $0`
exec jsc -e "var progdir='${progdir}/'
// function to do utf-8 work...
// uncommenting this function asks for also uncommenting its call in cmdline.js
//function utf_convert(fin) {
| | | > > > > > > > > > > > > > > > | > > > > > | 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 |
#!/bin/sh
# abc2svg with jsc (webkit2gtk)
progdir=`dirname $0`
exec jsc -e "var progdir='${progdir}/'
// function to do utf-8 work...
// uncommenting this function asks for also uncommenting its call in cmdline.js
//function utf_convert(fin) {
// var b1, b2, b3,
// fout = ''
// for (var i = 0; i < fin.length; i++) {
// b1 = fin.charCodeAt(i)
// if (b1 >= 0x80) {
// b2 = fin.charCodeAt(++i);
// if (b1 >= 0xe0) {
// b3 = fin.charCodeAt(++i);
// if (b1 >= 0xf0) { // >= 0x10000
// b1 = ((b1 & 0x07) << 18) +
// ((b2 & 0x3f) << 12) +
// ((b3 & 0x3f) << 6) +
// (fin.charCodeAt(++i) & 0x3f);
// fout += String.fromCharCode((b1 >> 10) + 0xd7c0,
// (b1 & 0x3ff) + 0xdc00)
// } else {
// fout += String.fromCharCode(((b1 & 0x0f) << 12) +
// ((b2 & 0x3f) << 6) +
// (b3 & 0x3f))
// }
// } else {
// fout += String.fromCharCode(((b1 & 0x1f) << 6) +
// (b2 & 0x3f))
// }
// } else {
// fout += fin[i]
// }
// }
// return fout
//}
load(progdir + 'abc2svg-1.js')
// interpreter specific functions
abc2svg.print = function(str) {
print(str)
}
abc2svg.printErr = function(str) {
printErr(str)
}
abc2svg.quit = function() {
quit(1)
}
abc2svg.readFile = function(fname) {
return read(fname)
}
|
| ︙ | ︙ |
Changes to abcnode.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
process.exit(1)
}
abc2svg.readFile = function(fname) {
var fs = require("fs");
return fs.readFileSync(fname).toString()
}
abc2svg.loadjs = function(fn, relay, onerror) {
try {
var geval = eval;
geval(abc2svg.readFile(progdir + fn))
if (relay)
relay()
| > > > > > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
process.exit(1)
}
abc2svg.readFile = function(fname) {
var fs = require("fs");
return fs.readFileSync(fname).toString()
}
abc2svg.get_mtime= function(fn) {
var fs = require("fs")
return fs.statSync(fn).mtime
}
abc2svg.loadjs = function(fn, relay, onerror) {
try {
var geval = eval;
geval(abc2svg.readFile(progdir + fn))
if (relay)
relay()
|
| ︙ | ︙ | |||
66 67 68 69 70 71 72 73 74 75 76 |
g_options global ABC options\n\
ABC_file ABC file\n\
f_options file options');
abc2svg.quit(1)
}
args.shift()
args.shift()
abc_cmd("abcnode", args)
EOF
node /tmp/toto.js "$@"
| > | 72 73 74 75 76 77 78 79 80 81 82 83 |
g_options global ABC options\n\
ABC_file ABC file\n\
f_options file options');
abc2svg.quit(1)
}
args.shift()
args.shift()
global.user = user; // (for modules/page.js)
abc_cmd("abcnode", args)
EOF
node /tmp/toto.js "$@"
|
Added abcqjs.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 |
:;# shell script to convert ABC or MEI music notation to other format
# using abc2svg and quickjs (https://bellard.org/quickjs/)
test -f /tmp/abcqjs.js && exec qjs --std /tmp/abcqjs.js $0 "$@"
cat > /tmp/abcqjs.js << EOF
//javascript
var i,
args = scriptArgs
args.shift() // remove '/tmp/abcqjs.js'
var core = "abc2svg-1.js",
path = args.shift(). // the 1st argument is the script name
match(/(.*\/).*/)
path = path ? path[1] : ""
i = args.length
while (--i >= 0) {
if (/\.mei$/.test(args[i])) {
core = "mei2svg-1.js"
break
}
}
std.loadScript(path + core)
// interpreter specific functions
function load(fn) {
return std.loadScript(fn)
}
abc2svg.print = function(str) {
print(str)
}
abc2svg.printErr = function(str) {
std.err.printf("%s\n", str)
}
abc2svg.quit = function() {
std.exit(1)
}
abc2svg.readFile = function(fname) {
var l, f,
b = "",
bt = "",
cnt = 30
try {
f = std.open(fname, "r")
} catch(e) {
return ""
}
while (1) {
if (--cnt < 0) {
cnt = 30
bt += b
b = ""
}
l = f.getline()
if (l == null)
break
b += l + "\n"
}
f.close()
return bt + b
} // readfile()
abc2svg.get_mtime = function(fn) {
return new Date(os.stat(fn)[0].mtime)
}
abc2svg.loadjs = function(fn, relay, onerror) {
try {
std.loadScript(path + fn)
if (relay)
relay()
} catch(e) {
if (onerror)
onerror()
else
printErr('Cannot read file ' + fn)
}
} // loadjs()
std.loadScript(path + "cmdline.js")
// main
if (/\.js$/.test(args[0])) {
if (args[0][0] == "/")
std.loadScript(args[0])
else
std.loadScript(path + args[0])
args.shift()
}
if (typeof abc2svg.abc_init != 'function')
std.loadScript(path + "toxhtml.js")
if (!args[0]) {
abc2svg.printErr('ABC translator with quickjs\
and abc2svg-' + abc2svg.version + ' ' + abc2svg.vdate + '\n\
Usage:\n\
abcqjs [script.js] [g_options] ABC_file [f_options] [ABC_file [f_options]]*\n\
Arguments:\n\
script.js generation script to load - default: toxhtml.js (XHTML+SVG)\n\
g_options global ABC options\n\
ABC_file ABC file\n\
f_options file options')
abc2svg.quit()
}
abc_cmd("abcqjs", args)
EOF
exec qjs --std /tmp/abcqjs.js $0 "$@"
The previous solution with the shebang line as
#!/usr/bin/env -S qjs --std
did not work with non-GNU versions of env
|
Added abctopdf.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
#!/bin/sh
#
# abctopdf - converts ABC to PDF using abc2svg
#
# Copyright (C) 2019 Jean-François Moine - License GPL3+
if [ $# -eq 0 ]; then
cat << EOF
ABC to PDF translator using abc2svg
Usage:
abctopdf [g_options] ABC_file [f_options] [ABC_file [f_options]]* [-o output_file]
Arguments:
g_options global ABC options
ABC_file ABC file
f_options file options
output_file output file - default is "./abc.pdf"
EOF
exit 1
fi
# choose a abc2svg batch script with an available JS interpreter
if [ ${0#./} != $0 ]; then
bdir="./"
else
bdir=`dirname $0`
if [ $bdir != '.' ]; then
bdir="$bdir/"
else
bdir=''
fi
fi
# (sorted from fastest to slowest in ARM machines)
for c in qjs jsc js24 js52 js60 d8 abc2svg node end; do
if [ $c = 'end' ]; then
echo "$0: could not find a javascript interpreter - abort"
exit 1
fi
if command -v $c >/dev/null 2>&1; then
case $c in
(qjs) c=abcqjs;;
(jsc) c=abcjsc;;
(js24) c=abcjs24;;
(js52) c=abcjs52;;
(js60) c=abcjs60;;
(d8) c=abcv8;;
(abc2svg) c=abc2svg;;
(node) c=abcnode;;
esac
if command -v $c >/dev/null 2>&1; then
abcscr=$c
break
fi
if command -v $bdir$c >/dev/null 2>&1; then
abcscr=$bdir$c
break
fi
fi
done
echo "Using $abcscr"
# get the output file name (after '-o')
# default name
out='abc.pdf'
n=0
for a do
if [ "$a" = "-o" ]; then
n=1
elif [ $n -eq 1 ]; then
out=$a
n=0
else
set -- "$@" "$a"
fi
shift
done
# check if some chromium-based browser is available
# test rsvg-convert
for c in chromium-browser vivaldi opera brave-browser epic google-chrome; do
if command -v $c >/dev/null 2>&1; then
echo "and $c"
command $abcscr "$@" > /tmp/o.xhtml
$c --headless --disable-gpu --print-to-pdf=$out /tmp/o.xhtml
rm /tmp/o.xhtml
exit 0
fi
done
# check the required programs
if ! command -v rsvg-convert >/dev/null 2>&1; then
echo "$0: program 'rsvg-convert' not found - abort"
exit 1
fi
echo "and rsvg-convert"
# build a ABC file (with JS script) to change the font and page definitions
# this solves the following problems:
# - the maintainer of librsvg does not want to handle the CSS shorthand 'font:'
# - rsvg-convert always gets the SVG images at 72ppi, ignoring the -p/-d values
# - the sets of SVG images per page must be converted to a set of one SVG per page
cat > /tmp/fix.abc << EOF
%%pageheight 29.7cm
%%fullsvg 1
%%musicfont abc2svg
%%beginjs
var fix_out
function font_bug(str) {
return str.replace(/font:.*?["};]/g, function(p) { // "
var w = p.slice(5, -1).match(/[^ \t"]+|".+?"/g), // "
l = w.length,
r = 'font-family:' + w[--l] + ';font-size:' + w[--l]
while (--l >= 0) {
switch (w[l]) {
case 'italic':
r += ';font-style:italic'
break
case 'oblique':
r += ';font-style:oblique'
break
case 'bold':
r += ';font-weight:bold'
break
}
}
return r + p[p.length - 1]
})
}
// install
// - front-end
fix_out = abc2svg.page.img_out
abc2svg.page.img_out = function(page, p) {
fix_out(page, font_bug(p))
}
// - back-end
var page_h, page_out,
page_sty = ""
// get the style from the image and remove it from the block
function get_style(p) {
var i,
sty = p.match(/<style.*?>((.|\n)*?)<\/style>/)
if (!sty)
return p
sty = sty[1].split('\n')
if (!page_sty)
page_sty = '<style type="text/css">\n</style>\n'
for (i = 0; i < sty.length; i++) {
if (page_sty.indexOf(sty[i]) < 0)
page_sty = page_sty.replace('</style>\n',
sty[i] + '\n</style>\n')
}
return p.replace(/<style(.|\n)*?\/style>\n/, '')
} // get_style()
// low level output
abc.page.user_out = function(p) {
var h, w,
cfmt = abc.cfmt()
switch (p.slice(0, 4)) {
case "<div": // new page
page_h = 0
page_out = ""
break
case "<svg": // SVG image
p = get_style(p)
page_out += p
.replace(/<svg(.|\n)*?>/,
'<g transform="translate(0, ' +
page_h.toFixed(1) + ')">')
.replace('</svg>', '</g>\n')
page_h += Number(p.match(/height="(\d+)px"/)[1])
break
case "</di": // end of page
w = cfmt.pagewidth
h = cfmt.pageheight
abc2svg.print('\
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
color="black" class="music" stroke-width=".7"\n\
width="' +
(w * .75).toFixed(0) + 'px" height="' +
(h * .75).toFixed(0) + 'px" viewBox="0 0 ' +
w.toFixed(0) + ' ' +
h.toFixed(0) + '"' +
(cfmt.bgcolor ?
(' style="background-color: ' +
cfmt.bgcolor + '"') : '') +
'>\n' +
page_sty +
page_out + "</svg>")
break
}
} // user_out()
// for tests
abc2svg.abort = function(e) {
abc2svg.printErr('abort: '+e.message+'\n'+e.stack)
abc2svg.quit()
}
%%endjs
EOF
# purge /tmp
rm -f /tmp/abc*.svg
# generate a (XHTML+SVG) file with a abc2svg batch script
# then, extract the SVG images (pages) to /tmp
n=0
command $abcscr /tmp/fix.abc "$@" | while read v; do
case "$v" in
"<svg"*)
n=$(($n+1))
fn="/tmp/abc$n.svg"
echo $v > $fn
;;
"</svg"*)
echo $v >> $fn
fn=
;;
"</body"*)
break;;
*)
if [ "X$fn" != "X" ]; then
echo $v >> $fn
fi
;;
esac
done
# convert the SVG images to PDF
if [ -f /tmp/abc1.svg ]; then
rsvg-convert -f pdf $(ls -rt /tmp/abc*.svg) -o $out
else
echo 'Errors during the generation'
fi
# cleanup
rm -f /tmp/abc*.svg /tmp/fix.abc
|
Changes to build.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 | core/svg.js core/tune.js core/lyrics.js core/gchord.js core/tail.js\ core/modules.js >> $out echo "abc2svg.version=\"$VERSION\";abc2svg.vdate=\"$DATE\"" >> $out cp modules/ambitus.js ambitus-$MAJOR.js cp modules/break.js break-$MAJOR.js cp modules/capo.js capo-$MAJOR.js cp modules/clip.js clip-$MAJOR.js cp modules/combine.js combine-$MAJOR.js cp modules/diag.js diag-$MAJOR.js cp modules/equalbars.js equalbars-$MAJOR.js cp modules/grid.js grid-$MAJOR.js cp modules/grid2.js grid2-$MAJOR.js cp modules/MIDI.js MIDI-$MAJOR.js | > | > > | > > | 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 | core/svg.js core/tune.js core/lyrics.js core/gchord.js core/tail.js\ core/modules.js >> $out echo "abc2svg.version=\"$VERSION\";abc2svg.vdate=\"$DATE\"" >> $out cp modules/ambitus.js ambitus-$MAJOR.js cp modules/break.js break-$MAJOR.js cp modules/capo.js capo-$MAJOR.js cat util/midi.js modules/clair.js >> clair-$MAJOR.js cp modules/clip.js clip-$MAJOR.js cp modules/combine.js combine-$MAJOR.js cp modules/diag.js diag-$MAJOR.js cp modules/equalbars.js equalbars-$MAJOR.js cp modules/grid.js grid-$MAJOR.js cp modules/grid2.js grid2-$MAJOR.js cp modules/MIDI.js MIDI-$MAJOR.js cat modules/page.js modules/strftime.js > page-$MAJOR.js cp modules/perc.js perc-$MAJOR.js cat modules/wps.js modules/psvg.js > psvg-$MAJOR.js cp modules/soloffs.js soloffs-$MAJOR.js cp modules/sth.js sth-$MAJOR.js cp modules/temper.js temper-$MAJOR.js cp editor/edit.css edit-$MAJOR.css cp util/abcdoc.js abcdoc-$MAJOR.js cp util/abcemb.js abcemb-$MAJOR.js cp util/abcemb1.js abcemb1-$MAJOR.js cp util/abcemb2.js abcemb2-$MAJOR.js cp util/abcweb2.js abcweb2-$MAJOR.js cp util/follow.js follow-$MAJOR.js cp util/json.js json-$MAJOR.js cp util/midi.js setmidi-$MAJOR.js cp util/toaudio.js toaudio-$MAJOR.js cat util/play.js util/toaudio.js util/toaudio5.js util/midi.js\ util/sf2-parser.js util/tomidi5.js > play-$MAJOR.js cat util/play.js util/sndgen.js util/sndaud.js util/midi.js\ util/sf2-parser.js util/sndmid.js > snd-$MAJOR.js sed "s+@MAJOR@+$MAJOR+" editor/edit.xhtml > edit-$MAJOR.xhtml sed "s+@MAJOR@+$MAJOR+" editor/abckbd.js > abckbd-$MAJOR.js sed "s+@MAJOR@+$MAJOR+" editor/abckbd2.js > abckbd2-$MAJOR.js sed "s+@MAJOR@+$MAJOR+" editor/edit.js > edit-$MAJOR.js |
Changes to build.ninja.
1 2 | # rules for ninja (ninja-build) | | | | | | < > > > > > > > > > > > > | 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 |
# rules for ninja (ninja-build)
# minifying with 'jsmin' or 'uglifyjs' may be disabled by running
# NOMIN=1 ninja -v
MAJOR=1
# ninja tool
tool=samu
rule cp
command = cp $in $out
rule cpm
command = sed "s+@MAJOR@+$MAJOR+" $in > $out
rule font
command = fontforge -c 'open("font/abc2svg.sfd").generate("abc2svg.ttf")';$
fontforge -c 'open("font/abc2svg.sfd").generate("abc2svg.woff")';$
echo '// abc2svg music font' > font.js;$
echo "var musicfont = 'url(\"data:application/octet-stream;base64,\\" >> font.js;$
base64 abc2svg.ttf | sed 's/$$/\\/' >> font.js;$
echo "\") format(\"truetype\")'" >> font.js
rule jsc
command = VERSION=`grep '"version"' package.json|cut -d'"' -f4`;$
if command -v fossil >/dev/null 2>&1; then $
c=`fossil info | grep checkout:`;$
t=`fossil info | grep tags: | awk '{print $$NF}'`;$
if [ "$${t#v}" != "$$VERSION" ]; then $
VERSION="$${VERSION}-$$(echo $$c | cut -d' ' -f2 | cut -c1-10)";$
fi;$
DATE=`echo $$c | cut -d' ' -f3`;$
else $
DATE=`date '+%Y-%m-%d' -r package.json`;$
fi;$
cp core/license $out;$
if [ "x$$NOMIN" = "x" ]; then $
if command -v jsmin >/dev/null 2>&1; then $
cat $in | jsmin >> $out;$
else $
cat $in | uglifyjs >> $out;$
fi;$
else $
cat $in >> $out;$
fi;$
echo "abc2svg.version=\"$$VERSION\";abc2svg.vdate=\"$$DATE\"" >> $out
rule jscu
command = cp core/license $out;$
if [ "x$$NOMIN" = "x" ]; then $
if command -v jsmin >/dev/null 2>&1; then $
cat $in | jsmin >> $out;$
else $
uglifyjs $in >> $out;$
fi;$
else $
cat $in >> $out;$
fi
rule edit
command = if [ "x$$NOMIN" = "x" ]; then $
if command -v jsmin >/dev/null 2>&1; then $
sed "s+@MAJOR@+$MAJOR+" $in | jsmin > $out;$
else $
sed "s+@MAJOR@+$MAJOR+" $in | uglifyjs > $out;$
fi;$
else $
sed "s+@MAJOR@+$MAJOR+" $in > $out;$
fi
# generate all Scc1t2/n.js from sf2-Scc1t2/n.sf2
rule sf
command = for f in sf2-Scc1t2/*.sf2; do $
|
| ︙ | ︙ | |||
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | build font: font | font/abc2svg.sfd build sf: sf | Scc1t2/ build abc2svg-$MAJOR.js: jsc core/abc2svg.js core/deco.js core/draw.js $ font.js core/format.js core/front.js core/music.js core/parse.js core/subs.js $ core/svg.js core/tune.js core/lyrics.js core/gchord.js core/tail.js $ core/modules.js | package.json build ambitus-$MAJOR.js: jscu modules/ambitus.js build break-$MAJOR.js: jscu modules/break.js build capo-$MAJOR.js: jscu modules/capo.js build clip-$MAJOR.js: jscu modules/clip.js build combine-$MAJOR.js: jscu modules/combine.js build diag-$MAJOR.js: jscu modules/diag.js build equalbars-$MAJOR.js: jscu modules/equalbars.js build grid-$MAJOR.js: jscu modules/grid.js build grid2-$MAJOR.js: jscu modules/grid2.js build MIDI-$MAJOR.js: jscu modules/MIDI.js | > > > > > | > > > > | | > > | | > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | build font: font | font/abc2svg.sfd build sf: sf | Scc1t2/ build abc2svg-$MAJOR.js: jsc core/abc2svg.js core/deco.js core/draw.js $ font.js core/format.js core/front.js core/music.js core/parse.js core/subs.js $ core/svg.js core/tune.js core/lyrics.js core/gchord.js core/tail.js $ core/modules.js | package.json build mei2svg-$MAJOR.js: jsc core/abc2svg.js core/deco.js core/draw.js $ font.js core/format.js core/front.js core/music.js core/parse.js core/subs.js $ core/svg.js core/tune.js core/lyrics.js core/gchord.js core/mei.js core/tail.js $ core/modules.js | package.json build ambitus-$MAJOR.js: jscu modules/ambitus.js build break-$MAJOR.js: jscu modules/break.js build capo-$MAJOR.js: jscu modules/capo.js build clair-$MAJOR.js: jscu util/midi.js modules/clair.js build clip-$MAJOR.js: jscu modules/clip.js build combine-$MAJOR.js: jscu modules/combine.js build diag-$MAJOR.js: jscu modules/diag.js build equalbars-$MAJOR.js: jscu modules/equalbars.js build grid-$MAJOR.js: jscu modules/grid.js build grid2-$MAJOR.js: jscu modules/grid2.js build MIDI-$MAJOR.js: jscu modules/MIDI.js build page-$MAJOR.js: jscu modules/page.js modules/strftime.js build perc-$MAJOR.js: jscu modules/perc.js build psvg-$MAJOR.js: jscu modules/wps.js modules/psvg.js build soloffs-$MAJOR.js: jscu modules/soloffs.js build sth-$MAJOR.js: jscu modules/sth.js build temper-$MAJOR.js: jscu modules/temper.js build edit-$MAJOR.css: cp editor/edit.css build abcdoc-$MAJOR.js: jscu util/abcdoc.js build abcemb-$MAJOR.js: jscu util/abcemb.js build abcemb1-$MAJOR.js: jscu util/abcemb1.js build abcemb2-$MAJOR.js: jscu util/abcemb2.js build abcweb2-$MAJOR.js: jscu util/abcweb2.js build follow-$MAJOR.js: jscu util/follow.js build json-$MAJOR.js: jscu util/json.js build setmidi-$MAJOR.js: jscu util/midi.js build toaudio-$MAJOR.js: jscu util/toaudio.js build play-$MAJOR.js: jscu util/play.js util/toaudio.js $ util/toaudio5.js util/midi.js util/sf2-parser.js util/tomidi5.js build snd-$MAJOR.js: jscu util/play.js util/sndgen.js $ util/sndaud.js util/midi.js util/sf2-parser.js util/sndmid.js build edit-$MAJOR.xhtml: cpm editor/edit.xhtml build abckbd-$MAJOR.js: edit editor/abckbd.js build abckbd2-$MAJOR.js: edit editor/abckbd2.js build edit-$MAJOR.js: edit editor/edit.js build all: phony abc2svg-$MAJOR.js abcdoc-$MAJOR.js $ abcemb-$MAJOR.js abcemb1-$MAJOR.js abcemb2-$MAJOR.js $ abcweb2-$MAJOR.js $ json-$MAJOR.js $ setmidi-$MAJOR.js toaudio-$MAJOR.js snd-$MAJOR.js play-$MAJOR.js psvg-$MAJOR.js $ ambitus-$MAJOR.js break-$MAJOR.js capo-$MAJOR.js clair-$MAJOR.js clip-$MAJOR.js $ combine-$MAJOR.js diag-$MAJOR.js equalbars-$MAJOR.js grid-$MAJOR.js grid2-$MAJOR.js $ MIDI-$MAJOR.js page-$MAJOR.js perc-$MAJOR.js soloffs-$MAJOR.js sth-$MAJOR.js $ temper-$MAJOR.js edit-$MAJOR.css edit-$MAJOR.js edit-$MAJOR.xhtml $ abckbd-$MAJOR.js abckbd2-$MAJOR.js follow-$MAJOR.js # not mei2svg-$MAJOR.js default all # npm/fossil new release rule version command = npm version $out;$ tag=`ag '"version"' package.json|cut -d'"' -f4`;$ fossil commit -m "New release v$$tag" -tag v$$tag;$ $tool -v;$ npm publish build minor: version build patch: version |
Changes to cmdline.js.
| ︙ | ︙ | |||
34 35 36 37 38 39 40 |
// print or store the error messages
if (typeof abc2svg.printErr == 'function')
user.errmsg = function(msg, l, c) { abc2svg.printErr(msg) }
else
user.errmsg = function(msg, l, c) { user.errtxt += msg + '\n' }
| | > > > | > | | | < < < | > | > | | > | | > > > > > > > > > > | > > > | < < | 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 |
// print or store the error messages
if (typeof abc2svg.printErr == 'function')
user.errmsg = function(msg, l, c) { abc2svg.printErr(msg) }
else
user.errmsg = function(msg, l, c) { user.errtxt += msg + '\n' }
var abc // (global for 'toxxx.js')
// treat a file
function do_file(fn) {
var ext, file
try {
file = user.read_file(fn)
} catch (e) {
// get the file extension
ext = fn.slice((fn.lastIndexOf('.') - 1 >>> 0) + 2)
if (!ext) {
fn += ".abc"
try {
file = user.read_file(fn)
} catch (e) {
}
}
}
if (!file && fn != "default.abc") {
// abc2svg.abort(new Error("Cannot read file '" + fn + "'"))
user.errmsg("Cannot read file '" + fn + "'")
return
}
// if (typeof(utf_convert) == "function")
// file = utf_convert(file)
if (fn.slice(-4) == ".mei") {
if (!abc.mei2mus)
abc2svg.abort(new Error("No MEI support"));
abc.mei2mus(file)
return
}
// load the required modules (synchronous)
abc2svg.modules.load(file)
// generate
try {
abc.tosvg(fn, file)
} catch (e) {
abc2svg.abort(e)
}
} // do_file()
function abc_cmd(cmd, args) {
var arg, parm, fn;
// initialize the backend
abc = new abc2svg.Abc(user)
if (typeof global == "object" && !global.abc)
global.abc = abc
abc2svg.abc_init(args)
// load 'default.abc'
try {
do_file("default.abc")
} catch (e) {
}
while (1) {
arg = args.shift()
if (!arg)
break
|
| ︙ | ︙ | |||
107 108 109 110 111 112 113 |
do_file(fn);
abc2svg.abc_end()
}
// nodejs
if (typeof module == 'object' && typeof exports == 'object') {
| < | 122 123 124 125 126 127 128 129 130 131 |
do_file(fn);
abc2svg.abc_end()
}
// nodejs
if (typeof module == 'object' && typeof exports == 'object') {
exports.user = user;
exports.abc_cmd = abc_cmd
}
|
Changes to core/abc2svg.js.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 | // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>. | | > | | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// define the abc2svg object is not yet done
if (typeof abc2svg == "undefined")
var abc2svg = {};
// constants
abc2svg.C = {
BLEN: 1536,
// symbol types
BAR: 0,
CLEF: 1,
CUSTOS: 2,
GRACE: 4,
|
| ︙ | ︙ | |||
51 52 53 54 55 56 57 | // slur/tie types (3 + 1 bits) SL_ABOVE: 0x01, SL_BELOW: 0x02, SL_AUTO: 0x03, SL_HIDDEN: 0x04, SL_DOTTED: 0x08 // (modifier bit) | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
// slur/tie types (3 + 1 bits)
SL_ABOVE: 0x01,
SL_BELOW: 0x02,
SL_AUTO: 0x03,
SL_HIDDEN: 0x04,
SL_DOTTED: 0x08 // (modifier bit)
};
// key table - index = number of accidentals + 7
abc2svg.keys = [
new Int8Array([-1,-1,-1,-1,-1,-1,-1 ]), // 7 flat signs
new Int8Array([-1,-1,-1, 0,-1,-1,-1 ]), // 6 flat signs
new Int8Array([ 0,-1,-1, 0,-1,-1,-1 ]), // 5 flat signs
new Int8Array([ 0,-1,-1, 0, 0,-1,-1 ]), // 4 flat signs
new Int8Array([ 0, 0,-1, 0, 0,-1,-1 ]), // 3 flat signs
new Int8Array([ 0, 0,-1, 0, 0, 0,-1 ]), // 2 flat signs
new Int8Array([ 0, 0, 0, 0, 0, 0,-1 ]), // 1 flat signs
new Int8Array([ 0, 0, 0, 0, 0, 0, 0 ]), // no accidental
new Int8Array([ 0, 0, 0, 1, 0, 0, 0 ]), // 1 sharp signs
new Int8Array([ 1, 0, 0, 1, 0, 0, 0 ]), // 2 sharp signs
new Int8Array([ 1, 0, 0, 1, 1, 0, 0 ]), // 3 sharp signs
new Int8Array([ 1, 1, 0, 1, 1, 0, 0 ]), // 4 sharp signs
new Int8Array([ 1, 1, 0, 1, 1, 1, 0 ]), // 5 sharp signs
new Int8Array([ 1, 1, 1, 1, 1, 1, 0 ]), // 6 sharp signs
new Int8Array([ 1, 1, 1, 1, 1, 1, 1 ]) // 7 sharp signs
]
// base-40 representation of musical pitch
// (http://www.ccarh.org/publications/reprints/base40/)
abc2svg.p_b40 = new Int8Array( // staff pitch to base-40
// C D E F G A B
[ 2, 8, 14, 19, 25, 31, 37 ])
abc2svg.b40_p = new Int8Array( // base-40 to staff pitch
// C D
[0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
// E F G
2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4,
// A B
5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6 ])
abc2svg.b40_a = new Int8Array( // base-40 to accidental
// C D
[-2, -1, 0, 1, 2, 0, -2, -1, 0, 1, 2, 0,
// E F G
-2, -1, 0, 1, 2, -2, -1, 0, 1, 2, 0, -2, -1, 0, 1, 2, 0,
// A B
-2, -1, 0, 1, 2, 0, -2, -1, 0, 1, 2 ])
abc2svg.b40_m = new Int8Array( // base-40 to midi
// C D
[-2, -1, 0, 1, 2, 0, 0, 1, 2, 3, 4, 0,
// E F G
2, 3, 4, 5, 6, 3, 4, 5, 6, 7, 0, 5, 6, 7, 8, 9, 0,
// A B
7, 8, 9, 10, 11, 0, 9, 10, 11, 12, 13 ])
abc2svg.b40k = new Int8Array( // base-40 interval to possible transposition
// C D
[36, 1, 2, 3, 8, 2, 2, 7, 8,13,14, 2,
// 37
// E F G
8,13,14,19,20,13,14,19,20,25, 2,19,24,25,30,31, 2,
// 20
// A B
25,30,31,36,37, 2,31,36,37,38, 3 ])
// 2
abc2svg.b40sf = new Int8Array( // base-40 interval to key signature
// C D
[-2,-7, 0, 7, 2, 88, 0,-5, 2,-3, 4, 88,
// E F G
2,-3, 4,-1, 6,-3, 4,-1, 6, 1,88,-1,-6, 1,-4, 3,88,
// A B
1,-4, 3,-2, 5,88, 3,-2, 5, 0, 7 ])
abc2svg.isb40 = new Int8Array( // interval with sharp to base-40 interval
[0, 1, 6,11,12,17,18,23,28,29,34,35])
abc2svg.ifb40 = new Int8Array( // interval with flat to base-40 interval
[0, 5, 6,11,12,17,22,23,28,29,34,39])
abc2svg.pab40 = function(p, a) {
p += 19 // staff pitch from C-1
var b40 = ((p / 7) | 0) * 40 + abc2svg.p_b40[p % 7]
if (a && a != 3) // if some accidental, but not natural
b40 += a
return b40
} // pit2b40()
abc2svg.b40p = function(b) {
return ((b / 40) | 0) * 7 + abc2svg.b40_p[b % 40] - 19
} // b40p()
abc2svg.b40a = function(b) {
return abc2svg.b40_a[b % 40]
} // b40a()
abc2svg.b40m = function(b) {
return ((b / 40) | 0) * 12 + abc2svg.b40_m[b % 40]
} // b40m()
// compare pitches
// This function is used to sort the note pitches
abc2svg.pitcmp = function(n1, n2) { return n1.pit - n2.pit }
// start of the Abc object
abc2svg.Abc = function(user) {
"use strict";
// constants
var C = abc2svg.C;
// mask some unsafe functions
var require = empty_function,
|
| ︙ | ︙ | |||
90 91 92 93 94 95 96 97 98 99 |
IN = 96, // resolution 96 PPI
CM = 37.8, // 1 inch = 2.54 centimeter
YSTEP = 256 /* number of steps for y offsets */
// error texts
var errs = {
bad_char: "Bad character '$1'",
bad_val: "Bad value in $1",
bar_grace: "Cannot have a bar in grace notes",
ignored: "$1: inside tune - ignored",
| > | > | > < < > | > | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
IN = 96, // resolution 96 PPI
CM = 37.8, // 1 inch = 2.54 centimeter
YSTEP = 256 /* number of steps for y offsets */
// error texts
var errs = {
bad_char: "Bad character '$1'",
bad_grace: "Bad character in grace note sequence",
bad_val: "Bad value in $1",
bar_grace: "Cannot have a bar in grace notes",
ignored: "$1: inside tune - ignored",
misplaced: "Misplaced '$1' in %%score",
must_note: "!$1! must be on a note",
must_note_rest: "!$1! must be on a note or a rest",
nonote_vo: "No note in voice overlay",
not_ascii: "Not an ASCII character",
not_enough_n: 'Not enough notes/rests for %%repeat',
not_enough_m: 'Not enough measures for %%repeat',
not_enough_p: "Not enough parameters in %%map",
not_in_tune: "Cannot have '$1' inside a tune"
}
var self = this, // needed for modules
glovar = {
meter: {
type: C.METER, // meter in tune header
wmeasure: 1, // no M:
a_meter: [] // default: none
}
},
info = {}, // information fields
parse = {
ctx: {},
prefix: '%',
state: 0,
ottava: [],
line: new scanBuf
},
tunes = [], // first time symbol and voice array per tune for playing
psvg // PostScript
// utilities
function clone(obj, lvl) {
if (!obj)
return obj
var tmp = new obj.constructor
for (var k in obj)
if (obj.hasOwnProperty(k)) {
if (lvl && typeof obj[k] == 'object')
tmp[k] = clone(obj[k], lvl - 1)
else
tmp[k] = obj[k]
}
|
| ︙ | ︙ | |||
177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
}
user.errmsg(h + txt, l, c)
}
function error(sev, s, msg, a1, a2, a3, a4) {
var i, j, regex, tmp
if (user.textrans) {
tmp = user.textrans[msg]
if (tmp)
msg = tmp
}
if (arguments.length > 3)
msg = msg.replace(/\$./g, function(a) {
| > > | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
}
user.errmsg(h + txt, l, c)
}
function error(sev, s, msg, a1, a2, a3, a4) {
var i, j, regex, tmp
if (!sev && cfmt.quiet)
return
if (user.textrans) {
tmp = user.textrans[msg]
if (tmp)
msg = tmp
}
if (arguments.length > 3)
msg = msg.replace(/\$./g, function(a) {
|
| ︙ | ︙ |
Changes to core/deco.js.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 |
// decorations - populate with standard decorations
var decos = {
dot: "0 stc 5 1 1",
tenuto: "0 emb 5 3 3",
slide: "1 sld 3 7 0",
arpeggio: "2 arp 12 10 0",
roll: "3 roll 7 6 6",
| | | | | 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 |
// decorations - populate with standard decorations
var decos = {
dot: "0 stc 5 1 1",
tenuto: "0 emb 5 3 3",
slide: "1 sld 3 7 0",
arpeggio: "2 arp 12 10 0",
roll: "3 roll 7 6 6",
fermata: "3 hld 10 7 7",
emphasis: "3 accent 7 4 4",
lowermordent: "3 lmrd 10 5 5",
coda: "3 coda 24 10 10",
uppermordent: "3 umrd 10 5 5",
segno: "3 sgno 22 8 8",
trill: "3 trl 14 5 5",
upbow: "3 upb 10 5 5",
downbow: "3 dnb 9 5 5",
gmark: "3 grm 6 5 5",
wedge: "0 wedge 7 3 3", // (staccatissimo or spiccato)
turnx: "3 turnx 10 0 5",
breath: "3 brth 0 1 20",
longphrase: "3 lphr 0 1 1",
mediumphrase: "3 mphr 0 1 1",
shortphrase: "3 sphr 0 1 1",
invertedfermata: "3 hld 10 7 7",
invertedturn: "3 turn 10 0 5",
invertedturnx: "3 turnx 10 0 5",
"0": "3 fng 8 3 3 0",
"1": "3 fng 8 3 3 1",
"2": "3 fng 8 3 3 2",
"3": "3 fng 8 3 3 3",
"4": "3 fng 8 3 3 4",
|
| ︙ | ︙ | |||
82 83 84 85 86 87 88 | mp: "6 mp 18 6 16", p: "6 p 18 2 8", pp: "6 pp 18 5 14", ppp: "6 ppp 18 8 20", pppp: "6 pppp 18 10 25", pralltriller: "3 umrd 10 5 5", sfz: "6 sfz 18 4 10", | | | | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
mp: "6 mp 18 6 16",
p: "6 p 18 2 8",
pp: "6 pp 18 5 14",
ppp: "6 ppp 18 8 20",
pppp: "6 pppp 18 10 25",
pralltriller: "3 umrd 10 5 5",
sfz: "6 sfz 18 4 10",
ped: "4 ped 18 6 10",
"ped-up": "4 pedoff 12 4 4",
"ped(": "4 lped 20 1 1",
"ped)": "4 lped 20 1 1",
"crescendo(": "6 cresc 18 0 0",
"crescendo)": "6 cresc 18 0 0",
"<(": "6 cresc 18 0 0",
"<)": "6 cresc 18 0 0",
"diminuendo(": "6 dim 18 0 0",
|
| ︙ | ︙ | |||
334 335 336 337 338 339 340 | // de.y = s.y; return } if (s.multi) up = s.multi > 0 else up = s.stem < 0 | | > > > | | > > > | < | 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
// de.y = s.y;
return
}
if (s.multi)
up = s.multi > 0
else
up = s.stem < 0
if (up) {
y = s.ymx | 0
} else if (dd.name[0] == 'w') {
de.inv = true
y = s.ymn
} else {
y = s.ymn - dd.h
}
if (y > -6 && y < 24) {
if (up)
y += 3;
y = (((y + 6) / 6) | 0) * 6 - 6 /* between lines */
}
if (up)
s.ymx = y + dd.h
else if (dd.name[0] == 'w')
s.ymn = y - dd.h
else
s.ymn = y
de.y = y
if (s.type == C.NOTE)
de.x += s.notes[s.stem >= 0 ? 0 : s.nhd].shhd
if (dd.name[0] == 'd' /* if dot decoration */
&& s.nflags >= -1) { /* on stem */
if (up) {
if (s.stem > 0)
de.x += 3.5 // stem_xoff
|
| ︙ | ︙ | |||
809 810 811 812 813 814 815 | error(1, s, "!$1! must be on the last of a couple of notes", dd.name) continue } s.trem2 = true; s.beam_end = true; | | | | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 | error(1, s, "!$1! must be on the last of a couple of notes", dd.name) continue } s.trem2 = true; s.beam_end = true; s.beam_st = false; prev.beam_st = true; prev.beam_end = false; s.ntrem = prev.ntrem = Number(dd.name[4]); for (j = 0; j <= s.nhd; j++) s.notes[j].dur *= 2; for (j = 0; j <= prev.nhd; j++) prev.notes[j].dur *= 2 continue case 35: /* xstem */ |
| ︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 | || stv_g.st < 0) // or not staff scale // || voice_tb[s.v].scale != 1) out_deco_val(x, y, f, de.val / stv_g.scale, de.defl) else out_deco_val(x, y, f, de.val, de.defl) if (de.defl.noen) new_de.push(de.start) // to be continued next line | | < | 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 |
|| stv_g.st < 0) // or not staff scale
// || voice_tb[s.v].scale != 1)
out_deco_val(x, y, f, de.val / stv_g.scale, de.defl)
else
out_deco_val(x, y, f, de.val, de.defl)
if (de.defl.noen)
new_de.push(de.start) // to be continued next line
} else if (dd.str != undefined) {
str = dd.str
if (str[0] == '@') {
a = str.match(/^@([0-9.-]+),([0-9.-]+);?/);
x += Number(a[1]);
y += Number(a[2]);
str = str.replace(a[0], "")
}
|
| ︙ | ︙ | |||
1204 1205 1206 1207 1208 1209 1210 |
} else if (dd.dd_st) {
de.lden = true;
de.defl.nost = true
}
}
} // create_dh()
| | | 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 |
} else if (dd.dd_st) {
de.lden = true;
de.defl.nost = true
}
}
} // create_dh()
// create all decorations of a note (chord and heads)
function create_all(s) {
var m
if (s.a_dd)
create_deco(s)
if (s.notes) {
for (m = 0; m < s.notes.length; m++) {
|
| ︙ | ︙ | |||
1357 1358 1359 1360 1361 1362 1363 |
// - chord symbols
// - repeat brackets
/* (the staves are not yet defined) */
/* (unscaled delayed output) */
function draw_deco_staff() {
var s, first_gchord, p_voice, x, y, w, i, v, de, dd,
gch, gch2, ix, top, bot,
| | | 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 |
// - chord symbols
// - repeat brackets
/* (the staves are not yet defined) */
/* (unscaled delayed output) */
function draw_deco_staff() {
var s, first_gchord, p_voice, x, y, w, i, v, de, dd,
gch, gch2, ix, top, bot,
minmax = new Array(nstaff + 1),
nd = a_de.length
/* draw the repeat brackets */
function draw_repbra(p_voice) {
var s, s1, y, y2, i, p, w, wh, first_repeat;
/* search the max y offset */
|
| ︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 |
if (gch.type != 'g')
continue
gch2 = gch // chord closest to the staff
if (gch.y < 0)
break
}
if (gch2) {
| | | 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 |
if (gch.type != 'g')
continue
gch2 = gch // chord closest to the staff
if (gch.y < 0)
break
}
if (gch2) {
w = gch2.wh[0]
if (gch2.y >= 0) {
y = y_get(s.st, true, s.x, w)
if (y > minmax[s.st].ymax)
minmax[s.st].ymax = y
} else {
y = y_get(s.st, false, s.x, w)
if (y < minmax[s.st].ymin)
|
| ︙ | ︙ | |||
1622 1623 1624 1625 1626 1627 1628 |
y = y_get(st, true, 0, 20)
if (y < staff_tb[st].topbar + 14)
y = staff_tb[st].topbar + 14;
xy_str(0, y, bar_num.toString());
y_set(st, true, 0, 20, y + gene.curfont.size + 2)
} else if (bar_num % cfmt.measurenb == 0) {
for ( ; ; s = s.ts_next) {
| | > > > > > > < < | | | | 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 |
y = y_get(st, true, 0, 20)
if (y < staff_tb[st].topbar + 14)
y = staff_tb[st].topbar + 14;
xy_str(0, y, bar_num.toString());
y_set(st, true, 0, 20, y + gene.curfont.size + 2)
} else if (bar_num % cfmt.measurenb == 0) {
for ( ; ; s = s.ts_next) {
switch (s.type) {
case C.TIMESIG:
case C.CLEF:
case C.KEYSIG:
case C.FMTCHG:
case C.STBRK:
continue
}
break
}
// don't display the number twice
if (s.type != C.BAR || !s.bar_num) {
if (s.prev)
s = s.prev;
x = s.x + s.wr;
any_nb = true;
w = w0
if (bar_num >= 10)
w *= bar_num >= 100 ? 3 : 2
if (gene.curfont.box)
w += 4;
y = y_get(st, true, x, w)
|
| ︙ | ︙ | |||
1669 1670 1671 1672 1673 1674 1675 | break } set_dscale(st) continue default: continue case C.BAR: | | | 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 | break } set_dscale(st) continue default: continue case C.BAR: if (!s.bar_num || s.bar_num <= 1) continue break } bar_num = s.bar_num if (cfmt.measurenb == 0 || (bar_num % cfmt.measurenb) != 0 |
| ︙ | ︙ | |||
1716 1717 1718 1719 1720 1721 1722 |
}
gene.nbar = bar_num
if (font_size)
param_set_font("measurefont", "* " + font_size.toString());
}
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 |
}
gene.nbar = bar_num
if (font_size)
param_set_font("measurefont", "* " + font_size.toString());
}
/* -- draw the parts and the tempo information -- */
/* (the staves are being defined) */
function draw_partempo(st, top) {
var s, some_part, some_tempo, h, w, y,
dy = 0, /* put the tempo indication at top */
ht = 0
/* get the minimal y offset */
var ymin = staff_tb[st].topbar + 8,
dosh = 0,
shift = 1,
x = -100 // (must be negative for %%soloffs)
for (s = tsfirst; s; s = s.ts_next) {
if (s.type != C.TEMPO || s.del)
continue
if (!some_tempo)
some_tempo = s;
w = s.tempo_wh[0]
if (s.time == 0 && s.x > 40) // at start of tune and no %%soloffs,
s.x = 40; // shift the tempo over the key signature
y = y_get(st, true, s.x - 16, w)
if (y > ymin)
ymin = y
if (x >= s.x - 16 && !(dosh & (shift >> 1)))
dosh |= shift;
shift <<= 1;
x = s.x - 16 + w
}
if (some_tempo) {
set_sscale(-1);
set_font("tempo");
ht = gene.curfont.size + 8;
y = 2 - ht;
h = y - ht
if (dosh != 0)
ht *= 2
if (top < ymin + ht)
dy = ymin + ht - top
/* draw the tempo indications */
for (s = some_tempo; s; s = s.ts_next) {
if (s.type != C.TEMPO
|| s.del) // (displayed by %%titleformat)
continue
if (user.anno_start || user.anno_stop) {
s.wl = 16;
s.wr = 30;
s.ymn = (dosh & 1) ? h : y;
s.ymx = s.ymn + 14;
anno_start(s)
}
writempo(s, s.x - 16, (dosh & 1) ? h : y);
anno_stop(s);
dosh >>= 1
}
}
/* then, put the parts */
/*fixme: should reduce vertical space if parts don't overlap tempo...*/
|
| ︙ | ︙ |
Changes to core/draw.js.
| ︙ | ︙ | |||
25 26 27 28 29 30 31 | STEM_CH_MIN = 14, /* min stem height for chords under beams */ STEM_CH_MIN2 = 10, /* ... for notes with two beams */ STEM_CH_MIN3 = 9, /* ... for notes with three beams */ STEM_CH_MIN4 = 9, /* ... for notes with four beams */ BEAM_DEPTH = 3.2, /* width of a beam stroke */ BEAM_OFFSET = .25, /* pos of flat beam relative to staff line */ BEAM_SHIFT = 5, /* shift of second and third beams */ | < | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
STEM_CH_MIN = 14, /* min stem height for chords under beams */
STEM_CH_MIN2 = 10, /* ... for notes with two beams */
STEM_CH_MIN3 = 9, /* ... for notes with three beams */
STEM_CH_MIN4 = 9, /* ... for notes with four beams */
BEAM_DEPTH = 3.2, /* width of a beam stroke */
BEAM_OFFSET = .25, /* pos of flat beam relative to staff line */
BEAM_SHIFT = 5, /* shift of second and third beams */
BEAM_STUB = 8, /* length of stub for flag under beam */
SLUR_SLOPE = .5, /* max slope of a slur */
GSTEM = 15, /* grace note stem length */
GSTEM_XOFF = 2.3 /* x offset for grace note stem */
var cache
|
| ︙ | ︙ | |||
63 64 65 66 67 68 69 | d1 = rnd6(top - BEAM_OFFSET); d2 = rnd6(bot + BEAM_OFFSET) return d1 * d1 > d2 * d2 ? d2 : d1 } /* duplicate a note for beaming continuation */ | | | < > > | | | | < | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
d1 = rnd6(top - BEAM_OFFSET);
d2 = rnd6(bot + BEAM_OFFSET)
return d1 * d1 > d2 * d2 ? d2 : d1
}
/* duplicate a note for beaming continuation */
function sym_dup(s) {
var m, note
s = clone(s)
s.invis = true
delete s.extra;
delete s.text
delete s.a_gch
delete s.a_ly
delete s.a_dd;
s.notes = clone(s.notes)
for (m = 0; m <= s.nhd; m++) {
note = s.notes[m] = clone(s.notes[m])
delete note.a_dcn
}
return s
}
/* -- calculate a beam -- */
/* (the staves may be defined or not) */
var min_tb = [
[STEM_MIN, STEM_MIN,
STEM_MIN2, STEM_MIN3, STEM_MIN4, STEM_MIN4],
[STEM_CH_MIN, STEM_CH_MIN,
STEM_CH_MIN2, STEM_CH_MIN3, STEM_CH_MIN4, STEM_CH_MIN4]
]
// (possible hook)
Abc.prototype.calculate_beam = function(bm, s1) {
var s, s2, g, notes, nflags, st, v, two_staves, two_dir,
x, y, ys, a, b, stem_err, max_stem_err,
p_min, p_max, s_closest,
stem_xoff, scale,
visible, dy
if (!s1.beam_st) { /* beam from previous music line */
s = sym_dup(s1);
lkvsym(s, s1);
lktsym(s, s1);
s.x -= 12
if (s.x > s1.prev.x + 12)
s.x = s1.prev.x + 12;
s.beam_st = true
delete s.beam_end;
s.tmp = true
delete s.sls;
s1 = s
}
/* search last note in beam */
notes = nflags = 0; /* set x positions, count notes and flags */
two_staves = two_dir = false;
st = s1.st;
|
| ︙ | ︙ | |||
152 153 154 155 156 157 158 | if (s.ts_next) s.ts_next.ts_prev = s; s2.ts_next = s; s.ts_prev = s2 delete s.beam_st; s.beam_end = true; s.tmp = true | | < | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | if (s.ts_next) s.ts_next.ts_prev = s; s2.ts_next = s; s.ts_prev = s2 delete s.beam_st; s.beam_end = true; s.tmp = true delete s.sls; s.x += 12 if (s.x < realwidth - 12) s.x = realwidth - 12; s2 = s; notes++ break } |
| ︙ | ︙ | |||
209 210 211 212 213 214 215 | } } s.xs = s.x + x * scale; if (s == s2) break } | | | | | | < < < | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | } } s.xs = s.x + x * scale; if (s == s2) break } // have flat beams on grace notes when asked if (s.grace && cfmt.flatbeams) a = 0 // if a note inside the beam is the closest to the beam, the beam is flat else if (!two_dir && notes >= 3 && s_closest != s1 && s_closest != s2) a = 0 y = s1.ys + staff_tb[st].y if (a == undefined) a = (s2.ys + staff_tb[s2.st].y - y) / (s2.xs - s1.xs) if (a != 0) a = cfmt.beamslope * a / (cfmt.beamslope + Math.abs(a)) // max steepness for beam // pivot around the middle of the beam b = (y + s2.ys + staff_tb[s2.st].y) / 2 - a * (s2.xs + s1.xs) / 2 /*fixme: have a look again*/ /* have room for the symbols in the staff */ max_stem_err = 0; /* check stem lengths */ |
| ︙ | ︙ | |||
738 739 740 741 742 743 744 | xygl(x, y, "acc" + acc + '_' + micro_n + '_' + micro_d) return } } xygl(x, y, "acc" + acc) } | | > | | > > | > > > > > > > > > > > > > | | | < < | > | | < | < < < | | < | < < < < < > > > > > > > > > > > > > > > | | | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 |
xygl(x, y, "acc" + acc + '_' + micro_n + '_' + micro_d)
return
}
}
xygl(x, y, "acc" + acc)
}
// draw helper lines
//fixme: double lines when needed for different voices
// (possible hook)
Abc.prototype.draw_hl = function(x, s, hltype) {
var i, j, n,
hla = [],
st = s.st,
p_staff = staff_tb[st]
// check if any helper line
if (!p_staff.hll)
return // no helper line (no line)
for (i = 0; i <= s.nhd; i++) {
if (!p_staff.hlmap[s.notes[i].pit - p_staff.hll])
hla.push((s.notes[i].pit - 18) * 3)
}
n = hla.length
if (!n)
return // no
// handle the helper lines out of the staff
var staffb = p_staff.y,
stafflines = p_staff.stafflines,
top = (stafflines.length - 1) * 6,
bot = p_staff.botline,
yl = bot,
yu = top
for (i = 0; i < hla.length; i++) {
if (hla[i] < yl) {
yl = (((hla[i] + 51) / 6) | 0) * 6 - 48;
n--
} else if (hla[i] > yu) {
yu = ((hla[i] / 6) | 0) * 6;
n--
}
}
for (; yl < bot; yl += 6)
xygl(x, staffb + yl, hltype)
for (; yu > top; yu -= 6)
xygl(x, staffb + yu, hltype)
if (!n)
return // no more helper lines
// draw the helper lines inside the staff
i = yl;
j = yu
while (i > bot && stafflines[i / 6] == '-')
i -= 6
while (j < top && stafflines[j / 6] == '-')
j += 6
for ( ; i < j; i += 6) {
if (stafflines[i / 6] == '-')
xygl(x, staffb + i, hltype) // hole
}
}
/* -- draw a key signature -- */
// (possible hook)
var sharp_cl = new Int8Array([24, 9, 15, 21, 6, 12, 18]),
flat_cl = new Int8Array([12, 18, 24, 9, 15, 21, 6]),
sharp1 = new Int8Array([-9, 12, -9, -9, 12, -9]),
sharp2 = new Int8Array([12, -9, 12, -9, 12, -9]),
flat1 = new Int8Array([9, -12, 9, -12, 9, -12]),
flat2 = new Int8Array([-12, 9, -12, 9, -12, 9])
Abc.prototype.draw_keysig = function(x, s) {
if (s.k_none || s.k_play)
return
var old_sf = s.k_old_sf,
st = s.st,
staffb = staff_tb[st].y,
i, shift, p_seq,
clef_ix = s.k_y_clef
|
| ︙ | ︙ | |||
874 875 876 877 878 879 880 |
}
}
} else if (s.k_a_acc.length) {
/* explicit accidentals */
var acc,
last_acc = s.k_a_acc[0].acc,
| | > > > > > > | | 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 |
}
}
} else if (s.k_a_acc.length) {
/* explicit accidentals */
var acc,
last_acc = s.k_a_acc[0].acc,
last_shift = 100,
s2 = {
st: st,
nhd: 0,
notes: [{}]
}
for (i = 0; i < s.k_a_acc.length; i++) {
acc = s.k_a_acc[i];
shift = (s.k_y_clef // clef shift
+ acc.pit - 18) * 3
if (i != 0
&& (shift > last_shift + 18
|| shift < last_shift - 18))
x -= 5.5 // no clash
else if (acc.acc != last_acc)
x += 3;
last_acc = acc.acc;
s2.notes[0].pit = shift / 3 + 18;
self.draw_hl(x, s2, "hl");
last_shift = shift;
draw_acc(x, staffb + shift,
acc.acc, acc.micro_n, acc.micro_d);
x += 5.5
}
}
}
|
| ︙ | ︙ | |||
924 925 926 927 928 929 930 |
/* (the staves are defined) */
var rest_tb = [
"r128", "r64", "r32", "r16", "r8",
"r4",
"r2", "r1", "r0", "r00"]
function draw_rest(s) {
| | | | > | > > > > > > > | 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 |
/* (the staves are defined) */
var rest_tb = [
"r128", "r64", "r32", "r16", "r8",
"r4",
"r2", "r1", "r0", "r00"]
function draw_rest(s) {
var s2, i, j, x, y, yb, bx,
p_staff = staff_tb[s.st]
// if rest alone in the measure or measure repeat,
// change the head and center
if (s.dur_orig == s.p_v.meter.wmeasure
|| (s.rep_nb && s.rep_nb >= 0)) {
if (s.dur < C.BLEN * 2)
s.nflags = -2 // semibreve / whole
else if (s.dur < C.BLEN * 4)
s.nflags = -3
else
s.nflags = -4;
s.dots = 0;
/* don't use next/prev: there is no bar in voice overlay */
s2 = s.ts_next
while (s2 && s2.time != s.time + s.dur)
s2 = s2.ts_next;
x = s2 ? s2.x : realwidth;
s2 = s
|
| ︙ | ︙ | |||
986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 | anno_stop(s) return } set_scale(s); anno_start(s); y = s.y; i = 5 - s.nflags /* rest_tb index (5 = C_XFLAGS) */ if (i == 7 && y == 12 && p_staff.stafflines.length <= 2) y -= 6 /* semibreve a bit lower */ // draw the rest | > > > | | 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 |
anno_stop(s)
return
}
set_scale(s);
anno_start(s);
if (s.notes[0].color)
set_color(s.notes[0].color);
y = s.y;
i = 5 - s.nflags /* rest_tb index (5 = C_XFLAGS) */
if (i == 7 && y == 12
&& p_staff.stafflines.length <= 2)
y -= 6 /* semibreve a bit lower */
// draw the rest
xygl(x, y + yb, s.notes[0].head || rest_tb[i])
/* output ledger line(s) when greater than minim */
if (i >= 6) {
j = y / 6
switch (i) {
default:
switch (p_staff.stafflines[j + 1]) {
|
| ︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 |
x += 8;
y += yb + 3
for (i = 0; i < s.dots; i++) {
xygl(x, y, "dot");
x += 3.5
}
}
anno_stop(s)
}
/* -- draw grace notes -- */
/* (the staves are defined) */
function draw_gracenotes(s) {
| > | | | > > | 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 |
x += 8;
y += yb + 3
for (i = 0; i < s.dots; i++) {
xygl(x, y, "dot");
x += 3.5
}
}
set_color();
anno_stop(s)
}
/* -- draw grace notes -- */
/* (the staves are defined) */
function draw_gracenotes(s) {
var yy, x0, y0, x1, y1, x2, y2, x3, y3, bet1, bet2, slur,
dy1, dy2, g, last, note,
bm = {}
/* draw the notes */
// bm.s2 = undefined /* (draw flags) */
for (g = s.extra; g; g = g.next) {
if (g.beam_st && !g.beam_end) {
if (self.calculate_beam(bm, g))
draw_beams(bm)
}
anno_start(g);
draw_note(g, !bm.s2)
if (g == bm.s2)
bm.s2 = null /* (draw flags again) */
anno_stop(g)
if (g.sls || g.sl2)
slur = true
if (!g.next)
break /* (keep the last note) */
}
// if an acciaccatura, draw a bar
if (s.sappo) {
g = s.extra
|
| ︙ | ︙ | |||
1086 1087 1088 1089 1090 1091 1092 | x1, y1, g.stem > 0) } /* slur */ //fixme: have a full key symbol in voice if (s.p_v.key.k_bagpipe /* no slur when bagpipe */ || !cfmt.graceslurs | | > | > | | 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 |
x1, y1, g.stem > 0)
}
/* slur */
//fixme: have a full key symbol in voice
if (s.p_v.key.k_bagpipe /* no slur when bagpipe */
|| !cfmt.graceslurs
|| slur // explicit slur
|| s.tie_s // some tie
|| !s.next
|| s.next.type != C.NOTE)
return
last = g
if (((g.stem >= 0 || s.multi < 0) && g.notes[0].pit <= 28)
|| g.notes[0].pit < 16) { // slur below
yy = 127
for (g = s.extra; g; g = g.next) {
if (g.y < yy) {
yy = g.y;
last = g
}
}
x0 = last.x;
y0 = last.y - 5
if (s.extra != last) {
x0 -= 4;
y0 += 1
}
s = s.next;
x3 = s.x - 1
if (s.stem < 0 && s.nflags > -2)
x3 -= 4;
y3 = 3 * (s.notes[0].pit - 18) - 5;
dy1 = (x3 - x0) * .4
if (dy1 > 3)
dy1 = 3;
dy2 = dy1;
bet1 = .2;
|
| ︙ | ︙ | |||
1129 1130 1131 1132 1133 1134 1135 |
dy2 = (y0 - y3) * .2;
bet1 = 0
} else if (y3 > y0 + 4) {
y3 = y0 + 4;
x0 = last.x + 2;
y0 = last.y - 4
}
| | | | 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 |
dy2 = (y0 - y3) * .2;
bet1 = 0
} else if (y3 > y0 + 4) {
y3 = y0 + 4;
x0 = last.x + 2;
y0 = last.y - 4
}
} else { // slur above
yy = -127
for (g = s.extra; g; g = g.next) {
if (g.y > yy) {
yy = g.y;
last = g
}
}
x0 = last.x;
y0 = last.y + 5
if (s.extra != last) {
x0 -= 4;
y0 -= 1
}
s = s.next;
x3 = s.x - 1
if (s.stem >= 0 && s.nflags > -2)
x3 -= 2;
y3 = 3 * (s.notes[s.nhd].pit - 18) + 5;
dy1 = (x0 - x3) * .4
if (dy1 < -3)
dy1 = -3;
dy2 = dy1;
bet1 = .2;
|
| ︙ | ︙ | |||
1230 1231 1232 1233 1234 1235 1236 |
return staff_tb[s.st].y + 3 * (note.pit - 18)
}
/* -- draw m-th head with accidentals and dots -- */
/* (the staves are defined) */
// sets {x,y}_note
function draw_basic_note(x, s, m, y_tb) {
| | | 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 |
return staff_tb[s.st].y + 3 * (note.pit - 18)
}
/* -- draw m-th head with accidentals and dots -- */
/* (the staves are defined) */
// sets {x,y}_note
function draw_basic_note(x, s, m, y_tb) {
var i, p, yy, dotx, doty, inv,
old_color = false,
note = s.notes[m],
staffb = staff_tb[s.st].y, /* bottom of staff */
y = 3 * (note.pit - 18), /* note height on staff */
shhd = note.shhd * stv_g.scale,
x_note = x + shhd,
y_note = y + staffb
|
| ︙ | ︙ | |||
1321 1322 1323 1324 1325 1326 1327 | default: // black note p = "hd" break } } if (note.color != undefined) old_color = set_color(note.color) | < < | 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 |
default: // black note
p = "hd"
break
}
}
if (note.color != undefined)
old_color = set_color(note.color)
if (p) {
if (inv) {
g_open(x_note, y_note, 0, 1, -1);
x_note = y_note = 0
}
if (!self.psxygl(x_note, y_note, p))
xygl(x_note, y_note, p)
|
| ︙ | ︙ | |||
1344 1345 1346 1347 1348 1349 1350 |
dotx = x + (7.7 + s.xmx) * stv_g.scale
if (y_tb[m] == undefined) {
y_tb[m] = 3 * (s.notes[m].pit - 18)
if ((s.notes[m].pit & 1) == 0)
y_tb[m] += 3
}
doty = y_tb[m] + staffb
| > | | | 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 |
dotx = x + (7.7 + s.xmx) * stv_g.scale
if (y_tb[m] == undefined) {
y_tb[m] = 3 * (s.notes[m].pit - 18)
if ((s.notes[m].pit & 1) == 0)
y_tb[m] += 3
}
doty = y_tb[m] + staffb
i = (note.dur / 12) >> ((5 - nflags) - dots)
while (dots-- > 0) {
xygl(dotx, doty, (i & (1 << dots)) ? "dot" : "dot+")
dotx += 3.5
}
}
/* draw the accidental */
if (note.acc) {
x -= note.shac * stv_g.scale
|
| ︙ | ︙ | |||
1383 1384 1385 1386 1387 1388 1389 |
note = s.notes[s.stem < 0 ? s.nhd : 0]; // master note head
x_hl = x = x_head(s, note);
staffb = staff_tb[s.st].y
/* output the ledger lines */
if (s.grace) {
| | > | | < | | 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 |
note = s.notes[s.stem < 0 ? s.nhd : 0]; // master note head
x_hl = x = x_head(s, note);
staffb = staff_tb[s.st].y
/* output the ledger lines */
if (s.grace) {
hltype = "ghl";
x_hl += 1.5
} else {
hltype = "hl"
switch (s.head) {
case C.OVALBARS:
case C.OVAL:
x_hl -= .3;
hltype = "hl1"
break
case C.SQUARE:
x_hl -= 2;
hltype = "hl1"
break
}
}
self.draw_hl(x_hl, s, hltype)
/* draw the stem and flags */
y = y_head(s, note)
if (!s.stemless) {
slen = s.ys - s.y;
nflags = s.nflags
if (s.ntrem)
|
| ︙ | ︙ | |||
1424 1425 1426 1427 1428 1429 1430 |
out_stem(x, y, slen, s.grace,
nflags, cfmt.straightflags)
}
} else if (s.xstem) { /* cross-staff stem */
s2 = s.ts_prev;
slen = (s2.stem > 0 ? s2.y : s2.ys) - s.y;
slen += staff_tb[s2.st].y - staffb;
| < < | 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 |
out_stem(x, y, slen, s.grace,
nflags, cfmt.straightflags)
}
} else if (s.xstem) { /* cross-staff stem */
s2 = s.ts_prev;
slen = (s2.stem > 0 ? s2.y : s2.ys) - s.y;
slen += staff_tb[s2.st].y - staffb;
out_stem(x, y, slen)
}
/* draw the tremolo bars */
if (fl && s.trem1) {
var ntrem = s.ntrem || 0,
x1 = x;
|
| ︙ | ︙ | |||
1456 1457 1458 1459 1460 1461 1462 | /* draw the note heads */ x = s.x for (m = 0; m <= s.nhd; m++) draw_basic_note(x, s, m, y_tb) } | | < < < < < < < < < < < < | | > > > > > > > > > > > > > > > > > > > > > | > | 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 |
/* draw the note heads */
x = s.x
for (m = 0; m <= s.nhd; m++)
draw_basic_note(x, s, m, y_tb)
}
// find where to start a long decoration
function prev_scut(s) {
while (s.prev) {
s = s.prev
if (s.rbstart)
return s
}
/* return a symbol of any voice starting before the start of the voice */
s = s.p_v.sym
while (s.type != C.CLEF)
s = s.ts_prev /* search a main voice */
if (s.next && s.next.type == C.KEY)
s = s.next
if (s.next && s.next.type == C.METER)
return s.next
return s
}
/* -- decide whether a slur goes up or down (same voice) -- */
function slur_direction(k1, k2) {
var s, some_upstem, low, dir
// check if slur sequence in a multi-voice staff
function slur_multi(s1, s2) {
// while (1) {
// if (s1.multi) // if multi voice
// //fixme: may change
// return s1.multi
// if (s1 == s2)
// break
// s1 = s1.next
// }
if (s1.multi)
return s1.multi
if (s2.multi)
return s2.multi
return 0
} // slur_multi()
if (k1.grace && k1.stem > 0)
return -1
dir = slur_multi(k1, k2)
if (dir)
return dir
for (s = k1; ; s = s.next) {
if (s.type == C.NOTE) {
if (!s.stemless) {
if (s.stem < 0)
return 1
some_upstem = true
}
if (s.notes[0].pit < 22) /* if under middle staff */
low = true
}
// if (s == k2)
if (s.time == k2.time) // (k2 may be a grace note)
break
}
if (!some_upstem && !low)
return 1
return -1
}
|
| ︙ | ︙ | |||
1562 1563 1564 1565 1566 1567 1568 | // dx = 10. // dy = 1.6 * dir dy = 2 * dir; dz = .2 + .001 * (x2 - x1) if (dz > .6) dz = .6; dz *= dir | | | > | | 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 | // dx = 10. // dy = 1.6 * dir dy = 2 * dir; dz = .2 + .001 * (x2 - x1) if (dz > .6) dz = .6; dz *= dir // var scale_y = stv_g.st < 0 ? stv_g.scale : 1 var scale_y = 1 // (see set_dscale()) if (!dotted) output += '<path d="M' else output += '<path class="stroke" stroke-dasharray="5,5" d="M'; 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) + ' ' + |
| ︙ | ︙ | |||
1589 1590 1591 1592 1593 1594 1595 | ((xx1 + dx - x2) / stv_g.scale).toFixed(1) + ' ' + ((y2 + dz - yy1 - dy) / scale_y).toFixed(1) + ' ' + ((x1 - x2) / stv_g.scale).toFixed(1) + ' ' + ((y2 + dz - y1) / scale_y).toFixed(1); output += '"/>\n' } | < < < < < < < < < < < < < | | > > | | | | < < < < | | < | | | | | > | > | < | | | | | | | | < < < | < | | | < | | | < < < < < < | | < | > | | 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 |
((xx1 + dx - x2) / stv_g.scale).toFixed(1) + ' ' +
((y2 + dz - yy1 - dy) / scale_y).toFixed(1) + ' ' +
((x1 - x2) / stv_g.scale).toFixed(1) + ' ' +
((y2 + dz - 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
not1, // note if start on a note head
sl) { // ending variables: type, note, end on a note
var i,
k, g, x1, y1, x2, y2, height, addy,
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,
k1 = path[0],
k2 = path[i2]
/*fixme: if two staves, may have upper or lower slur*/
var nn = 1,
upstaff = k1.st,
two_staves = false
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 != upstaff) {
two_staves = true
if (k.st < upstaff)
upstaff = k.st
}
}
}
/*fixme: KO when two staves*/
if (two_staves) error(2, k1, "*** multi-staves slurs not treated yet");
/* fix endpoints */
x1 = k1.x
if (k1.notes && k1.notes[0].shhd)
x1 += k1.notes[0].shhd;
x2 = k2.x
if (k2.notes)
x2 += k2.notes[0].shhd
if (not1) { // start on a note
y1 = 3 * (not1.pit - 18) + 2 * dir
x1 += 3
} else { // start on a chord
y1 = dir > 0 ? k1.ymx + 2 : k1.ymn - 2
if (k1.type == C.NOTE) {
if (dir > 0) {
if (k1.stem > 0) {
x1 += 5
if (k1.beam_end
&& k1.nflags >= -1 /* if with a stem */
|
| ︙ | ︙ | |||
1714 1715 1716 1717 1718 1719 1720 |
}
// } else {
// y1 = k1.y - 8
}
}
}
}
| | > | > | | 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 |
}
// } else {
// y1 = k1.y - 8
}
}
}
}
if (sl.is_note) { // end on a note
y2 = 3 * (sl.note.pit - 18) + 2 * dir
x2 -= 3
} else { // end on a chord
y2 = dir > 0 ? k2.ymx + 2 : k2.ymn - 2
if (k2.type == C.NOTE) {
if (dir > 0) {
if (k2.stem > 0) {
x2 += 1
if (k2.beam_st
&& k2.nflags >= -1
|
| ︙ | ︙ | |||
1766 1767 1768 1769 1770 1771 1772 |
else
y2 = y1
if (k1 != k2)
x2 = k2.x - k2.wl * .3
}
if (nn >= 3) {
| > | | | | | | | | | | 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 |
else
y2 = y1
if (k1 != k2)
x2 = k2.x - k2.wl * .3
}
if (nn >= 3) {
k = path[1]
if (k.type != C.BAR
&& k.x < x1 + 48) {
if (dir > 0) {
y = k.ymx - 2
if (y1 < y)
y1 = y
} else {
y = k.ymn + 2
if (y1 > y)
y1 = y
}
}
k = path[i2 - 1]
if (k.type != C.BAR
&& k.x > x2 - 48) {
if (dir > 0) {
y = k.ymx - 2
if (y2 < y)
y2 = y
} else {
y = k.ymn + 2
if (y2 > y)
y2 = y
}
}
}
a = (y2 - y1) / (x2 - x1) /* slur steepness */
|
| ︙ | ︙ | |||
1832 1833 1834 1835 1836 1837 1838 |
x2 = k2.x + GSTEM_XOFF * 1.5;
h = 0;
a = (y2 - y1) / (x2 - x1)
if (k1 != k2
&& k1.v == k2.v) {
addy = y1 - a * x1
| | > | 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 |
x2 = k2.x + GSTEM_XOFF * 1.5;
h = 0;
a = (y2 - y1) / (x2 - x1)
if (k1 != k2
&& k1.v == k2.v) {
addy = y1 - a * x1
for (i = 1; i < i2; i++) {
k = path[i]
if (k.st != upstaff)
continue
switch (k.type) {
case C.NOTE:
case C.REST:
if (dir > 0) {
y = 3 * (k.notes[k.nhd].pit - 18) + 6
|
| ︙ | ︙ | |||
1909 1910 1911 1912 1913 1914 1915 |
} else {
if (height > -.8 * y)
height = -.8 * y
}
height *= cfmt.slurheight;
// anno_start(k1_o, 'slur');
| | | > > | > > > > | | | > | | | > > < | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | > > > > > > > > > > > > > > > | | | | < < | | < < < < < < < < < | < < < < < < < < < < < < < < < < < < | < < < < < < < < | < < < < < < < < < < < < | < < < < < < | < < | | < < | < < < | < < < < < < < < < < < < < < < < < < < | | < < | | < | | < < < < < | | < < | | < < < < < < < < < | < < < < < | < < < < < | < < < | | < < < < | | < | | > | > > | | | < | | < | | | | < < < < < < < < < < | < < < < < < < | | < | | | | < < | | | < < < | < < | < < < | > | | | | < < | 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 |
} else {
if (height > -.8 * y)
height = -.8 * y
}
height *= cfmt.slurheight;
// anno_start(k1_o, 'slur');
slur_out(x1, y1, x2, y2, dir, height, ty & C.SL_DOTTED);
// anno_stop(k1_o, 'slur');
/* have room for other symbols */
dx = x2 - x1;
a = (y2 - y1) / dx;
/*fixme: it seems to work with .4, but why?*/
// addy = y1 - a * x1 + .4 * height
//fixme: the following code seems better!
addy = y1 - a * x1
if (height > 0)
addy += 4 * Math.sqrt(height) - 2
else
addy -= 4 * Math.sqrt(-height) - 2
for (i = 0; i < i2; i++) {
k = path[i]
if (k.st != upstaff)
continue
y = a * k.x + addy
if (k.ymx < y)
k.ymx = y
else if (k.ymn > y)
k.ymn = y
if (i == i2 - 1) {
dx = x2
if (k2.sl1)
dx -= 5;
y -= height / 3
} else {
dx = path[i + 1].x
}
if (i != 0)
x1 = k.x
else
y -= height / 3
dx -= x1;
y_set(upstaff, dir > 0, x1, dx, y)
}
}
/* -- draw the slurs between 2 symbols --*/
function draw_slurs(s, last) {
var gr1, i, m, note, sls, nsls
// draw a slur knowing the start and stop elements
function draw_sls(s, // start symbol
sl, // stop note
snote) { // optional start note
var k, v, i, dir,
path = [],
enote = sl.note,
s2 = enote.s // end of slur
if (last && s2.time > last.time)
return // will be drawn next time
// if the slur continues on the next music line,
// stop it on the invisible bar at end of current line
if (tsnext && s2.time >= tsnext.time) {
s.p_v.sls.push(sl); // continuation on next line
s2 = s.p_v.s_next.prev // one voice
while (s2.next)
s2 = s2.next; // search the ending bar
sl = Object.create(sl); // new slur
sl.note = {
s: s2
}
}
// set the slur position
switch (sl.ty & 0x07) {
case C.SL_ABOVE: dir = 1; break
case C.SL_BELOW: dir = -1; break
default:
if (s.v != s2.v)
dir = -1 // always above ?
else
dir = slur_direction(s, s2);
sl.ty &= ~0x07;
sl.ty |= dir > 0 ? C.SL_ABOVE : C.SL_BELOW
break
}
// build the path of the symbols under the slur
if (dir * // if slur on first voice
(cur_sy.voices[s.v].range <= cur_sy.voices[s2.v].range ?
1 : -1) > 0)
v = s.v
else
v = s2.v
if (gr1 // if start on a grace note
&& !(s2.grace // and not end in the same
&& s.v == s2.v // grace note sequence
&& s.time == s2.time)) {
do {
path.push(s); // add all grace notes
s = s.next
} while (s);
s = gr1.next
} else {
path.push(s);
if (s.grace)
s = s.next
else
s = s.ts_next
}
if (!s2.grace) { // if end on a normal note
while (1) {
if (s.v == v)
path.push(s)
if (s == s2)
break
s = s.ts_next
}
} else if (s.grace) { // if start/end in the same sequence
while (1) {
if (s.v == v)
path.push(s)
if (s == s2)
break
s = s.next
}
} else { // end on a grace note
k = s2
while (k.prev)
k = k.prev // .extra pointer
while (1) {
if (s.v == v)
path.push(s)
if (s.extra == k)
break
s = s.ts_next
}
s = k
while (1) {
path.push(s)
if (s == s2)
break
s = s.next
}
}
// if some nested slurs/tuplets, draw them
for (i = 1; i < path.length - 1; i++) {
s = path[i]
if (s.sls || s.sl1)
draw_slurs(s, last)
if (s.tp)
draw_tuplet(s)
}
draw_slur(path, snote, sl)
return 1 // slur drawn, remove it
} // draw_sls()
// code of draw_slurs()
while (1) {
if (!s || s == last) {
if (!gr1 // if end of grace notes
|| !(s = gr1.next) // return to normal notes
|| s == last)
break
gr1 = null
}
if (s.type == C.GRACE) { // if start of grace notes
gr1 = s; // continue in the grace note sequence
s = s.extra
continue
}
if (s.sls) { // slurs from the chord
sls = s.sls
s.sls = null
nsls = []
for (i = 0; i < sls.length; i++) {
if (!draw_sls(s, sls[i]))
nsls.push(sls[i])
}
if (nsls.length)
s.sls = nsls
}
if (s.sl1) { // slurs from the note heads
for (m = 0; m <= s.nhd; m++) {
note = s.notes[m]
if (note.sls) {
sls = note.sls
note.sls = null
nsls = []
for (i = 0; i < sls.length; i++) {
if (!draw_sls(s, sls[i], note))
nsls.push(sls[i])
}
if (nsls.length)
note.sls = nsls
}
}
}
s = s.next
}
}
/* -- draw a tuplet -- */
/* (the staves are not yet defined) */
/* (delayed output) */
/* See http://moinejf.free.fr/abcm2ps-doc/tuplets.xhtml
* for the value of 'tp.f' */
function draw_tuplet(s1, tp) {
var s2, s3, g, upstaff, nb_only, some_slur,
x1, x2, y1, y2, xm, ym, a, s0, yy, yx, dy, a, dir, r,
tp = s1.tp.shift() // tuplet parameters
if (!s1.tp.length)
delete s1.tp // last tuplet
// treat the slurs and the nested tuplets
upstaff = s1.st
set_dscale(s1.st)
for (s2 = s1; s2; s2 = s2.next) {
if (s2.type != C.NOTE && s2.type != C.REST) {
if (s2.type == C.GRACE) {
for (g = s2.extra; g; g = g.next) {
if (g.sls || g.sl1)
draw_slurs(g)
}
}
continue
}
if (s2.sls || s2.sl1)
draw_slurs(s2)
if (s2.st < upstaff)
upstaff = s2.st
if (s2.tp)
draw_tuplet(s2)
if (s2.tpe)
break
}
if (!s2) {
error(1, s1, "No end of tuplet in this music line")
return
}
s2.tpe--
if (tp.f[0] == 1) /* if 'when' == never */
return
dir = tp.f[3] // 'where'
if (!dir) { // if auto
s3 = s1
while (s3.type != C.NOTE)
s3 = s3.next
dir = s3.stem > 0 ? C.SL_ABOVE : C.SL_BELOW
}
if (s1 == s2 // tuplet with 1 note (!)
|| tp.f[1] == 2) { // what == nothing
nb_only = true
} else if (tp.f[1] == 1) { /* 'what' == slur */
nb_only = true;
draw_slur([s1, s2], null, {ty: dir})
} else {
/* search if a bracket is needed */
if (tp.f[0] != 2 // if 'when' != always
&& s1.type == C.NOTE && s2.type == C.NOTE) {
nb_only = true
for (s3 = s1; ; s3 = s3.next) {
if (s3.type != C.NOTE
&& s3.type != C.REST) {
if (s3.type == C.GRACE
|| s3.type == C.SPACE)
continue
|
| ︙ | ︙ | |||
2247 2248 2249 2250 2251 2252 2253 |
}
}
}
}
/* if number only, draw it */
if (nb_only) {
| | < < < | < < | | < < < | | < < < | < < < < | | | | > > > > > | < < < < | 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 |
}
}
}
}
/* if number only, draw it */
if (nb_only) {
if (tp.f[2] == 1) /* if 'which' == none */
return
xm = (s2.x + s1.x) / 2
a = s2.x - s1.x // width around the middle
if (dir == C.SL_ABOVE)
ym = y_get(upstaff, 1, xm - a / 2, a) + 2
else
ym = y_get(upstaff, 0, xm - a / 2, a) - 10
if (s1.stem * s2.stem > 0) {
if (s1.stem > 0)
xm += 1.5
else
xm -= 1.5
}
if (tp.f[2] == 0) /* if 'which' == number */
out_bnum(xm, ym, tp.p)
else
out_bnum(xm, ym, tp.p + ':' + tp.q)
for (s3 = s1; ; s3 = s3.next) {
if (s3.x >= xm)
break
}
if (dir == C.SL_ABOVE) {
ym += 10
if (s3.ymx < ym)
s3.ymx = ym;
y_set(upstaff, true, xm - 3, 6, ym)
} else {
if (s3.ymn > ym)
s3.ymn = ym;
y_set(upstaff, false, xm - 3, 6, ym)
}
return
}
// here, what is square bracket
/*fixme: two staves not treated*/
/*fixme: to optimize*/
if (dir == C.SL_ABOVE) {
/* sole or upper voice: the bracket is above the staff */
if (s1.st == s2.st) {
y1 = y2 = staff_tb[upstaff].topbar + 4
} else {
y1 = s1.ymx;
|
| ︙ | ︙ | |||
2332 2333 2334 2335 2336 2337 2338 | for (s3 = s2; !s3.dur; s3 = s3.prev) ; ym = y_get(upstaff, 1, s3.x - 4, 8) if (ym > y2) y2 = ym } | | | 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 |
for (s3 = s2; !s3.dur; s3 = s3.prev)
;
ym = y_get(upstaff, 1, s3.x - 4, 8)
if (ym > y2)
y2 = ym
}
// end the bracket according to the last note duration
if (s2.dur > s2.prev.dur) {
if (s2.next)
x2 = s2.next.x - s2.next.wl - 5
else
x2 = realwidth - 6
} else {
x2 = s2.x + 4;
|
| ︙ | ︙ | |||
2492 2493 2494 2495 2496 2497 2498 |
y_set(upstaff, false, s3.x, s3.next.x - s3.x, yy)
}
if (s3 == s2)
break
}
} /* lower voice */
| | | < | | | | | > | | | | < > | | > | | | | | | | | | | < | > > > | | | | | | | | | | | | < | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > | | | | < < | < | < < | | < | | > > > > | < > | | < | < < < < < < < < < | | | < < < < | < | | | | | < < < < > > > < < | | | | > | > | > | < < < < | | < | < < < < < < < < < < < < < < < < < < < < | < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > | | | | | | | | | | | > | < < < | < < < < < < < < < < | | > > | > | | > | < > > | < | < | | | | < < | > | | > > > > > > > | < | | < < < < < | < < < < < < > | < < | | | | | | 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 |
y_set(upstaff, false, s3.x, s3.next.x - s3.x, yy)
}
if (s3 == s2)
break
}
} /* lower voice */
if (tp.f[2] == 1) { /* if 'which' == none */
out_tubr(x1, y1 + 4, x2 - x1, y2 - y1, dir == C.SL_ABOVE);
return
}
out_tubrn(x1, y1, x2 - x1, y2 - y1, dir == C.SL_ABOVE,
tp.f[2] == 0 ? tp.p.toString() : tp.p + ':' + tp.q);
if (dir == C.SL_ABOVE)
y_set(upstaff, true, xm - 3, 6, yy + 2)
else
y_set(upstaff, false, xm - 3, 6, yy)
}
/* -- draw the ties between two notes/chords -- */
function draw_note_ties(not1, job) {
var m, x1, x2, s, y, h, time,
not2 = not1.tie_n,
p = job == 2 ? not1.pit : not2.pit,
dir = (not1.tie_ty & 0x07) == C.SL_ABOVE ? 1 : -1,
s1 = not1.s,
st = s1.st,
s2 = not2.s,
x2 = s2.x,
sh = not1.shhd // head shift
for (m = 0; m < s1.nhd; m++)
if (s1.notes[m] == not1)
break
if (dir > 0) {
if (m < s1.nhd && p + 1 == s1.notes[m + 1].pit)
if (s1.notes[m + 1].shhd > sh)
sh = s1.notes[m + 1].shhd
} else {
if (m > 0 && p == s1.notes[m - 1].pit + 1)
if (s1.notes[m - 1].shhd > sh)
sh = s1.notes[m - 1].shhd
}
x1 = s1.x + sh * .6
if (job != 2) {
for (m = 0; m < s2.nhd; m++)
if (s2.notes[m] == not2)
break
sh = s2.notes[m].shhd
if (dir > 0) {
if (m < s2.nhd && p + 1 == s2.notes[m + 1].pit)
if (s2.notes[m + 1].shhd < sh)
sh = s2.notes[m + 1].shhd
} else {
if (m > 0 && p == s2.notes[m - 1].pit + 1)
if (s2.notes[m - 1].shhd < sh)
sh = s2.notes[m - 1].shhd
}
x2 += sh * .6
}
switch (job) {
case 0:
p = (not1.pit & 1) ? not1.pit : not2.pit
break
case 3: /* clef or staff change */
dir = -dir
// fall thru
case 1: /* no starting note */
x1 = s1.x
if (x1 > x2 - 20)
x1 = x2 - 20
p = not2.pit
st = s2.st
break
/* case 2: * no ending note */
default:
if (s1 != s2) {
x2 -= s2.wl
if (s2.type == C.BAR)
x2 += 5
} else {
time = s1.time + s1.dur
for (s = s1.ts_next; s; s = s.ts_next)
//(fixme: must check if the staff continues??)
if (s.time > time)
break
x2 = s ? s.x : realwidth
}
if (x2 < x1 + 16)
x2 = x1 + 16
break
}
if (x2 - x1 > 20) {
x1 += 3.5
x2 -= 3.5
} else {
x1 += 1.5
x2 -= 1.5
}
if (s1.dots && !(not1.pit & 1)
&& ((dir > 0 && !s1.dot_low)
|| (dir < 0 && s1.dot_low)))
x1 += 5
y = staff_tb[st].y + 3 * (p - 18)
h = (.03 * (x2 - x1) + 16) * dir
// anno_start(k1, 'slur')
slur_out(x1, y, x2, y, dir, h, not1.tie_ty & C.SL_DOTTED)
// anno_stop(k1, 'slur')
}
/* -- draw ties between neighboring notes/chords -- */
function draw_ties(k1, k2,
job) { // 0: normal
// 1: no starting note
// 2: no ending note
// 3: no start for clef or staff change
var k3, i, j, not1, not3, time, pit, pit2,
mhead3 = [],
nh1 = k1.nhd
/* half ties from last note in line or before new repeat */
if (job == 2) {
for (i = 0; i <= nh1; i++) {
not1 = k1.notes[i]
if (not1.tie_ty) {
k3 = not1.tie_n
not1.tie_n = { s: k2 || k1 }
draw_note_ties(not1, job)
not1.tie_n = k3
}
}
return
}
// draw the ties or memorize the ones without ending
for (i = 0; i <= nh1; i++) {
not1 = k1.notes[i]
if (!not1.tie_ty)
continue
if (!not1.s)
not1.s = k1
if (not1.tie_n)
draw_note_ties(not1, job)
else
mhead3.push(not1) /* no match */
}
/* if any bad tie, try an other voice of the same staff */
if (!mhead3.length)
return /* no bad tie */
time = k1.time + k1.dur
k3 = k1.ts_next
if (job != 1)
job = 0
while (k3 && k3.time < time)
k3 = k3.ts_next
while (k3 && k3.time == time) {
if (k3.type != C.NOTE
|| k3.st != k1.st) {
k3 = k3.ts_next
continue
}
for (i = mhead3.length; --i >= 0; ) {
not1 = mhead3[i]
pit = not1.opit || not1.pit
for (j = k3.nhd; j >= 0; j--) {
not3 = k3.notes[j]
pit2 = not3.opit || not3.pit
if (pit2 == pit) {
not1.tie_n = not3
if (!not3.s)
not3.s = k3
draw_note_ties(not1, job)
mhead3.splice(i, 1)
break
}
}
}
if (!mhead3.length)
break
k3 = k3.ts_next
}
if (mhead3.length)
error(1, k1, "Bad tie")
}
/* -- draw all ties between neighboring notes -- */
function draw_all_ties(p_voice) {
var s, s1, s2, clef_chg, time, x, dx, s_next, m
function draw_ties_g(s1, s2, job) {
if (s1.type == C.GRACE) {
for (var g = s1.extra; g; g = g.next) {
if (g.tie_s)
draw_ties(g, s2, job)
}
} else {
draw_ties(s1, s2, job)
}
} // draw_ties_g()
/* search the start of ties */
// clef_chg = false
s_next = p_voice.sym
set_color(s_next.color)
while (1) {
for (s1 = s_next; s1; s1 = s1.next) {
if (s1.ti2 // if no tie start
&& (s1 != s_next
|| !s_next.prev)) { // (at start of line)
s = s1.ti2
s.x = s1.x
s2 = s.next
s.next = s1
s.st = s1.st
s.time = s1.time - s.dur
draw_ties(s, s1, 1)
s.next = s2 // restore the linkage for play
}
if (s1.tie_s)
break
}
if (!s1)
break
// check if the tied note is in this line
s2 = s1.tie_s // ending note of the tie
if (s2.v == s1.v) {
s_next = s2
s = s1
while (1) {
if (!s.next) {
s2 = s
s = null
break
}
s = s.next
if (s == s2)
break
}
} else {
s_next = s1.next
s = s1
while (1) {
if (!s.ts_next) {
s = null
break
}
s = s.ts_next
if (s == s2)
break
}
if (!s) {
s2 = s1
while (s2.next)
s2 = s2.next
}
}
if (!s) { // end of line
draw_ties_g(s1, s2, 2);
break
}
// check if some clef changes (may occur in an other voice)
time = s1.time + s.dur
for (s = s1.ts_next; s != s2; s = s.ts_next) {
if (s.st != s1.st)
continue
if (s.time > time)
break
if (s.type == C.CLEF) {
clef_chg = true
break
}
}
/* ties with clef or staff change */
if (clef_chg || s1.st != s2.st) {
clef_chg = false;
dx = (s2.x - s1.x) * .4;
|
| ︙ | ︙ | |||
2876 2877 2878 2879 2880 2881 2882 | s1.x = s2.x - 24.; draw_ties(s1, s2, 3); s1.x = x continue } draw_ties_g(s1, s2, s2.type == C.NOTE ? 0 : 2) } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < > | 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 |
s1.x = s2.x - 24.;
draw_ties(s1, s2, 3);
s1.x = x
continue
}
draw_ties_g(s1, s2, s2.type == C.NOTE ? 0 : 2)
}
}
/* -- draw the symbols near the notes -- */
/* (the staves are not yet defined) */
/* order:
* - scaled
* - beams
* - decorations near the notes
* - measure bar numbers
* - decorations tied to the notes
* - tuplets and slurs
* - not scaled
* - chord symbols
* - staff decorations
* - lyrics
* - measure numbers
* The buffer output is delayed until the definition of the staff system
*/
function draw_sym_near() {
var p_voice, p_st, s, v, st, y, g, w, i, st, dx, top, bot,
output_sav = output;
output = ""
/* calculate the beams but don't draw them (the staves are not yet defined) */
for (v = 0; v < voice_tb.length; v++) {
var bm = {},
first_note = true;
|
| ︙ | ︙ | |||
3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 |
else
y -= 5
if (s.ymn > y)
s.ymn = y;
y_set(s.st, false, s.x, 0, y)
}
}
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v];
s = p_voice.sym
if (!s)
continue
set_color(s.color);
st = p_voice.st;
// if (st == undefined) {
//error(1, s, "BUG: no staff for voice " + p_voice.id)
// continue
// }
| > > | | | < < < < < | | > < < | 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 |
else
y -= 5
if (s.ymn > y)
s.ymn = y;
y_set(s.st, false, s.x, 0, y)
}
}
draw_deco_note()
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v];
s = p_voice.sym
if (!s)
continue
set_color(s.color);
st = p_voice.st;
// if (st == undefined) {
//error(1, s, "BUG: no staff for voice " + p_voice.id)
// continue
// }
// draw the slurs and tuplets
for ( ; s; s = s.next) {
if (s.tp)
draw_tuplet(s)
if (s.sls || s.sl1)
draw_slurs(s)
}
}
set_color()
/* set the top and bottom out of the staves */
for (st = 0; st <= nstaff; st++) {
p_st = staff_tb[st];
top = p_st.topbar + 2;
bot = p_st.botbar - 2
/*fixme:should handle stafflines changes*/
for (i = 0; i < YSTEP; i++) {
if (top > p_st.top[i])
p_st.top[i] = top
if (bot < p_st.bot[i])
p_st.bot[i] = bot
}
}
if (cfmt.measurenb >= 0)
draw_measnb();
draw_deco_staff();
/* if any lyric, draw them now as unscaled */
set_dscale(-1)
// set_sscale(-1)
|
| ︙ | ︙ | |||
3147 3148 3149 3150 3151 3152 3153 |
set_dscale(-1);
output = output_sav
}
/* -- draw the name/subname of the voices -- */
function draw_vname(indent) {
| | | | | < < < < < < < > > | | | | < < < | < < | | | | 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 |
set_dscale(-1);
output = output_sav
}
/* -- draw the name/subname of the voices -- */
function draw_vname(indent) {
var p_voice, n, st, v, a_p, p, y, name_type, h, h2,
staff_d = []
for (st = cur_sy.nstaff; st >= 0; st--) {
if (cur_sy.st_print[st])
break
}
if (st < 0)
return
// check if full or sub names
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (!p_voice.sym || !cur_sy.voices[v])
continue
st = cur_sy.voices[v].st
if (!cur_sy.st_print[st])
continue
if (p_voice.new_name) {
name_type = 2
break
}
if (p_voice.snm)
name_type = 1
}
if (!name_type)
return
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (!p_voice.sym || !cur_sy.voices[v])
continue
st = cur_sy.voices[v].st
if (!cur_sy.st_print[st])
continue
if (p_voice.new_name)
delete p_voice.new_name;
p = name_type == 2 ? p_voice.nm : p_voice.snm
if (!p)
continue
if (!staff_d[st])
staff_d[st] = p
else
staff_d[st] += "\\n" + p
}
if (staff_d.length == 0)
return
set_font("voice");
h = gene.curfont.size
h2 = h / 2
indent = -indent * .5 /* center */
for (st = 0; st < staff_d.length; st++) {
if (!staff_d[st])
continue
a_p = staff_d[st].split('\\n');
y = staff_tb[st].y
+ staff_tb[st].topbar * .5
* staff_tb[st].staffscale
+ h2 * (a_p.length - 2)
// if instrument with 2 staves, center the voice name
if ((cur_sy.staves[st].flags & OPEN_BRACE)
&& (cur_sy.staves[st + 1].flags & CLOSE_BRACE)
&& !staff_d[st + 1])
y -= (staff_tb[st].y - staff_tb[st + 1].y) * .5
for (n = 0; n < a_p.length; n++) {
p = a_p[n];
xy_str(indent, y, p, "c");
y -= h
}
}
}
// -- set the y offset of the staves and return the height of the whole system --
function set_staff() {
var s, i, st, prev_staff, v,
|
| ︙ | ︙ | |||
3365 3366 3367 3368 3369 3370 3371 |
/* -- draw the staff systems and the measure bars -- */
function draw_systems(indent) {
var s, s2, st, x, x2, res, sy,
staves_bar, bar_force,
xstaff = [],
bar_bot = [],
bar_height = [],
| | | | < < | 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 |
/* -- draw the staff systems and the measure bars -- */
function draw_systems(indent) {
var s, s2, st, x, x2, res, sy,
staves_bar, bar_force,
xstaff = [],
bar_bot = [],
bar_height = [],
ba = [], // bars [symbol, bottom, height]
sb = [],
thb = []
/* -- set the bottom and height of the measure bars -- */
function bar_set() {
var st, staffscale, top, bot,
dy = 0
for (st = 0; st <= cur_sy.nstaff; st++) {
|
| ︙ | ︙ | |||
3408 3409 3410 3411 3412 3413 3414 | if (!/[\[|]/.test(stafflines)) return // no line w = x2 - x1; set_sscale(st); ws = w / stv_g.scale // check if default staff | | > | 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 |
if (!/[\[|]/.test(stafflines))
return // no line
w = x2 - x1;
set_sscale(st);
ws = w / stv_g.scale
// check if default staff
if (cache && cache.st_l == stafflines
&& cache.st_ws == (ws | 0)) {
xygl(x1, staff_tb[st].y, 'stdef' + cfmt.fullsvg)
return
}
for (i = 0; i < l; i++, y -= 6) {
if (stafflines[i] == '.')
continue
dy = 0
|
| ︙ | ︙ | |||
3431 3432 3433 3434 3435 3436 3437 | 'h' + ws.toFixed(1); dy = 0 continue } if (ty != undefined) ln += '"/>\n'; ty = stafflines[i] | | | | | > > > | | | | > > | | | | | | | > > > > > > | > > > > > | > | | | | > > > > > > > > > > > > > | < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < | 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 |
'h' + ws.toFixed(1);
dy = 0
continue
}
if (ty != undefined)
ln += '"/>\n';
ty = stafflines[i]
ln += '<path class="' +
(ty == '[' ? 'slthW' : 'slW') +
'" d="m0 ' + y + 'h' + ws.toFixed(1);
dy = 0
}
ln += '"/>'
}
y = staff_tb[st].y
if (!cache
&& w > get_lwidth() - 10) {
cache = {
st_l: stafflines,
st_ws: ws | 0
}
i = 'stdef' + cfmt.fullsvg;
if (ln.indexOf('<path', 1) < 0)
glyphs[i] = ln.replace('path', 'path id="' + i + '"')
else
glyphs[i] = '<g id="' + i + '">\n' + ln + '\n</g>';
xygl(x1, y, i)
return
}
out_XYAB('<g transform="translate(X, Y)">\n' + ln + '\n</g>\n', x1, y)
} // draw_staff()
// draw a measure bar
function draw_bar(s, bot, h) {
var i, s2, yb, w,
bar_type = s.bar_type,
st = s.st,
p_staff = staff_tb[st],
x = s.x
// don't put a line between the staves if there is no bar above
if (st != 0
&& s.ts_prev
//fixme: 's.ts_prev.st != st - 1' when floating voice in lower staff
// && (s.ts_prev.type != C.BAR || s.ts_prev.st != st - 1))
&& s.ts_prev.type != C.BAR)
h = p_staff.topbar * p_staff.staffscale;
s.ymx = s.ymn + h;
anno_start(s)
if (s.color)
set_color(s.color);
// compute the middle vertical offset of the staff
yb = p_staff.y + 12;
if (p_staff.stafflines != '|||||')
yb += (p_staff.topbar + p_staff.botbar) / 2 - 12 // bottom
// if measure repeat, draw the '%' like glyphs
if (s.bar_mrep) {
set_sscale(st)
if (s.bar_mrep == 1) {
for (s2 = s.prev; s2.type != C.REST; s2 = s2.prev)
;
xygl(s2.x, yb, "mrep")
} else {
xygl(x, yb, "mrep2")
if (s.v == cur_sy.top_voice)
xy_str(x, yb + p_staff.topbar - 9,
s.bar_mrep.toString(), "c")
}
}
if (bar_type == '||:')
bar_type = '[|:'
for (i = bar_type.length; --i >= 0; ) {
switch (bar_type[i]) {
case "|":
if (s.bar_dotted) {
set_sscale(-1);
w = (5 * p_staff.staffscale).toFixed(1);
out_XYAB(
'<path class="bW" stroke-dasharray="A,A" d="MX Yv-G"/>\n',
x, bot, w, h)
} else if (s.color) {
out_XYAB('<path class="bW" d="MX Yv-F"/>\n',
x, bot, h)
} else {
sb.push(new Float32Array([x, bot, h]))
}
break
default:
// case "[":
// case "]":
x -= 3;
if (s.color)
out_XYAB('<path class="bthW" d="MX Yv-F"/>\n',
x + 1.5, bot, h)
else
thb.push(new Float32Array([x + 1.5, bot, h]))
break
case ":":
x -= 2;
set_sscale(st);
xygl(x + 1, yb - 12, "rdots")
break
}
x -= 3
}
set_color();
anno_stop(s)
} // draw_bar()
// output all the bars
function out_bars() {
var i, b, bx,
l = ba.length
set_font("annotation");
if (gene.curfont.box) {
gene.curfont.box = false
bx = true
}
for (i = 0; i < l; i++) {
b = ba[i]; // symbol, bottom, height
draw_bar(b[0], b[1], b[2])
}
if (bx)
gene.curfont.box = true
set_sscale(-1)
l = sb.length
if (l) { // single bars [x, y, h]
output += '<path class="bW" d="'
for (i = 0; i < l; i++) {
b = sb[i];
out_XYAB('MX Yv-F', b[0], b[1], b[2])
}
output += '"/>\n'
}
l = thb.length
if (l) { // thick bars [x, y, h]
output += '<path class="bthW" d="'
for (i = 0; i < l; i++) {
b = thb[i];
out_XYAB('MX Yv-F', b[0], b[1], b[2])
}
output += '"/>\n'
}
} // out_bars()
// draw_systems()
draw_vname(indent)
/* draw the staff, skipping the staff breaks */
for (st = 0; st <= nstaff; st++)
|
| ︙ | ︙ | |||
3648 3649 3650 3651 3652 3653 3654 | draw_staff(st, x, x2) if (sy.st_print[st]) xstaff[st] = x2 } cur_sy = sy; bar_set() continue | | < | | > | > | 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 |
draw_staff(st, x, x2)
if (sy.st_print[st])
xstaff[st] = x2
}
cur_sy = sy;
bar_set()
continue
case C.BAR: // display the bars after the staves
if (s.second || s.invis || !s.bar_type)
break
ba.push([s, bar_bot[s.st], bar_height[s.st]])
break
case C.STBRK:
if (cur_sy.voices[s.v]
&& cur_sy.voices[s.v].range == 0) {
if (s.xmx > 14) {
/* draw the left system if stbrk in all voices */
var nv = 0
for (var i = 0; i < voice_tb.length; i++) {
if (cur_sy.voices[i]
&& cur_sy.voices[i].range > 0)
nv++
}
for (s2 = s.ts_next; s2; s2 = s2.ts_next) {
if (s2.type != C.STBRK)
break
nv--
}
|
| ︙ | ︙ | |||
3709 3710 3711 3712 3713 3714 3715 | if (x < 0 || x >= realwidth) continue draw_staff(st, x, realwidth) } // and the bars out_bars() | | | | 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 |
if (x < 0 || x >= realwidth)
continue
draw_staff(st, x, realwidth)
}
// and the bars
out_bars()
// set_sscale(-1)
}
/* -- draw remaining symbols when the staves are defined -- */
// (possible hook)
Abc.prototype.draw_symbols = function(p_voice) {
var bm = {},
s, g, x, y, st;
// bm.s2 = undefined
for (s = p_voice.sym; s; s = s.next) {
if (s.invis) {
switch (s.type) {
|
| ︙ | ︙ | |||
3810 3811 3812 3813 3814 3815 3816 | if (s.second || s.invis || !staff_tb[s.st].topbar) break set_color(); set_sscale(s.st); anno_start(s); | | | 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 | if (s.second || s.invis || !staff_tb[s.st].topbar) break set_color(); set_sscale(s.st); anno_start(s); self.draw_keysig(x, s); anno_stop(s) break case C.MREST: set_scale(s); x += 32; anno_start(s); xygl(x, staff_tb[s.st].y + 12, "mrest"); |
| ︙ | ︙ | |||
3868 3869 3870 3871 3872 3873 3874 | } draw_all_deco(); set_sscale(-1) /* restore the scale */ } /* -- set the tie directions for one voice -- */ | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 |
}
draw_all_deco();
set_sscale(-1) /* restore the scale */
}
/* -- set the tie directions for one voice -- */
function set_tie_dir(s) {
var i, ntie, dir, sec, pit, ty
for ( ; s; s = s.next) {
if (!s.tie_s)
continue
/* if other voice, set the ties in opposite direction */
if (s.multi != 0) {
dir = s.multi > 0 ? C.SL_ABOVE : C.SL_BELOW
for (i = 0; i <= s.nhd; i++) {
ty = s.notes[i].tie_ty
if (!((ty & 0x07) == C.SL_AUTO))
continue
s.notes[i].tie_ty = (ty & C.SL_DOTTED) | dir
}
continue
}
/* if one note, set the direction according to the stem */
sec = ntie = 0;
pit = 128
for (i = 0; i <= s.nhd; i++) {
if (s.notes[i].tie_ty) {
ntie++
if (pit < 128
&& s.notes[i].pit <= pit + 1)
sec++;
pit = s.notes[i].pit
}
}
if (ntie <= 1) {
dir = s.stem < 0 ? C.SL_ABOVE : C.SL_BELOW
for (i = 0; i <= s.nhd; i++) {
ty = s.notes[i].tie_ty
if (ty) {
if ((ty & 0x07) == C.SL_AUTO)
s.notes[i].tie_ty =
(ty & C.SL_DOTTED) | dir
break
}
}
continue
}
if (sec == 0) {
if (ntie & 1) {
/* in chords with an odd number of notes, the outer noteheads are paired off
* center notes are tied according to their position in relation to the
* center line */
ntie = (ntie - 1) / 2;
dir = C.SL_BELOW
for (i = 0; i <= s.nhd; i++) {
ty = s.notes[i].tie_ty
if (!ty)
continue
if (ntie == 0) { /* central tie */
if (s.notes[i].pit >= 22)
dir = C.SL_ABOVE
}
if ((ty & 0x07) == C.SL_AUTO)
s.notes[i].tie_ty =
(ty & C.SL_DOTTED) | dir
if (ntie-- == 0)
dir = C.SL_ABOVE
}
continue
}
/* even number of notes, ties divided in opposite directions */
ntie /= 2;
dir = C.SL_BELOW
for (i = 0; i <= s.nhd; i++) {
ty = s.notes[i].tie_ty
if (!ty)
continue
if ((ty & 0x07) == C.SL_AUTO)
s.notes[i].tie_ty =
(ty & C.SL_DOTTED) | dir
if (--ntie == 0)
dir = C.SL_ABOVE
}
continue
}
/*fixme: treat more than one second */
/* if (nsec == 1) { */
/* When a chord contains the interval of a second, tie those two notes in
* opposition; then fill in the remaining notes of the chord accordingly */
pit = 128
for (i = 0; i <= s.nhd; i++) {
if (s.notes[i].tie_ty) {
if (pit < 128
&& s.notes[i].pit <= pit + 1) {
ntie = i
break
}
pit = s.notes[i].pit
}
}
dir = C.SL_BELOW
for (i = 0; i <= s.nhd; i++) {
ty = s.notes[i].tie_ty
if (!ty)
continue
if (ntie == i)
dir = C.SL_ABOVE
if ((ty & 0x07) == C.SL_AUTO)
s.notes[i].tie_ty =
(ty & C.SL_DOTTED) | dir
}
/*fixme..
continue
}
..*/
/* if a chord contains more than one pair of seconds, the pair farthest
* from the center line receives the ties drawn in opposition */
|
| ︙ | ︙ | |||
3998 3999 4000 4001 4002 4003 4004 |
if (!s)
continue
s = s.next
if (!s)
continue
set_tie_dir(s)
for ( ; s; s = s.next) {
| | > | | > | 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 |
if (!s)
continue
s = s.next
if (!s)
continue
set_tie_dir(s)
for ( ; s; s = s.next) {
if (!s.tie_s)
continue
if (s.notes[0].pit < 20
&& s.notes[0].tie_ty
&& (s.notes[0].tie_ty & 0x07) == C.SL_BELOW)
;
else if (s.notes[s.nhd].pit > 24
&& s.notes[s.nhd].tie_ty
&& (s.notes[s.nhd].tie_ty & 0x07) == C.SL_ABOVE)
;
else
continue
s2 = s.next
while (s2 && s2.type != C.NOTE)
s2 = s2.next
if (s2) {
|
| ︙ | ︙ |
Changes to core/format.js.
| ︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
var font_tb = [],
font_scale_tb = {
serif: 1,
serifBold: 1,
'sans-serif': 1,
'sans-serifBold': 1,
Palatino: 1.1,
monospace: 1.35
},
fmt_lock = {}
var cfmt = {
| > | > | | | < | | < < < < < < < < < | | | | 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 107 108 109 110 111 112 113 114 115 116 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
var font_tb = [],
font_st = {}, // font style => font_tb index for incomplete user fonts
font_scale_tb = {
serif: 1,
serifBold: 1,
'sans-serif': 1,
'sans-serifBold': 1,
Palatino: 1.1,
monospace: 1.35
},
fmt_lock = {}
var cfmt = {
annotationfont: {name: "sans-serif", size: 12 },
aligncomposer: 1,
beamslope: .4, // max slope of a beam
// botmargin: .7 * IN, // != 1.8 * CM,
breaklimit: .7,
breakoneoln: true,
cancelkey: true,
composerfont: { name: "serif", style: "italic", size: 14 },
composerspace: 6,
// contbarnb: false,
dblrepbar: ':][:',
decoerr: true,
dynalign: true,
footerfont: { name: "serif", size: 16 },
fullsvg: '',
gchordfont: { name: "sans-serif", size: 12 },
gracespace: new Float32Array([4, 8, 11]), // left, inside, right
graceslurs: true,
headerfont: { name: "serif", size: 16 },
historyfont: { name: "serif", size: 16 },
hyphencont: true,
indent: 0,
infofont: {name: "serif", style: "italic", size: 14 },
infoname: 'R "Rhythm: "\n\
B "Book: "\n\
S "Source: "\n\
D "Discography: "\n\
N "Notes: "\n\
Z "Transcription: "\n\
H "History: "',
infospace: 0,
keywarn: true,
leftmargin: 1.4 * CM,
lineskipfac: 1.1,
linewarn: true,
maxshrink: .65, // nice scores
maxstaffsep: 2000,
maxsysstaffsep: 2000,
measurefont: {name: "serif", style: "italic", size: 10},
measurenb: -1,
musicspace: 6,
// notespacingfactor: 1.33
partsfont: {name: "serif", size: 15},
parskipfac: .4,
partsspace: 8,
// pageheight: 29.7 * CM,
pagewidth: 21 * CM,
printmargin: 0,
rightmargin: 1.4 * CM,
rbdbstop: true,
rbmax: 4,
rbmin: 2,
repeatfont: {name: "serif", size: 13},
scale: 1,
slurheight: 1.0,
staffsep: 46,
stemheight: 21, // one octave
stretchlast: .25,
stretchstaff: true,
subtitlefont: {name: "serif", size: 16},
subtitlespace: 3,
sysstaffsep: 34,
tempofont: {name: "serif", weight: "bold", size: 12},
textfont: {name: "serif", size: 16},
// textoption: undefined,
textspace: 14,
titlefont: {name: "serif", size: 20},
// titleleft: false,
titlespace: 6,
titletrim: true,
// transp: 0, // global transpose
// topmargin: .7 * IN,
topspace: 22,
tuplets: [0, 0, 0, 0],
vocalfont: {name: "serif", weight: "bold", size: 13},
vocalspace: 10,
voicefont: {name: "serif", weight: "bold", size: 13},
// voicescale: 1,
writefields: "CMOPQsTWw",
wordsfont: {name: "serif", size: 16},
wordsspace: 5
}
function get_bool(param) {
|
| ︙ | ︙ | |||
147 148 149 150 151 152 153 | if (!scale) scale = 1.1; font.swfac = font.size * scale } // %%xxxfont fontname|* [encoding] [size|*] | | | > > | | > < < | | | | | > > > > > > > > > > > > > > > > > > > > > > | > > > > | | | | | > | | | | | | < < < < < < < < < < | < < < > | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
if (!scale)
scale = 1.1;
font.swfac = font.size * scale
}
// %%xxxfont fontname|* [encoding] [size|*]
function param_set_font(xxxfont, p) {
var font, n, a
// "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"
}
// create a new font
font = cfmt[xxxfont];
if (!font) { // set-font-<n> or new element
font = {}
} else {
font = {
name: font.name,
size: font.size,
box: font.box
}
}
cfmt[xxxfont] = font;
// fill the values
a = p.match(/\s+(no)?box(\s|$)/)
if (a) { // if box
if (a[1])
font.box = false // nobox
else
font.box = true;
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'
break
case 'glyph':
font.wadj = 'spacingAndGlyphs'
break
default:
syntax(1, errs.bad_val, "%%" + xxxfont)
break
}
p = p.replace(a[0], a[2])
}
// the font size is the last item
a = p.match(/\s+([0-9.]+|\*)$/)
if (a) {
if (a[1] != "*") {
font.size = Number(a[1])
font.swfac = 0
}
p = p.replace(a[0], "")
}
a = p.match(/[- ]?[nN]ormal/)
if (a) {
font.normal = true
p = p.replace(a[0], '')
}
a = p.match(/[- ]?[bB]old/)
if (a) {
font.weight = "bold"
p = p.replace(a[0], '')
}
a = p.match(/[- ]?[iI]talic/)
if (a) {
font.style = "italic"
p = p.replace(a[0], '')
}
a = p.match(/[- ]?[oO]blique/)
if (a) {
font.style = "oblique"
p = p.replace(a[0], '')
}
switch (p) {
case "":
case "*": return
case "Times-Roman":
case "Times": p = "serif"; break
case "Helvetica": p = "sans-serif"; break
case "Courier": p = "monospace"; break
}
font.swfac = 0
font.name = p
}
// get a length with a unit - return the number of pixels
function get_unit(param) {
var v = parseFloat(param)
switch (param.slice(-2)) {
|
| ︙ | ︙ | |||
306 307 308 309 310 311 312 |
}
/* -- set the position of elements in a voice -- */
function set_pos(k, v) { // keyword, value
k = k.slice(0, 3)
if (k == "ste")
k = "stm"
| | | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
}
/* -- set the position of elements in a voice -- */
function set_pos(k, v) { // keyword, value
k = k.slice(0, 3)
if (k == "ste")
k = "stm"
set_v_param("pos", k + ' ' + v)
}
// set/unset the fields to write
function set_writefields(parm) {
var c, i,
a = parm.split(/\s+/)
|
| ︙ | ︙ | |||
330 331 332 333 334 335 336 | if (cfmt.writefields.indexOf(c) >= 0) cfmt.writefields = cfmt.writefields.replace(c, '') } } } // set a voice specific parameter | < | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
if (cfmt.writefields.indexOf(c) >= 0)
cfmt.writefields = cfmt.writefields.replace(c, '')
}
}
}
// set a voice specific parameter
function set_v_param(k, v) {
if (curvoice) {
self.set_vp([k + '=', v])
return
}
k = [k + '=', v];
var vid = '*'
|
| ︙ | ︙ | |||
368 369 370 371 372 373 374 | img.width = img.lm + img.rm + 150 } set_posx() } // set_page() // set a format parameter // (possible hook) | | < < < < < < | > > | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 |
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)) {
param_set_font(cmd, param)
return
}
switch (cmd) {
case "aligncomposer":
case "barsperstaff":
case "infoline":
case "measurenb":
case "rbmax":
case "rbmin":
case "shiftunison":
v = parseInt(param)
if (isNaN(v)) {
syntax(1, "Bad integer value");
break
}
cfmt[cmd] = v
break
case "microscale":
f = parseInt(param)
if (isNaN(f) || f < 4 || f > 256 || f % 1) {
syntax(1, errs.bad_val, "%%" + cmd)
break
}
set_v_param("uscale", f)
break
case "bgcolor":
case "fgcolor":
case "dblrepbar":
case "titleformat":
cfmt[cmd] = param
break
case "beamslope":
case "breaklimit": // float values
case "lineskipfac":
case "maxshrink":
case "pagescale":
case "parskipfac":
case "scale":
case "slurheight":
|
| ︙ | ︙ | |||
455 456 457 458 459 460 461 462 463 464 465 466 467 468 | case "dynalign": case "flatbeams": case "graceslurs": case "graceword": case "hyphencont": case "keywarn": case "linewarn": case "rbdbstop": case "singleline": case "squarebreve": case "splittune": case "straightflags": case "stretchstaff": case "timewarn": | > | 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 | case "dynalign": case "flatbeams": case "graceslurs": case "graceword": case "hyphencont": case "keywarn": case "linewarn": case "quiet": case "rbdbstop": case "singleline": case "squarebreve": case "splittune": case "straightflags": case "stretchstaff": case "timewarn": |
| ︙ | ︙ | |||
533 534 535 536 537 538 539 |
set_pos(cmd, param)
break
case "font":
get_font_scale(param)
break
case "fullsvg":
if (parse.state != 0) {
| | | 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 |
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+/)
|
| ︙ | ︙ | |||
621 622 623 624 625 626 627 | else cfmt[cmd] = v break case "combinevoices": syntax(1, "%%combinevoices is deprecated - use %%voicecombine instead") break case "voicemap": | | | | | | < | | < < < | | < < < | < | > | > | | 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 |
else
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
default: // memorize all global commands
if (parse.state == 0) // (needed for modules)
cfmt[cmd] = param
break
}
}
// 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 = '"' + n.replace(/"/g, "") + '"' // '
return r + font.size.toFixed(1) + 'px ' + n
}
function style_font(font) {
return 'font:' + st_font(font)
}
Abc.prototype.style_font = style_font
// build a font class
function font_class(font) {
if (font.class)
return 'f' + font.fid + cfmt.fullsvg + ' ' + font.class
|
| ︙ | ︙ | |||
682 683 684 685 686 687 688 |
}
font_style += "\n.f" + font.fid + cfmt.fullsvg +
" {" + style_font(font) + "}"
}
}
// get the font of the 'xxxfont' parameter
| | > > | | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 |
}
font_style += "\n.f" + font.fid + cfmt.fullsvg +
" {" + style_font(font) + "}"
}
}
// get the font of the 'xxxfont' parameter
function get_font(fn) {
var font, font2, fid, st
fn += "font"
font = cfmt[fn]
if (!font) {
syntax(1, "Unknown font $1", '$' + fn[1]);
return gene.curfont
}
if (!font.name || !font.size) { // if incomplete user font
font2 = Object.create(gene.curfont)
if (font.name)
font2.name = font.name
if (font.normal) {
if (font2.weight) // !! don't use delete !!
font2.weight = null
if (font2.style)
font2.style = null
} else {
if (font.weight)
font2.weight = font.weight
if (font.style)
font2.style = font.style
}
if (font.class)
font2.class = font.class
if (font.size)
font2.size = font.size
st = st_font(font2)
fid = font_st[st]
if (fid != undefined)
return font_tb[fid]
font_st[st] = font_tb.length
font2.fid = font2.used = undefined
font = font2
}
use_font(font)
return font
}
|
Changes to core/front.js.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// abc2svg-core is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// translation table from the ABC draft version 2.2
var abc_utf = {
"=D": "Đ",
"=H": "Ħ",
"=T": "Ŧ",
"=d": "đ",
| > > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// abc2svg-core is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
var sav = {}, // save global (between tunes) definitions
mac = {}, // macros (m:)
maci = {} // first letters of macros
// translation table from the ABC draft version 2.2
var abc_utf = {
"=D": "Đ",
"=H": "Ħ",
"=T": "Ŧ",
"=d": "đ",
|
| ︙ | ︙ | |||
58 59 60 61 62 63 64 |
"5": "𝄫"
}
// convert the escape sequences to utf-8
function cnv_escape(src) {
var c, c2,
dst = "",
| | | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
"5": "𝄫"
}
// convert the escape sequences to utf-8
function cnv_escape(src) {
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]
|
| ︙ | ︙ | |||
83 84 85 86 87 88 89 |
j = i + 3
continue
}
break
case 'u':
j = Number("0x" + src.slice(i + 1, i + 5));
if (isNaN(j) || j < 0x20) {
| | < < < | < < < < | < < > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | < < < < < < < < < < < < > > | < < | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
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
}
dst += String.fromCharCode(j);
j = i + 5
continue
case 't': // TAB
dst += ' ';
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 (!/[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 '.':
dst += c2 + "\u0307" // dot
j = i + 2
continue
case '"':
dst += c2 + "\u0308" // dieresis
j = i + 2
continue
case 'o':
dst += c2 + "\u030a" // ring
j = i + 2
continue
case 'H':
dst += c2 + "\u030b" // hungarumlaut
j = i + 2
continue
case 'v':
dst += c2 + "\u030c" // caron
j = i + 2
continue
// case ',':
// dst += c2 + "\u0326" // comma below
// j = i + 2
// continue
case 'c':
dst += c2 + "\u0327" // cedilla
j = i + 2
continue
case ';':
dst += c2 + "\u0328" // ogonek
j = i + 2
continue
}
break
}
dst += '\\' + c;
j = i + 1
}
return dst + src.slice(j)
}
// ABC include
var include = 0
function do_include(fn) {
var file, parse_sav
if (!user.read_file) {
syntax(1, "No read_file support")
return
}
if (include > 2) {
syntax(1, "Too many include levels")
return
}
file = user.read_file(fn)
if (!file) {
syntax(1, "Cannot read file '$1'", fn)
return
}
include++;
parse_sav = clone(parse);
tosvg(fn, file);
parse_sav.state = parse.state;
parse = parse_sav;
include--
}
// parse ABC code
function tosvg(in_fname, // file name
file, // file content
bol, eof) { // beginning/end of file
var i, c, eol, end,
select,
line0, line1,
last_info, opt, text, a, b, s,
pscom,
txt_add = '\n' // for "+:"
// check if a tune is selected
function tune_selected() {
var re, res,
i = file.indexOf('K:', bol)
|
| ︙ | ︙ | |||
253 254 255 256 257 258 259 |
else
eol = eof
return false
} // tune_selected()
// remove the comment at end of text
function uncomment(src, do_escape) {
| < | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
else
eol = eof
return false
} // tune_selected()
// remove the comment at end of text
function uncomment(src, do_escape) {
if (!src)
return src
if (src.indexOf('%') >= 0)
src = src.replace(/([^\\])%.*/, '$1')
.replace(/\\%/g, '%');
src = src.replace(/\s+$/, '')
if (do_escape && src.indexOf('\\') >= 0)
return cnv_escape(src)
return src
} // uncomment()
function end_tune() {
generate()
if (info.W)
put_words(info.W);
put_history();
blk_flush();
parse.state = 0; // file header
cfmt = sav.cfmt;
info = sav.info;
char_tb = sav.char_tb;
glovar = sav.glovar;
maps = sav.maps;
mac = sav.mac;
maci = sav.maci;
parse.tune_v_opts = null;
parse.scores = null;
init_tune()
img.chg = true;
set_page();
} // end_tune()
// get %%voice
function do_voice(select, in_tune) {
var opt, bol
if (select == "end")
return // end of previous %%voice
// get the options
if (in_tune) {
if (!parse.tune_v_opts)
parse.tune_v_opts = {};
opt = parse.tune_v_opts
} else {
if (!parse.voice_opts)
parse.voice_opts = {};
opt = parse.voice_opts
}
opt[select] = []
while (1) {
bol = ++eol
if (file[bol] != '%')
break
eol = file.indexOf('\n', eol);
if (file[bol + 1] != line1)
continue
bol += 2
if (eol < 0)
text = file.slice(bol)
else
text = file.slice(bol, eol);
a = text.match(/\S+/)
switch (a[0]) {
default:
opt[select].push(uncomment(text, true))
continue
case "score":
case "staves":
case "tune":
case "voice":
bol -= 2
break
}
break
}
eol = parse.eol = bol - 1
} // do_voice()
// apply the options to the current tune
function tune_filter() {
var o, opts, j, pc, h,
i = file.indexOf('K:', bol)
i = file.indexOf('\n', i);
h = file.slice(parse.bol, i) // tune header
for (i in parse.tune_opts) {
if (!parse.tune_opts.hasOwnProperty(i))
continue
if (!(new RegExp(i)).test(h))
continue
opts = parse.tune_opts[i]
for (j = 0; j < opts.t_opts.length; j++) {
pc = opts.t_opts[j]
switch (pc.match(/\S+/)[0]) {
case "score":
case "staves":
if (!parse.scores)
parse.scores = [];
parse.scores.push(pc)
break
default:
self.do_pscom(pc)
break
}
}
opts = opts.v_opts
if (!opts)
continue
for (j in opts) {
if (!opts.hasOwnProperty(j))
continue
if (!parse.tune_v_opts)
parse.tune_v_opts = {};
if (!parse.tune_v_opts[j])
parse.tune_v_opts[j] = opts[j]
else
parse.tune_v_opts[j] =
parse.tune_v_opts[j].
concat(opts[j])
}
}
} // tune_filter()
// export functions and/or set module hooks
if (abc2svg.modules
&& (abc2svg.modules.hooks.length || abc2svg.modules.g_hooks.length))
set_hooks()
// initialize
parse.file = file; // used for errors
|
| ︙ | ︙ | |||
360 361 362 363 364 365 366 |
pscom = true
}
// pseudo-comments
if (pscom) {
pscom = false;
bol += 2 // skip %%/I:
| < < < < < < < < < > | < | | | | | | | | | < < < | | | | < < < | < < | | | < < | | | < | | > > > > > > | < < < < < < > > > > > > > > > > > > > > > > > > > | 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 |
pscom = true
}
// pseudo-comments
if (pscom) {
pscom = false;
bol += 2 // skip %%/I:
text = file.slice(bol, eol)
a = text.match(/([^\s]+)\s*(.*)/)
if (!a || a[1][0] == '%')
continue
switch (a[1]) {
case "abcm2ps":
case "ss-pref":
parse.prefix = a[2] // may contain a '%'
continue
case "abc-include":
do_include(uncomment(a[2]))
continue
}
// beginxxx/endxxx
if (a[1].slice(0, 5) == 'begin') {
b = a[1].substr(5);
end = '\n' + line0 + line1 + "end" + b;
i = file.indexOf(end, eol)
if (i < 0) {
syntax(1, "No $1 after %%$2",
end.slice(1), a[1]);
parse.eol = eof
continue
}
self.do_begin_end(b, uncomment(a[2]),
file.slice(eol + 1, i).replace(
new RegExp('^' + line0 + line1, 'gm'),
''));
parse.eol = file.indexOf('\n', i + 6)
if (parse.eol < 0)
parse.eol = eof
continue
}
switch (a[1]) {
case "select":
if (parse.state != 0) {
syntax(1, errs.not_in_tune, "%%select")
continue
}
select = uncomment(text.slice(7))
if (select[0] == '"')
select = select.slice(1, -1);
if (!select) {
delete parse.select
continue
}
select = select.replace(/\(/g, '\\(');
select = select.replace(/\)/g, '\\)');
// select = select.replace(/\|/g, '\\|');
parse.select = new RegExp(select, 'm')
continue
case "tune":
if (parse.state != 0) {
syntax(1, errs.not_in_tune, "%%tune")
continue
}
select = uncomment(a[2])
// if void %%tune, free all tune options
if (!select) {
parse.tune_opts = {}
continue
}
if (select == "end")
continue // end of previous %%tune
if (!parse.tune_opts)
parse.tune_opts = {};
parse.tune_opts[select] = opt = {
t_opts: []
// v_opts: {}
};
while (1) {
bol = ++eol
if (file[bol] != '%')
break
eol = file.indexOf('\n', eol);
if (file[bol + 1] != line1)
continue
bol += 2
if (eol < 0)
text = file.slice(bol)
else
text = file.slice(bol, eol);
a = text.match(/([^\s]+)\s*(.*)/)
switch (a[1]) {
case "tune":
break
case "voice":
do_voice(uncomment(a[2],
true), true)
continue
default:
opt.t_opts.push(
uncomment(text, true))
continue
}
break
}
if (parse.tune_v_opts) {
opt.v_opts = parse.tune_v_opts;
parse.tune_v_opts = null
}
parse.eol = bol - 1
continue
case "voice":
if (parse.state != 0) {
syntax(1, errs.not_in_tune, "%%voice")
continue
}
select = uncomment(a[2])
/* if void %%voice, free all voice options */
if (!select) {
parse.voice_opts = null
continue
}
do_voice(select)
continue
}
self.do_pscom(uncomment(text, true))
continue
}
// music line (or free text)
if (line1 != ':' || !/[A-Za-z+]/.test(line0)) {
|
| ︙ | ︙ | |||
534 535 536 537 538 539 540 |
eol = file.indexOf('\nX:', parse.eol)
if (eol < 0)
eol = eof;
parse.eol = eol
continue
}
| | < | | | | | | > > > | 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 |
eol = file.indexOf('\nX:', parse.eol)
if (eol < 0)
eol = eof;
parse.eol = eol
continue
}
sav.cfmt = clone(cfmt);
sav.info = clone(info, 2) // (level 2 for info.V[])
sav.char_tb = clone(char_tb);
sav.glovar = clone(glovar);
sav.maps = clone(maps, 1);
sav.mac = clone(mac);
sav.maci = clone(maci);
info.X = text;
parse.state = 1 // tune header
if (parse.tune_opts)
tune_filter()
continue
case 'T':
switch (parse.state) {
case 0:
continue
case 1:
case 2:
if (info.T == undefined) // (keep empty T:)
info.T = text
else
info.T += "\n" + text
continue
}
s = new_block("title");
|
| ︙ | ︙ | |||
584 585 586 587 588 589 590 |
break
case 'm':
if (parse.state >= 2) {
syntax(1, errs.ignored, line0)
continue
}
| < < < | | 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 |
break
case 'm':
if (parse.state >= 2) {
syntax(1, errs.ignored, line0)
continue
}
a = text.match(/(.*?)[= ]+(.*)/)
if (!a || !a[2]) {
syntax(1, errs.bad_val, "m:")
continue
}
mac[a[1]] = a[2];
maci[a[1][0]] = true // first letter
break
// info fields in tune body only
case 's':
if (parse.state != 3
|| cfmt.writefields.indexOf(line0) < 0)
break
|
| ︙ | ︙ | |||
617 618 619 620 621 622 623 | last_info = line0 continue } break case '|': // "|:" starts a music line if (parse.state < 2) continue | | | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 |
last_info = line0
continue
}
break
case '|': // "|:" starts a music line
if (parse.state < 2)
continue
parse.line.buffer = text
parse_music_line()
continue
default:
if ("ABCDFGHNOSZ".indexOf(line0) >= 0) {
if (parse.state >= 2) {
syntax(1, errs.ignored, line0)
continue
|
| ︙ | ︙ |
Changes to core/gchord.js.
| ︙ | ︙ | |||
161 162 163 164 165 166 167 | } } // transpose a chord symbol var note_names = "CDEFGAB", acc_name = ["bb", "b", "", "#", "##"] | | | | | | > | < < < | | < < < < < < | < | < < < | < < < | | > | < < < < < < | < < < < < < < < < < | | | < | | | | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
}
}
// transpose a chord symbol
var note_names = "CDEFGAB",
acc_name = ["bb", "b", "", "#", "##"]
function gch_tr1(p, transp) {
var i, o, n, a, ip, b40,
csa = p.split('/')
for (i = 0; i < csa.length; i++) { // main and optional bass
p = csa[i];
o = p.search(/[ABCDEFG]/);
if (o < 0)
continue // strange chord symbol!
ip = o + 1
a = 0
while (p[ip] == '#') {
a++;
ip++
}
while (p[ip] == 'b') {
a--;
ip++
}
n = note_names.indexOf(p[o]) + 16
b40 = (abc2svg.pab40(n, a) + transp + 200) % 40
b40 = abc2svg.b40k[b40]
csa[i] = p.slice(0, o) +
note_names[abc2svg.b40_p[b40]] +
acc_name[abc2svg.b40_a[b40] + 2] +
p.slice(ip)
}
return csa.join('/')
} // gch_tr1
function gch_transp(s) {
var gch,
i = s.a_gch.length
while (--i >= 0) {
gch = s.a_gch[i]
if (gch.type == 'g')
gch.text = gch_tr1(gch.text, curvoice.vtransp)
}
}
// -- build the chord indications / annotations --
// (possible hook)
Abc.prototype.gch_build = function(s) {
/* split the chord indications / annotations
* and initialize their vertical offsets */
var gch, wh, xspc, ix,
pos = curvoice.pos.gch == C.SL_BELOW ? -1 : 1,
y_above = 0,
y_below = 0,
|
| ︙ | ︙ | |||
266 267 268 269 270 271 272 |
if (cfmt.chordnames) {
gch.otext = gch.text; // save for %%diagram
gch.text = gch.text.replace(/A|B|C|D|E|F|G/g,
function(c){return cfmt.chordnames[c]})
if (cfmt.chordnames.B == 'H')
gch.text = gch.text.replace(/Hb/g, 'Bb')
}
| | > < < < < < | | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
if (cfmt.chordnames) {
gch.otext = gch.text; // save for %%diagram
gch.text = gch.text.replace(/A|B|C|D|E|F|G/g,
function(c){return cfmt.chordnames[c]})
if (cfmt.chordnames.B == 'H')
gch.text = gch.text.replace(/Hb/g, 'Bb')
}
gch.text = gch.text.replace(/##|#|=|bb|b| /g,
function(x) {
switch (x) {
case '##': return "𝄪"
case '#': return "\u266f"
case '=': return "\u266e"
case 'b': return "\u266d"
case ' ': return ' '
}
return "𝄫"
});
} else {
if (gch.type == '@'
&& !user.anno_start && !user.anno_stop) {
gch.wh = [0, 0]
continue /* no width */
}
}
/* set the offsets and widths */
set_font(gch.font);
wh = strwh(gch.text);
gch.wh = wh
if (gch.font.box)
wh[1] += 4
switch (gch.type) {
case '@':
break
case '^': /* above */
xspc = wh[0] * GCHPRE
if (xspc > 8)
|
| ︙ | ︙ | |||
367 368 369 370 371 372 373 | } } // -- draw the chord symbols and annotations // (the staves are not yet defined) // (unscaled delayed output) // (possible hook) | | | | | | 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
}
}
// -- draw the chord symbols and annotations
// (the staves are not yet defined)
// (unscaled delayed output)
// (possible hook)
Abc.prototype.draw_gchord = function(s, gchy_min, gchy_max) {
var gch, text, ix, x, y, y2, hbox, h, y_above, y_below,
// adjust the vertical offset according to the chord symbols
w = 0,
yav = s.dur ?
(((s.notes[s.nhd].pit + s.notes[0].pit) >> 1) - 18) * 3 :
12 // fixed offset on measure bars
for (ix = 0; ix < s.a_gch.length; ix++) {
gch = s.a_gch[ix]
if (gch.wh[0] > w)
w = gch.wh[0]
}
y_above = y_get(s.st, 1, s.x - 3, w);
y_below = y_get(s.st, 0, s.x - 3, w)
if (y_above < gchy_max)
y_above = gchy_max
if (y_below > gchy_min)
y_below = gchy_min;
set_dscale(s.st);
for (ix = 0; ix < s.a_gch.length; ix++) {
gch = s.a_gch[ix];
use_font(gch.font);
set_font(gch.font);
h = gch.font.size;
hbox = gch.font.box ? 2 : 0;
w = gch.wh[0];
x = s.x + gch.x;
text = gch.text
switch (gch.type) {
case '_': /* below */
y = gch.y + y_below;
y_set(s.st, 0, x, w, y - hbox)
|
| ︙ | ︙ |
Changes to core/lyrics.js.
| ︙ | ︙ | |||
495 496 497 498 499 500 501 |
return y / sc
}
// -- draw all the lyrics --
/* (the staves are not yet defined) */
function draw_all_lyrics() {
var p_voice, s, v, nly, i, x, y, w, a_ly, ly,
| | | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 |
return y / sc
}
// -- draw all the lyrics --
/* (the staves are not yet defined) */
function draw_all_lyrics() {
var p_voice, s, v, nly, i, x, y, w, a_ly, ly,
lyst_tb = new Array(nstaff+ 1),
nv = voice_tb.length,
h_tb = new Array(nv),
nly_tb = new Array(nv),
above_tb = new Array(nv),
rv_tb = new Array(nv),
top = 0,
bot = 0,
|
| ︙ | ︙ |
Added core/mei.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 |
// abc2svg - mei.js - MEI front-end
//
// Copyright (C) 2019 Jean-Francois Moine
//
// This file is part of abc2svg-core.
//
// abc2svg-core is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg-core is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// convert the xml source into a tree
function xml2tree(xml) {
var i, j, item, n, no, an,
e = 0,
stack = [],
root = {
name: "root"
},
o = root
while (1) {
i = xml.indexOf('<', e) // start of tag
if (i < 0)
break
if (i > e + 1) { // if some content
item = xml.slice(e + 1, i)
.replace(/\s*/, '') // remove left spaces
if (item) {
if (!o.children)
o.children = []
o.children.push({
name: "text",
content: item
})
}
}
e = xml.indexOf('>', i) // end
if (e < 0)
//fixme: error
return root
switch (xml[i + 1]) {
case '?':
continue // XML header
case '!':
e = xml.indexOf('-->', i) // XML comment
if (e < 0)
return root
continue
case '/':
item = xml.slice(i + 2, e)
if (item != o.name) {
error(1, null, 'Found tag </' + item +
'> instead of </'+o.name + '>')
continue
}
o = stack.pop()
if (!o)
error(1, null, 'No start tag "' + item + '"')
continue
}
item = xml.slice(i + 1, e)
n = item.match(/(\w+)[\s]*([^]*)/)
no = {
name: n[1],
ix: i
}
if (!o.children)
o.children = []
o.children.push(no)
if (n[2].slice(-1) != '/') { // if some content
stack.push(o)
o = no
} else {
n[2] = n[2].slice(0, -1)
}
if (!n[2])
continue
n = n[2].match(/[^\s"=]+=?|".*?"/g) // "
for (j = 0; j < n.length; j += 2) {
an = n[j].slice(0, -1)
no[an] = n[j + 1].slice(1, -1)
}
}
return root
}
// convert MEI to music suitable to the abc2svg generator
Abc.prototype.mei2mus = function(mei) {
var curr = { // various elements while parsing the MEI source
beam: 0,
delayed: {},
fnt: {},
ftn: 0,
ids: {},
meastim: 0,
mu: C.BLEN / 4,
pt: .01, // default unit ! en cm
tp: [] // tuplets
},
acc_ty = {
"ff": -2,
"f": -1,
"s": 1,
"x": 2,
// "ss": 2,
"n": 3
},
bar_ty = {
dashed: ".|",
dbl: "||",
dbldashed: ".||",
dbldotted: ".||",
dotted: ".|",
end: "|]",
invis: "[]",
rptstart: "|:",
rptboth: "::",
rptend: ":|",
single: "|"
},
fn = "",
// --- functions associated to the start of MIE tags
fns = {
// accidental
accid: function(tag) {
var s = curr.s,
note = s.notes[s.nhd]
if (acc_ty[tag.accid])
note.acc = acc_ty[tag.accid]
}, // accid()
arpeg: function(tag) {
var s
if (!tag.plist)
return
// plist = list of notes of the chord
s = tag.plist.split(/\s+/)[0].slice(1) // top note
s = curr.ids[s] // always defined
s = s.s // chord
add_dcn(s, "arpeggio")
}, // arpeg()
// articulation inside chord or note
artic: function(tag) {
artic(curr.chord || curr.s, tag)
}, // artic()
barLine: function(tag) {
var s, ty
if (tag.form)
ty = bar_ty[tag.form]
if (!ty)
ty = "|"
s = {
type: C.BAR,
istart: tag.ix,
bar_type: ty,
dur: 0,
multi: 0
}
sym_link(s)
if (ty[0] == '.') {
s.bar_type = ty.slice(1)
s.bar_dotted = true
}
}, // barLine()
// start of beam
beam: function(tag) {
curr.beam = 1
}, // beam()
// beam crossing staves or measure bars
beamSpan: function(tag) {
var s = get_ref(tag),
s2 = get_ref(tag, s)
if (!s || !s2)
return
s.beam_st = true
if (s.st == s2.st) {
while (s != s2) {
if (s.type == C.BAR)
s.beam_on = true
}
// } else {
//fixme: beams on 2 voices do not work!
}
s2.beam_end = true
}, // beamSpan()
breath: function(tag) {
var s = get_ref(tag)
if (!s)
return
if (s.s) // !
s = s.s
// tag.place above/below
add_dcn(s, "breath")
}, // breath()
// start of chord
chord: function(tag) {
var dur = durcnv(tag),
s = {
type: C.NOTE,
istart: tag.ix,
stem: 0,
multi: 0,
nhd: -1,
xmx: 0,
dur: dur,
dur_orig: dur,
notes: []
}
switch (tag["stem.dir"]) {
case "up": s.stem = 1; break
case "down": s.stem = -1; break
}
switch (curr.beam) {
case 0:
s.beam_st = true
s.beam_end = true
break
case 1:
s.beam_st = true
curr.beam = 2
break
}
//if (0) {
// switch (tag.tie) {
// case "i":
// case "m":
// curvoice.tie_s = s
// break
// }
//}
if (tag.artic)
artic(s, tag)
//fixme:cross-staff chord
// tag.stem.with
//fixme: staff change?
// tag.staff
if (tag.grace)
s.grace = true
sym_link(s)
curr.chord = s
}, // chord()
clef: function(tag) {
var s = new_clef(tag.shape + tag.line)
if (s)
get_clef(s)
}, // clef()
composer: set_text,
// annotation
dir: set_text,
// start of division
div: set_text,
dynam: set_text,
// variant ending
ending: function(tag) {
curr.ending = tag.n // "1", "2"
}, // ending()
// single element of figured bass - in <harm>
f: function(tag) {
if (curr.text)
curr.text += "\n"
}, // f()
// figured bass - in <harm>
// fb: function(tag) {
// }, // fb()
fileDesc: function(tag) {
return true // skip
}, // fileDesc()
fing: set_text,
fermata: function(tag) {
var s = get_ref(tag)
if (!s)
return
if (s.s)
s = s.s
// tag.place above/below
add_dcn(s, tag.form != "inv" ? "fermata" : "invertedfermata")
}, // fermata()
// group of grace notes
graceGrp: function(tag) {
// tag.attach pre
},
// crescendo, diminuendo
hairpin: function(tag) {
var s = get_ref(tag),
s2 = get_ref(tag, s)
if (!s || !s2)
return
if (s.s) // on notes!
s = s.s
if (s2.s)
s2 = s2.s
switch (tag.place) {
case "above": s.pos.dyn = C.SL_ABOVE; break
case "below": s.pos.dyn = C.SL_BELOW; break
}
switch (tag.form) {
default:
// case "cres":
add_dcn(s, "<(")
add_dcn(s2, "<)")
break
case "dim":
add_dcn(s, ">(")
add_dcn(s2, ">)")
break
}
}, // hairpin()
// chord symbol (harmony)
harm: set_text,
// start of incipit
incip: function(tag) {
//fixme: skip
return true
// tosvg(fn, "X:1")
// parse.state = 1 // inside tune
}, // incip()
// start of line or start of line group
l: function(tag) {
if (curr.text)
curr.text += "\n"
}, // l()
// start of label or labelAbbr
label: function(tag) {
if (curr.st == undefined // not in staff definition
&& !curr.staffGrp) // not in staffGrp
return true
set_text(tag)
}, // label()
// layer (voice) - must be inside staff
layer: function(tag) {
var v, p_v, old_sy, s, vid, t,
st = curr.st, // ABC staff number
staff = par_sy.staves[st],
n = tag.n
// set the (ABC) start of tune
if (parse.state < 2) {
staves_found = 0// don't generate a dummy staff system
if (staff["meter.sym"] || staff["meter.count"]) {
new_meter(metercnv(staff))
curr.mu = meteru(staff)
delete staff["meter.sym"]
delete staff["meter.count"]
}
get_key(staff["key.sig"] ? keycnv(staff) : "C")
}
// build the voice ID = "#staff[#layer]"
vid = (curr.st + 1).toString()
if (n && n != "1")
vid += n
// if the voice is not in the current staff system, update it
p_v = new_voice(vid)
// if a new voice, do a full definition
if (p_v.new) {
v = p_v.v
p_v.st = p_v.cst = st
p_v.time = curr.meastim
// // if inside tune, add a new staff system
// if (voice_tb[v].time != 0 && !curr.newsy) {
// curr.newsy = true
// old_sy = par_sy
// par_sy = clone(par_sy)
// par_sy.voices = clone(par_sy.voices)
// par_sy.staves = clone(par_sy.staves)
// old_sy.next = par_sy
// }
if (!par_sy.voices[0])
par_sy.top_voice = v // first voice
if (n)
n = Number(n) - 1
else
n = 0
par_sy.voices[v] = {
st: st
// range: // set below
// sep:
// maxsep:
}
// sort the voices
if (!par_sy.rv)
par_sy.rv = []
par_sy.rv.push({
v: v,
r: st * 10 + n
})
par_sy.rv.sort(function(n1, n2) {
return n1.r - n2.r
})
for (n = 0; n < par_sy.rv.length; n++) {
v = par_sy.rv[n].v
par_sy.voices[v].range = n
}
v = p_v.v
while (--v >= 0) {
if (par_sy.voices[v].st == st) {
p_v.second =
par_sy.voices[p_v.v].second = true
break
}
}
}
if (tag.label) {
t = tag
} else if (staff.label) {
t = staff.label
staff.label = null
}
if (t) {
p_v.nm = t.label
p_v.new_name = true
if (t["label.abbr"])
p_v.snm = t["label.abbr"]
}
get_voice(vid)
if (staff["clef.shape"]) { // if clef change
s = new_clef(clefcnv(staff))
delete staff["clef.shape"] // one clef per staff
if (s) {
get_clef(s)
// put the clef before the measure bar
if (s.prev && s.prev.bar_type) {
s.next = s.prev
if (s.prev.prev)
s.prev.prev.next = s
else
s.p_v.sym = s
s.prev = s.prev.prev
s.next.prev = s
s.next.next = null
curvoice.last_sym = s.next
}
}
}
//if (0) {
// // if a new voice inside tune, add a measure bar
// if (new_v)
// sym_link({
// type: C.BAR,
// meas: curr.meas,
////fixme: the bar type depends on the previous measure
// bar_type: "|",
// dur: 0,
// multi: 0
// })
//}
}, // layer()
lb: function(tag) {
//fixme: here for chord symbol/annotation
// may be for page header/footer or ...
// curr.text += ";"
curr.text += "\n"
}, // lb()
mei: function(tag) {
if (!tag.meiversion || tag.meiversion[0] != "4")
error(0, null, "Bad MEI version " + tag.meiversion)
},
meter: function(tag) {
var m
if (tag.count) {
m = tag.count
if (tag.unit)
m += "/" + tag.unit
new_meter(m)
m = C.BLEN / (tag.unit ? Number(tag.unit) : 1)
} else switch (tag.sym) {
case "common": new_meter("C"); m = 4; break
case "cut": new_meter("C|"); m = 2; break
}
if (m)
curr.mu = C.BLEN / m
}, // meter()
mRest: function(tag) {
var s = {
type: C.REST,
istart: tag.ix,
stem: 0,
multi: 0,
nhd: 0,
xmx: 0,
dur: curvoice.wmeasure,
dur_orig: curvoice.wmeasure
}
// tag.cutout
sym_link(s)
if (curvoice.wmeasure == 1) // if no meter
curr.mrest = true
if (par_sy.staves[s.st].invis)
s.invis = true
}, // mRest()
// new measure
measure: function(tag) {
// anacrusis when n="0" type="upbeat"
curr.meas = tag.n // for errors
}, // measure()
mordent: function(tag) {
//fixme: handle note in chord
var ty,
s = get_ref(tag)
if (!s)
return
if (s.s)
s = s.s
//fixme: handle mordent in chord
switch (tag.form) {
default:
// case "upper":
ty = "uppermordent"; break
case "lower": ty = "lowermordent"; break
}
add_dcn(s, ty)
}, // mordent()
multiRest: function(tag) {
var dur = curvoice.wmeasure * tag.num,
s = {
type: C.MREST,
istart: tag.ix,
stem: 0,
multi: 0,
nhd: 0,
xmx: 0,
dur: dur,
dur_orig: dur
}
sym_link(s)
}, // multiRest()
// start of the tune
music: function(tag) {
info.X = "1"
parse.fname = "mei"
parse.state = 1 // inside tune
}, // music()
note: function(tag) {
var note, s, acc, pit, dur, v, i, vi, gr, ref, st,
oct = tag.oct,
id = tag["xml:id"]
if (!tag.pname) {
if (tag["pname.ges"]) {
tag.pname = tag["pname.ges"] //fixme
// return
} else if (tag.sameas) {
ref = tag.sameas
if (ref[0] == '#')
ref = ref.slice(1)
s = clone(curr.ids[ref]) // always defined
if (!s.type) { // if in chord
note = s
s = null
} else {
s.notes = clone(s.notes)
s.notes[0] = note = clone(s.notes[0])
note = s
}
} else {
// may be
// <note cue="true" head.shape="slash" stem.dir="up"/>
return
}
}
if (!note) {
if (!oct)
oct = curr.oct
note = {
pit: "cdefgab".indexOf(tag.pname.toLowerCase()) +
oct * 7 - 12,
shhd: 0,
shac: 0
}
}
if (curr.chord) {
s = curr.chord
dur = s.dur
//fixme: tie in chord?
// if (s.tie_s)
// note.tie_ty = C.SL_AUTO
s.notes[++s.nhd] = note
} else {
dur = durcnv(tag)
if (!s) {
s = {
type: C.NOTE,
stem: 0,
multi: 0,
nhd: 0,
xmx: 0,
dur: dur,
dur_orig: dur,
notes: [note]
}
}
s.istart = tag.ix
switch (tag["stem.dir"]) {
case "up": s.stem = 1; break
case "down": s.stem = -1; break
}
if (tag.grace) { // if in a grace note sequence
gr = curvoice.last_sym
if (gr && gr.type != C.GRACE) {
gr = { // new grace note
type: C.GRACE,
istart: tag.ix,
dur: 0,
stem: 0,
multi: 0
}
//fixme
// if (tag["stem.mod"] == "1slash")
// gr.sappo = true
sym_link(gr)
gr.extra = s
} else {
gr = gr.extra
while (gr.next) // add the note
gr = gr.next
gr.next = s
s.prev = gr
}
s.cst = s.st = curvoice.st
s.v = curvoice.v
s.p_v = curvoice
} else {
switch (curr.beam) {
case 0:
s.beam_st = true
s.beam_end = true
break
case 1:
s.beam_st = true
curr.beam = 2
break
}
sym_link(s)
}
}
if (id) {
note.s = s
do_delayed(id, curr.chord ? note : s)
}
note.dur = dur
if (acc_ty[tag.accid])
note.acc = acc_ty[tag.accid]
//fixme: may have notes of the chord on different staves
if (tag.staff)
s.st = curr.st_cnv[tag.staff - 1] // ABC staff number
//fixme:
// head.auth
// "smufl"
//fixme:
// if auth == smufl,
// head.shape is a glyph reference as "#xE000" or "U+E000"
// switch (tag["head.shape"]) {
// case "slash": // ??
// }
//fixme:
// switch (tag["head.fill"]) {
// case "void":
// case "solid":
// case "top":
// case "bottom":
// case "left":
// case "right":
// }
//fixme:
// tag["head.visible"]
if (tag.grace)
s.grace = true
switch (tag.tuplet) {
case "i1":
curr.tp.push(s)
break
// case "m1":
// ignored
case "t1":
if (curr.tp.length)
tp_set(curr.tp.pop(), {
num: 3,
numbase: 2
})
//fixme: else error
break
}
//fixme: always <tie> ?
//if (0) {
// switch (tag.tie) {
// case "t":
// case "m":
// s.tie_s = curvoice.tei_s
////fixme: KO if chord
// s.notes[0].tie_m = s.notes.length - 1
// if (tag.tie == "t")
// break
// // fall thru
// case "i":
// note.tie_ty = C.SL_AUTO
// curvoice.tei_s = s
// break
// }
//}
// used for play ?
// if (tag.slur) {
// }
if (tag.color)
s.color = tag.color
curr.s = s // last note
curr.oct = oct // last octave
// other attributes
if (tag.artic)
artic(s, tag)
//fixme:cross-staff chord
// tag.stem.with
switch (tag.breaksec) {
case "1": s.beam_br1 = true; break
case "2": s.beam_br2 = true; break
}
//fixme: tag.staff may be used in chords for cross-staff chords
// tag.staff # new staff
//fixme: not visual?
// if (tag.fermata)
// add_dcn(s, "fermata")
}, // note()
// part: function(tag) {
// }, // part()
// parts: function(tag) {
// }, // parts()
// new page for text
pb: function(tag) {
var s
//fixme: tag.n (page number)
if (parse.state == 3) {
s = new_block("newpage")
s.param = tag.n || ""
} else {
blk_flush()
block.newpage = true
}
}, // pb()
pedal: function(tag) {
var dcn,
s = get_ref(tag)
if (!s)
return
if (s.s)
s = s.s
switch (tag.dir) {
default:
// case "up":
dcn = "ped)"; break
case "down": dcn = "ped("; break
}
add_dcn(s, dcn)
}, // pedal()
rend: function(tag) {
var font, n,
f = ""
if (tag.fontfam)
f += " " + tag.fontfam
if (tag.fontname)
f += " " + tag.fontname
if (tag.fontweight)
f += " " + tag.fontweight
if (tag.fontstyle)
f += " " + tag.fontstyle
if (!f)
f = "*"
else
f = f.slice(1)
if (tag.fontsize) {
n = parseInt(tag.fontsize) * 1.33 // 72 -> 96 DPI
f += " " + n.toString()
} else {
f += " *"
}
if (f != "* *") {
n = curr.fnt[f]
if (!n) {
n = ++curr.ftn
curr.fnt[f] = n
param_set_font("setfont-" + n, f)
}
curr.text += '$' + n
curr.rend = true
}
}, // rend()
rest: function(tag) {
var id = tag["xml:id"],
dur = durcnv(tag),
s = {
type: C.REST,
istart: tag.ix,
stem: 0,
multi: 0,
nhd: 0,
xmx: 0,
dur: dur,
dur_orig: dur
}
if (tag.name == "rest") {
switch (curr.beam) {
case 0:
s.beam_st = true
s.beam_end = true
break
case 1:
s.beam_st = true
curr.beam = 2
break
}
} else { // space
s.invis = true
}
sym_link(s)
if (id)
do_delayed(id, s)
switch (tag.tuplet) {
case "i1":
curr.tp.push(s)
break
// case "m1":
// ignored
case "t1":
if (curr.tp.length)
tp_set(curr.tp.pop(), {
num: 3,
numbase: 2
})
//fixme: else error
break
}
}, // rest()
revisionDesc: function(tag) {
return true // skip
}, // revisionDesc()
// newline for music
sb: function(tag) {
curvoice.last_sym.eoln = true
}, // sb()
// score: function(tag) {
// tag.n
// tag.id
// }, // score()
// score definition (= new staff system)
// may contain a staffGrp (no staffGrp in <section>?)
// may appear in section/(ending?) or between section/ending (in score/part)
scoreDef: function(tag) {
var w, h, v, tmp
curr.scoreDef = tag
if (parse.state >= 2) {
// if (tag["clef.shape"]) {
// s = new_clef(clefcnv(tag))
// if (s) {
// get_clef(s)
////fixme: move the clef - see layer:
// }
// }
if (tag["key.sig"]) {
tmp = keycnv(tag)
for (v = 0; v < voice_tb.length; v++) {
curvoice = voice_tb[v]
get_key(tmp)
}
}
// if (tag["meter.count"]) {
// new_meter(metercnv(tag))
// curr.mu = meteru(tag)
// }
}
// // init the staff system
// if (!curr.st_cnv)
// curr.st_cnv = []
// page layout
//fixme: the value of vu.height is odd!
// recompute the height/width conversion
if (tag["page.height"] && tag["page.width"]) {
h = tag["page.height"]
w = tag["page.width"]
if (/^\d+$/.test(h + w))
curr.pt = h / w > 1.3 ?
1123.66 / h : // A4
1056 / h // US letter
}
// if (tag["page.botmar"])
// module
// if (tag["page.height"])
// module
if (tag["page.leftmar"])
self.set_format("leftmargin",
unitcnv(tag["page.leftmar"]))
if (tag["page.rightmar"])
self.set_format("rightmargin",
unitcnv(tag["page.rightmar"]))
if (tag["page.scale"])
self.set_format("pagescale", tag["page.scale"])
// if (tag["page.topmar"])
// module
if (tag["page.width"])
self.set_format("pagewidth",
unitcnv(tag["page.width"]))
// if (tag["music.name"])
// musicfont = tag["music.name"]
// if (tag["music.size"])
//fixme
}, // scoreDef()
// section: function(tag) {
// }, // section()
slur: function(tag) {
var sl,
s1 = get_ref(tag),
s2 = get_ref(tag, s1),
ty = C.SL_AUTO
if (!s1 || !s2)
return
switch (tag.curvedir) {
case "above": ty = C.SL_ABOVE; break
case "below": ty = C.SL_BELOW; break
}
switch (tag.lform) {
case "dashed":
case "dotted": ty |= C.SL_DOTTED; break
}
sl = { ty: ty }
if (s2.s) {
sl.is_note = true // to note
sl.note = s2
} else {
s2.notes[0].s = s2
sl.note = s2.notes[0] // to chord
}
if (!s1.sls)
s1.sls = []
s1.sls.push(sl)
if (s1.s) // if from note of chord
s1.s.sl1 = true
//fixme: ko if grace note
}, // slur()
sourceDesc: function(tag) {
return true // skip
},
// staff - must be inside measure and must contain layers
staff: function(tag) {
curr.st = curr.st_cnv[tag.n - 1] // ABC staff number
if (curr.st == undefined) {
error(1, null, "Unknown staff " + tag.n)
return true
}
var staff = par_sy.staves[curr.st]
switch (tag.visible) {
case "false":
staff.invis = true
break
case "true":
staff.invis = false
break
}
}, // staff()
// staff definition
// the order in the staffGrp is the (ABC) staff number
// may appear in scoreDef, measure, staffGrp
// between measures (in section/ending)
// and between section/ending (in score/part)
staffDef: function(tag) {
var k, st, def, staff, sy,
n = tag.n - 1, // MEI staff number
grp = curr.staffGrp
if (!curr.st_cnv)
curr.st_cnv = []
else
st = curr.st_cnv[n] // ABC staff number
if (st == undefined) { // if new staff
staff = {
stafflines: '|||||',
staffscale: 1,
flags: 0
}
if (grp) {
staff.flags = grp.flags
grp.flags &= STOP_BAR
}
if (parse.state == 3 && !curr.newsy) {
curr.newsy = true
sy = par_sy
par_sy = clone(sy)
sy.next = par_sy
par_sy.voices = clone(par_sy.voices)
par_sy.staves = clone(par_sy.staves)
}
st = par_sy.staves.length // ABC staff number
par_sy.staves.push(staff) // new staff
par_sy.nstaff = st
curr.st_cnv[n] = st // MEI to ABC staff conversion
} else {
staff = par_sy.staves[st]
}
// set the default values from the scoreDef
def = curr.scoreDef
if (def) {
for (k in def) {
switch (k.slice(0, 3)) {
case "cle":
case "key":
case "met":
staff[k] = def[k]
break
}
}
}
// set the values from the current element
for (k in tag) {
switch (k.slice(0, 3)) {
case "cle":
case "key":
case "met":
staff[k] = tag[k]
break
}
}
//fixme
// if (!staff["clef.shape"]) {
// error(1, null, "No clef in staff " + tag.n)
// staff["clef.shape"] = "G"
// staff["clef.line"] = "2"
// staff.lines = "5"
// }
if (tag.label) {
staff.label = tag
} else if (grp && grp.label) {
staff.label = {
label: grp.label
}
delete grp.label
}
// if (tag["music.name"])
//fixme
// if (tag["music.size"])
//fixme
if (tag.spacing) {
//fixme: no unit is 10th of mm ?
var v = tag.spacing.slice(-1)
if (v >= '0' && v <= '9')
staff.maxsep = Number(tag.spacing) / 100 * CM
else
staff.maxsep = get_unit(tag.spacing)
}
if (tag.children)
curr.st = st
}, // staffDef()
// group of staves
// may be contained in a scoreDef
staffGrp: function(tag) {
if (!tag.symbol)
return // unused?
var grp = curr.staffGrp
if (!grp) {
curr.staffGrp = grp = {
lvl: 0,
flags: 0
}
switch (tag.symbol) {
case "brace": grp.flags |= OPEN_BRACE; break
case "bracket": grp.flags |= OPEN_BRACKET; break
}
} else {
grp.lvl++
switch (tag.symbol) {
case "brace": grp.flags |= OPEN_BRACE2; break
case "bracket": grp.flags |= OPEN_BRACKET2; break
}
}
if (tag["bar.thru"] == "false")
grp.flags |= STOP_BAR
}, // staffGrp()
syl: set_text,
// start of tempo and title
tempo: function(tag) {
set_text(tag)
if (!tag.children)
fne[tag.name](tag)
}, // tempo()
text: function(tag) {
if (curr.text != undefined)
curr.text += tag.content.replace(/[ \t\n]+/g, ' ')
},
// tie
tie: function(tag) {
var s1 = get_ref(tag),
s2 = get_ref(tag, s1),
ty = C.SL_AUTO
if (!s1 || !s2)
return
switch (tag.curvedir) {
case "above": ty = C.SL_ABOVE; break
case "below": ty = C.SL_BELOW; break
}
switch (tag.lform) {
case "dashed":
case "dotted": ty |= C.SL_DOTTED; break
}
if (s1.s) {
s1.tie_ty = ty
if (s2.s) { // note - note
s1.s.tie_s = s2.s
s1.tie_n = s2
s2.s.ti2 = s1.s
} else { // note - single note
s1.s.tie_s = s2
s1.tie_n = s2.notes[0]
s2.ti2 = s1.s
}
} else {
s1.notes[0].tie_ty = ty
if (s2.s) { // single note - note
s1.tie_s = s2.s
s1.notes[0].tie_n = s2
s2.s.ti2 = s1
} else { // single note - single note
s1.tie_s = s2
s1.notes[0].tie_n = s2.notes[0]
s2.ti2 = s1
}
}
}, // tie()
trill: function(tag) {
var s2,
s = get_ref(tag)
if (!s)
return
if (tag.dur || tag["dur.ges"] || tag.endid || tag.tstamp2) {
s2 = get_ref(tag, s)
if (!s2)
return
}
if (s.s) // on note
s = s.s
switch (tag.place) {
case "above": s.pos.orn = C.SL_ABOVE; break
case "below": s.pos.orn = C.SL_BELOW; break
}
if (!s2) {
add_dcn(s, "trill")
return
}
if (s.time >= s2.time) {
error(1, null, "Bad trill endings")
return
}
add_dcn(s, "trill(")
add_dcn(s2, "trill)")
}, // trill()
// start of tuplet (one nested level only)
tuplet: function(tag) {
curr.tp.push(curvoice.last_sym || true)
}, //tuplet()
// start of tupletSpan
tupletSpan: function(tag) {
var last, next, f,
s = get_ref(tag),
s2 = get_ref(tag, s)
if (!s || !s2)
return
if (s.tp.length) {
tp_fl(s.tp[0].f, tag)
return
}
last = curvoice.last_sym
curvoice.last_sym = s2
next = s2.next
s2.next = null
tp_set(s, tag)
s2.next = next
curvoice.last_sym = last
}, // tupletSpan()
verse: function(tag) {
curr.verse = tag
}, // verse()
work: function(tag) {
curr.work = true
}, // work()
}, // fns
// --- functions associated to the end of MIE tags
fne = {
// end of beam
beam: function(tag) {
curr.s.beam_end = true
curr.beam = 0
}, // beam()
// end of chord
chord: function(tag) {
var id = tag["xml:id"]
if (id)
do_delayed(id, curr.chord)
curr.chord = null
}, // chord()
// end of composer
composer: function(tag) {
if (!curr.text)
return
if (info.C == undefined)
info.C = curr.text
else
info.C += "\n" + curr.text
curr.text = undefined
}, // composer()
// end of annotation (dir) / chord symbol (harm) / annotation (dynam)
dir: function(tag) {
var gch, ty, t, i,
font = gene.deffont,
s = get_ref(tag)
if (!s)
return
if (s.s)
s = s.s
switch (tag.name) {
case "dir":
case "dynam":
switch (tag.place) {
default:
// case "above":
ty = "^"; break
case "below": ty = "_"; break
}
break
default:
ty = "g"
switch (tag.place) {
default:
// case "above":
s.pos.gch = C.SL_ABOVE; break
case "below": s.pos.gch = C.SL_BELOW; break
}
break
}
a_gch = s.a_gch || []
t = curr.text.split('\n')
if (t[0][0] == ' ')
t[0] = t[0].slice(1)
for (i = 0; i < t.length; i++) {
gch = {
type: ty,
font: font,
text: t[i]
}
a_gch.push(gch)
}
self.gch_build(s)
curr.text = undefined
}, // dir()
// end of division
div: function(tag) {
var s
switch (tag.type) {
case undefined:
s = new_block("text")
s.text = curr.text
break
case "verse":
if (info.W == undefined)
info.W = ""
if (tag.label)
info.W += tag.label + " "
info.W += curr.text + "\n\n"
break
default:
error(1, null, "Tag <div> type "+ tag.type + "not treated")
break
}
curr.text = undefined
}, // div()
// end of dynam
dynam: function(tag) {
var t,
s = get_ref(tag)
if (!s)
return
if (s.s)
s = s.s
t = curr.text.replace(/[ \t\n]+/g, ' ')
if (t[0] == ' ')
t = t.slice(1)
switch (tag.place) {
case "above": s.pos.dyn = C.SL_ABOVE; break
case "below": s.pos.dyn = C.SL_BELOW; break
}
add_dcn(s, t, tag)
curr.text = undefined
}, //dynam()
// end of variant ending
ending: function(tag) {
var v = voice_tb.length
while (--v >= 0) {
if (voice_tb[v].last_sym)
voice_tb[v].last_sym.rbstop = 2
}
}, // ending()
fing: function(tag) {
var s = get_ref(tag)
if (!s)
return
if (s.s)
s = s.s
switch (tag.place) {
case "above": s.pos.orn = C.SL_ABOVE; break
case "below": s.pos.orn = C.SL_BELOW; break
}
add_dcn(s, curr.text)
curr.text = undefined
}, // fing()
// // end of incipit
// incip: function(tag) {
// tosvg(fn, "\n") // generate
// curr.st_cnv = null
// curr.meastim = 0
// curr.mu = C.BLEN / 4
// }, // incip()
// end of label (voice name)
label: function(tag) {
if (!curr.text)
return
var grp = curr.staffGrp,
st = curr.st // ABC staff number
if (st == undefined) {
if (grp) {
grp.label = curr.text
curr.text = undefined
}
return
}
var staff = par_sy.staves[st]
if (!staff.label)
staff.label = {}
staff.label.label = curr.text
curr.text = undefined
}, // label()
labelAbbr: function(tag) {
if (!curr.text)
return
var st = curr.st, // ABC staff number
staff = par_sy.staves[st]
if (!staff.label)
staff.label = {}
staff.label["label.abbr"] = curr.text
curr.text = undefined
}, // labelAbbr()
// end of measure
measure: function(tag) {
var v, s, s2, s3, p_v, tim, ty, dotted,
n = voice_tb.length
if (curr.tp.length) {
error(1, null, "No end of tuplet")
curr.tp = []
}
// change the bars at start of the measure (or start of tune)
if (tag.left) {
ty = bar_ty[tag.left]
if (ty && ty[0] == '.') {
ty = ty.slice(1)
dotted = true
}
}
if (ty || curr.ending) {
for (v = 0; v < n; v++) {
p_v = voice_tb[v]
s2 = s = p_v.last_sym
if (s)
s = s.prev
while (s && !s.bar_type)
s = s.prev
if (!s) { // start of tune: add a measure bar
s3 = p_v.sym
p_v.last_sym = p_v.sym = null
curvoice = p_v
sym_link({
type: C.BAR,
istart: tag.ix,
bar_type: ty || "|",
dur: 0,
multi: 0
})
s = p_v.last_sym
p_v.last_sym = s2
s.next = s3
if (s3)
s3.prev = s
s.time = curr.meastim
} else if (ty) {
s.bar_type = ty
}
if (dotted)
s.bar_dotted = true
if (curr.ending) {
s.rbstop = 2
s.rbstart = 2
s.text = curr.ending
}
}
dotted = false
ty = null
delete curr.ending
}
// add the ending bar
if (tag.right)
ty = bar_ty[tag.right]
if (!ty)
ty = "|"
// if a new staff system, add it at start of the measure
// // (before the - previous - measure bar)
// (just after the - previous - measure bar)
if (curr.newsy) {
curr.newsy = false
for (s = voice_tb[par_sy.top_voice].last_sym;
s;
s = s.prev) {
if (s.type == C.BAR)
break
}
if (s) { // ?
s2 = clone(s)
s2.type = C.STAVES
s2.bar_type = 0
s2.sy = par_sy
// s2.prev = s.prev
// s2.prev.next = s2
// s2.next = s
// s.prev = s2
s2.next = s.next
if (s.next)
s2.next.prev = s2
s.next = s2
s2.prev = s
}
}
// synchronize the voices
// adjust the duration of the full measure rests
// add the measure bars
tim = 0
for (v = 0; v < n; v++) {
p_v = voice_tb[v]
if (p_v.time > tim)
tim = p_v.time
}
if (curr.mrest) { // if some full measure rests
curr.mrest = false
for (v = 0; v < n; v++) {
p_v = voice_tb[v]
s = p_v.last_sym // there may be only rest and bar
if (s && s.type == C.BAR)
s = s.prev
if (!s || s.type != C.REST || s.time != curr.meastim)
continue
s.dur = s.dur_orig = tim - curr.meastim
//fixme: should set a flag saying 'full measure rest'
if (s.next)
s.next.time = tim // bar time
}
}
if (ty[0] == '.') {
ty = ty.slice(1)
dotted = true
}
for (v = 0; v < n; v++) {
p_v = voice_tb[v]
p_v.time = tim
s = p_v.last_sym
if (s && s.time == tim && s.bar_type)
continue
// get_voice(p_v.id)
curvoice = p_v
s = {
type: C.BAR,
istart: tag.ix,
bar_type: ty,
dur: 0,
multi: 0
}
if (dotted)
s.bar_dotted = true
if (v == par_sy.top_voice)
s.bar_num = Number(tag.n) + 1
sym_link(s)
}
curr.meastim = tim
}, // measure()
// end of the tune
music: function(tag) {
sanitize()
//fixme: copy of end_tune()
generate()
if (info.W)
put_words(info.W)
put_history()
blk_flush()
}, // music()
// // end of page footer
// pgFoot: function(tag) {
// <p>
// }, // pgFoot()
// // end of page header
// pgHead: function(tag) {
// <title>
// <persName role>
// }, // pgHead()
// end of rendition
rend: function(tag) {
if (curr.rend) {
curr.rend = false
curr.text += "$0"
}
}, // rend()
// end of score definition
scoreDef: function(tag) {
curr.scoreDef = null
}, //scoreDef()
// end of staff definition
staffDef: function(tag) {
delete curr.st
}, //staffDef()
// end of staff group
staffGrp: function(tag) {
var grp = curr.staffGrp,
st = par_sy.staves.length - 1, // last staff
staff = par_sy.staves[st]
if (!grp)
return
if (--grp.lvl < 0) {
curr.staffGrp = null
switch (tag.symbol) {
case "brace": staff.flags |= CLOSE_BRACE; break
case "bracket": staff.flags |= CLOSE_BRACKET; break
}
return
}
switch (tag.symbol) {
case "brace": staff.flags |= CLOSE_BRACE2; break
case "bracket": staff.flags |= CLOSE_BRACKET2; break
}
}, // staffGrp()
// end of syllabe
syl: function(tag) {
var t = curr.text.replace(/[ \t\n]+/g, ' ')
curr.text = undefined
if (t[0] == ' ')
t = t.slice(1)
var l, wh, c,
s = curr.s // note
curvoice.have_ly = true
wh = strwh(t)
if (curr.verse && curr.verse.n)
l = curr.verse.n - 1 // verse number (0...n-1)
else
l = 0 // ('n' omitted)
if (t.slice(-1) == '-')
t = t.slice(0, -1) + '\n'
switch (tag.con) { // connector
case "s":
t += ' '
break
case "d":
t += '-'
break
case "u":
t += '_'
break
// case "t":
// c = '~'
// break
// case "c":
// break
// case "v":
// break
// case "i":
// break
// case "b":
// break
}
switch (tag.wordpos) {
case "i": // initial
case "m": // middle
if (t.slice(-2) != "\n") {
if (c == '_')
t += c
t += "\n"
}
break
// case "t":
// break
}
if (!s.a_ly)
s.a_ly = []
s.a_ly[l] = {
t: t,
font: gene.curfont,
wh: wh
}
}, // syl()
// end of tempo
tempo: function(tag) {
var t = curr.text.replace(/[ \t\n]+/g, ' ')
curr.text = undefined
// if (t[0] == ' ')
// t = t.slice(1)
// if (!t || t == "undefined")
// return
var s,
s2 = {
type: C.TEMPO,
dur: 0
}
if (t)
s2.tempo_str1 = t
if (tag.mm) {
s2.tempo_notes = [curr.mu]
s2.tempo = tag.mm
}
if (parse.state <= 1) {
info.Q = '"' + t + '"'
glovar.tempo = s2
return
}
// insert the tempo before the reference
s = get_ref(tag)
if (!s)
return
s2.prev = s.prev
s.prev = s2
s2.next = s
if (s2.prev)
s2.prev.next = s2
else
s.p_v.sym = s2
s2.v = s.v
s2.p_v = s.p_v
s2.st = s.st
s2.time = s.time
}, // tempo()
// end of title
title: function(tag) {
var t = curr.text.replace(/[ \t]+/g, ' ')
curr.text = undefined
if (t[0] == ' ')
t = t.slice(1)
if (parse.state != 3) {
if (info.T == undefined)
info.T = t
else
info.T += "\n" + t
} else {
var s = new_block("title")
s.text = t
}
}, // title()
// end of tuplet
tuplet: function(tag) {
var s = curr.tp.pop() // symbol before the start of the tuplet
// or 'true' if the tune starts with a tuplet
if (s && (tag.dur || tag.num))
tp_set(s == true ? curvoice.sym : s.next, tag)
}, // tuplet()
// end of work
work: function(tag) {
curr.work = false
}, // work()
} // fne
// common code
fns.lg = fns.l // start of line group
fns.labelAbbr = fns.label // start of labelAbbr
fns.space = fns.rest // space
fns.title = fns.tempo
fne.harm = fne.dir // end of chord symbol (harmony)
// add a decoration into a symbol
function add_dcn(s, dcn, tag) {
var dd = dd_tb[dcn]
// build a dynamic decoration
function build_dyn(t) {
var i,
str = "",
dd = {
name: t,
func: 6,
glyph: t,
h: 18,
wl: t.length * .3,
wr: t.length * .7
}
for (i = 0; i < t.length; i++) {
switch (t[i]) {
case 'f': str += "\ue522"; break
case 'p': str += "\ue520"; break
case 'r': str += "\ue523"; break
case 's': str += "\ue524"; break
}
}
tgls[t] = {
x: -4,
y: -6,
c: str
}
return dd
} // build_dyn()
if (!dd) {
if (decos[dcn]) { // if known decoration
dd = deco_def(dcn)
} else {
if (!tag)
//fixme: error
return
if (tag.name != "dynam"
|| /[^fprs]/.test(dcn)) {
fne.dir(tag) // display as annotation
return
}
dd_tb[dcn] = dd = build_dyn(dcn)
}
}
if (!s.a_dd)
s.a_dd = []
// switch (tag.place) {
// default:
//// case "above":
// case "below":
//fixme: how to force the place of the decoration?
// }
s.a_dd.push(dd)
} // add_dcn()
// articulation (inside a chord/note)
function artic(s, tag) {
var dcn, i,
d_tb = {
acc: "accent",
dnbow: "downbow",
marc: "marcato",
open: "open",
snap: "snap",
spic: "wedge",
stacc: "dot",
ten: "tenuto",
upbow: "upbow",
},
d = tag.artic.split(/\s+/)
switch (tag.place) {
case "above": s.pos.orn = C.SL_ABOVE; break
case "below": s.pos.orn = C.SL_BELOW; break
}
for (i = 0; i < d.length; i++) {
dcn = d_tb[d[i]]
if (dcn)
add_dcn(s, dcn)
else
error(1, null, "Articulation " + d[i] + " not handled")
}
} // artic()
// define a new element reference and
// resolve its definition in the associated elements
function do_delayed(id, s) {
var i, n, tag,
delayed_a = curr.delayed[id]
curr.ids[id] = s
if (!delayed_a)
return // no element is waiting for this element
curr.delayed[id] = null
n = delayed_a.length
for (i = 0; i < n; i++) {
tag = delayed_a[i]
fns[tag.name](tag)
}
}
// convert a clef
function clefcnv(tag) {
var clef = {"G": "G",
"GG": "G",
"F": "F",
"C": "C",
"perc": "P",
"TAB": "tab"}[tag["clef.shape"]]
if (tag["clef.line"])
clef += tag["clef.line"]
if (tag["clef.dis"]) {
if (tag["clef.dis.place"] == "above")
clef += '+' + tag["clef.dis"]
else
clef += '-' + tag["clef.dis"]
}
return clef
} // clefcnv()
// convert a (CMN) duration
function durcnv(tag) {
var dur
switch (tag.dur) {
case "breve": dur = C.BLEN * 2; break
case "long": dur = C.BLEN * 4; break
//fixme: beat?
case undefined: dur = C.BLEN / 4; break
default: dur = C.BLEN / tag.dur
}
switch (tag.dots) {
case "1": dur *= 3/2; break
case "2": dur *= 7/4; break
case "3": dur *= 15/8; break
}
if (isNaN(dur))
error(1, null, "Bad duration " + tag.dur + " tag:" + tag.name)
return dur
} // durcnv()
// change the source reference in error messages
var err_old
function error_new(sev, s, msg, a1, a2, a3, a4) {
if (!s)
s = {}
if (!s.fname)
s.fname = "(no ref)"
if (!s.istart)
s.istart = parse.istart
err_old(sev, s, msg, a1, a2, a3, a4)
}
err_old = error
error = error_new
// get the symbol (chord, note or rest) pointed to
// by startid/endid or tstamp/tstamp2
// @end is the pointer to the start symbol
function get_ref(tag, end) {
var s, st, v_rg, v, voice, tim,
rg = 100,
ref = tag[end ? "endid" : "startid"]
if (ref) {
if (ref[0] == '#')
ref = ref.slice(1)
s = curr.ids[ref] // symbol or note
if (!s) { // the symbol is not defined yet
if (!curr.delayed[ref])
curr.delayed[ref] = []
curr.delayed[ref].push(tag)
return // null
}
} else { // try a time stamp
ref = end ? tag.tstamp2 : tag.tstamp
if (!ref) {
error(1, null, "No "+ (end ? "end" : "start") +
" reference tag:" + tag.name)
return //
}
if (ref[1] == 'm') {
if (ref[0] == '0' && ref[2] == '+')
ref = ref.slice(3)
else
//fixme: tstamp2 may have more values
return
}
// convert the beat into internal time
tim = curr.meastim + curr.mu * (ref - 1)
// search the voice
st = curr.st_cnv[tag.staff ? (tag.staff - 1) : 0]
//fixme: may be simplified using the voice ID (main voice of the staff is V:<#staff>
for (v = 0; v < par_sy.voices.length; v++) {
voice = par_sy.voices[v]
if (!voice || voice.st != st)
continue
if (voice.range < rg) {
v_rg = v
rg = voice.range
}
}
if (rg >= 100) {
error(1, null, "No voice in staff " + st +
" tag:" + tag.name)
return
}
// and the symbol
for (s = voice_tb[v_rg].last_sym; s; s = s.prev) {
if (s.time <= tim) {
if (ref != 0)
break
while (s && s.type != C.BAR)
s = s.prev
break
}
}
}
if (!s) {
error(1, null, "No symbol at beat " + ref +
" in staff " + tag.staff + " tag:" + tag.name)
return
}
if (!end)
return s
if (s == end) {
error(1, s, "References on a same element")
if (!s.next)
return
s = s.next
}
if (s.time <= end.time) {
error(0, s, "References going back in time")
return
}
return s
} // get_ref()
// convert a key
function keycnv(tag) {
var sig2kM = {
"0" : "C",
"1s": "G",
"2s": "D",
"3s": "A",
"4s": "E",
"5s": "B",
"6s": "F#",
"7s": "C#",
"1f": "F",
"2f": "Bb",
"3f": "Eb",
"4f": "Ab",
"5f": "Db",
"6f": "Gb",
"7f": "Cb"
},
sig2km = {
"0" : "Am",
"1s": "Em",
"2s": "Bm",
"3s": "F#m",
"4s": "C#m",
"5s": "G#m",
"6s": "D#m",
"7s": "A#m",
"1f": "Dm",
"2f": "Gm",
"3f": "Cm",
"4f": "Fm",
"5f": "Bbm",
"6f": "Ebm",
"7f": "Abm"
}
return tag["key.mode"] != "minor" ?
sig2kM[tag["key.sig"]] :
sig2km[tag["key.sig"]]
} // keycnv()
// convert a meter
function metercnv(tag) {
switch (tag["meter.sym"]) {
case "common": return "C"
case "cut": return "C|"
}
if (tag["meter.unit"])
return tag["meter.count"] + "/" + tag["meter.unit"]
return tag["meter.count"]
} // metercnv()
// get the unit of a meter
function meteru(tag) {
var mu = 1
switch (tag["meter.sym"]) {
case "common": mu = 4; break
case "cut": mu = 2; break
}
if (tag["meter.unit"])
mu = Number(tag["meter.unit"])
return C.BLEN / mu
} // meteru()
function set_text(tag) {
var f
switch (tag.name) {
case "dir": f = "annotation"; break
case "dynam": f = "dynam"; break
// case "fing": f = null; break
case "harm": f = "gchord"; break
case "syl": f = "vocal"; break
// case "tempo": f = null; break
case "title": f = "title"; break
}
if (f)
set_font(f)
curr.text = ""
}
// set tuplet flags
function tp_fl(f, tag) {
if (tag["num.visible"] == "false") {
f[0] = 1 // when = never
} else {
if (tag["bracket.visible"] == "false")
f[1] = 2 // what = nothing
if (tag["num.format"] == "ratio")
f[2] = 2 // which = ratio
}
switch (tag["bracket.place"]) {
case "above": f[3] = 1; break // where = above
case "below": f[3] = 2; break // where = below
}
} // tp_fl()
// handle the end of one tuplet
function tp_set(s, tag) {
var fact, s2, s3, n,
nbas = tag.numbase || 2, // numbas default = 2 ?
f = Object.create(cfmt.tuplets)
while (s.grace)
s = s.next
if (!s.tp)
s.tp = []
s.tp.push({
p: tag.num,
q: nbas,
f: f
})
tp_fl(f, tag)
// adjust the duration of the symbols
if (tag.dur)
fact = durcnv(tag) / (curvoice.time - s1.time)
else
fact = nbas / tag.num
tp_adj(s, fact)
s2 = curvoice.last_sym
if (!s2.dur) { // if some odd element at end of the tuplet
for (s3 = s2; !s3.dur; s3 = s3.prev)
;
s3.tpe = s2.tpe // move the end of tuplet
delete s2.tpe
}
n = 0
for (s3 = s; s3; s3 = s3.next) {
if (s3.dur)
n++
}
s.tp[s.tp.length - 1].ro = n // (needed for toabc)
} // tp_set()
//fixme: no unit is 10th of mm ?
function unitcnv(v) {
var nv = v.slice(-1)
if (nv >= '0' && nv <= '9')
return (v * curr.pt).toString()
return v
}
// check for bugs in the source
function sanitize() {
var i, v,
used_st = []
// check for used staves
for (v = 0; v < voice_tb.length; v++) {
i = voice_tb[v].st
if (i)
used_st[i] = true
}
for (i = par_sy.nstaff; i > 0; i--) {
if (used_st[i])
break
}
if (i != par_sy.nstaff)
error(1, null, "Unused staves "+(i+1)+".."+par_sy.nstaff)
par_sy.nstaff = i
} // sanitize()
// convert to music
function parse_mei(tag) {
if (fns[tag.name]) {
parse.istart = tag.ix
if (fns[tag.name](tag))
return // skip when error
}
if (!tag.children)
return
var i,
n = tag.children.length
for (i = 0; i < n; i++)
parse_mei(tag.children[i])
if (fne[tag.name])
fne[tag.name](tag)
} // parse_mei()
// main code of mei2mus()
parse.file = mei
cfmt.graceslurs = false
glovar.ulen = C.BLEN / 4
param_set_font("dynamfont", "serifItalicBold 16")
parse_mei(xml2tree(mei)) // convert to internal music representation
} // mei2mus()
|
Changes to core/modules.js.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 | // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>. | > > | > > | 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 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// empty function
if (!abc2svg.loadjs) {
abc2svg.loadjs = function(fn, onsuccess, onerror) {
if (onerror)
onerror()
}
}
abc2svg.modules = {
ambitus: { fn: 'ambitus-1.js' },
beginps: { fn: 'psvg-1.js' },
break: { fn: 'break-1.js' },
capo: { fn: 'capo-1.js' },
clip: { fn: 'clip-1.js' },
clairnote: { fn: 'clair-1.js' },
voicecombine: { fn: 'combine-1.js' },
diagram: { fn: 'diag-1.js' },
equalbars: { fn: 'equalbars-1.js' },
grid: { fn: 'grid-1.js' },
grid2: { fn: 'grid2-1.js' },
MIDI: { fn: 'MIDI-1.js' },
pageheight: { fn: 'page-1.js' },
|
| ︙ | ︙ |
Changes to core/music.js.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 | tsnext, // next line when cut realwidth, // real staff width while generating insert_meter, // insert time signature (1) and indent 1st line (2) spf_last, // spacing for last short line /* width of notes indexed by log2(note_length) */ space_tb = new Float32Array([ | | > | > > | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | tsnext, // next line when cut realwidth, // real staff width while generating insert_meter, // insert time signature (1) and indent 1st line (2) spf_last, // spacing for last short line /* width of notes indexed by log2(note_length) */ space_tb = new Float32Array([ // factor 1.3 instead of 1.414 and crotchet 30px instead of 40px // change again: // factor 1.33 instead of 1.3 and crotchet 35px instead of 30px 8.4, 11.2, 14.9, 19.8, 26.3, 35, 46.6, 61.9, 82.3, 109.5 ]), smallest_duration /* -- decide whether to shift heads to other side of stem on chords -- */ /* this routine is called only once per tune */ // distance for no overlap - index: [prev acc][cur acc] |
| ︙ | ︙ | |||
66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
var w_note = new Float32Array([
3.5, // FULL
3.7, // EMPTY
5, // OVAL
6, // OVALBARS
7 // SQUARE
])
function set_head_shift(s) {
var i, i1, i2, d, ps, dx,
dx_head = dx_tb[s.head],
dir = s.stem,
n = s.nhd
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
var w_note = new Float32Array([
3.5, // FULL
3.7, // EMPTY
5, // OVAL
6, // OVALBARS
7 // SQUARE
])
// get head type, dots, flags of note/rest for a duration
function identify_note(s, dur_o) {
var head, flags,
dots = 0,
dur = dur_o
if (dur % 12 != 0)
error(1, s, "Invalid note duration $1", dur);
dur /= 12 /* see C.BLEN for values */
if (!dur)
error(1, s, "Note too short")
for (flags = 5; dur != 0; dur >>= 1, flags--) {
if (dur & 1)
break
}
dur >>= 1
if ((dur + 1) & dur)
error(0, s, "Non standard note duration $1", dur_o)
while (dur >> dots > 0)
dots++
flags -= dots
if (flags >= 0) {
head = C.FULL
} else switch (flags) {
default:
error(1, s, "Note too long");
flags = -4
/* fall thru */
case -4:
head = C.SQUARE
break
case -3:
head = cfmt.squarebreve ? C.SQUARE : C.OVALBARS
break
case -2:
head = C.OVAL
break
case -1:
head = C.EMPTY
break
}
return [head, dots, flags]
}
function set_head_shift(s) {
var i, i1, i2, d, ps, dx,
dx_head = dx_tb[s.head],
dir = s.stem,
n = s.nhd
if (!n)
return // single note
/* set the head shifts */
dx = dx_head * .78
if (s.grace)
dx *= .5
if (dir >= 0) {
|
| ︙ | ︙ | |||
95 96 97 98 99 100 101 |
ps = s.notes[n].pit
}
var shift = false,
dx_max = 0
for (i = i1; i != i2; i += dir) {
d = s.notes[i].pit - ps;
ps = s.notes[i].pit
| | | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
ps = s.notes[n].pit
}
var shift = false,
dx_max = 0
for (i = i1; i != i2; i += dir) {
d = s.notes[i].pit - ps;
ps = s.notes[i].pit
if (!d) {
if (shift) { /* unison on shifted note */
var new_dx = s.notes[i].shhd =
s.notes[i - dir].shhd + dx
if (dx_max < new_dx)
dx_max = new_dx
continue
}
|
| ︙ | ︙ | |||
130 131 132 133 134 135 136 |
}
}
s.xmx = dx_max /* shift the dots */
}
// set the accidental shifts for a set of chords
function acc_shift(notes, dx_head) {
| | | | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
}
}
s.xmx = dx_max /* shift the dots */
}
// set the accidental shifts for a set of chords
function acc_shift(notes, dx_head) {
var i, i1, i2, dx, dx1, dx2, ps, p1, acc,
n = notes.length
// set the shifts from the head shifts
for (i = n - 1; --i >= 0; ) { // (no shift on top)
dx = notes[i].shhd
if (!dx || dx > 0)
continue
dx = dx_head - dx;
|
| ︙ | ︙ | |||
153 154 155 156 157 158 159 | if (p1 > ps + 3) continue if (notes[i1].shac < dx) notes[i1].shac = dx } } | | | > > | | > > > | > > > > > > > > > > | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
if (p1 > ps + 3)
continue
if (notes[i1].shac < dx)
notes[i1].shac = dx
}
}
// set the shifts of the highest and lowest notes
for (i1 = n; --i1 >= 0; ) {
if (notes[i1].acc) {
p1 = notes[i1].pit // top note with accidental
dx1 = notes[i1].shac
if (!dx1) {
dx1 = notes[i1].shhd
if (dx1 < 0)
dx1 = dx_head - dx1
else
dx1 = dx_head
}
break
}
}
if (i1 < 0) // no accidental
return
for (i2 = 0; i2 < i1; i2++) {
if (notes[i2].acc) {
ps = notes[i2].pit // bottom note with accidental
dx2 = notes[i2].shac
if (!dx2) {
dx2 = notes[i2].shhd
if (dx2 < 0)
dx2 = dx_head - dx2
else
dx2 = dx_head
}
break
}
}
if (i1 == i2) { // only one accidental
notes[i1].shac = dx1
return
}
if (p1 > ps + 4) { // if interval greater than a sixth
if (dx1 > dx2)
dx2 = dx1 // align the accidentals
notes[i1].shac = notes[i2].shac = dx2
} else {
notes[i1].shac = dx1
notes[i2].shac = dx2 = dx1 + 7
}
dx2 += 7
// shift the remaining accidentals
for (i = i1; --i > i2; ) { // from top to bottom
acc = notes[i].acc
if (!acc)
continue
dx = notes[i].shac
if (dx < dx2)
dx = dx2
ps = notes[i].pit
for (i1 = n; --i1 > i; ) {
if (!notes[i1].acc)
continue
p1 = notes[i1].pit
if (p1 >= ps + 4) { // pitch far enough
if (p1 > ps + 4 // if more than a fifth
|
| ︙ | ︙ | |||
190 191 192 193 194 195 196 |
notes[i].shac = dx
}
}
/* set the horizontal shift of accidentals */
/* this routine is called only once per tune */
function set_acc_shft() {
| | | 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
notes[i].shac = dx
}
}
/* set the horizontal shift of accidentals */
/* this routine is called only once per tune */
function set_acc_shft() {
var s, s2, st, i, acc, st, t, dx_head, notes
// search the notes with accidentals at the same time
s = tsfirst
while (s) {
if (s.type != C.NOTE
|| s.invis) {
s = s.ts_next
|
| ︙ | ︙ | |||
223 224 225 226 227 228 229 |
}
if (!acc) {
s = s2
continue
}
dx_head = dx_tb[s.head]
| < < < < | < | | | | 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
}
if (!acc) {
s = s2
continue
}
dx_head = dx_tb[s.head]
// build a pseudo chord and shift the accidentals
notes = []
for ( ; s != s2; s = s.ts_next)
Array.prototype.push.apply(notes, s.notes)
notes.sort(abc2svg.pitcmp)
acc_shift(notes, dx_head)
}
}
// link a symbol before an other one
function lkvsym(s, next) { // voice linkage
s.next = next;
s.prev = next.prev
|
| ︙ | ︙ | |||
482 483 484 485 486 487 488 | } // Compute the smallest spacing between symbols according to chord symbols // so that they stay at the same offset. // Constraints: // - assume the chord symbols are only in the first staff // - treat only the first chord symbol of each symbol | | | > | | | | | | | | > > > > > | 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 |
}
// Compute the smallest spacing between symbols according to chord symbols
// so that they stay at the same offset.
// Constraints:
// - assume the chord symbols are only in the first staff
// - treat only the first chord symbol of each symbol
// - the chord symbols under the staff are ignored
function set_w_chs(s) {
var i, ch, w0, s0, dw,
x = 0,
n = 0
for ( ; s; s = s.ts_next) {
if (s.shrink) {
x += s.shrink;
n++
}
if (!s.a_gch)
continue
for (i = 0; i < s.a_gch.length; i++) {
ch = s.a_gch[i]
if (ch.type != 'g' || ch.y < 0) // upper chord symbol only
continue
if (w0) {
if (w0 > x + ch.x) {
dw = (w0 - x - ch.x) / n
while (1) {
s0 = s0.ts_next
if (s0.shrink)
s0.shrink += dw
if (s0 == s)
break
}
}
}
s0 = s;
w0 = ch.wh[0];
n = 0;
// x = ch.font.box ? -2 : 0
x = 0
break
}
}
}
// compute the width needed by the left and right annotations
function gchord_width(s, wlnote, wlw) {
var gch, w, ix,
arspc = 0
for (ix = 0; ix < s.a_gch.length; ix++) {
gch = s.a_gch[ix]
switch (gch.type) {
case '<': /* left */
w = gch.wh[0] + wlnote
if (w > wlw)
wlw = w
break
case '>': /* right */
w = gch.wh[0] + s.wr
if (w > arspc)
arspc = w
break
}
}
if (s.wr < arspc)
s.wr = arspc
return wlw
}
/* -- set the width of a symbol -- */
/* This routine sets the minimal left and right widths wl,wr
* so that successive symbols are still separated when
* no extra glue is put between them */
// (possible hook)
Abc.prototype.set_width = function(s) {
var s2, i, m, xx, w, wlnote, wlw, acc,
bar_type, meter, last_acc, n1, n2, esp, tmp
if (s.play) { // if play symbol
s.wl = s.wr = 0
return
}
switch (s.type) {
case C.NOTE:
case C.REST:
/* set the note widths */
s.wr = wlnote = hw_tb[s.head]
|
| ︙ | ︙ | |||
601 602 603 604 605 606 607 | case C.BAR: case C.CLEF: case C.KEY: case C.METER: wlnote -= 3 break } | < < < < < | | | 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 |
case C.BAR:
case C.CLEF:
case C.KEY:
case C.METER:
wlnote -= 3
break
}
}
/* room for the decorations */
if (s.a_dd)
wlnote += deco_width(s)
/* space for flag if stem goes up on standalone note */
if (s.beam_st && s.beam_end
&& s.stem > 0 && s.nflags > 0) {
if (s.wr < s.xmx + 9)
s.wr = s.xmx + 9
}
/* leave room for dots and set their offset */
if (s.dots) {
if (s.wl == undefined) // don't recompute if new music line
switch (s.head) {
case C.SQUARE:
case C.OVALBARS:
s.xmx += 3
break
case C.OVAL:
s.xmx += 1
break
}
if (s.wr < s.xmx + 8)
s.wr = s.xmx + 8
if (s.dots >= 2)
s.wr += 3.5 * (s.dots - 1)
|
| ︙ | ︙ | |||
660 661 662 663 664 665 666 |
if ((s.y > 27 && s2.y > 27)
|| (s.y < -3 && s2.y < -3)) {
if (wlw < 6)
wlw = 6
}
/* have ties wide enough */
| | | 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 |
if ((s.y > 27 && s2.y > 27)
|| (s.y < -3 && s2.y < -3)) {
if (wlw < 6)
wlw = 6
}
/* have ties wide enough */
if (s2.tie) {
if (wlw < 14)
wlw = 14
}
break
case C.CLEF: /* extra space at start of line */
if (s2.second
|| s2.clef_small)
|
| ︙ | ︙ | |||
703 704 705 706 707 708 709 | if (s.a_gch) xx = gchord_width(s, xx, xx) if (s.a_dd) xx += deco_width(s); s.wl = xx return case C.BAR: | < < | 788 789 790 791 792 793 794 795 796 797 798 799 800 801 |
if (s.a_gch)
xx = gchord_width(s, xx, xx)
if (s.a_dd)
xx += deco_width(s);
s.wl = xx
return
case C.BAR:
bar_type = s.bar_type
switch (bar_type) {
case "|":
w = 5 // 3 + 2
break
default:
w = 2 + 2.8 * bar_type.length
|
| ︙ | ︙ | |||
762 763 764 765 766 767 768 769 770 771 772 773 774 775 |
s.wl = s.wr = 1 // (!! not 0 !!)
return
}
s.wl = s.clef_small ? 9 : 12
s.wr = s.clef_small ? 7 : 12
return
case C.KEY:
s.wl = 3;
esp = 4
if (!s.k_a_acc) {
n1 = s.k_sf /* new key sig */
if (s.k_old_sf && (cfmt.cancelkey || n1 == 0))
n2 = s.k_old_sf /* old key */
else
| > > > > > > | 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 |
s.wl = s.wr = 1 // (!! not 0 !!)
return
}
s.wl = s.clef_small ? 9 : 12
s.wr = s.clef_small ? 7 : 12
return
case C.KEY:
if ((!s.k_a_acc && !s.k_sf && !s.k_old_sf) // if no accidental
|| s.k_none // or no key
|| s.k_play) { // or key for play
s.wl = s.wr = 0 // no width
return
}
s.wl = 3;
esp = 4
if (!s.k_a_acc) {
n1 = s.k_sf /* new key sig */
if (s.k_old_sf && (cfmt.cancelkey || n1 == 0))
n2 = s.k_old_sf /* old key */
else
|
| ︙ | ︙ | |||
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 |
s.wr = wlw + 6
return
case C.MREST:
s.wl = 6;
s.wr = 66
return
case C.GRACE:
s.wl = set_graceoffs(s);
s.wr = 0
if (s.a_ly)
ly_width(s, wlw)
return
case C.STBRK:
s.wl = s.xmx
if (s.next && s.next.type == C.CLEF) {
s.wr = 2
delete s.next.clef_small /* big clef */
} else {
s.wr = 8
}
return
case C.CUSTOS:
s.wl = s.wr = 4
return
| > > | < < < < < | < < < < < < < | 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 |
s.wr = wlw + 6
return
case C.MREST:
s.wl = 6;
s.wr = 66
return
case C.GRACE:
if (s.invis)
break
s.wl = set_graceoffs(s);
s.wr = 0
if (s.a_ly)
ly_width(s, wlw)
return
case C.STBRK:
s.wl = s.xmx
if (s.next && s.next.type == C.CLEF) {
s.wr = 2
delete s.next.clef_small /* big clef */
} else {
s.wr = 8
}
return
case C.CUSTOS:
s.wl = s.wr = 4
return
case C.TEMPO: // no width, but build the tempo string
tempo_build(s)
break
case C.BLOCK: // no width
case C.PART:
case C.REMARK:
case C.STAVES:
break
default:
|
| ︙ | ︙ | |||
929 930 931 932 933 934 935 | else if (len >= C.BLEN / 64) i = 1 else i = 0 } l = len - ((C.BLEN / 16 / 8) << i) space = space_tb[i] | | | > | > > | > > > > | | | | 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 |
else if (len >= C.BLEN / 64)
i = 1
else
i = 0
}
l = len - ((C.BLEN / 16 / 8) << i)
space = space_tb[i]
if (l) {
if (l < 0) {
space = space_tb[0] * len / (C.BLEN / 16 / 8)
} else {
if (i >= 9)
i = 8
space += (space_tb[i + 1] - space_tb[i]) *
l / ((C.BLEN / 16 / 8) << i)
}
}
return space
}
// set the natural space
function set_space(s) {
var space, prev_time, len,
s2 = s.ts_prev
if (s.play)
return 0
while (s2.play) // if play symbol
s2 = s2.ts_prev
prev_time = s2.time
len = s.time - prev_time // time skip
if (!len) {
switch (s.type) {
case C.MREST:
return s.wl
///*fixme:do same thing at start of line*/
// case C.NOTE:
// case C.REST:
// if (s.ts_prev.type == C.BAR) {
|
| ︙ | ︙ | |||
991 992 993 994 995 996 997 | return space continue } break } /* reduce spacing within a beam */ | > > > | | > > > > > > > | 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 |
return space
continue
}
break
}
/* reduce spacing within a beam */
if (s.dur && len <= C.BLEN / 4) {
s2 = s
while (s2) {
if (!s2.beam_st) {
space *= .9 // ex fnnp
break
}
s2 = s2.ts_next
if (!s2 || s2.seqst)
break
}
}
/* decrease spacing when stem down followed by stem up */
/*fixme:to be done later, after x computed in sym_glue*/
if (s.type == C.NOTE && s.nflags >= -1
&& s.stem > 0) {
var stemdir = true
|
| ︙ | ︙ | |||
1032 1033 1034 1035 1036 1037 1038 |
// set a fixed spacing inside tuplets
function set_sp_tup(s, s_et) {
var s2,
tim = s.time,
endtime = s_et.time + s_et.dur,
ttim = endtime - tim,
| | | 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 |
// set a fixed spacing inside tuplets
function set_sp_tup(s, s_et) {
var s2,
tim = s.time,
endtime = s_et.time + s_et.dur,
ttim = endtime - tim,
space = time2space(s, ttim / s.tp[0].q) * s.tp[0].q / ttim
// start on the second note/rest
do {
s = s.ts_next
} while (!s.seqst)
//fixme: problem when BAR inside the tuplet sequence (in case user error)
// while (!s.dur)
|
| ︙ | ︙ | |||
1108 1109 1110 1111 1112 1113 1114 | shrink: s.wr + 3 } s.next = s.ts_next = bar return bar } /* -- set the width and space of all symbols -- */ | | < < | > | | | | | > > | | | | < | | | | | > > > | | | > > > > > > > | | | | > | | | | | | 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 |
shrink: s.wr + 3
}
s.next = s.ts_next = bar
return bar
}
/* -- set the width and space of all symbols -- */
// this function is called once for the whole tune
function set_allsymwidth() {
var maxx, new_val, s_tupc, s_tupn, st, s_chs,
s = tsfirst,
s2 = s,
xa = 0,
xl = [],
wr = [],
ntup = 0
/* loop on all symbols */
maxx = xa
while (1) {
do {
if (s.a_gch && !s_chs)
s_chs = s;
self.set_width(s);
st = s.st
if (xl[st] == undefined)
xl[st] = 0
if (wr[st] == undefined)
wr[st] = 0;
new_val = xl[st] + wr[st] + s.wl
if (new_val > maxx)
maxx = new_val;
s = s.ts_next
} while (s && !s.seqst);
// set the spaces of the time sequence
s2.shrink = maxx - xa
if (!ntup) // if not inside a tuplet sequence
s2.space = s2.ts_prev ? set_space(s2) : 0
if (!s2.shrink && !s2.space && s2.type == C.CLEF) {
delete s2.seqst; /* no space */
s2.time = s2.ts_prev.time
}
if (!s)
break
// update the min left space per staff
for (st = 0; st < wr.length; st++)
wr[st] = 0;
xa = maxx
do {
st = s2.st;
xl[st] = xa
if (s2.wr > wr[st])
wr[st] = s2.wr
if (s2.tp) { // start of tuplet
if (!ntup
&& !s_tupc)
s_tupc = s2 // keep the first tuplet address
ntup += s2.tp.length
}
if (s2.tpe) // end of tuplet
ntup -= s2.tpe;
s2 = s2.ts_next
} while (!s2.seqst)
}
// let the chord symbols at the same offset
if (s_chs)
set_w_chs(s_chs)
// adjust the spacing inside the tuplets
s = s_tupc
if (!s)
return
do {
s2 = s; // start of tuplet
ntup = 0
while (1) { // search the end of the tuplet sequence
if (s.tp)
ntup += s.tp.length
if (s.tpe)
ntup -= s.tpe
if (!ntup)
break
s = s.ts_next
}
set_sp_tup(s2, s)
do { // search next tuplet
s = s.ts_next
} while (s && !s.tp)
} while (s)
}
// insert a rest, this one replacing a sequence or a measure
function to_rest(so) {
var s = clone(so)
s.prev.next = so.ts_prev = so.prev = s.ts_prev.ts_next = s
s.next = s.ts_next = so
so.seqst = false
so.invis = so.play = true
s.type = C.REST
// just keep nl and seqst
delete s.in_tuplet
delete s.sl1
delete s.a_dd
delete s.a_gch
delete s.sls
//fixme: what if chord / slur in notes / ... ?
/*fixme: should set many parameters for set_width*/
// set_width(s)
return s
}
/* -- set the repeat sequences / measures -- */
function set_repeat(s) { // first note
var s2, s3, i, j, dur,
n = s.repeat_n,
k = s.repeat_k,
st = s.st,
v = s.v
s.repeat_n = 0 // treated
/* treat the sequence repeat */
if (n < 0) { /* number of notes / measures */
n = -n;
i = n /* number of notes to repeat */
|
| ︙ | ︙ | |||
1270 1271 1272 1273 1274 1275 1276 |
for (j = k; --j >= 0; ) {
i = n /* number of notes/rests */
if (s.dur)
i--;
s2 = s.ts_next
while (i > 0) {
if (s2.st == st) {
| > > | | < < | 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 |
for (j = k; --j >= 0; ) {
i = n /* number of notes/rests */
if (s.dur)
i--;
s2 = s.ts_next
while (i > 0) {
if (s2.st == st) {
s2.invis = s2.play = true
if (s2.seqst && s2.ts_next.seqst)
s2.seqst = false
if (s2.v == v
&& s2.dur)
i--
}
s2 = s2.ts_next
}
s = to_rest(s)
s.dur = s.notes[0].dur = dur;
s.rep_nb = -1; // single repeat
s.beam_st = true;
self.set_width(s)
s.head = C.SQUARE;
for (s = s2; s; s = s.ts_next) {
if (s.st == st
&& s.v == v
&& s.dur)
break
}
|
| ︙ | ︙ | |||
1346 1347 1348 1349 1350 1351 1352 |
/* replace */
dur /= n
if (n == 2) { /* repeat 2 measures (once) */
s3 = s
for (s2 = s.ts_next; ; s2 = s2.ts_next) {
if (s2.st != st)
continue
| > | < | > > > > | | < < < < > | < | > > > > | | < < < < > | < | > > > > | | > < < < < | 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 |
/* replace */
dur /= n
if (n == 2) { /* repeat 2 measures (once) */
s3 = s
for (s2 = s.ts_next; ; s2 = s2.ts_next) {
if (s2.st != st)
continue
if (s2.type == C.BAR) {
if (s2.v == v)
break
continue
}
s2.invis = s2.play = true
if (s2.seqst && s2.ts_next.seqst)
s2.seqst = false
}
s3 = to_rest(s3)
s3.dur = s3.notes[0].dur = dur;
s3.invis = true
s2.bar_mrep = 2
s3 = s2.next;
for (s2 = s3.ts_next; ; s2 = s2.ts_next) {
if (s2.st != st)
continue
if (s2.type == C.BAR) {
if (s2.v == v)
break
continue
}
s2.invis = s2.play = true
if (s2.seqst && s2.ts_next.seqst)
s2.seqst = false
}
s3 = to_rest(s3)
s3.dur = s3.notes[0].dur = dur;
s3.invis = true;
self.set_width(s3)
return
}
/* repeat 1 measure */
s3 = s
for (j = k; --j >= 0; ) {
for (s2 = s3.ts_next; ; s2 = s2.ts_next) {
if (s2.st != st)
continue
if (s2.type == C.BAR) {
if (s2.v == v)
break
continue
}
s2.invis = s2.play = true
if (s2.seqst && s2.ts_next.seqst)
s2.seqst = false
}
s3 = to_rest(s3)
s3.dur = s3.notes[0].dur = dur;
s3.beam_st = true
if (k == 1) {
s3.rep_nb = 1
break
}
s3.rep_nb = k - j + 1; // number to print above the repeat rest
s3 = s2.next
}
|
| ︙ | ︙ | |||
1450 1451 1452 1453 1454 1455 1456 | dur: C.BLEN / 4 } } new_s.stemless = true } /* -- define the beginning of a new music line -- */ | | | < < < < | < < < | 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 |
dur: C.BLEN / 4
}
}
new_s.stemless = true
}
/* -- define the beginning of a new music line -- */
function set_nl(s) {
var s2, s3, p_voice, done
// set the end of line marker
function set_eol(s) {
if (cfmt.custos && voice_tb.length == 1)
custos_add(s)
s.nl = true
} // set_eol()
// set the eol on the next symbol
function set_eol_next(s) {
if (!s.next) { // special case: the voice stops here
set_eol(s)
return s
|
| ︙ | ︙ | |||
1500 1501 1502 1503 1504 1505 1506 |
if (cfmt.keywarn || cfmt.timewarn) {
for (s2 = s.ts_next; s2; s2 = s2.ts_next) {
switch (s2.type) {
case C.BAR:
case C.CLEF:
continue
case C.KEY:
| | > > > > | 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 |
if (cfmt.keywarn || cfmt.timewarn) {
for (s2 = s.ts_next; s2; s2 = s2.ts_next) {
switch (s2.type) {
case C.BAR:
case C.CLEF:
continue
case C.KEY:
if (!cfmt.keywarn
|| (!s2.k_a_acc && !s2.k_sf && !s2.k_old_sf)
|| s2.k_none
|| s2.k_play) // play only
continue
// fall thru
case C.METER:
if (s2.type == C.METER && !cfmt.timewarn)
continue
s3 = s2.ts_prev;
if (s3 == s) { // if next symbol
s = s2 // advance the eol
continue
|
| ︙ | ︙ | |||
1544 1545 1546 1547 1548 1549 1550 | continue } if (w_tb[s2.type]) break // symbol with a width } } | < < < < | 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 |
continue
}
if (w_tb[s2.type])
break // symbol with a width
}
}
/* if normal symbol, cut here */
switch (s.type) {
case C.CLEF:
case C.BAR:
case C.STAVES:
break
case C.GRACE: /* don't cut on a grace note */
|
| ︙ | ︙ | |||
1633 1634 1635 1636 1637 1638 1639 1640 |
self.set_width(p_voice.meter)
return [p_voice.clef.wl + p_voice.clef.wr +
p_voice.key.wl + p_voice.key.wr,
p_voice.meter.wl + p_voice.meter.wr]
}
// get the width of the symbols up to the next eoln or eof
function get_width(s, last) {
| > > | | > | > > > | | | > > > | | < | > | | > > > | > > | 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 |
self.set_width(p_voice.meter)
return [p_voice.clef.wl + p_voice.clef.wr +
p_voice.key.wl + p_voice.key.wr,
p_voice.meter.wl + p_voice.meter.wr]
}
// get the width of the symbols up to the next eoln or eof
// also, set a x (nice spacing) to all symbols
// two returned values: width of nice spacing, width with max shrinking
function get_width(s, last) {
var shrink, space,
w = 0,
wmx = 0,
sp_fac = (1 - cfmt.maxshrink)
do {
if (s.seqst) {
shrink = s.shrink
wmx += shrink
if ((space = s.space) < shrink)
w += shrink
else
w += shrink * cfmt.maxshrink
+ space * sp_fac
s.x = w
}
if (s == last)
break
s = s.ts_next
} while (s)
if (last)
wmx += last.wr // big key signatures may be wide enough
return [w, wmx]
}
/* -- search where to cut the lines according to the staff width -- */
function set_lines( s, /* first symbol */
last, /* last symbol / null */
lwidth, /* w - (clef & key sig) */
indent) { /* for start of tune */
var first, s2, s3, x, xmin, xmid, xmax, wwidth, shrink, space, ws,
nlines, cut_here
// take care of big key signatures at end of line
if (cfmt.keywarn && last && last.type == C.BAR
&& last.next && last.next.time == last.next.time
&& last.next.type == C.KEY)
last = last.next
ws = get_width(s, last) // 2 widths: nice and shrinked
// check if the symbols can enter in one line
if (ws[1] + indent < lwidth) {
if (last)
last = set_nl(last)
return last
}
/* loop on cutting the tune into music lines */
wwidth = ws[0] + indent
while (1) {
nlines = Math.ceil(wwidth / lwidth)
if (nlines <= 1) {
if (last)
last = set_nl(last)
return last
}
|
| ︙ | ︙ | |||
1814 1815 1816 1817 1818 1819 1820 |
indent = 0
}
return s
}
/* -- cut the tune into music lines -- */
function cut_tune(lwidth, indent) {
| | | | | 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 |
indent = 0
}
return s
}
/* -- cut the tune into music lines -- */
function cut_tune(lwidth, indent) {
var s2, i,
//fixme: not usable yet
// pg_sav = {
// leftmargin: cfmt.leftmargin,
// rightmargin: cfmt.rightmargin,
// pagewidth: cfmt.pagewidth,
// scale: cfmt.scale
// },
s = tsfirst
// take care of the voice subnames
if (indent) {
i = set_indent()
lwidth -= i;
indent -= i;
}
/* adjust the line width according to the starting clef
* and key signature */
|
| ︙ | ︙ | |||
1855 1856 1857 1858 1859 1860 1861 | continue s2.eoln = true; i = cfmt.barsperstaff } } /* cut at explicit end of line, checking the line width */ | < < | | < < < < | | < < < < < < < < < < < < | < | | < < < | 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 |
continue
s2.eoln = true;
i = cfmt.barsperstaff
}
}
/* cut at explicit end of line, checking the line width */
s2 = s
for ( ; s; s = s.ts_next) {
//fixme: not usable yet
// if (s.type == C.BLOCK) {
// switch (s.subtype) {
// case "leftmargin":
// case "rightmargin":
// case "pagescale":
// case "pagewidth":
// case "scale":
// case "staffwidth":
// set_format(s.subtype, s.param)
// break
// }
// continue
// }
if (!s.ts_next)
s = null
else if (!s.eoln)
continue
else
s.eoln = false
s2 = set_lines(s2, s, lwidth, indent)
if (!s2)
break
// (s2 may be tsfirst - no ts_prev - when only one
// embedded info in the first line after the first K:)
if (!s2.ts_prev) {
delete s2.nl
continue
}
s = s2.ts_prev; // don't miss an eoln
indent = 0
}
//fixme: not usable yet
// // restore the page parameters at start of line
// cfmt.leftmargin = pg_sav.leftmargin;
|
| ︙ | ︙ | |||
1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 |
default:
// s.ymx = top;
s.ymx = 24;
s.ymn = 0
break
}
}
// set the clefs (treble or bass) in a 'auto clef' sequence
// return the starting clef type
function set_auto_clef(st, s_start, clef_type_start) {
var s, min, max, time, s2, s3;
/* get the max and min pitches in the sequence */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 |
default:
// s.ymx = top;
s.ymx = 24;
s.ymn = 0
break
}
}
// set the ottava decorations and the associated pitch shift
function set_ottava() {
var s, st, delta, note, g, o,
m = nstaff + 1,
staff_d = new Int16Array(new Array(m * 2)), // (-ottava)
staff_noo = new Int8Array(new Array(m)) // number of ottava values
// add an ottava decoration
function ottava_add(s, ottava, start) {
var dc_st = ["15mb(", "8vb(", null, "8va(", "15ma("],
dc_en = ["15mb)", "8vb)", null, "8va)", "15ma)"];
deco_cnv([(start ? dc_st : dc_en)[2 + ottava]], s)
}
for (st = 0; st <= nstaff; st++) {
staff_d[st] = 0;
staff_noo[st] = 0
}
for (s = tsfirst; s; s = s.ts_next) {
st = s.st
if (s.ottava != undefined)
while (s.ottava.length) {
o = s.ottava.shift()
if (o) {
if (staff_noo[st]++ == 0) { // if first ottava
ottava_add(s, o, true)
staff_d[st] = -o * 7
}
} else {
if (--staff_noo[st] == 0) { // if last ottava
ottava_add(s, -staff_d[st] / 7);
staff_d[st] = 0
}
}
}
switch (s.type) {
case C.REST:
if (voice_tb.length == 1)
break
case C.NOTE:
delta = staff_d[st]
if (delta
&& !s.p_v.key.k_drum) {
for (m = s.nhd; m >= 0; m--) {
note = s.notes[m];
if (!note.opit)
note.opit = note.pit;
note.pit += delta
}
}
break
case C.GRACE:
for (g = s.extra; g; g = g.next) {
delta = staff_d[st]
if (delta
&& !s.p_v.key.k_drum) {
for (m = 0; m <= g.nhd; m++) {
note = g.notes[m]
if (!note.opit)
note.opit = note.pit
note.pit += delta
}
}
}
break
}
}
}
// set the clefs (treble or bass) in a 'auto clef' sequence
// return the starting clef type
function set_auto_clef(st, s_start, clef_type_start) {
var s, min, max, time, s2, s3;
/* get the max and min pitches in the sequence */
|
| ︙ | ︙ | |||
2136 2137 2138 2139 2140 2141 2142 |
* - 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,
| | | | | < | | > | | 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 |
* - 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: ""
}
}
// set the starting clefs of the staves
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (!sy.voices[v])
continue
st = sy.voices[v].st
if (!sy.voices[v].second) { // main voices
if (p_voice.staffnonote != undefined)
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;
if (!p_voice.clef.clef_auto)
staff_clef[st].autoclef = false
}
}
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (!sy.voices[v]
|| sy.voices[v].second) // main voices
continue
st = sy.voices[v].st;
s = p_voice.clef
if (staff_clef[st].autoclef) {
s.clef_type = set_auto_clef(st,
tsfirst,
|
| ︙ | ︙ | |||
2200 2201 2202 2203 2204 2205 2206 |
switch (s.type) {
case C.STAVES:
sy = s.sy
for (st = 0; st <= nstaff; st++)
staff_clef[st].autoclef = true
for (v = 0; v < voice_tb.length; v++) {
| | | | 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 |
switch (s.type) {
case C.STAVES:
sy = s.sy
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) {
if (p_voice.staffnonote != undefined)
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...
|
| ︙ | ︙ | |||
2323 2324 2325 2326 2327 2328 2329 |
}
staff_clef[st].clef = s
}
/* set a pitch to the symbols of voices with no note */
sy = cur_sy
for (v = 0; v < voice_tb.length; v++) {
| | | 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 |
}
staff_clef[st].clef = s
}
/* set a pitch to the symbols of voices with no note */
sy = cur_sy
for (v = 0; v < voice_tb.length; v++) {
if (!sy.voices[v])
continue
s2 = voice_tb[v].sym
if (!s2 || s2.notes[0].pit != 127)
continue
st = sy.voices[v].st
switch (staff_tb[st].clef.clef_type) {
default:
|
| ︙ | ︙ | |||
2372 2373 2374 2375 2376 2377 2378 | [6, 4], [10, 0], [10, 4], [10, 10] ] // (possible hook) | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > | 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 |
[6, 4],
[10, 0],
[10, 4],
[10, 10]
]
// (possible hook)
Abc.prototype.set_pitch = function(last_s) {
var s, s2, g, st, delta, pitch, note,
dur = C.BLEN,
m = nstaff + 1,
staff_delta = new Int16Array(new Array(m * 2)), // delta clef
sy = cur_sy
// set the starting clefs of the staves
for (st = 0; st <= nstaff; st++) {
s = staff_tb[st].clef;
staff_delta[st] = delta_tb[s.clef_type] + s.clef_line * 2
if (s.clefpit)
staff_delta[st] += s.clefpit
if (cfmt.sound) {
if (s.clef_octave && !s.clef_oct_transp)
staff_delta[st] += s.clef_octave
} else {
if (s.clef_oct_transp)
staff_delta[st] -= s.clef_octave
}
}
for (s = tsfirst; s != last_s; s = s.ts_next) {
st = s.st
switch (s.type) {
case C.CLEF:
staff_delta[st] = delta_tb[s.clef_type] +
s.clef_line * 2
if (s.clefpit)
staff_delta[st] += s.clefpit
if (cfmt.sound) {
if (s.clef_octave && !s.clef_oct_transp)
staff_delta[st] += s.clef_octave
} else {
if (s.clef_oct_transp)
staff_delta[st] -= s.clef_octave
}
set_yval(s)
break
case C.GRACE:
for (g = s.extra; g; g = g.next) {
delta = staff_delta[g.st]
if (delta
&& !s.p_v.key.k_drum) {
for (m = 0; m <= g.nhd; m++) {
note = g.notes[m];
note.opit = note.pit
note.pit += delta
}
}
g.ymn = 3 * (g.notes[0].pit - 18) - 2;
g.ymx = 3 * (g.notes[g.nhd].pit - 18) + 2
}
set_yval(s)
|
| ︙ | ︙ | |||
2483 2484 2485 2486 2487 2488 2489 | // s.ymn = 12 - 8 s.ymx = 24; s.ymn = 0 break } // fall thru case C.NOTE: | | | | > | | 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 |
// s.ymn = 12 - 8
s.ymx = 24;
s.ymn = 0
break
}
// fall thru
case C.NOTE:
delta = staff_delta[st]
if (delta
&& !s.p_v.key.k_drum) {
for (m = s.nhd; m >= 0; m--) {
note = s.notes[m]
note.opit = note.pit
note.pit += delta
}
}
if (s.type == C.NOTE) {
s.ymx = 3 * (s.notes[s.nhd].pit - 18) + 4;
s.ymn = 3 * (s.notes[0].pit - 18) - 4;
} else {
s.y = (((s.notes[0].pit - 18) / 2) | 0) * 6;
|
| ︙ | ︙ | |||
2511 2512 2513 2514 2515 2516 2517 | if (!last_s) smallest_duration = dur } /* -- set the stem direction when multi-voices -- */ /* this function is called only once per tune */ // (possible hook) | | | 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 |
if (!last_s)
smallest_duration = dur
}
/* -- set the stem direction when multi-voices -- */
/* this function is called only once per tune */
// (possible hook)
Abc.prototype.set_stem_dir = function() {
var t, u, i, st, rvoice, v,
v_st, // voice -> staff 1 & 2
st_v, vobj, // staff -> (v, ymx, ymn)*
v_st_tb, // array of v_st
st_v_tb = [], // array of st_v
s = tsfirst,
sy = cur_sy,
|
| ︙ | ︙ | |||
2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 | case C.REST: // handle %%voicecombine 0 if ((s.combine != undefined && s.combine < 0) || !s.ts_next || s.ts_next.type != C.REST || s.ts_next.st != s.st || s.time != s.ts_next.time || s.dur != s.ts_next.dur || (s.a_gch && s.ts_next.a_gch) || s.invis) break if (s.ts_next.a_gch) s.a_gch = s.ts_next.a_gch unlksym(s.ts_next) break case C.NOTE: case C.GRACE: break | > > > | 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 | case C.REST: // handle %%voicecombine 0 if ((s.combine != undefined && s.combine < 0) || !s.ts_next || s.ts_next.type != C.REST || s.ts_next.st != s.st || s.time != s.ts_next.time || s.dur != s.ts_next.dur || (s.a_dd && s.ts_next.a_dd) || (s.a_gch && s.ts_next.a_gch) || s.invis) break if (s.ts_next.a_dd) s.a_dd = s.ts_next.a_dd if (s.ts_next.a_gch) s.a_gch = s.ts_next.a_gch unlksym(s.ts_next) break case C.NOTE: case C.GRACE: break |
| ︙ | ︙ | |||
2850 2851 2852 2853 2854 2855 2856 | s.xmx = dx continue } } } /* -- create a starting symbol -- */ | > | < | < < < < | | < | < | > > | | | | > | | | < | | | | 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 |
s.xmx = dx
continue
}
}
}
/* -- create a starting symbol -- */
// last_s = symbol at same time
function new_sym(s, p_v, last_s) {
s.p_v = p_v
s.v = p_v.v
s.st = p_v.st
s.time = last_s.time
if (p_v.last_sym) {
s.next = p_v.last_sym.next
if (s.next)
s.next.prev = s;
p_v.last_sym.next = s;
s.prev = p_v.last_sym
}
p_v.last_sym = s;
lktsym(s, last_s)
if (s.ts_prev.type != s.type)
s.seqst = true
if (last_s.type == s.type && s.v != last_s.v) {
delete last_s.seqst;
last_s.shrink = 0
}
}
/* -- init the symbols at start of a music line -- */
function init_music_line() {
var p_voice, s, s2, s3, last_s, v, st, shr, shrmx,
nv = voice_tb.length
/* initialize the voices */
for (v = 0; v < nv; v++) {
if (!cur_sy.voices[v])
continue
p_voice = voice_tb[v];
p_voice.second = cur_sy.voices[v].second;
p_voice.last_sym = p_voice.sym;
/* move the voice to a printed staff */
st = cur_sy.voices[v].st
while (st < nstaff && !cur_sy.st_print[st])
st++;
p_voice.st = st
}
/* add a clef at start of the main voices */
last_s = tsfirst
while (last_s && last_s.type == C.CLEF) { // move the starting clefs
v = last_s.v
if (cur_sy.voices[v]
&& !cur_sy.voices[v].second) {
delete last_s.clef_small; /* normal clef */
p_voice = last_s.p_v;
p_voice.last_sym = p_voice.sym = last_s
}
last_s = last_s.ts_next
}
for (v = 0; v < nv; v++) {
p_voice = voice_tb[v]
if (p_voice.sym && p_voice.sym.type == C.CLEF)
continue
if (!cur_sy.voices[v]
|| (cur_sy.voices[v].second
&& !p_voice.bar_start)) // needed for correct linkage
continue
st = cur_sy.voices[v].st
if (!staff_tb[st]
|| !staff_tb[st].clef)
continue
|
| ︙ | ︙ | |||
2960 2961 2962 2963 2964 2965 2966 |
// (fixme: needed for sample5 X:3 Fugue & staffnonote.xhtml)
if (!cur_sy.st_print[st])
s.invis = true
}
/* add keysig */
for (v = 0; v < nv; v++) {
| | > | < | < < < < < < < < < | | > | < < < < > > > > > > > > > > > > > > > > > > | < < < < < < | < < < < < < | | < | < | < < < < < < < < < < < < < < < < < < < | < | < < < > > > > > > > > > > > > > > | 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 |
// (fixme: needed for sample5 X:3 Fugue & staffnonote.xhtml)
if (!cur_sy.st_print[st])
s.invis = true
}
/* add keysig */
for (v = 0; v < nv; v++) {
if (!cur_sy.voices[v]
|| cur_sy.voices[v].second
|| !cur_sy.st_print[cur_sy.voices[v].st])
continue
p_voice = voice_tb[v]
if (last_s && last_s.v == v && last_s.type == C.KEY) {
p_voice.last_sym = last_s;
last_s.k_old_sf = last_s.k_sf; // no key cancel
last_s = last_s.ts_next
continue
}
s2 = p_voice.key
if (s2.k_sf || s2.k_a_acc) {
s = clone(s2)
new_sym(s, p_voice, last_s)
s.k_old_sf = s2.k_sf // no key cancel
}
}
/* add time signature (meter) if needed */
if (insert_meter & 1) {
for (v = 0; v < nv; v++) {
p_voice = voice_tb[v];
s2 = p_voice.meter
if (!cur_sy.voices[v]
|| cur_sy.voices[v].second
|| !cur_sy.st_print[cur_sy.voices[v].st]
|| !s2.a_meter.length)
continue
if (last_s && last_s.v == v && last_s.type == C.METER) {
p_voice.last_sym = last_s;
last_s = last_s.ts_next
continue
}
s = clone(s2)
new_sym(s, p_voice, last_s)
}
insert_meter &= ~1 // no meter any more
}
// add an invisible bar for the various continued elements
for (v = 0; v < nv; v++) {
p_voice = voice_tb[v]
if (p_voice.sls.length) {
s = {
type: C.BAR,
fname: last_s.fname,
bar_type: "|",
dur: 0,
multi: 0,
invis: true,
sls: p_voice.sls
}
new_sym(s, p_voice, last_s)
p_voice.sls = []
}
}
/* add bar if needed (for repeat bracket) */
for (v = 0; v < nv; v++) {
p_voice = voice_tb[v];
s2 = p_voice.bar_start;
p_voice.bar_start = null
// if bar already, keep it in sequence
if (last_s && last_s.v == v && last_s.type == C.BAR) {
p_voice.last_sym = last_s;
last_s = last_s.ts_next
continue
}
if (!s2)
continue
if (!cur_sy.voices[v]
|| !cur_sy.st_print[cur_sy.voices[v].st])
continue
new_sym(s2, p_voice, last_s)
}
// compute the spacing of the added symbols
self.set_pitch(last_s);
s = tsfirst
while (1) {
s2 = s;
shrmx = 0
do {
self.set_width(s);
shr = s.wl
if (s.prev)
shr += s.prev.wr
if (shr > shrmx)
shrmx = shr;
s = s.ts_next
} while (s != last_s && !s.seqst);
s2.shrink = shrmx;
s2.space = 0
if (s == last_s)
break
}
// update the spacing before the first old time sequence
if (!s)
return
shr = 0
do {
self.set_width(s)
if (shr < s.wl)
shr = s.wl;
s = s.ts_next
} while (s && !s.seqst);
last_s.shrink = s2.wr + shr
last_s.space = 0
}
/* -- set a pitch in all symbols and the start/stop of the beams -- */
// and sort the pitches in the chords
function set_words(p_voice) {
var s, s2, nflags, lastnote, res,
start_flag = true,
pitch = 127 /* no note */
for (s = p_voice.sym; s; s = s.next) {
if (s.type == C.NOTE) {
|
| ︙ | ︙ | |||
3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 | start_flag = true if (!s.next && s.prev // && s.prev.type == C.NOTE // && s.prev.dur >= C.BLEN * 2) && s.prev.head == C.OVALBARS) s.prev.head = C.SQUARE break case C.NOTE: case C.REST: res = identify_note(s, s.dur_orig); s.head = res[0]; s.dots = res[1]; s.nflags = res[2] if (s.nflags <= -2) | > > > > | 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 | start_flag = true if (!s.next && s.prev // && s.prev.type == C.NOTE // && s.prev.dur >= C.BLEN * 2) && s.prev.head == C.OVALBARS) s.prev.head = C.SQUARE break case C.GRACE: for (s2 = s.extra; s2; s2 = s2.next) s2.notes.sort(abc2svg.pitcmp) break case C.NOTE: case C.REST: res = identify_note(s, s.dur_orig); s.head = res[0]; s.dots = res[1]; s.nflags = res[2] if (s.nflags <= -2) |
| ︙ | ︙ | |||
3186 3187 3188 3189 3190 3191 3192 |
if (s.beam_end)
start_flag = true
if (s.type == C.NOTE)
lastnote = s
break
}
if (s.type == C.NOTE) {
| | | | 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 |
if (s.beam_end)
start_flag = true
if (s.type == C.NOTE)
lastnote = s
break
}
if (s.type == C.NOTE) {
if (s.nhd)
s.notes.sort(abc2svg.pitcmp)
pitch = s.notes[0].pit
// if (s.prev
// && s.prev.type != C.NOTE) {
// s.prev.notes[0].pit = (s.prev.notes[0].pit
// + pitch) / 2
for (s2 = s.prev; s2; s2 = s2.prev) {
if (s2.type != C.REST)
|
| ︙ | ︙ | |||
3213 3214 3215 3216 3217 3218 3219 |
}
if (lastnote)
lastnote.beam_end = true
}
/* -- set the end of the repeat sequences -- */
function set_rb(p_voice) {
| | | < < < < < | | | | | | | > | | < < | | | | < < < | < < < < < < < | < < | < < < < < < < < < < < < | | < < < < | 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 |
}
if (lastnote)
lastnote.beam_end = true
}
/* -- set the end of the repeat sequences -- */
function set_rb(p_voice) {
var s2, n,
s = p_voice.sym
while (s) {
if (s.type != C.BAR || !s.rbstart || s.norepbra) {
s = s.next
continue
}
n = 0;
s2 = null
for (s = s.next; s; s = s.next) {
if (s.type != C.BAR)
continue
n++
if (s.rbstop)
break
if (!s.next) {
s.rbstop = 2 // right repeat with end
break
}
if (n == cfmt.rbmin)
s2 = s
if (n == cfmt.rbmax) {
if (s2)
s = s2;
s.rbstop = 1 // right repeat without end
break
}
}
}
}
/* -- initialize the generator -- */
/* this function is called only once per tune */
|
| ︙ | ︙ | |||
3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 |
// (test removed because v.second may change after %%staves)
// if (!p_voice.second && !p_voice.norepbra)
set_rb(p_voice)
}
/* set the staff of the floating voices */
set_float();
// set the clefs and adjust the pitches of all symbol
set_clefs();
self.set_pitch(null)
}
/* -- return the left indentation of the staves -- */
function set_indent(first) {
var st, v, w, p_voice, p, i, j, font,
nv = voice_tb.length,
maxw = 0
for (v = 0; v < nv; v++) {
p_voice = voice_tb[v]
| > > > | | 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 |
// (test removed because v.second may change after %%staves)
// if (!p_voice.second && !p_voice.norepbra)
set_rb(p_voice)
}
/* set the staff of the floating voices */
set_float();
if (glovar.ottava && cfmt.sound != "play")
set_ottava();
// set the clefs and adjust the pitches of all symbol
set_clefs();
self.set_pitch(null)
}
/* -- return the left indentation of the staves -- */
function set_indent(first) {
var st, v, w, p_voice, p, i, j, font,
nv = voice_tb.length,
maxw = 0
for (v = 0; v < nv; v++) {
p_voice = voice_tb[v]
if (!cur_sy.voices[v])
continue
st = cur_sy.voices[v].st
// if (!cur_sy.st_print[st])
// continue
p = ((first || p_voice.new_name) && p_voice.nm) ?
p_voice.nm : p_voice.snm
if (!p)
|
| ︙ | ︙ | |||
3378 3379 3380 3381 3382 3383 3384 |
maxw += cfmt.indent
return maxw
}
/* -- decide on beams and on stem directions -- */
/* this routine is called only once per tune */
function set_beams(sym) {
| | | | 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 |
maxw += cfmt.indent
return maxw
}
/* -- decide on beams and on stem directions -- */
/* this routine is called only once per tune */
function set_beams(sym) {
var s, t, g, beam, s_opp, n, m, mid_p, pu, pd,
laststem = -1
for (s = sym; s; s = s.next) {
if (s.type != C.NOTE) {
if (s.type != C.GRACE)
continue
g = s.extra
if (g.stem == 2) { /* opposite gstem direction */
|
| ︙ | ︙ | |||
3409 3410 3411 3412 3413 3414 3415 |
mid_p = s.mid / 3 + 18
/* notes in a beam have the same stem direction */
if (beam) {
s.stem = laststem
} else if (s.beam_st && !s.beam_end) { // beam start
beam = true;
| | > | | | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | > > < | | > > | < | 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 |
mid_p = s.mid / 3 + 18
/* notes in a beam have the same stem direction */
if (beam) {
s.stem = laststem
} else if (s.beam_st && !s.beam_end) { // beam start
beam = true;
// count the number of notes above the mid-line
n = pu = 0
for (g = s; g; g = g.next) {
if (g.type != C.NOTE) {
// if (g.beam_end)
// break
continue
}
if (g.stem || g.multi) { // if forced direction
s.stem = g.stem || g.multi
break
}
n += g.nhd + 1
for (m = 0; m <= g.nhd; m++) {
if (g.notes[m].pit >= mid_p)
pu++
}
if (g.beam_end)
break
}
if (!s.stem) {
pu *= 2
if (pu > n) {
s.stem = -1
} else if (pu < n) {
s.stem = 1
// same number of note above and below the mid-line
// get the highest and lowest pitches
} else {
pu = s.notes[s.nhd].pit;
pd = s.notes[0].pit
for (g = s.next; g; g = g.next) {
if (g.type != C.NOTE) {
// if (g.beam_end)
// break
continue
}
if (g.notes[g.nhd].pit > pu)
pu = g.notes[g.nhd].pit
if (g.notes[0].pit < pd)
pd = g.notes[0].pit
if (g.beam_end)
break
}
if (g.beam_end) {
if (pu + pd < mid_p * 2) {
s.stem = 1
} else if (pu + pd > mid_p * 2) {
s.stem = -1
} else {
//--fixme: equal: check all notes of the beam
if (cfmt.bstemdown)
s.stem = -1
}
}
}
}
if (!s.stem)
s.stem = laststem
} else { // no beam
n = (s.notes[s.nhd].pit + s.notes[0].pit) / 2
if (n == mid_p) {
for (m = 0; m <= s.nhd; m++) {
if (s.notes[m].pit >= mid_p)
break
}
n = m * 2 < s.nhd ? mid_p - 1 : mid_p + 1
}
if (n < mid_p)
s.stem = 1
else if (n > mid_p)
s.stem = -1
else if (cfmt.bstemdown)
s.stem = -1
else
|
| ︙ | ︙ | |||
3575 3576 3577 3578 3579 3580 3581 |
if (s1.shiftunison && (s1.shiftunison & 2))
return false
head = s2.dur >= C.BLEN / 2 ? 2 : 1
} else {
return false
}
}
| | | 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 |
if (s1.shiftunison && (s1.shiftunison & 2))
return false
head = s2.dur >= C.BLEN / 2 ? 2 : 1
} else {
return false
}
}
if (!head)
head = s1.p_v.scale < s2.p_v.scale ? 2 : 1
if (head == 1) {
for (i2 = i21; i2 < i22; i2++) {
s2.notes[i2].invis = true
delete s2.notes[i2].acc
}
for (i2 = 0; i2 <= s2.nhd; i2++)
|
| ︙ | ︙ | |||
3751 3752 3753 3754 3755 3756 3757 |
return right
}
/* -- shift the notes horizontally when voices overlap -- */
/* this routine is called only once per tune */
function set_overlap() {
| | | | > | > > > | 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 |
return right
}
/* -- shift the notes horizontally when voices overlap -- */
/* this routine is called only once per tune */
function set_overlap() {
var s, s1, s2, s3, i, i1, i2, m, sd, t, dp,
d, d2, dr, dr2, dx,
left1, right1, left2, right2, right3, pl, pr,
sy = cur_sy
// invert the voices
function v_invert() {
s1 = s2;
s2 = s;
d = d2;
pl = left1;
pr = right1;
dr2 = dr
}
for (s = tsfirst; s; s = s.ts_next) {
if (s.type != C.NOTE
|| s.invis) {
if (s.type == C.STAVES)
sy = s.sy
continue
}
/* treat the stem on two staves with different directions */
if (s.xstem
&& s.ts_prev.stem < 0) {
for (m = 0; m <= s.nhd; m++) {
s.notes[m].shhd -= 7; // stem_xoff
s.notes[m].shac += 16
|
| ︙ | ︙ | |||
3799 3800 3801 3802 3803 3804 3805 | break } if (!s2) continue s1 = s /* set the dot vertical offset */ | | > > > > > > > > > > > > > > > > > > | 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 |
break
}
if (!s2)
continue
s1 = s
/* set the dot vertical offset */
if (sy.voices[s1.v].range < sy.voices[s2.v].range)
s2.dot_low = true
else
s1.dot_low = true
/* no shift if no overlap */
if (s1.ymn > s2.ymx
|| s1.ymx < s2.ymn)
continue
if (same_head(s1, s2))
continue
// special case when only a second and no dots
if (!s1.dots && !s2.dots)
if ((s1.stem > 0 && s2.stem < 0
&& s1.notes[0].pit == s2.notes[s2.nhd].pit + 1)
|| (s1.stem < 0 && s2.stem > 0
&& s1.notes[s1.nhd].pit + 1 == s2.notes[0].pit)) {
if (s1.stem < 0) {
s1 = s2;
s2 = s
}
d = s1.notes[0].shhd + 7
for (m = 0; m <= s2.nhd; m++) // shift the lower note(s)
s2.notes[m].shhd += d
s2.xmx += d
s1.xmx = s2.xmx // align the dots
continue
}
/* compute the minimum space for 's1 s2' and 's2 s1' */
right1 = set_right(s1);
left2 = set_left(s2);
s3 = s1.ts_prev
if (s3 && s3.time == s1.time
|
| ︙ | ︙ | |||
3869 3870 3871 3872 3873 3874 3875 |
t = 0;
i1 = s1.nhd;
i2 = s2.nhd
while (1) {
dp = s1.notes[i1].pit - s2.notes[i2].pit
switch (dp) {
case 0:
| | > | > > > < < < < < < < < < | 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 |
t = 0;
i1 = s1.nhd;
i2 = s2.nhd
while (1) {
dp = s1.notes[i1].pit - s2.notes[i2].pit
switch (dp) {
case 0:
if (s1.notes[i1].acc != s2.notes[i2].acc
&& !s1.notes[i1].acc && !s2.notes[i2].acc) {
t = -1
break
}
if (s2.notes[i2].acc) {
if (!s1.notes[i1].acc)
s1.notes[i1].acc = s2.notes[i2].acc
s2.notes[i2].acc = 0
}
if (s1.dots && s2.dots
&& (s1.notes[i1].pit & 1))
t = 1
break
case -1:
if (s1.dots && s2.dots) {
if (s1.notes[i1].pit & 1) {
s1.dot_low = false;
s2.dot_low = false
} else {
s1.dot_low = true;
s2.dot_low = true
}
}
break
case -2:
if (s1.dots && s2.dots
&& !(s1.notes[i1].pit & 1)) {
s1.dot_low = false;
s2.dot_low = false
break
}
break
}
if (t < 0)
break
if (dp >= 0) {
|
| ︙ | ︙ | |||
3930 3931 3932 3933 3934 3935 3936 |
}
sd = 0;
if (s1.dots) {
if (s2.dots) {
if (!t) /* if no dot clash */
sd = 1 /* align the dots */
| | > < | 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 |
}
sd = 0;
if (s1.dots) {
if (s2.dots) {
if (!t) /* if no dot clash */
sd = 1 /* align the dots */
} else {
v_invert() // shift the first voice
}
} else if (s2.dots) {
if (d2 + dr < d + dr2)
sd = 1 /* align the dots */
}
pl = left2;
pr = right2
if (!s3 && d2 + dr < d + dr2)
v_invert()
d += 3
if (d < 0)
|
| ︙ | ︙ | |||
4029 4030 4031 4032 4033 4034 4035 | s1.xmx = s2.xmx // align the dots } } /* -- set the stem height -- */ /* this routine is called only once per tune */ // (possible hook) | | | 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 |
s1.xmx = s2.xmx // align the dots
}
}
/* -- set the stem height -- */
/* this routine is called only once per tune */
// (possible hook)
Abc.prototype.set_stems = function() {
var s, s2, g, slen, scale,ymn, ymx, nflags, ymin, ymax, res
for (s = tsfirst; s; s = s.ts_next) {
if (s.type != C.NOTE) {
if (s.type != C.GRACE)
continue
ymin = ymax = s.mid
|
| ︙ | ︙ | |||
4142 4143 4144 4145 4146 4147 4148 |
|| !s.beam_st
|| !s.beam_end)) {
slen -= 2
if (s.notes[s.nhd].pit > 28)
slen -= 2
}
s.y = ymn
| | | | | | 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 |
|| !s.beam_st
|| !s.beam_end)) {
slen -= 2
if (s.notes[s.nhd].pit > 28)
slen -= 2
}
s.y = ymn
if (s.notes[0].tie)
ymn -= 3;
s.ymn = ymn - 4;
s.ys = ymx + slen
if (s.ys < s.mid)
s.ys = s.mid;
s.ymx = (s.ys + 2.5) | 0
} else { /* stem down */
if (s.notes[0].pit < 18
&& (nflags <= 0
|| !s.beam_st || !s.beam_end)) {
slen -= 2
if (s.notes[0].pit < 16)
slen -= 2
}
s.ys = ymn - slen
if (s.ys > s.mid)
s.ys = s.mid;
s.ymn = (s.ys - 2.5) | 0;
s.y = ymx
/*fixme:the tie may be lower*/
if (s.notes[s.nhd].tie)
ymx += 3;
s.ymx = ymx + 4
}
}
}
/* -- split up unsuitable bars at end of staff -- */
// return true if the bar type has changed
function check_bar(s) {
var bar_type, i, b1, b2, s_bs, s2,
p_voice = s.p_v
/* search the last bar */
while (s.type == C.CLEF || s.type == C.KEY || s.type == C.METER) {
if (s.type == C.METER
&& s.time > p_voice.sym.time) /* if not empty voice */
insert_meter |= 1; /* meter in the next line */
s = s.prev
|
| ︙ | ︙ | |||
4201 4202 4203 4204 4205 4206 4207 | } bar_type = s.bar_type if (bar_type == ":") return if (bar_type.slice(-1) != ':') // if not left repeat bar return | > | > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 |
}
bar_type = s.bar_type
if (bar_type == ":")
return
if (bar_type.slice(-1) != ':') // if not left repeat bar
return
// add a left repeat bar in the next music line
s2 = p_voice.s_next
while (1) {
switch (s2.type) {
case C.BAR:
case C.GRACE:
case C.NOTE:
case C.REST:
break
default:
s2 = s2.next
if (!s2)
return
}
break
}
if (s2.type == C.BAR) {
s_bs = s2 // bar start
} else {
s_bs = clone(s)
s_bs.next = s2
s_bs.prev = s2.prev
if (s2 == p_voice.s_next)
p_voice.s_next = s_bs
else
s2.prev.next = s_bs
s2.prev = s_bs
while (!s2.seqst)
s2 = s2.ts_prev
s_bs.ts_next = s2
s_bs.ts_prev = s2.ts_prev
if (s2 == tsnext)
tsnext = s_bs
else
s2.ts_prev.ts_next = s_bs
s2.ts_prev = s_bs
delete s_bs.seqst
if (s_bs == tsnext || s2.ts_prev.type != C.BAR) {
if (s2.seqst) {
s_bs.seqst = true
} else {
s2.seqst = true
s2.shrink = s_bs.wr + s2.wl
s2.space = 0
}
}
}
if (bar_type[0] != ':') { // 'xx:' (not ':xx:')
if (bar_type == "||:") {
s_bs.bar_type = "[|:"
s.bar_type = "||"
return true
}
s_bs.bar_type = bar_type
if (s.prev && s.prev.type == C.BAR)
unlksym(s)
else
s.bar_type = "|"
return
}
// ':xx:' -> ':x|]' and '[|x:'
i = 0
while (bar_type[i] == ':')
i++
if (i < bar_type.length) {
s.bar_type = bar_type.slice(0, i) + '|]';
i = bar_type.length - 1
while (bar_type[i] == ':')
i--;
s_bs.bar_type = '[|' + bar_type.slice(i + 1)
} else {
i = (bar_type.length / 2) |0; // '::::' !
s.bar_type = bar_type.slice(0, i) + '|]';
s_bs.bar_type = '[|' + bar_type.slice(i)
}
return true
}
/* -- move the symbols of an empty staff to the next one -- */
function sym_staff_move(st) {
for (var s = tsfirst; s; s = s.ts_next) {
|
| ︙ | ︙ | |||
4275 4276 4277 4278 4279 4280 4281 | block.newpage = true; blk_out() break case "sep": set_page(); vskip(s.sk1); output += '<path class="stroke"\n\td="M'; | | < < < | 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 |
block.newpage = true;
blk_out()
break
case "sep":
set_page();
vskip(s.sk1);
output += '<path class="stroke"\n\td="M';
out_sxsy((img.width -s.l) / 2 - img.lm, ' ', 0)
output += 'h' + s.l.toFixed(1) + '"/>\n';
vskip(s.sk2);
break
case "text":
write_text(s.text, s.opt)
break
case "title":
write_title(s.text, true)
break
case "vskip":
vskip(s.sk);
// blk_out()
break
}
}
/* -- define the start and end of a piece of tune -- */
/* tsnext becomes the beginning of the next line */
function set_piece() {
var s, last, p_voice, st, v, nst, nv, tmp,
|
| ︙ | ︙ | |||
4343 4344 4345 4346 4347 4348 4349 |
}
}
}
} // set_brace()
// set the top and bottom of the staves
function set_top_bot() {
| | | | > > > > | > > > > > > > > > > > > > > > > > > | 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 |
}
}
}
} // set_brace()
// set the top and bottom of the staves
function set_top_bot() {
var st, p_staff, i, j, l
for (st = 0; st <= nstaff; st++) {
p_staff = staff_tb[st]
if (!non_empty_gl[st]) {
p_staff.botbar = p_staff.topbar = 0
continue
}
l = p_staff.stafflines.length;
p_staff.topbar = 6 * (l - 1)
for (i = 0; i < l - 1; i++) {
switch (p_staff.stafflines[i]) {
case '.':
case '-':
continue
}
break
}
p_staff.botline = p_staff.botbar = i * 6
if (i >= l - 2) { // 0, 1 or 2 lines
if (p_staff.stafflines[i] != '.') {
p_staff.botbar -= 6;
p_staff.topbar += 6
} else { // no line: big bar
p_staff.botbar -= 12;
p_staff.topbar += 12
continue // no helper line
}
}
// define the helper lines
p_staff.hll = 17 + i; // pitch of lowest note
// without helper line
// ('D' when standard staff)
p_staff.hlmap = new Int8Array(new Array((l - i + 1) * 2))
for (j = 1; i < l; i++, j += 2) {
switch (p_staff.stafflines[i]) {
case '|':
case '[':
p_staff.hlmap[j - 1] = 1; // no helper line
p_staff.hlmap[j] = 1;
p_staff.hlmap[j + 1] = 1
break
}
}
}
} // set_top_bot()
/* reset the staves */
nstaff = nst = sy.nstaff
|
| ︙ | ︙ | |||
4391 4392 4393 4394 4395 4396 4397 | // blocks.push(s); // unlksym(s); // s = s.ts_next // } break } if (!s.ts_next) | | > | < < < | 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 |
// blocks.push(s);
// unlksym(s);
// s = s.ts_next
// }
break
}
if (!s.ts_next)
last = s // keep the last symbol of the tune
switch (s.type) {
case C.STAVES:
set_brace();
sy.st_print = new Uint8Array(non_empty);
sy = s.sy;
nst = sy.nstaff
if (nstaff < nst) {
for (st = nstaff + 1; st <= nst; st++)
reset_staff(st);
nstaff = nst
}
non_empty = []
continue
// the block symbols will be treated after music line generation
case C.BLOCK:
if (!s.play)
blocks.push(s)
continue
}
st = s.st
if (non_empty[st])
continue
switch (s.type) {
default:
|
| ︙ | ︙ | |||
4521 4522 4523 4524 4525 4526 4527 | && last.type != C.KEY) s.space = s.shrink } } /* -- position the symbols along the staff -- */ // (possible hook) | | | 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 |
&& last.type != C.KEY)
s.space = s.shrink
}
}
/* -- position the symbols along the staff -- */
// (possible hook)
Abc.prototype.set_sym_glue = function(width) {
var s, g, ll,
some_grace,
spf, // spacing factor
xmin = 0, // sigma shrink = minimum spacing
xx = 0, // sigma natural spacing
x = 0, // sigma expandable elements
xs = 0, // sigma unexpandable elements with no space
|
| ︙ | ︙ | |||
4551 4552 4553 4554 4555 4556 4557 |
} else {
xs += s.shrink
}
}
}
// can occur when bar alone in a staff system
| | | > | 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 |
} else {
xs += s.shrink
}
}
}
// can occur when bar alone in a staff system
if (!xx) {
realwidth = 0
return
}
// last line?
ll = !tsnext || // yes
(tsnext.type == C.BLOCK // no, but followed by %%command
&& !tsnext.play)
|| blocks.length // (abcm2ps compatibility)
// strong shrink
if (xmin >= width) {
if (xmin > width)
error(1, s, "Line too much shrunk $1 $2 $3",
xmin.toFixed(1),
|
| ︙ | ︙ | |||
4634 4635 4636 4637 4638 4639 4640 |
for (g = s.extra; g; g = g.next)
g.x += x
}
}
// set the starting symbols of the voices for the new music line
function set_sym_line() {
| | | | | > > | | | > > > > > > | 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 |
for (g = s.extra; g; g = g.next)
g.x += x
}
}
// set the starting symbols of the voices for the new music line
function set_sym_line() {
var p_v, s,
v = voice_tb.length
// set the first symbol of each voice
while (--v >= 0) {
p_v = voice_tb[v]
if (p_v.sym && p_v.s_prev)
p_v.sym.prev = p_v.s_prev
s = p_v.s_next // (set in set_piece)
p_v.sym = s
if (s) {
if (s.prev)
s.prev.next = s
p_v.s_prev = s.prev // (save for play)
s.prev = null
} else {
p_v.s_prev = null
}
}
}
// set the left offset the images
function set_posx() {
posx = img.lm / cfmt.scale
}
|
| ︙ | ︙ | |||
4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 | return default: continue case C.STAVES: cur_sy = s.sy break case C.BLOCK: block_gen(s) break } unlksym(s) if (s.p_v.s_next == s) s.p_v.s_next = s.next } tsfirst = null /* no more notes */ } /* -- generate the music -- */ // (possible hook) | > > | | > | 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 |
return
default:
continue
case C.STAVES:
cur_sy = s.sy
break
case C.BLOCK:
if (s.play)
continue // keep for play
block_gen(s)
break
}
unlksym(s)
if (s.p_v.s_next == s)
s.p_v.s_next = s.next
}
tsfirst = null /* no more notes */
}
/* -- generate the music -- */
// (possible hook)
Abc.prototype.output_music = function() {
var v, lwidth, indent, line_height, ts1st, tslast, p_v
gen_init()
if (!tsfirst)
return
tunes.push([tsfirst, voice_tb]) // keep tune data for playing
set_global()
if (voice_tb.length > 1) /* if many voices */
self.set_stem_dir() // set the stems direction in 'multi'
for (v = 0; v < voice_tb.length; v++)
set_beams(voice_tb[v].sym); /* decide on beams */
|
| ︙ | ︙ | |||
4715 4716 4717 4718 4719 4720 4721 |
set_allsymwidth(); /* set the width of all symbols */
indent = set_indent(true)
/* if single line, adjust the page width */
if (cfmt.singleline) {
v = get_ck_width();
| | > > > > > > | | | | < > > > > > > > > > > > > > > > | 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 |
set_allsymwidth(); /* set the width of all symbols */
indent = set_indent(true)
/* if single line, adjust the page width */
if (cfmt.singleline) {
v = get_ck_width();
lwidth = indent + v[0] + v[1] + get_width(tsfirst, null)[0];
img.width = lwidth * cfmt.scale + img.lm + img.rm + 2
} else {
/* else, split the tune into music lines */
lwidth = get_lwidth();
cut_tune(lwidth, indent)
}
// save symbol pointers for play
ts1st = tsfirst
v = voice_tb.length
while (--v >= 0)
voice_tb[v].osym = voice_tb[v].sym
spf_last = 1.2 // last spacing factor
while (1) { /* loop per music line */
set_piece();
self.set_sym_glue(lwidth - indent)
if (realwidth) {
if (indent)
posx += indent;
draw_sym_near(); // delayed output
line_height = set_staff();
draw_systems(indent);
draw_all_sym();
delayed_update();
vskip(line_height)
if (indent) {
posx -= indent;
insert_meter &= ~2 // no more indentation
}
while (blocks.length)
block_gen(blocks.shift())
}
if (cfmt.splittune)
blk_flush()
else
svg_flush()
if (tslast)
tslast.ts_next.ts_prev = tslast
if (!tsnext)
break
tsnext.ts_prev.ts_next = // (restore for play)
tsfirst = tsnext
// next line
gen_init()
if (!tsfirst)
break
tslast = tsfirst.ts_prev
tsfirst.ts_prev = null;
set_sym_line();
lwidth = get_lwidth() // the image size may have changed
indent = set_indent()
}
// restore for play
tsfirst = ts1st
v = voice_tb.length
while (--v >= 0) {
p_v = voice_tb[v]
if (p_v.sym && p_v.s_prev)
p_v.sym.prev = p_v.s_prev
p_v.sym = p_v.osym
}
}
/* -- reset the generator -- */
function reset_gen() {
insert_meter = cfmt.writefields.indexOf('M') >= 0 ?
3 : /* insert meter and indent */
2 /* indent only */
}
|
Changes to core/parse.js.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 | // // You should have received a copy of the GNU Lesser General Public License // along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>. var a_gch, // array of parsed guitar chords a_dcn, // array of parsed decoration names multicol, // multi column object | | < < < < < | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
var a_gch, // array of parsed guitar chords
a_dcn, // array of parsed decoration names
multicol, // multi column object
maps = {} // maps object - see set_map()
var qplet_tb = new Int8Array([ 0, 1, 3, 2, 3, 0, 2, 0, 3, 0 ]),
ntb = "CDEFGABcdefgab"
// set the source references of a symbol
function set_ref(s) {
s.fname = parse.fname;
s.istart = parse.istart;
s.iend = parse.iend
}
|
| ︙ | ︙ | |||
93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
break
case 'p':
i = 4
case 'P': // perc
s.clef_type = "p";
s.clef_line = 3;
curvoice.key.k_sf = 0; // no accidental
curvoice.ckey.k_drum = true // no transpose
break
default:
syntax(1, "Unknown clef '$1'", clef_def)
return //undefined
}
if (clef_def[i] >= '1' && clef_def[i] <= '9') {
| > > > | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
break
case 'p':
i = 4
case 'P': // perc
s.clef_type = "p";
s.clef_line = 3;
curvoice.key.k_sf = 0; // no accidental
curvoice.ckey.k_sf = 0
curvoice.ckey.k_map = abc2svg.keys[7]
curvoice.ckey.k_b40 = 2
curvoice.ckey.k_drum = true // no transpose
break
default:
syntax(1, "Unknown clef '$1'", clef_def)
return //undefined
}
if (clef_def[i] >= '1' && clef_def[i] <= '9') {
|
| ︙ | ︙ | |||
120 121 122 123 124 125 126 | case '-': s.clef_octave = -7 break } return s } | < | < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > > | | | < < < < | | | < < < < < < < < < < < < < < | < | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
case '-':
s.clef_octave = -7
break
}
return s
}
// convert an interval to a base-40 interval
function get_interval(param, score) {
var i, val, tmp, note, pit
tmp = new scanBuf;
tmp.buffer = param
pit = []
for (i = 0; i < 2; i++) {
note = tmp.buffer[tmp.index] ? parse_acc_pit(tmp) : null
if (!note) {
if (i != 1 || !score) {
syntax(1, "Bad transpose value")
return
}
pit[i] = 23 // 'c' (C5)
} else {
pit[i] = abc2svg.pab40(note.pit, note.acc)
}
}
return pit[1] - pit[0]
}
// set the linebreak character
function set_linebreak(param) {
var i, item
for (i = 0; i < 128; i++) {
|
| ︙ | ︙ | |||
238 239 240 241 242 243 244 |
char_tb[item.charCodeAt(0)] = '\n'
}
}
// set a new user character (U: or %%user)
function set_user(parm) {
var k, c, v,
| | | < < < < > | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
char_tb[item.charCodeAt(0)] = '\n'
}
}
// set a new user character (U: or %%user)
function set_user(parm) {
var k, c, v,
a = parm.match(/(.)[= ]*(\[I:.+\]|".+"|!.+!)$/)
if (!a) {
syntax(1, 'Lack of starting [, ! or " in U: / %%user')
return
}
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
}
|
| ︙ | ︙ | |||
294 295 296 297 298 299 300 |
break
}
char_tb[k] = v
}
// get a stafflines value
function get_st_lines(param) {
| < < | < < < | < < | < | | | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
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 = parseInt(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
}
if (parse.state == 2)
goto_tune()
sym_link(s)
return s
}
// set the voice parameters
// (possible hook)
Abc.prototype.set_vp = function(a) {
var s, item, pos, val, clefpit
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
|
| ︙ | ︙ | |||
384 385 386 387 388 389 390 | else curvoice[item.slice(0, -1)] = val break case "cue=": curvoice.scale = a.shift() == 'on' ? .7 : 1 break case "instrument=": | > > > > > > > > > > > > > | | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
else
curvoice[item.slice(0, -1)] = val
break
case "cue=":
curvoice.scale = a.shift() == 'on' ? .7 : 1
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 = 0
curvoice.sndtran = get_interval('c' + item)
} else {
curvoice.sndtran = get_interval('c' +
item.slice(val + 1))
val = get_interval(item.replace('/', ''))
}
curvoice.transp = cfmt.sound ? curvoice.sndtran : val
break
case "map=": // %%voicemap
curvoice.map = a.shift()
break
case "name=":
case "nm=":
curvoice.nm = a.shift()
|
| ︙ | ︙ | |||
419 420 421 422 423 424 425 426 427 | val = parseFloat(a.shift()) if (isNaN(val) || val < .6 || val > 1.5) syntax(1, errs.bad_val, "%%voicescale") else curvoice.scale = val break case "score=": if (cfmt.sound) break | > > > < < < | > > > > | < | | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 | val = parseFloat(a.shift()) if (isNaN(val) || val < .6 || val > 1.5) syntax(1, errs.bad_val, "%%voicescale") else curvoice.scale = val break case "score=": // score=MN // (score=M == score=Mc) item = a.shift() if (cfmt.sound) break curvoice.transp = get_transp(item) break case "shift=": curvoice.shift = curvoice.sndsh = get_interval(a.shift()) break case "sound=": case "transpose=": // (abcMIDI compatibility) // concert-score display: apply sound= // sounding-score display: apply sound= only if M != c/C // sound: apply sound= curvoice.sndtran = get_interval(a.shift()) if (cfmt.sound) curvoice.transp = curvoice.sndtran break case "subname=": case "sname=": case "snm=": curvoice.snm = a.shift() if (curvoice.snm[0] == '"') curvoice.snm = curvoice.snm.slice(1, -1); |
| ︙ | ︙ | |||
512 513 514 515 516 517 518 |
if (info.V) {
if (info.V['*'])
a = info.V['*'].concat(a)
if (info.V[curvoice.id])
a = info.V[curvoice.id].concat(a)
}
}
| | | | > | | | < | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < | > > | > < | > | | | | | | | | | | | > > | | > | > > > > > > > > > > > > > > | 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 |
if (info.V) {
if (info.V['*'])
a = info.V['*'].concat(a)
if (info.V[curvoice.id])
a = info.V[curvoice.id].concat(a)
}
}
if (a.length)
self.set_vp(a)
} // set_kv_parm()
// memorize the K:/V: parameters
function memo_kv_parm(vid, // voice ID (V:) / '*' (K:/V:*)
a) { // array of items
if (!a.length)
return
if (!info.V)
info.V = {}
if (info.V[vid])
Array.prototype.push.apply(info.V[vid], a)
else
info.V[vid] = a
}
// K: key signature
// return the key and the voice/clef parameters
function new_key(param) {
var i, clef, key_end, c, tmp, exp,
sf = "FCGDAEB".indexOf(param[0]) - 1,
mode = 0,
s = {
type: C.KEY,
dur:0
}
// set the accidentals when K: with modified accidentals
function set_k_acc(s, sf) {
var i, j, n, nacc, p_acc,
accs = [],
pits = [],
m_n = [],
m_d = []
if (sf > 0) {
for (nacc = 0; nacc < sf; nacc++) {
accs[nacc] = 1; // sharp
pits[nacc] = [26, 23, 27, 24, 21, 25, 22][nacc]
}
} else {
for (nacc = 0; nacc < -sf; nacc++) {
accs[nacc] = -1; // flat
pits[nacc] = [22, 25, 21, 24, 20, 23, 26][nacc]
}
}
n = s.k_a_acc.length
for (i = 0; i < n; i++) {
p_acc = s.k_a_acc[i]
for (j = 0; j < nacc; j++) {
if (pits[j] == p_acc.pit) {
accs[j] = p_acc.acc
if (p_acc.micro_n) {
m_n[j] = p_acc.micro_n;
m_d[j] = p_acc.micro_d
}
break
}
}
if (j == nacc) {
accs[j] = p_acc.acc;
pits[j] = p_acc.pit
if (p_acc.micro_n) {
m_n[j] = p_acc.micro_n;
m_d[j] = p_acc.micro_d
}
nacc++
}
}
for (i = 0; i < nacc; i++) {
p_acc = s.k_a_acc[i]
if (!p_acc)
p_acc = s.k_a_acc[i] = {}
p_acc.acc = accs[i];
p_acc.pit = pits[i]
if (m_n[i]) {
p_acc.micro_n = m_n[i];
p_acc.micro_d = m_d[i]
} else {
delete p_acc.micro_n
delete p_acc.micro_d
}
}
} // set_k_acc()
// code of new_key()
set_ref(s);
// tonic
i = 1
if (sf < -1) {
switch (param[0]) {
case 'H': // bagpipe
switch (param[1]) {
case 'P':
case 'p':
s.k_bagpipe = param[1];
sf = param[1] == 'P' ? 0 : 2;
i++
break
default:
syntax(1, "Unknown bagpipe-like key")
key_end = true
break
}
break
case 'P':
syntax(1, "K:P is deprecated");
sf = 0;
s.k_drum = true;
key_end = true
break
case 'n': // none
if (param.indexOf("none") == 0) {
sf = 0;
s.k_none = true;
i = 4
break
}
// fall thru
default:
return [s, info_split(param)]
}
}
if (!key_end) {
switch (param[i]) {
case '#': sf += 7; i++; break
case 'b': sf -= 7; i++; break
}
param = param.slice(i).trim()
switch (param.slice(0, 3).toLowerCase()) {
default:
if (param[0] != 'm'
|| (param[1] != ' ' && param[1] != '\t'
&& param[1] != '\n')) {
key_end = true
break
}
// fall thru ('m')
case "aeo":
case "m":
case "min": sf -= 3;
mode = 5
break
case "dor": sf -= 2;
mode = 1
break
case "ion":
case "maj": break
case "loc": sf -= 5;
mode = 6
break
case "lyd": sf += 1;
mode = 3
break
case "mix": sf -= 1;
mode = 4
break
case "phr": sf -= 4;
mode = 2
break
}
if (!key_end)
param = param.replace(/\w+\s*/, '')
// [exp] accidentals
if (param.indexOf("exp ") == 0) {
param = param.replace(/\w+\s*/, '')
if (!param)
syntax(1, "No accidental after 'exp'");
exp = true
}
c = param[0]
if (c == '^' || c == '_' || c == '=') {
s.k_a_acc = [];
tmp = new scanBuf;
tmp.buffer = param
do {
var note = parse_acc_pit(tmp)
if (!note)
break
s.k_a_acc.push(note);
c = param[tmp.index]
while (c == ' ')
c = param[++tmp.index]
} while (c == '^' || c == '_' || c == '=');
if (!exp)
set_k_acc(s, sf)
param = param.slice(tmp.index)
} else if (exp && param.indexOf("none") == 0) {
sf = 0
param = param.replace(/\w+\s*/, '')
}
}
s.k_sf = sf;
// set the map of the notes with accidentals
if (s.k_a_acc) {
s.k_map = []
i = s.k_a_acc.length
while (--i >= 0) {
note = s.k_a_acc[i]
s.k_map[(note.pit + 19) % 7] = note.acc
}
} else {
s.k_map = abc2svg.keys[sf + 7]
}
s.k_mode = mode
// key note as base-40
s.k_b40 = [1,24,7,30,13,36,19, 2 ,25,8,31,14,37,20,3][sf + 7]
return [s, info_split(param)]
}
// M: meter
function new_meter(p) {
var s = {
type: C.METER,
|
| ︙ | ︙ | |||
693 694 695 696 697 698 699 |
m2 = 4
}
break
case 'c':
case 'o':
meter.top = p[i++]
if (!m1) {
| | | | | | > | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 |
m2 = 4
}
break
case 'c':
case 'o':
meter.top = p[i++]
if (!m1) {
if (p[i - 1] == 'c') {
m1 = 2;
m2 = 4 // c = 2/4
} else {
m1 = 3;
m2 = 4 // o = 3/4
}
switch (p[i]) {
case '|':
m2 /= 2 // c| = 2/2, o| = 3/2
break
case '.':
m1 *= 3;
m2 *= 2 // c. = 6/8, o. = 9/8
break
}
}
break
case '.':
case '|':
m1 = 0;
meter.top = p[i++]
break
case '(':
if (p[i + 1] == '(') { /* "M:5/4 ((2+3)/4)" */
in_parenth = true;
meter.top = p[i++];
s.a_meter.push(meter);
|
| ︙ | ︙ | |||
835 836 837 838 839 840 841 |
sym_link(s)
}
}
}
/* Q: tempo */
function new_tempo(text) {
| | | | | | > > > > > > > > > > > > > > > > | | | > > | > | < > > > | > | | | | < | | | > > | | | < < < < < < < < < < < < < | | | | < | | > | | | | | < < < < | < < < < | | | | < > | 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 |
sym_link(s)
}
}
}
/* Q: tempo */
function new_tempo(text) {
var i, c, d, nd,
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 = Number(nd[2])
if (d && !isNaN(d) && !(d & (d - 1))) {
n = Number(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.del = 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 = Number(text)
if (!s.tempo || isNaN(s.tempo)) {
syntax(1, "Bad tempo value")
return
}
}
}
if (parse.state != 3) {
if (parse.state == 1) { // tune header
info.Q = text;
glovar.tempo = s
return
|
| ︙ | ︙ | |||
1027 1028 1029 1030 1031 1032 1033 | break new_tempo(text) break case 'V': get_voice(text) break | | | | 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 | break new_tempo(text) break case 'V': get_voice(text) break // key signature at end of tune header or in tune body case 'K': if (!parse.state) // ignore if in file header break get_key(text) break // info in any state case 'N': case 'R': |
| ︙ | ︙ | |||
1063 1064 1065 1066 1067 1068 1069 |
}
}
// music line parsing functions
/* -- adjust the duration and time of symbols in a measure when L:auto -- */
function adjust_dur(s) {
| | > | | | | < | 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 |
}
}
// music line parsing functions
/* -- adjust the duration and time of symbols in a measure when L:auto -- */
function adjust_dur(s) {
var s2, time, auto_time, i, fac;
/* search the start of the measure */
s2 = curvoice.last_sym
if (!s2)
return;
/* the bar time is correct if there are multi-rests */
if (s2.type == C.MREST
|| s2.type == C.BAR) /* in second voice */
return
while (s2.type != C.BAR && s2.prev)
s2 = s2.prev;
time = s2.time;
auto_time = curvoice.time - time
fac = curvoice.wmeasure / auto_time
/* remove the invisible rest at start of tune */
if (time == 0) {
while (s2 && !s2.dur)
s2 = s2.next
if (s2 && s2.type == C.REST
&& s2.invis) {
time += s2.dur * fac
if (s2.prev)
s2.prev.next = s2.next
else
curvoice.sym = s2.next
if (s2.next)
s2.next.prev = s2.prev;
s2 = s2.next
}
}
if (curvoice.wmeasure == auto_time)
return /* already good duration */
for ( ; s2; s2 = s2.next) {
s2.time = time
if (!s2.dur || s2.grace)
continue
s2.dur *= fac;
s2.dur_orig *= fac;
time += s2.dur
if (s2.type != C.NOTE && s2.type != C.REST)
continue
for (i = 0; i <= s2.nhd; i++)
s2.notes[i].dur *= fac
}
curvoice.time = s.time = time
}
/* -- parse a bar -- */
function new_bar() {
var s2, c, bar_type,
|
| ︙ | ︙ | |||
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 |
}
if (bar_type[0] == ':') {
if (bar_type.length == 1) { // ":" alone
bar_type = '|';
s.bar_dotted = true
} else {
s.rbstop = 2 // right repeat with end
}
}
// set the guitar chord and the decorations
if (a_gch)
self.gch_build(s)
if (a_dcn) {
deco_cnv(a_dcn, s);
a_dcn = null
}
// set the start/stop of ottava
| > > | | < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | | 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 |
}
if (bar_type[0] == ':') {
if (bar_type.length == 1) { // ":" alone
bar_type = '|';
s.bar_dotted = true
} else {
s.rbstop = 2 // right repeat with end
if (curvoice.tie_s)
curvoice.tie_s.tie_s = s
}
}
// set the guitar chord and the decorations
if (a_gch)
self.gch_build(s)
if (a_dcn) {
deco_cnv(a_dcn, s);
a_dcn = null
}
// set the start/stop of ottava
if (parse.ottava.length) {
s2 = s
if (curvoice.cst != curvoice.st) { // if staff change
s2 = {
type: C.SPACE, // put the decoration on a ...
fname: parse.fname,
istart: parse.bol + line.index,
dur: 0,
multi: 0,
invis: true,
width: 1 // .. small space
}
sym_link(s2)
}
s2.ottava = parse.ottava
parse.ottava = []
}
/* if the last element is '[', it may start
* a chord or an embedded header */
switch (bar_type.slice(-1)) {
case '[':
if (/[0-9" ]/.test(c)) // "
break
bar_type = bar_type.slice(0, -1);
line.index--;
c = '['
break
case ':': // left repeat
s.rbstop = 2 // with bracket end
break
}
// check if repeat bar
if (c > '0' && c <= '9') {
s.text = c
while (1) {
c = line.next_char()
if ("0123456789,.-".indexOf(c) < 0)
break
s.text += c
}
s.rbstop = 2;
s.rbstart = 2
} else if (c == '"' && bar_type.slice(-1) == '[') {
s.text = ""
while (1) {
c = line.next_char()
if (!c) {
syntax(1, "No end of repeat string")
return
}
if (c == '"') {
line.index++
break
}
s.text += c
}
s.rbstop = 2;
s.rbstart = 2
}
// ']' as the first character indicates a repeat bar stop
if (bar_type[0] == ']') {
s.rbstop = 2 // with end
if (bar_type.length != 1)
bar_type = bar_type.slice(1)
else
s.invis = true
}
s.iend = parse.bol + line.index
if (s.rbstart
&& curvoice.norepbra
&& !curvoice.second)
s.norepbra = true
// handle the accidentals (ties and repeat)
if (s.text) {
if (bar_type.slice(-1) == '[')
bar_type = bar_type.slice(0, -1)
if (s.text[0] == '1') {
if (curvoice.tie_s)
curvoice.tie_s_rep = curvoice.tie_s
if (curvoice.acc_tie)
curvoice.acc_tie_rep = curvoice.acc_tie.slice()
else if (curvoice.acc_tie_rep)
curvoice.acc_tie_rep = null
} else {
if (curvoice.tie_s_rep) {
curvoice.tie_s = clone(curvoice.tie_s_rep)
curvoice.tie_s.notes = clone(curvoice.tie_s.notes)
for (var m = 0; m <= curvoice.tie_s.nhd; m++) {
curvoice.tie_s.notes[m] =
clone(curvoice.tie_s.notes[m])
curvoice.tie_s.notes[m].s =
curvoice.tie_s
}
}
if (curvoice.acc_tie_rep)
curvoice.acc_tie = curvoice.acc_tie_rep.slice()
}
}
curvoice.acc = [] // no accidental anymore
if (curvoice.ulen < 0) // L:auto
adjust_dur(s);
s2 = curvoice.last_sym
if (s2 && s2.time == curvoice.time) {
if (bar_type == "["
|| bar_type == "|:") {
// search if a previous bar at this time
do {
if (s2.type == C.BAR)
break
if (w_tb[s2.type]) // symbol with a width
|
| ︙ | ︙ | |||
1376 1377 1378 1379 1380 1381 1382 | err = false, flags = 0, brace = 0, bracket = 0, parenth = 0, flags_st = 0, e, | | | | 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 |
err = false,
flags = 0,
brace = 0,
bracket = 0,
parenth = 0,
flags_st = 0,
e,
a = p.match(/[^[\]|{}()*+\s]+|[^\s]/g)
if (!a) {
syntax(1, errs.bad_val, "%%score")
return // null
}
while (1) {
e = a.shift()
if (!e)
break
switch (e) {
|
| ︙ | ︙ | |||
1427 1428 1429 1430 1431 1432 1433 | case '*': if (brace && !parenth && !(flags & (OPEN_BRACE | OPEN_BRACE2))) flags |= FL_VOICE break case '+': flags |= MASTER_VOICE break | | | > | | | < < | | 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 |
case '*':
if (brace && !parenth && !(flags & (OPEN_BRACE | OPEN_BRACE2)))
flags |= FL_VOICE
break
case '+':
flags |= MASTER_VOICE
break
case ']':
case '}':
case ')':
syntax(1, "Bad voice ID in %%score");
err = true
break
default: // get / create the voice in the voice table
vid = e
while (1) {
e = a.shift()
if (!e)
break
switch (e) {
case ']':
|
| ︙ | ︙ | |||
1491 1492 1493 1494 1495 1496 1497 |
if (!e)
break
a.unshift(e)
break
}
}
if (flags_st != 0) {
| | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 |
if (!e)
break
a.unshift(e)
break
}
}
if (flags_st != 0) {
syntax(1, "'}', ')' or ']' missing in %%score");
err = true
}
if (err || !a_vf.length)
return //null
return a_vf
}
// split an info string
function info_split(text) {
if (!text)
return []
var a = text.match(/=?[^\s"=]+=?|".+?"/g) // "
if (!a) {
//fixme: bad error text
syntax(1, "Unterminated string")
return []
}
return a
}
// parse a duration and return [numerator, denominator]
// 'line' is not always 'parse.line'
var reg_dur = /(\d*)(\/*)(\d*)/g /* (stop comment) */
function parse_dur(line) {
var res, num, den;
|
| ︙ | ︙ | |||
1646 1647 1648 1649 1650 1651 1652 |
while (c == ',') {
pit -= 7;
c = line.next_char()
}
note = {
pit: pit,
shhd: 0,
| | < > | > > | < | | | > > | < < < < | < < | < | > | < < | > | | > > > > > | 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 |
while (c == ',') {
pit -= 7;
c = line.next_char()
}
note = {
pit: pit,
shhd: 0,
shac: 0
}
if (acc) {
note.acc = acc
if (micro_n) {
note.micro_n = micro_n;
note.micro_d = micro_d
}
}
return note
}
/* set the mapping of a note */
//
// The global 'maps' object is indexed by the map name.
// Its content is an object ('map') indexed from the map type:
// - normal = b40 pitch
// - octave = 'o' + b40 pitch in C..B interval
// - key = 'k' + scale index
// - all = 'all'
// The 'map' is stored in the note. It is an array of
// [0] array of heads (glyph names)
// [1] print (note)
// [2] color
// [3] play (b40)
function set_map(note) {
var map = maps[curvoice.map], // never null
n = note.b40,
nn = n.toString()
if (!map[nn]) {
nn = 'o' + (n % 40).toString() // octave
if (!map[nn]) {
n += 2 - curvoice.ckey.k_b40 // key
nn = 'k' + (abc2svg.b40_p[n % 40]).toString()
if (!map[nn]) {
nn = 'all' // 'all'
if (!map[nn])
return
}
}
}
note.map = map[nn]
if (note.map[1]) { // if print map
note.pit = note.map[1].pit
note.acc = note.map[1].acc
}
if (note.map[2]) // if color
note.color = note.map[2]
nn = note.map[3]
if (nn) // if play map
note.b40 = nn
}
/* -- parse note or rest with pitch and length -- */
// 'line' is not always 'parse.line'
function parse_basic_note(line, ulen) {
var nd,
note = parse_acc_pit(line)
|
| ︙ | ︙ | |||
1719 1720 1721 1722 1723 1724 1725 |
}
nd = parse_dur(line);
note.dur = ulen * nd[0] / nd[1]
return note
}
function parse_vpos() {
| < | | | | | | | | | | < < < | | | | > > | | | < | > > > > > | > | | > > > | < | < < < < | < < | | > | < < | < > | > | > > > > > > > > > > > | > > > | | < < < > | < < < < < < < < < < < < < < | < > > > | | | > | < < < < < < < < < | < | | < | | | | < > | < < < | | | < < | > | | | | < > > | | | | | > > > > > > > | > > > | | | < < < < < > | | < < < < < < | 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 |
}
nd = parse_dur(line);
note.dur = ulen * nd[0] / nd[1]
return note
}
function parse_vpos() {
var line = parse.line,
ty = 0
if (line.buffer[line.index - 1] == '.' && !a_dcn)
ty = C.SL_DOTTED
switch (line.next_char()) {
case "'":
line.index++
return ty + C.SL_ABOVE
case ",":
line.index++
return ty + C.SL_BELOW
}
return ty + C.SL_AUTO
}
// on end of slur, create the slur
function slur_add(enote, e_is_note) {
var i, s, sl, snote, s_is_note
// go back and find the last start of slur
for (i = curvoice.sls.length; --i >= 0; ) {
sl = curvoice.sls[i]
snote = sl.note
s_is_note = sl.is_note
delete sl.is_note
// the slur must not start and stop on a same symbol
if (snote.s != enote.s) {
sl.note = enote
if (e_is_note)
sl.is_note = e_is_note
s = s_is_note ? snote : snote.s
if (!s.sls)
s.sls = [];
s.sls.push(sl)
curvoice.sls.splice(i, 1)
// set a flag on the start symbol if slur from a note
if (s_is_note)
snote.s.sl1 = true
// set a flag if the slur starts on a grace note
if (sl.grace)
sl.grace.sl1 = true
// set a flag if the slur ends on a grace note
if (enote.s.grace)
enote.s.sl2 = true
return
}
}
if (enote.grace) {
error(1, enote.s, errs.bad_slur_end)
return
}
// the lack of a starting slur may be due to a repeat
for (s = enote.s.prev; s; s = s.prev) {
if (s.type == C.BAR
&& s.bar_type[0] == ':'
&& s.text) {
if (!s.sls)
s.sls = [];
s.sls.push({
note: enote,
//fixme: should go back to the bar "|1" and find the slur type...
ty: C.SL_AUTO
})
if (e_is_note)
s.sls[s.sls.length - 1].is_note = e_is_note
return
}
}
syntax(1, "Lack of starting slur")
}
// (possible hook)
Abc.prototype.new_note = function(grace, sls) {
var note, s, in_chord, c, dcn, type, tie_s, acc_tie,
i, n, s2, nd, res, num, dur, apit,
sl1 = [],
line = parse.line,
a_dcn_sav = a_dcn // save parsed decoration names
if (!grace
&& curvoice.tie_s) { // if tie from previous note / grace note
tie_s = curvoice.tie_s
curvoice.tie_s = null
}
// handle the ties
function do_ties(s, tie_s) {
var m, note
for (m = 0; m <= s.nhd; m++) {
note = s.notes[m]
if (tie_s.type != C.GRACE) {
for (i = 0; i <= tie_s.nhd; i++) {
if (!tie_s.notes[i].tie_ty)
continue
// (tie_s.notes[i].tie_n may exist
// on repeat restart)
if (tie_s.notes[i].b40 == note.b40) {
tie_s.notes[i].tie_n = note
note.s = s
tie_s.tie_s = s
break
}
}
} else {
for (s2 = tie_s.extra; s2; s2 = s2.next) {
if (!s2.notes[0].tie_ty)
continue
if (s2.notes[0].b40 == note.b40) {
s2.tie_s = s
s2.notes[0].tie_n = note
note.s = s
s2.notes[0].s = s2
tie_s.tie_s = s
break
}
}
}
s.ti2 = tie_s // pointer to the tie start
}
} // do_ties()
a_dcn = null;
parse.stemless = false;
s = {
type: C.NOTE,
fname: parse.fname,
stem: 0,
|
| ︙ | ︙ | |||
1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 | s.invis = true; s.dur = 0; c = line.next_char() if (c >= '0' && c <= '9') s.width = line.get_int() else s.width = 10 break case 'x': s.invis = true case 'z': s.type = C.REST; line.index++; nd = parse_dur(line); | > > | 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 | s.invis = true; s.dur = 0; c = line.next_char() if (c >= '0' && c <= '9') s.width = line.get_int() else s.width = 10 if (tie_s) curvoice.tie_s = tie_s break case 'x': s.invis = true case 'z': s.type = C.REST; line.index++; nd = parse_dur(line); |
| ︙ | ︙ | |||
1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 |
}]
break
case '[': // chord
in_chord = true;
c = line.next_char()
// fall thru
default: // accidental, chord, note
if (curvoice.uscale)
s.uscale = curvoice.uscale;
s.notes = []
// loop on the chord
while (1) {
// when in chord, get the slurs and decorations
if (in_chord) {
while (1) {
if (!c)
break
i = c.charCodeAt(0);
if (i >= 128) {
syntax(1, errs.not_ascii)
return //null
}
type = char_tb[i]
switch (type[0]) {
case '(':
| > > > > < | | 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 |
}]
break
case '[': // chord
in_chord = true;
c = line.next_char()
// fall thru
default: // accidental, chord, note
if (curvoice.acc_tie) {
acc_tie = curvoice.acc_tie
curvoice.acc_tie = null
}
if (curvoice.uscale)
s.uscale = curvoice.uscale;
s.notes = []
// loop on the chord
while (1) {
// when in chord, get the slurs and decorations
if (in_chord) {
while (1) {
if (!c)
break
i = c.charCodeAt(0);
if (i >= 128) {
syntax(1, errs.not_ascii)
return //null
}
type = char_tb[i]
switch (type[0]) {
case '(':
sl1.push(parse_vpos());
c = line.char()
continue
case '!':
if (!a_dcn)
a_dcn = []
if (type.length > 1) {
a_dcn.push(type.slice(1, -1))
|
| ︙ | ︙ | |||
2004 2005 2006 2007 2008 2009 2010 | curvoice.ulen) if (!note) return //null // transpose if (curvoice.octave) note.pit += curvoice.octave * 7 | > | > > | | < > | > > > > > > > | > > > | > > > > > > > > > > > > > < | < | < < < < | | > > > > > > > > > > > | > > > | | < < > > > > > > > > > > > > > > > > > | | < | 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 |
curvoice.ulen)
if (!note)
return //null
// transpose
if (curvoice.octave)
note.pit += curvoice.octave * 7
apit = note.pit + 19 // pitch from C-1
// get the explicit or implicit accidental
// and keep the absolute pitch in base-40
i = note.acc
if (i) {
curvoice.acc[apit] = i
} else {
i = curvoice.acc[apit]
if (!i && acc_tie)
i = acc_tie[apit]
if (!i)
i = curvoice.ckey.k_map[apit % 7] || 0
}
note.b40 = abc2svg.pab40(note.pit, i)
if (curvoice.map
&& maps[curvoice.map])
set_map(note)
// starting slurs
if (sl1.length) {
while (1) {
i = sl1.shift()
if (!i)
break
curvoice.sls.push({
is_note: true,
note: note,
ty: i
})
}
note.s = s; // link the note to the chord
}
if (a_dcn) {
note.a_dcn = a_dcn;
a_dcn = null
}
s.notes.push(note)
if (!in_chord)
break
// in chord: get the ending slurs and the ties
c = line.char()
while (1) {
switch (c) {
case ')':
note.s = s
slur_add(note, true)
c = line.next_char()
continue
case '-':
note.tie_ty = parse_vpos()
note.s = s
curvoice.tie_s = s
if (curvoice.acc[apit]
|| (acc_tie
&& acc_tie[apit])) {
if (!curvoice.acc_tie)
curvoice.acc_tie = []
curvoice.acc_tie[apit] =
curvoice.acc[apit] ||
acc_tie[apit]
}
c = line.char()
continue
case '.':
c = line.next_char()
switch (c) {
case '-':
case '(':
continue
}
syntax(1, "Misplaced dot")
break
}
break
}
if (c == ']') {
line.index++;
// adjust the chord duration
nd = parse_dur(line);
s.nhd = s.notes.length - 1
for (i = 0; i <= s.nhd ; i++) {
note = s.notes[i];
note.dur = note.dur * nd[0] / nd[1]
}
break
}
}
// handle the starting slurs
if (sls.length) {
while (1) {
i = sls.shift()
if (!i)
break
s.notes[0].s = s
curvoice.sls.push({
note: s.notes[0],
ty: i
})
if (grace)
curvoice.sls[curvoice.sls.length - 1].grace =
grace
}
}
// the duration of the chord is the duration of the 1st note
s.dur_orig = s.notes[0].dur;
s.dur = s.notes[0].dur * curvoice.dur_fact
}
if (s.grace && s.type != C.NOTE) {
syntax(1, errs.bad_grace)
return //null
}
if (s.notes) { // if note or rest
if (!grace) {
switch (curvoice.pos.stm) {
case C.SL_ABOVE: s.stem = 1; break
case C.SL_BELOW: s.stem = -1; break
case C.SL_HIDDEN: s.stemless = true; break
}
// adjust the symbol duration
num = curvoice.brk_rhythm
if (num) {
curvoice.brk_rhythm = 0;
s2 = curvoice.last_note
if (num > 0) {
n = num * 2 - 1;
s.dur = s.dur * n / num;
|
| ︙ | ︙ | |||
2128 2129 2130 2131 2132 2133 2134 | s.notes[i].dur /= div; s.dur /= div; s.dur_orig /= div if (grace.stem) s.stem = grace.stem } | > | > > > > > > > > > > > > > > > | > | > > > | < > > > | < < < < > | > | | > > > | > > | > | > | | > > > < < < < < < < < < < | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 |
s.notes[i].dur /= div;
s.dur /= div;
s.dur_orig /= div
if (grace.stem)
s.stem = grace.stem
}
curvoice.last_note = s
// get the possible ties and end of slurs
c = line.char()
while (1) {
switch (c) {
case '-':
var ty = parse_vpos()
for (i = 0; i <= s.nhd; i++) {
s.notes[i].tie_ty = ty
s.notes[i].s = s
}
if (grace)
grace.tie_s = curvoice.tie_s = grace
else
curvoice.tie_s = s
for (i = 0; i <= s.nhd; i++) {
note = s.notes[i]
apit = note.pit + 19 // pitch from C-1
if (curvoice.acc[apit]
|| (acc_tie
&& acc_tie[apit])) {
if (!curvoice.acc_tie)
curvoice.acc_tie = []
curvoice.acc_tie[apit] =
curvoice.acc[apit] ||
acc_tie[apit]
}
}
c = line.char()
continue
case ')':
s.notes[0].s = s
slur_add(s.notes[0])
c = line.next_char()
continue
case '.':
if (line.buffer[line.index + 1] != '-')
break
c = line.next_char()
continue
}
break
}
// handle the ties ending on this chord/note
if (tie_s) // if tie from previous note / grace note
do_ties(s, tie_s)
}
sym_link(s)
if (cfmt.shiftunison)
s.shiftunison = cfmt.shiftunison
if (!grace) {
if (!curvoice.lyric_restart)
curvoice.lyric_restart = s
if (!curvoice.sym_restart)
curvoice.sym_restart = s
}
if (a_dcn_sav)
deco_cnv(a_dcn_sav, s, s.prev)
if (parse.ottava.length) {
s.ottava = parse.ottava
parse.ottava = []
}
if (parse.stemless)
s.stemless = true
s.iend = parse.bol + line.index
return s
}
// adjust the duration of the elements in a tuplet
function tp_adj(s, fact) {
var tim = s.time
curvoice.time = s.time + (curvoice.time - s.time) * fact
while (1) {
//fixme: tuplets in grace notes?
s.in_tuplet = true
if (!s.grace) {
s.time = tim
if (s.dur) {
s.dur = Math.round(s.dur * fact)
tim += s.dur
}
}
if (!s.next) {
s.dur = curvoice.time - s.time
if (s.tpe)
s.tpe++
else
s.tpe = 1
break
}
s = s.next
}
} // tp_adj()
// characters in the music line (ASCII only)
var nil = "0",
char_tb = [
nil, nil, nil, nil, /* 00 - .. */
nil, nil, nil, nil,
nil, " ", "\n", nil, /* . \t \n . */
nil, nil, nil, nil,
nil, nil, nil, nil,
nil, nil, nil, nil,
|
| ︙ | ︙ | |||
2224 2225 2226 2227 2228 2229 2230 |
"n", "n", "n", "{", /* x y z { */
"|", "}", "!gmark!", nil, /* | } ~ (del) */
],
ottava = {"8va(":1, "8va)":0, "15ma(":2, "15ma)":0,
"8vb(":-1, "8vb)":0, "15mb(":-2, "15mb)":0}
function parse_music_line() {
| | | | < | 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 |
"n", "n", "n", "{", /* x y z { */
"|", "}", "!gmark!", nil, /* | } ~ (del) */
],
ottava = {"8va(":1, "8va)":0, "15ma(":2, "15ma)":0,
"8vb(":-1, "8vb)":0, "15mb(":-2, "15mb)":0}
function parse_music_line() {
var grace, last_note_sav, a_dcn_sav, no_eol, s, tps,
tp = [],
tpn = -1,
sls = [],
line = parse.line
// check if a transposing macro matches a source sequence
// if yes return the base note
function check_mac(m) {
var i, j, b
|
| ︙ | ︙ | |||
2255 2256 2257 2258 2259 2260 2261 |
while (line.buffer[j + 1] == ',') {
b -= 7;
j++
}
}
line.index = j
return b
| > | > > > > > > > > > > > > > > | | < < < < < < < < < < | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > | | | < < < < < < < | | > > > > > > > | > | > > > > | 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 |
while (line.buffer[j + 1] == ',') {
b -= 7;
j++
}
}
line.index = j
return b
} // check_mac()
// convert a note as a number into a note as a ABC string
function n2n(n) {
var c = ntb[n]
while (n < 0) {
n += 7;
c += ','
}
while (n > 14) {
n -= 7;
c += "'"
}
return c
} // n2n()
// expand a transposing macro
function expand(m, b) {
var c, i,
r = "", // result
n = m.length
for (i = 0; i < n; i++) {
c = m[i]
if (c >= 'h' && c <= 'z') {
r += n2n(b + c.charCodeAt(0) - 'n'.charCodeAt(0))
} else {
r += c
}
}
return r
} // expand()
// parse a macro
function parse_mac(k, m, b) {
var te, ti, curv, s,
line_sav = line,
istart_sav = parse.istart;
parse.line = line = new scanBuf;
parse.istart += line_sav.index;
// if the macro is not displayed
if (cfmt.writefields.indexOf('m') < 0) {
// build the display sequence from the original sequence
line.buffer = k.replace('n', n2n(b))
s = curvoice.last_sym
ti = curvoice.time // start time
parse_seq(true)
if (!s)
s = curvoice.sym
for (s = s.next ; s; s = s.next)
s.noplay = true
te = curvoice.time // end time
curv = curvoice
// and put the macro sequence in a play specific voice
curvoice = clone_voice(curv.id + '-p')
if (!par_sy.voices[curvoice.v]) {
curvoice.second = true
par_sy.voices[curvoice.v] = {
st: curv.st,
second: true,
range: curvoice.v
}
}
curvoice.time = ti
s = curvoice.last_sym
parse.line = line = new scanBuf
parse.istart += line_sav.index
line.buffer = b ? expand(m, b) : m
parse_seq(true)
if (curvoice.time != te)
syntax(1, "Bad length of the macro sequence")
if (!s)
s = curvoice.sym
for ( ; s; s = s.next)
s.invis = s.play = true
curvoice = curv
} else {
line.buffer = b ? expand(m, b) : m;
parse_seq(true)
}
parse.line = line = line_sav
parse.istart = istart_sav
} // parse_mac()
// parse a music sequence
function parse_seq(in_mac) {
var c, idx, type, k, s, dcn, i, n, text, note
while (1) {
c = line.char()
if (!c)
break
// special case for '.' (dot)
if (c == '.') {
switch (line.buffer[line.index + 1]) {
case '(':
case '-':
case '|':
c = line.next_char()
break
}
}
// check if start of a macro
if (!in_mac && maci[c]) {
n = 0
for (k in mac) {
if (!mac.hasOwnProperty(k)
|| k[0] != c)
continue
if (k.indexOf('n') < 0) {
if (line.buffer.indexOf(k, line.index)
!= line.index)
continue
line.index += k.length
} else {
n = check_mac(k)
if (!n)
continue
}
parse_mac(k, mac[k], n)
n = 1
break
}
if (n)
continue
}
idx = c.charCodeAt(0)
if (idx >= 128) {
syntax(1, errs.not_ascii)
line.index++
break
}
type = char_tb[idx]
switch (type[0]) {
case ' ': // beam break
s = curvoice.last_note
if (s) {
s.beam_end = true
if (grace)
grace.gr_shift = true
}
break
case '\n': // line break
if (cfmt.barsperstaff)
break
if (par_sy.voices[curvoice.v]
&& par_sy.voices[curvoice.v].range == 0
&& curvoice.last_sym)
curvoice.last_sym.eoln = true
break
case '&': // voice overlay
if (grace) {
syntax(1, errs.bad_grace)
break
}
c = line.next_char()
if (c == ')') {
get_vover(')')
break
}
get_vover('&')
continue
case '(': // slur start - tuplet - vover
c = line.next_char()
if (c > '0' && c <= '9') { // tuplet
if (grace) {
syntax(1, errs.bad_grace)
break
}
var pplet = line.get_int(),
qplet = qplet_tb[pplet],
rplet = pplet,
c = line.char()
if (c == ':') {
c = line.next_char()
|
| ︙ | ︙ | |||
2407 2408 2409 2410 2411 2412 2413 | continue } } } if (qplet == 0 || qplet == undefined) qplet = (curvoice.wmeasure % 9) == 0 ? 3 : 2; | < | | > | | | > | < < > | < | > > > > > > | > > > > | | < < | 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 |
continue
}
}
}
if (qplet == 0 || qplet == undefined)
qplet = (curvoice.wmeasure % 9) == 0 ?
3 : 2;
if (tpn < 0)
tpn = tp.length // new tuplet
tp.push({
p: pplet,
q: qplet,
r: rplet,
ro: rplet,
f: cfmt.tuplets
})
continue
}
if (c == '&') { // voice overlay start
if (grace) {
syntax(1, errs.bad_grace)
break
}
get_vover('(')
break
}
line.index--;
sls.push(parse_vpos())
continue
case ')': // slur end
if (curvoice.ignore)
break
s = curvoice.last_sym
if (s) {
switch (s.type) {
case C.SPACE:
if (!s.notes) {
s.notes = []
s.notes[0] = {}
}
case C.NOTE:
case C.REST:
break
case C.GRACE:
// stop the slur on the last grace note
for (s = s.extra; s.next; s = s.next)
;
break
default:
s = null
break
}
}
if (!s) {
syntax(1, errs.bad_char, c)
break
}
s.notes[0].s = s
slur_add(s.notes[0])
break
case '!': // start of decoration
if (!a_dcn)
a_dcn = []
if (type.length > 1) { // decoration letter
dcn = type.slice(1, -1)
} else {
|
| ︙ | ︙ | |||
2476 2477 2478 2479 2480 2481 2482 |
}
if (!c) {
line.index = i;
syntax(1, "No end of decoration")
break
}
}
| | | > | > > > > > | < | | < < < < < < < < < < < < < < < > > > > | < < < < | < > | < < < | < < | | < | | | | < | > | < < < < < < | > | > < < < < | < < < < < < < < < < | < < < < | > | < < | < < < < | > > > > | < > > > > | 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 |
}
if (!c) {
line.index = i;
syntax(1, "No end of decoration")
break
}
}
if (ottava[dcn] != undefined) {
glovar.ottava = true;
parse.ottava.push(ottava[dcn])
} else {
a_dcn.push(dcn)
}
break
case '"':
if (grace) {
syntax(1, errs.bad_grace)
break
}
parse_gchord(type)
break
case '[':
if (type.length > 1) { // U: [I:xxx]
self.do_pscom(type.slice(3, -1))
break
}
var c_next = line.buffer[line.index + 1]
if ('|[]: "'.indexOf(c_next) >= 0
|| (c_next >= '1' && c_next <= '9')) {
if (grace) {
syntax(1, errs.bar_grace)
break
}
new_bar()
continue
}
if (line.buffer[line.index + 2] == ':') {
if (grace) {
syntax(1, errs.bad_grace)
break
}
i = line.buffer.indexOf(']', line.index + 1)
if (i < 0) {
syntax(1, "Lack of ']'")
break
}
text = line.buffer.slice(line.index + 3, i).trim()
parse.istart = parse.bol + line.index;
parse.iend = parse.bol + ++i;
line.index = 0;
do_info(c_next, text);
line.index = i
continue
}
// fall thru ('[' is start of chord)
case 'n': // note/rest
s = self.new_note(grace, sls)
if (!s)
continue
// handle the tuplets
if (grace || !s.notes)
continue
if (tpn >= 0) { // new tuplet
s.tp = tp.slice(tpn)
tpn = -1
if (tps)
s.tp[0].s = tps // if nested
tps = s
} else if (!tps) {
continue // no tuplet active
}
k = tp[tp.length - 1]
if (--k.r > 0)
continue // not end of tuplet yet
while (1) {
tp_adj(tps, k.q / k.p)
i = k.ro // number of notes of this tuplet
if (k.s)
tps = k.s // start of upper tuplet
tp.pop() // previous level
if (!tp.length) {
tps = null // done
break
}
k = tp[tp.length - 1]
k.r -= i
if (k.r > 0)
break
}
continue
case '<': /* '<' and '>' */
if (!curvoice.last_note) {
syntax(1, "No note before '<'")
break
}
|
| ︙ | ︙ | |||
2666 2667 2668 2669 2670 2671 2672 |
s = curvoice.last_note
if (!grace || !s) {
syntax(1, errs.bad_char, c)
break
}
if (a_dcn)
syntax(1, "Decoration ignored");
| < | < > > > > > > | < < | | < < < < < > < | 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 |
s = curvoice.last_note
if (!grace || !s) {
syntax(1, errs.bad_char, c)
break
}
if (a_dcn)
syntax(1, "Decoration ignored");
grace.extra = grace.next;
grace.extra.prev = null;
grace.next = null;
curvoice.last_sym = grace;
grace = null
if (!s.prev // if one grace note
&& !curvoice.ckey.k_bagpipe) {
for (i = 0; i <= s.nhd; i++)
s.notes[i].dur *= 2;
s.dur *= 2;
s.dur_orig *= 2
}
curvoice.last_note = last_note_sav;
a_dcn = a_dcn_sav
break
case "\\":
if (!line.buffer[line.index + 1]) {
no_eol = true
break
}
// fall thru
default:
syntax(1, errs.bad_char, c)
break
}
line.index++
}
} // parse_seq()
if (parse.state != 3) { // if not in tune body
if (parse.state != 2)
return
goto_tune()
}
if (parse.tp) {
tp = parse.tp
tps = parse.tps
parse.tp = null
}
parse_seq()
if (tp.length) {
parse.tp = tp
parse.tps = tps
}
if (grace) {
syntax(1, "No end of grace note sequence");
curvoice.last_sym = grace.prev;
curvoice.last_note = last_note_sav
if (grace.prev)
grace.prev.next = null
}
if (cfmt.breakoneoln && curvoice.last_note)
curvoice.last_note.beam_end = true
if (no_eol || cfmt.barsperstaff)
return
if (char_tb['\n'.charCodeAt(0)] == '\n'
&& par_sy.voices[curvoice.v]
&& par_sy.voices[curvoice.v].range == 0
&& curvoice.last_sym)
curvoice.last_sym.eoln = true
}
|
Changes to core/subs.js.
| ︙ | ︙ | |||
92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
h = font.size,
w = 0,
n = str.length,
i0 = 0,
i = 0
el.style.font = style_font(font).slice(5);
while (1) {
i = str.indexOf('$', i)
if (i < 0)
break
c = str[i + 1]
if (c == '0') {
| > > > > > > > > > > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
h = font.size,
w = 0,
n = str.length,
i0 = 0,
i = 0
el.style.font = style_font(font).slice(5);
str = str.replace(/<|>|&[^&]*?;|&| /g, function(c){
switch (c) {
case '<': return "<"
case '>': return ">"
case '&': return "&"
case " ": return ' ' // space + nbspace
}
return c // &xxx;
})
while (1) {
i = str.indexOf('$', i)
if (i < 0)
break
c = str[i + 1]
if (c == '0') {
|
| ︙ | ︙ | |||
178 179 180 181 182 183 184 |
// output a string handling the font changes
function out_str(str) {
var n_font,
o_font = gene.curfont,
c_font = o_font;
| | > > > > > > > > > > | | < | | > > | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
// output a string handling the font changes
function out_str(str) {
var n_font,
o_font = gene.curfont,
c_font = o_font;
output += str.replace(/<|>|&[^&]*?;|&| |\$./g, function(c){
switch (c) {
case '<': return "<"
case '>': return ">"
case '&':
return "&"
case ' ':
return ' ' // space + nbspace
default:
if (c[0] != '$')
break
if (c[1] == '0')
n_font = gene.deffont
else if (c[1] >= '1' && c[1] <= '9')
n_font = get_font("u" + c[1])
else
break
c = ''
if (n_font == c_font)
return c
if (c_font != o_font)
c = "</tspan>";
c_font = n_font
if (c_font == o_font)
return c
return c + '<tspan\n\tclass="' +
font_class(n_font) + '">'
}
return c // &xxx;
})
if (c_font != o_font) {
output += "</tspan>";
gene.curfont = c_font // keep current font for next paragraph
}
}
|
| ︙ | ︙ | |||
744 745 746 747 748 749 750 |
if (info_sz[c])
sz += info_sz[c];
set_font(font);
x = xa[align];
y = ya[align] + sz
if (c == 'Q') { /* special case for tempo */
| | | > | | 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 |
if (info_sz[c])
sz += info_sz[c];
set_font(font);
x = xa[align];
y = ya[align] + sz
if (c == 'Q') { /* special case for tempo */
self.set_width(glovar.tempo)
if (!glovar.tempo.del) {
if (align != 'l') {
tempo_build(glovar.tempo)
w = glovar.tempo.tempo_wh[0]
if (align == 'c')
w *= .5;
x -= w
}
writempo(glovar.tempo, x, -y)
}
} else if (str) {
xy_str(x, -y, str, align)
}
if (c == 'T') {
font_name = info_font.T = "subtitle";
|
| ︙ | ︙ |
Changes to core/svg.js.
| ︙ | ︙ | |||
14 15 16 17 18 19 20 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>. var output = "", // output buffer | | > | | | | | > | | 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 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
var output = "", // output buffer
style = '\
\ntext, tspan{fill:currentColor}\
\n.stroke{stroke:currentColor;fill:none}\
\n.bW{stroke:currentColor;fill:none;stroke-width:1}\
\n.bthW{stroke:currentColor;fill:none;stroke-width:3}\
\n.slW{stroke:currentColor;fill:none;stroke-width:.7}\
\n.slthW{stroke:currentColor;fill:none;stroke-width:1.5}\
\n.sW{stroke:currentColor;fill:none;stroke-width:.7}\
\n.mtx{font:130% music}',
font_style = '',
posx = cfmt.leftmargin / cfmt.scale, // default x offset of the images
posy = 0, // y offset in the block
img = { // image
width: cfmt.pagewidth, // width
lm: cfmt.leftmargin, // left and right margins
rm: cfmt.rightmargin
// chg: false
},
defined_glyph = {},
defs = '',
fulldefs = '', // unreferenced defs as <filter>
stv_g = { /* staff/voice graphic parameters */
scale: 1,
dy: 0,
st: -1,
v: -1,
g: 0
// color: undefined
},
block = {} /* started & newpage */
// glyphs in music font
var tgls = {
|
| ︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
hd: {x:-3.7, y:0, c:"\ue0a4"},
ghd: {x:2, y:0, c:"\ue0a4", sc:.66}, // grace note head
pshhd: {x:-3.7, y:0, c:"\ue0a9"},
pfthd: {x:-3.7, y:0, c:"\ue0b3"},
x: {x:-3.7, y:0, c:"\ue0a9"}, // 'x' note head
"circle-x": {x:-3.7, y:0, c:"\ue0b3"}, // 'circle-x' note head
srep: {x:-5, y:0, c:"\ue101"},
diamond: {x:-4, y:0, c:"\ue1b9"},
triangle: {x:-4, y:0, c:"\ue1bb"},
dot: {x:-2, y:0, c:"\ue1e7"},
flu1: {x:-.3, y:0, c:"\ue240"}, // flags
fld1: {x:-.3, y:0, c:"\ue241"},
flu2: {x:-.3, y:0, c:"\ue242"},
fld2: {x:-.3, y:0, c:"\ue243"},
| > | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
hd: {x:-3.7, y:0, c:"\ue0a4"},
ghd: {x:2, y:0, c:"\ue0a4", sc:.66}, // grace note head
pshhd: {x:-3.7, y:0, c:"\ue0a9"},
pfthd: {x:-3.7, y:0, c:"\ue0b3"},
x: {x:-3.7, y:0, c:"\ue0a9"}, // 'x' note head
"circle-x": {x:-3.7, y:0, c:"\ue0b3"}, // 'circle-x' note head
srep: {x:-5, y:0, c:"\ue101"},
"dot+": {x:-5, y:0, sc:.7, c:"\ue101"},
diamond: {x:-4, y:0, c:"\ue1b9"},
triangle: {x:-4, y:0, c:"\ue1bb"},
dot: {x:-2, y:0, c:"\ue1e7"},
flu1: {x:-.3, y:0, c:"\ue240"}, // flags
fld1: {x:-.3, y:0, c:"\ue241"},
flu2: {x:-.3, y:0, c:"\ue242"},
fld2: {x:-.3, y:0, c:"\ue243"},
|
| ︙ | ︙ | |||
153 154 155 156 157 158 159 |
sfz: {x:-4, y:-6, c:"\ue539"},
trl: {x:-4, y:-4, c:"\ue566"}, // trill
turn: {x:-5, y:-4, c:"\ue567"},
turnx: {x:-5, y:-4, c:"\ue569"},
umrd: {x:-7, y:-2, c:"\ue56c"},
lmrd: {x:-7, y:-2, c:"\ue56d"},
dplus: {x:-4, y:10, c:"\ue582"}, // plus
| | | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
sfz: {x:-4, y:-6, c:"\ue539"},
trl: {x:-4, y:-4, c:"\ue566"}, // trill
turn: {x:-5, y:-4, c:"\ue567"},
turnx: {x:-5, y:-4, c:"\ue569"},
umrd: {x:-7, y:-2, c:"\ue56c"},
lmrd: {x:-7, y:-2, c:"\ue56d"},
dplus: {x:-4, y:10, c:"\ue582"}, // plus
sld: {x:-8, y:12, c:"\ue5d0"}, // slide
grm: {x:-2, y:0, c:"\ue5e2"}, // grace mark
dnb: {x:-4, y:0, c:"\ue610"}, // down bow
upb: {x:-3, y:0, c:"\ue612"}, // up bow
opend: {x:-2, y:0, c:"\ue614"}, // harmonic
roll: {x:0, y:0, c:"\ue618"},
thumb: {x:0, y:0, c:"\ue624"},
snap: {x:-2, y:0, c:"\ue630"},
|
| ︙ | ︙ | |||
185 186 187 188 189 190 191 |
}
// convert a meter string to a SmuFL encoded string
function m_gl(s) {
return s.replace(/[Cco]\||[co]\.|./g,
function(e) {
var m = tgls["mtr" + e]
| > | | | > | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
}
// convert a meter string to a SmuFL encoded string
function m_gl(s) {
return s.replace(/[Cco]\||[co]\.|./g,
function(e) {
var m = tgls["mtr" + e]
//fixme: !! no m.x nor m.y yet !!
// if (!m.x && !m.y)
return m.c
// return '<tspan dx="'+ m.x.toFixed(1) +
// '" dy="' + m.y.toFixed(1) +
// '">' +
// m.c + '</tspan>'
})
}
// mark a glyph as used and add it in <defs>
function def_use(gl) {
var i, j, g
|
| ︙ | ︙ | |||
276 277 278 279 280 281 282 |
// check if new sequence needed
if (stv_g.scale == 1 && !stv_g.color)
return
// open the new sequence
output += '<g '
if (stv_g.scale != 1) {
| | > > | > > > | | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
// check if new sequence needed
if (stv_g.scale == 1 && !stv_g.color)
return
// open the new sequence
output += '<g '
if (stv_g.scale != 1) {
if (stv_g.st < 0)
output += voice_tb[stv_g.v].scale_str
else if (stv_g.v < 0)
output += staff_tb[stv_g.st].scale_str
else
output += 'transform="translate(0,' +
(posy - stv_g.dy).toFixed(1) +
') scale(' + stv_g.scale.toFixed(2) + ')"'
}
if (stv_g.color) {
if (stv_g.scale != 1)
output += ' ';
output += 'color="' + stv_g.color +
'" fill="' + stv_g.color + '"'
}
output += ">\n";
stv_g.started = true
}
/* set the color */
function set_color(color) {
|
| ︙ | ︙ | |||
316 317 318 319 320 321 322 323 324 325 326 327 |
else
dy = posy
if (new_scale == stv_g.scale && dy == stv_g.dy)
return
stv_g.scale = new_scale;
stv_g.dy = dy;
stv_g.st = st;
set_g()
}
/* -- set the voice or staff scale -- */
function set_scale(s) {
| > > | > > > | > | | | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
else
dy = posy
if (new_scale == stv_g.scale && dy == stv_g.dy)
return
stv_g.scale = new_scale;
stv_g.dy = dy;
stv_g.st = st;
stv_g.v = -1;
set_g()
}
/* -- set the voice or staff scale -- */
function set_scale(s) {
var new_dy,
new_scale = s.p_v.scale
if (new_scale == 1) {
set_sscale(s.st)
return
}
new_dy = posy
if (staff_tb[s.st].staffscale != 1) {
new_scale *= staff_tb[s.st].staffscale;
new_dy = staff_tb[s.st].y
}
if (new_scale == stv_g.scale && stv_g.dy == posy)
return
stv_g.scale = new_scale;
stv_g.dy = new_dy;
stv_g.st = staff_tb[s.st].staffscale == 1 ? -1 : s.st;
stv_g.v = s.v;
set_g()
}
// -- set the staff output buffer and scale when delayed output
function set_dscale(st, no_scale) {
if (output) {
|
| ︙ | ︙ | |||
363 364 365 366 367 368 369 |
// 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) {
| < | < < < | < | 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
// 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' +
|
| ︙ | ︙ | |||
473 474 475 476 477 478 479 |
}
Abc.prototype.sx = sx
function sy(y) {
if (stv_g.g)
return -y
if (stv_g.scale == 1)
return posy - y
| | | | | 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 |
}
Abc.prototype.sx = sx
function sy(y) {
if (stv_g.g)
return -y
if (stv_g.scale == 1)
return posy - y
if (stv_g.v >= 0)
return (stv_g.dy - y) / voice_tb[stv_g.v].scale
return stv_g.dy - y // staff scale only
}
Abc.prototype.sy = sy;
Abc.prototype.sh = function(h) {
if (stv_g.st < 0)
return h / stv_g.scale
return h
}
|
| ︙ | ︙ | |||
505 506 507 508 509 510 511 |
y = sy(y);
output += x.toFixed(1) + sep + y.toFixed(1)
}
Abc.prototype.out_sxsy = out_sxsy
// define the start of a path
function xypath(x, y, fill) {
| > | > > > > > > | | | | | | | | | < | < | < | < < > | 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
y = sy(y);
output += x.toFixed(1) + sep + y.toFixed(1)
}
Abc.prototype.out_sxsy = out_sxsy
// define the start of a path
function xypath(x, y, fill) {
if (fill)
out_XYAB('<path d="mX Y', x, y)
else
out_XYAB('<path class="stroke" d="mX Y', x, y)
}
Abc.prototype.xypath = xypath
// output a glyph
function xygl(x, y, gl) {
// (avoid ps<->js loop)
// if (psxygl(x, y, gl))
// return
if (glyphs[gl]) {
def_use(gl)
out_XYAB('<use x="X" y="Y" xlink:href="#A"/>\n', x, y, gl)
} else {
var tgl = tgls[gl]
if (tgl) {
x += tgl.x * stv_g.scale;
y -= tgl.y
if (tgl.sc)
out_XYAB('<text transform="translate(X,Y) scale(A)">B</text>\n',
x, y, tgl.sc, tgl.c);
else
out_XYAB('<text x="X" y="Y">A</text>\n', x, y, tgl.c)
} else {
error(1, null, 'no definition of $1', gl)
}
}
}
// - specific functions -
// gua gda (acciaccatura)
function out_acciac(x, y, dx, dy, up) {
if (up) {
x -= 1;
y += 4
|
| ︙ | ︙ | |||
568 569 570 571 572 573 574 |
}
// staff system bracket
function out_bracket(x, y, h) {
x += posx - 5;
y = posy - y - 3;
h += 2;
| < | | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 |
}
// staff system bracket
function out_bracket(x, y, h) {
x += posx - 5;
y = posy - y - 3;
h += 2;
output += '<path d="m' + x.toFixed(1) + ' ' + y.toFixed(1) + '\n\
c10.5 1 12 -4.5 12 -3.5c0 1 -3.5 5.5 -8.5 5.5\n\
v' + h.toFixed(1) + '\n\
c5 0 8.5 4.5 8.5 5.5c0 1 -1.5 -4.5 -12 -3.5"/>\n'
}
// hyphen
function out_hyph(x, y, w) {
var n, a_y,
|
| ︙ | ︙ | |||
591 592 593 594 595 596 597 |
out_XYAB('<path class="stroke" stroke-width="1.2"\n\
stroke-dasharray="5,A"\n\
d="mX YhB"/>\n',
x, y + 6, // set the line a bit upper
Math.round((d - 5) / stv_g.scale), d * n + 5)
}
// stem [and flags]
| < | | | | | | 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 |
out_XYAB('<path class="stroke" stroke-width="1.2"\n\
stroke-dasharray="5,A"\n\
d="mX YhB"/>\n',
x, y + 6, // set the line a bit upper
Math.round((d - 5) / stv_g.scale), d * n + 5)
}
// stem [and flags]
function out_stem(x, y, h, grace,
nflags, straight) { // optional
//fixme: dx KO with half note or longa
var dx = grace ? GSTEM_XOFF : 3.5,
slen = -h
if (h < 0)
dx = -dx; // down
x += dx * stv_g.scale
if (stv_g.v >= 0)
slen /= voice_tb[stv_g.v].scale;
out_XYAB('<path class="sW" d="mX YvF"/>\n', // stem
x, y, slen)
if (!nflags)
return
y += h
if (h > 0) { // up
if (!straight) {
if (!grace) {
xygl(x, y, "flu" + nflags)
return
} else { // grace
output += '<path d="'
if (nflags == 1) {
out_XYAB('MX Yc0.6 3.4 5.6 3.8 3 10\n\
1.2 -4.4 -1.4 -7 -3 -7\n', x, y)
} else {
while (--nflags >= 0) {
out_XYAB('MX Yc1 3.2 5.6 2.8 3.2 8\n\
1.4 -4.8 -2.4 -5.4 -3.2 -5.2\n', x, y);
y -= 3.5
}
}
}
} else { // straight
output += '<path d="'
//fixme: to do
if (!grace) {
//fixme: check endpoints
y += 1
while (--nflags >= 0) {
out_XYAB('MX Yl7 3.2 0 3.2 -7 -3.2z\n',
x, y);
|
| ︙ | ︙ | |||
652 653 654 655 656 657 658 |
}
} else { // down
if (!straight) {
if (!grace) {
xygl(x, y, "fld" + nflags)
return
} else { // grace
| | | | | 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 |
}
} else { // down
if (!straight) {
if (!grace) {
xygl(x, y, "fld" + nflags)
return
} else { // grace
output += '<path d="'
if (nflags == 1) {
out_XYAB('MX Yc0.6 -3.4 5.6 -3.8 3 -10\n\
1.2 4.4 -1.4 7 -3 7\n', x, y)
} else {
while (--nflags >= 0) {
out_XYAB('MX Yc1 -3.2 5.6 -2.8 3.2 -8\n\
1.4 4.8 -2.4 5.4 -3.2 5.2\n', x, y);
y += 3.5
}
}
}
} else { // straight
output += '<path d="'
if (!grace) {
//fixme: check endpoints
y += 1
while (--nflags >= 0) {
out_XYAB('MX Yl7 -3.2 0 -3.2 -7 3.2z\n',
x, y);
y += 5.4
}
// } else { // grace
//--fixme: error?
}
}
}
output += '"/>\n'
}
// tremolo
function out_trem(x, y, ntrem) {
out_XYAB('<path d="mX Y\n\t', x - 4.5, y)
while (1) {
output += 'l9 -3v3l-9 3z'
if (--ntrem <= 0)
break
output += 'm0 5.4'
}
output += '"/>\n'
|
| ︙ | ︙ | |||
827 828 829 830 831 832 833 |
}
}
function out_lped(x, y, val, defl) {
y += 4;
if (!defl.nost)
xygl(x, y, "ped");
if (!defl.noen)
| | | 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 |
}
}
function out_lped(x, y, val, defl) {
y += 4;
if (!defl.nost)
xygl(x, y, "ped");
if (!defl.noen)
xygl(x + val + 6, y, "pedoff")
}
function out_8va(x, y, val, defl) {
if (!defl.nost) {
out_XYAB('<text x="X" y="Y" \
style="font:italic bold 12px serif">8\
<tspan dy="-4" style="font-size:10px">va</tspan></text>\n',
x - 8, y);
|
| ︙ | ︙ | |||
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 |
var name = de.dd.glyph
if (deco_l_tb[name])
deco_l_tb[name](x, y, de)
else
error(1, null, "No function for decoration '$1'", name)
}
// update the vertical offset
function vskip(h) {
posy += h
}
// create the SVG image of the block
function svg_flush() {
if (multicol || !output || !user.img_out || posy == 0)
return
var head = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > | < | < | 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 |
var name = de.dd.glyph
if (deco_l_tb[name])
deco_l_tb[name](x, y, de)
else
error(1, null, "No function for decoration '$1'", name)
}
// return a tempo note
function tempo_note(s, dur) {
var p,
elts = identify_note(s, dur)
switch (elts[0]) { // head
case C.OVAL:
p = "\ueca2"
break
case C.EMPTY:
p = "\ueca3"
break
default:
switch (elts[2]) { // flags
case 2:
p = "\ueca9"
break
case 1:
p = "\ueca7"
break
default:
p = "\ueca5"
break
}
break
}
if (elts[1])
p += '<tspan dx=".1em">\uecb7</tspan>'
return p
} // tempo_note()
// build the tempo string
function tempo_build(s) {
var i, j, bx, p, wh, dy,
w = 0,
str = []
if (s.tempo_str) // already done
return
set_font("tempo")
if (s.tempo_str1) {
str.push(s.tempo_str1)
w += strwh(s.tempo_str1)[0]
}
if (s.tempo_notes) {
dy = ' dy="-.05em"' // notes a bit higher
for (i = 0; i < s.tempo_notes.length; i++) {
p = tempo_note(s, s.tempo_notes[i])
str.push('<tspan\n\tclass="mtx"' + dy + '>' +
p + '</tspan>')
j = p.length > 1 ? 2 : 1 // (note and optional dot)
w += j * gene.curfont.swfac
dy = ''
}
str.push('<tspan dy=".065em">=</tspan>')
w += cwidf('=')
if (s.tempo_ca) {
str.push(s.tempo_ca)
w += strwh(s.tempo_ca)[0]
j = s.tempo_ca.length + 1
}
if (s.tempo) { // with a number of beats per minute
str.push(s.tempo)
w += strwh(s.tempo.toString())[0]
} else { // with a beat as a note
p = tempo_note(s, s.new_beat)
str.push('<tspan\n\tclass="mtx" dy="-.05em">' +
p + '</tspan>')
j = p.length > 1 ? 2 : 1
w += j * gene.curfont.swfac
dy = 'y'
}
}
if (s.tempo_str2) {
if (dy)
str.push('<tspan\n\tdy=".065em">' +
s.tempo_str2 + '</tspan>')
else
str.push(s.tempo_str2)
w += strwh(s.tempo_str2)[0]
}
// build the string
s.tempo_str = str.join(' ')
w += cwidf(' ') * (str.length - 1)
s.tempo_wh = [w, 13.0] // (the height is not used)
if (dy)
s.tempo_dy = dy
} // tempo_build()
// output a tempo
function writempo(s, x, y) {
var bx
set_font("tempo")
if (gene.curfont.box) {
gene.curfont.box = false
bx = x
}
//fixme: xy_str() cannot be used because <tspan> in s.tempo_str
//fixme: then there cannot be font changes by "$n" in the Q: texts
output += '<text class="' + font_class(gene.curfont) +
'" x="'
out_sxsy(x, '" y="', y + gene.curfont.size * .2)
output += '">' + s.tempo_str + '</text>\n'
if (bx) {
gene.curfont.box = true
bh = gene.curfont.size + 4;
output += '<rect class="stroke" x="'
out_sxsy(bx - 2, '" y="', y + bh - 1)
output += '" width="' + (s.tempo_wh[0] + 2).toFixed(1) +
'" height="' + bh.toFixed(1) +
'"/>\n'
}
// don't display anymore
s.del = true
} // writempo()
// update the vertical offset
function vskip(h) {
posy += h
}
// create the SVG image of the block
function svg_flush() {
if (multicol || !output || !user.img_out || posy == 0)
return
var head = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
color="',
g = ''
if (cfmt.fgcolor)
head += cfmt.fgcolor + '" fill="' + cfmt.fgcolor + '"'
else
head += 'black"';
head += ' stroke-width=".7"'
if (cfmt.bgcolor)
head += ' style="background-color: ' + cfmt.bgcolor + '"';
posy *= cfmt.scale
if (user.imagesize) {
head += '\n' +
user.imagesize +
' viewBox="0 0 ' + img.width.toFixed(0) + ' ' +
posy.toFixed(0) + '">\n'
} else {
head += '\n\twidth="' + img.width.toFixed(0) +
'px" height="' + posy.toFixed(0) + 'px">\n'
}
if (style || font_style || musicfont) {
head += '<style type="text/css">' + style + font_style
if (musicfont) {
if (musicfont.indexOf('(') > 0) {
head += '\nsvg{font:24px music}\n\
@font-face {\n\
font-family:"music";\n\
src:' + musicfont + '}';
} else {
head += '\nsvg{font:24px '+ musicfont +'}'
}
}
head += '\n</style>\n'
}
defs += fulldefs
if (defs)
head += '<defs>' + defs + '\n</defs>\n'
|
| ︙ | ︙ |
Changes to core/tail.js.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 | // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>. | < < < < < < < < < < < | 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 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// initialize
init_tune()
// Abc functions used by the modules
Abc.prototype.add_style = function(s) { style += s };
Abc.prototype.cfmt = function() { return cfmt };
Abc.prototype.clone = clone;
Abc.prototype.deco_cnv = deco_cnv;
Abc.prototype.draw_note = draw_note;
Abc.prototype.errs = errs;
Abc.prototype.font_class = font_class;
Abc.prototype.gch_tr1 = gch_tr1;
Abc.prototype.get_a_gch = function() { return a_gch };
Abc.prototype.get_bool = get_bool;
Abc.prototype.get_cur_sy = function() { return cur_sy };
Abc.prototype.get_curvoice = function() { return curvoice };
Abc.prototype.get_delta_tb = function() { return delta_tb };
Abc.prototype.get_decos = function() { return decos };
Abc.prototype.get_font = get_font;
Abc.prototype.get_font_style = function() { return font_style };
Abc.prototype.get_glyphs = function() { return glyphs };
Abc.prototype.get_img = function() { return img };
Abc.prototype.get_maps = function() { return maps };
Abc.prototype.get_multi = function() { return multicol };
Abc.prototype.get_newpage = function() {
|
| ︙ | ︙ | |||
63 64 65 66 67 68 69 |
Abc.prototype.get_top_v = function() { return par_sy.top_voice };
Abc.prototype.get_tsfirst = function() { return tsfirst };
Abc.prototype.get_unit = get_unit;
Abc.prototype.get_voice_tb = function() { return voice_tb };
Abc.prototype.goto_tune = goto_tune;
Abc.prototype.info = function() { return info };
Abc.prototype.new_block = new_block;
| < < | | < < < < < < < < < > | 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 |
Abc.prototype.get_top_v = function() { return par_sy.top_voice };
Abc.prototype.get_tsfirst = function() { return tsfirst };
Abc.prototype.get_unit = get_unit;
Abc.prototype.get_voice_tb = function() { return voice_tb };
Abc.prototype.goto_tune = goto_tune;
Abc.prototype.info = function() { return info };
Abc.prototype.new_block = new_block;
Abc.prototype.out_arp = out_arp;
Abc.prototype.out_deco_str = out_deco_str;
Abc.prototype.out_deco_val = out_deco_val;
Abc.prototype.out_ltr = out_ltr;
Abc.prototype.param_set_font = param_set_font;
Abc.prototype.parse = parse;
Abc.prototype.psdeco = empty_function;
Abc.prototype.psxygl = empty_function;
Abc.prototype.set_cur_sy = function(sy) { cur_sy = sy };
Abc.prototype.set_dscale = set_dscale;
Abc.prototype.set_font = set_font;
Abc.prototype.set_scale = set_scale;
Abc.prototype.set_tsfirst = function(s) { tsfirst = s };
Abc.prototype.set_v_param = set_v_param;
Abc.prototype.strwh = strwh;
Abc.prototype.stv_g = function() { return stv_g };
Abc.prototype.svg_flush = svg_flush;
Abc.prototype.syntax = syntax;
Abc.prototype.tunes = tunes
Abc.prototype.unlksym = unlksym;
Abc.prototype.use_font = use_font;
Abc.prototype.xy_str = xy_str;
Abc.prototype.xygl = xygl;
var hook_init // set after setting the first module hooks
|
| ︙ | ︙ | |||
126 127 128 129 130 131 132 |
}
set_hs(gh);
hook_init = true
}
} // set_hooks()
} // end of Abc()
| < < | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
}
set_hs(gh);
hook_init = true
}
} // set_hooks()
} // end of Abc()
// compatibility
var Abc = abc2svg.Abc
// nodejs
if (typeof module == 'object' && typeof exports == 'object') {
exports.abc2svg = abc2svg;
exports.Abc = Abc
}
|
Changes to core/tune.js.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 |
curvoice,
staves_found,
vover, // voice overlay
tsfirst
/* apply the %%voice options of the current voice */
function voice_filter() {
| | | < | > > > > > | > | > > | | | > > > > > > | 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 |
curvoice,
staves_found,
vover, // voice overlay
tsfirst
/* apply the %%voice options of the current voice */
function voice_filter() {
var opt
function vfilt(opts, opt) {
var i,
sel = new RegExp(opt)
if (sel.test(curvoice.id)
|| sel.test(curvoice.nm)) {
for (i = 0; i < opts.length; i++)
self.do_pscom(opts[i])
}
}
// global
if (parse.voice_opts)
for (opt in parse.voice_opts) {
if (parse.voice_opts.hasOwnProperty(opt))
vfilt(parse.voice_opts[opt], opt)
}
// tune
if (parse.tune_v_opts)
for (opt in parse.tune_v_opts) {
if (parse.tune_v_opts.hasOwnProperty(opt))
vfilt(parse.tune_v_opts[opt], opt)
}
}
/* -- link a ABC symbol into the current voice -- */
function sym_link(s) {
if (!s.fname)
set_ref(s)
if (!curvoice.ignore) {
|
| ︙ | ︙ | |||
125 126 127 128 129 130 131 | /* copy the mrest decorations to the last rest */ s2.a_dd = a_dd } /* -- sort all symbols by time and vertical sequence -- */ // weight of the symbols !! depends on the symbol type !! var w_tb = new Uint8Array([ | | | | | | | | > > > > > | > > > > > > > > > > | > | > > | < < < < < < | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
/* copy the mrest decorations to the last rest */
s2.a_dd = a_dd
}
/* -- sort all symbols by time and vertical sequence -- */
// weight of the symbols !! depends on the symbol type !!
var w_tb = new Uint8Array([
4, // bar
1, // clef
8, // custos
0, // (free)
3, // grace
5, // key
6, // meter
9, // mrest
9, // note
0, // part
9, // rest
3, // space
0, // staves
7, // stbrk
0, // tempo
0, // (free)
0, // block
0 // remark
])
function sort_all() {
var s, s2, p_voice, v, time, w, wmin, ir, multi,
prev, nb, ir2, v2, fl, new_sy,
nv = voice_tb.length,
vtb = [],
vn = [], // voice indexed by range
mrest_time = -1,
sy = cur_sy
for (v = 0; v < nv; v++)
vtb.push(voice_tb[v].sym)
// set the first symbol
ir2 = nv
multi = -1
for (v = 0; v < nv; v++) {
if (!sy.voices[v])
continue
ir = sy.voices[v].range
if (ir < ir2)
ir2 = ir
vn[ir] = v
multi++
}
v = vn[ir2]
tsfirst = prev = vtb[v]
if (!tsfirst)
return // no music
vtb[v] = tsfirst.next
prev.seqst = true
fl = !w_tb[prev.type] || tsfirst.type == tsfirst.next
// loop on the symbols of all voices
while (1) {
if (new_sy && fl) {
sy = new_sy;
new_sy = null;
multi = -1;
vn = []
for (v = 0; v < nv; v++) {
if (!sy.voices[v])
continue
ir = sy.voices[v].range
vn[ir] = v;
multi++
}
}
/* search the min time and symbol weight */
wmin = time = 1000000 /* big int */
|
| ︙ | ︙ | |||
261 262 263 264 265 266 267 |
// set all voices of previous and next staff systems
// as reachable
for (ir2 = 0; ir2 < nv; ir2++) {
if (vn[ir2] == undefined)
break
}
for (v2 = 0; v2 < nv; v2++) {
| | < < < | < | < < | | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
// set all voices of previous and next staff systems
// as reachable
for (ir2 = 0; ir2 < nv; ir2++) {
if (vn[ir2] == undefined)
break
}
for (v2 = 0; v2 < nv; v2++) {
if (!new_sy.voices[v2]
|| sy.voices[v2])
continue
vn[ir2++] = v2
}
}
if (fl) {
fl = 0;
s.seqst = true
}
s.ts_prev = prev
prev.ts_next = s
prev = s
vtb[v] = s.next
}
fl = wmin /* start a new sequence if some width */
}
}
// adjust some voice elements
function voice_adj(sys_chg) {
var p_voice, s, s2, v
// set the duration of the notes under a feathered beam
function set_feathered_beam(s1) {
var s, s2, t, d, b, i, a,
d = s1.dur,
n = 1
|
| ︙ | ︙ | |||
354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
s.next.prev = s;
p_voice.sym = s
}
}
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (p_voice.ignore)
p_voice.ignore = false
for (s = p_voice.sym; s; s = s.next) {
if (s.time >= staves_found)
break
}
for ( ; s; s = s.next) {
| > > > > > > > > > > > > > > > > > > > > > > > > | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 |
s.next.prev = s;
p_voice.sym = s
}
}
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (!sys_chg // if not %%score
&& p_voice.sls.length) { // and no end of slur
while (1) {
var sl = p_voice.sls.shift()
if (!sl)
break
s = sl.note.s
for (s2 = s.next; s2; s2 = s2.next) {
if (s2.bar_type && s2.bar_type[0] == ':')
break
}
if (s2) {
if (!s.sls)
s.sls = []
s.sls.push({
ty: sl.ty,
note: {s: s2}
})
} else {
syntax(1, "Lack of ending slur(s)")
}
}
}
if (p_voice.ignore)
p_voice.ignore = false
for (s = p_voice.sym; s; s = s.next) {
if (s.time >= staves_found)
break
}
for ( ; s; s = s.next) {
|
| ︙ | ︙ | |||
474 475 476 477 478 479 480 |
if (init) { /* first staff system */
cur_sy = par_sy = sy_new
return
}
// update the previous system
for (v = 0; v < voice_tb.length; v++) {
| | < < < | | 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 |
if (init) { /* first staff system */
cur_sy = par_sy = sy_new
return
}
// update the previous system
for (v = 0; v < voice_tb.length; v++) {
if (par_sy.voices[v]) {
st = par_sy.voices[v].st
var sy_staff = par_sy.staves[st],
p_voice = voice_tb[v]
if (p_voice.staffnonote != undefined)
sy_staff.staffnonote = p_voice.staffnonote
if (p_voice.staffscale)
sy_staff.staffscale = p_voice.staffscale;
}
}
for (st = 0; st < par_sy.staves.length; st++) {
sy_new.staves[st] = clone(par_sy.staves[st]);
sy_new.staves[st].flags = 0
}
par_sy.next = sy_new;
par_sy = sy_new
}
/* -- set the bar numbers -- */
// (possible hook)
Abc.prototype.set_bar_num = function() {
var s, s2, tim, bar_time, bar_num, rep_dtime,
v = cur_sy.top_voice,
wmeasure = voice_tb[v].meter.wmeasure,
bar_rep = gene.nbar
/* don't count a bar at start of line */
for (s = tsfirst; ; s = s.ts_next) {
|
| ︙ | ︙ | |||
565 566 567 568 569 570 571 | case C.MREST: bar_num += s.nmes - 1 while (s.ts_next && s.ts_next.type != C.BAR) s = s.ts_next break case C.BAR: | < < > > > > | > | 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 |
case C.MREST:
bar_num += s.nmes - 1
while (s.ts_next
&& s.ts_next.type != C.BAR)
s = s.ts_next
break
case C.BAR:
if (s.time < bar_time) { // incomplete measure
if (s.text && s.text[0] == '1') {
bar_rep = bar_num;
rep_dtime = bar_time - s.time
}
break
}
/* check if any repeat bar at this time */
tim = s.time;
s2 = s
do {
if (s2.dur)
break
if (s2.type == C.BAR && s2.text) // if repeat bar
break
s2 = s2.next
} while (s2 && s2.time == tim);
if (s.bar_num)
bar_num = s.bar_num // (%%setbarnb)
else
bar_num++
if (s2 && s2.type == C.BAR && s2.text) {
if (s2.text[0] == '1') {
rep_dtime = 0;
bar_rep = bar_num
} else { // restart bar numbering
if (!cfmt.contbarnb)
bar_num = bar_rep
|
| ︙ | ︙ | |||
621 622 623 624 625 626 627 |
// note mapping
// %%map map_name note [print [note_head]] [param]*
function get_map(text) {
if (!text)
return
| | | | > > > | | > | < | | | > > > | | | | | | | | | > | | | > > > > | | > > > | | | < < | < | < | | < < | > > > > | | | > > > > | | | > > > | | > | | | | | | < < < < | < | | | < | | > | | | | < | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < < < < < > > > > > > > > > > | | | 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 |
// note mapping
// %%map map_name note [print [note_head]] [param]*
function get_map(text) {
if (!text)
return
var i, note, notes, map, tmp, ns, ty,
a = info_split(text)
if (a.length < 3) {
syntax(1, not_enough_p)
return
}
ns = a[1]
if (ns[0] == '*' || ns.indexOf("all") == 0) {
ns = 'all'
} else {
if (ns.indexOf("octave,") == 0 // remove the octave part
|| ns.indexOf("key,") == 0) {
ty = ns[0]
ns = ns.split(',')[1]
ns = ns.replace(/[,']*/, '').toUpperCase(); //'
} else {
ty = ''
}
if (ty == 'k') {
ns = 'k' + ntb.indexOf(ns)
} else {
tmp = new scanBuf;
tmp.buffer = ns
note = parse_acc_pit(tmp)
if (!note) {
syntax(1, "Bad note in %%map")
return
}
ns = ty + abc2svg.pab40(note.pit, note.acc).toString()
}
}
notes = maps[a[0]]
if (!notes)
maps[a[0]] = notes = {}
map = notes[ns]
if (!map)
notes[ns] = map = []
// try the optional 'print' and 'heads' parameters
if (!a[2])
return
i = 2
if (a[2].indexOf('=') < 0) {
if (a[2][0] != '*') {
tmp = new scanBuf; // print
tmp.buffer = a[2];
map[1] = parse_acc_pit(tmp)
}
if (!a[3])
return
i++
if (a[3].indexOf('=') < 0) {
map[0] = a[3].split(',') // heads
i++
}
}
for (; i < a.length; i++) {
switch (a[i]) {
case "heads=":
if (!a[++i]) {
syntax(1, not_enough_p)
break
}
map[0] = a[i].split(',')
break
case "print=":
case "play=":
if (!a[++i]) {
syntax(1, not_enough_p)
break
}
tmp = new scanBuf;
tmp.buffer = a[i];
note = parse_acc_pit(tmp)
if (a[i - 1][1] == 'r')
map[1] = note
else
map[3] = abc2svg.pab40(note.pit, note.acc)
break
case "color=":
if (!a[++i]) {
syntax(1, not_enough_p)
break
}
map[2] = a[i]
break
}
}
}
// set the transposition in the previous or first key signature
function set_transp() {
var s, transp, sndtran
if (curvoice.ckey.k_bagpipe || curvoice.ckey.k_drum)
return
if (cfmt.transp && curvoice.transp) // if %%transpose and score=
syntax(0, "Mix of old and new transposition syntaxes");
if (cfmt.transp != undefined
|| curvoice.transp != undefined
|| curvoice.shift != undefined)
transp = (cfmt.transp || 0) + // %%transpose
(curvoice.transp || 0) + // score= / sound= / instrument=
(curvoice.shift || 0) // shift=
if (curvoice.sndtran != undefined
|| curvoice.sndsh != undefined)
sndtran = (curvoice.sndtran || 0) +
(curvoice.sndsh || 0)
if (transp == undefined) {
if (sndtran == undefined)
return
} else {
curvoice.vtransp = transp
}
if (is_voice_sig()) { // if no symbol yet
curvoice.key = s = clone(curvoice.okey)
} else {
s = curvoice.last_sym
while (1) { // set the transposition in the previous K:
if (s.type == C.KEY)
break
s = s.prev
if (!s) {
s = curvoice.key
break
}
}
}
if (transp != undefined)
s.k_transp = transp
if (sndtran != undefined)
s.k_sndtran = sndtran
curvoice.ckey = clone(s)
if (curvoice.key.k_none)
s.k_sf = 0
}
/* transpose a note / chord */
function note_transp(s, sk, note) {
var ak, an, d, b40,
n = note.pit,
a = note.acc
if (!a && sk.k_a_acc) // if accidental list
a = sk.k_map[(n + 19) % 7] // invisible accidental
b40 = abc2svg.pab40(n, a) + sk.k_transp // base-40 transposition
note.pit = abc2svg.b40p(b40) // new pitch
if (!a) { // if no old accidental
if (!sk.k_a_acc // if no accidental list
&& !sk.k_none) // and normal key
return // same accidental (in the key)
}
an = abc2svg.b40a(b40) // new accidental
if (a) {
if (sk.k_a_acc) { // if accidental list
ak = sk.k_map[(note.pit + 19) % 7]
if (ak == an)
an = 0 // accidental in the key
}
if (!an)
an = 3
} else if (sk.k_none) { // if no key
if (acc_same_pitch(s, note.pit)) // and accidental from previous notes
return // no change
} else if (sk.k_a_acc) { // if accidental list
if (acc_same_pitch(s, note.pit)) // and accidental from previous notes
return // no change
ak = sk.k_map[(note.pit + 19) % 7]
if (ak)
an = 3 // natural
} else {
return // same accidental (in the key)
}
d = note.micro_d
if (d /* microtone */
&& a != an) { /* different accidental type */
n = note.micro_n
//fixme: double sharps/flats ?*/
//fixme: does not work in all cases (tied notes, previous accidental)
switch (an) {
case 3: // natural
if (n > d / 2) {
n -= d / 2;
note.micro_n = n;
an = a
} else {
an = -a
}
break
case 2: // double sharp
if (n > d / 2) {
note.pit += 1;
n -= d / 2
} else {
n += d / 2
}
an = a
note.micro_n = n
break
case -2: // double flat
if (n >= d / 2) {
note.pit -= 1;
n -= d / 2
} else {
n += d / 2
}
an = a
note.micro_n = n
break
}
}
note.acc = an
}
// adjust the pitches according to the transposition(s)
function pit_adj() {
var i, p_v, s, sk, g,
nv = voice_tb.length
while (--nv >= 0) {
p_v = voice_tb[nv]
if (p_v.vtransp == undefined)
continue // no transposition in this voice
if (p_v.key.k_transp) {
sk = p_v.key
key_transp(sk)
} else {
sk = null
}
s = p_v.sym
while (s) {
// search a transposing key signature
if (!sk) {
for (; s; s = s.next) {
if (s.type == C.KEY
&& s.k_transp)
break
}
}
// transpose
for (; s; s = s.next) {
switch (s.type) {
case C.GRACE:
for (g = s.extra; g; g = g.next) {
for (i = 0; i <= g.nhd; i++)
note_transp(g, sk, g.notes[i])
}
continue
case C.NOTE:
for (i = 0; i <= s.nhd; i++)
note_transp(s, sk, s.notes[i])
continue
case C.KEY:
if (sk)
s.k_sf = sk.k_sf
key_transp(s)
if (!s.k_transp) // end of transposition
break
sk = s
default:
continue
}
break
}
sk = null
}
}
} // pit_adj()
// get a 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, "Bad transpose value")
return
}
val += 36
return (((val / 12) | 0) - 3) * 40 +
(param.slice(-1) == 'b' ?
abc2svg.ifb40 :
abc2svg.isb40)[val % 12]
}
return get_interval(param, true)
} // 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(/(\w|-)+/)
if (!cmd)
return
cmd = cmd[0];
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 "center":
if (parse.state >= 2) {
if (parse.state == 2)
goto_tune()
s = new_block("text");
s.text = param
s.opt = 'c'
return
}
write_text(param, 'c')
return
case "clef":
if (parse.state >= 2) {
if (parse.state == 2)
goto_tune();
s = new_clef(param)
if (s)
|
| ︙ | ︙ | |||
797 798 799 800 801 802 803 |
case "maxsysstaffsep":
if (parse.state == 3) {
par_sy.voices[curvoice.v].maxsep = get_unit(param)
return
}
break
case "multicol":
| | | 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 |
case "maxsysstaffsep":
if (parse.state == 3) {
par_sy.voices[curvoice.v].maxsep = get_unit(param)
return
}
break
case "multicol":
generate(1)
switch (param) {
case "start":
blk_out();
multicol = {
posy: posy,
maxy: posy,
lmarg: cfmt.leftmargin,
|
| ︙ | ︙ | |||
855 856 857 858 859 860 861 |
goto_tune()
}
n = parseInt(param)
if (isNaN(n) || n < -2 || n > 2) {
syntax(1, errs.bad_val, "%%ottava")
return
}
| > | | 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 |
goto_tune()
}
n = parseInt(param)
if (isNaN(n) || n < -2 || n > 2) {
syntax(1, errs.bad_val, "%%ottava")
return
}
glovar.ottava = true;
parse.ottava.push(n)
return
case "repbra":
if (parse.state >= 2) {
if (parse.state == 2)
goto_tune();
curvoice.norepbra = !get_bool(param)
}
|
| ︙ | ︙ | |||
917 918 919 920 921 922 923 | } if (h1 < 1) h1 = 14 if (h2 < 1) h2 = h1 if (len < 1) len = 90 | | | > > | > | < < | 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 |
}
if (h1 < 1)
h1 = 14
if (h2 < 1)
h2 = h1
if (len < 1)
len = 90
if (parse.state == 3) {
s = new_block(cmd);
s.x = (lwidth - len) / 2 / cfmt.scale;
s.l = len / cfmt.scale;
s.sk1 = h1;
s.sk2 = h2
return
}
blk_out();
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
}
if (parse.state == 2)
goto_tune()
glovar.new_nbar = val
return
case "staff":
if (parse.state != 3) {
if (parse.state != 2)
return
goto_tune()
}
|
| ︙ | ︙ | |||
990 991 992 993 994 995 996 | s.stbrk_forced = true } sym_link(s) return case "stafflines": case "staffscale": case "staffnonote": | | > > > > > | > > > | | > > | < < < | | 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 |
s.stbrk_forced = true
}
sym_link(s)
return
case "stafflines":
case "staffscale":
case "staffnonote":
set_v_param(cmd, param)
return
case "staves":
case "score":
if (parse.state == 0)
return
if (parse.scores && parse.scores.length > 0) {
text = parse.scores.shift();
cmd = text.match(/([^\s]+)\s*(.*)/);
get_staves(cmd[1], cmd[2])
} else {
get_staves(cmd, param)
}
return
case "sysstaffsep":
//--fixme: may be global
if (parse.state == 3) {
par_sy.voices[curvoice.v].sep = get_unit(param)
return
}
break
case "text":
if (parse.state >= 2) {
if (parse.state == 2)
goto_tune()
s = new_block(cmd);
s.text = param
s.opt = cfmt.textoption
return
}
write_text(param, cfmt.textoption)
return
case "transpose": // (abcm2ps compatibility)
if (cfmt.sound)
return
switch (parse.state) {
case 0:
cfmt.transp = 0
// fall thru
case 1:
case 2:
val = get_transp(param)
if (val)
cfmt.transp = (cfmt.transp || 0) + val
return
}
for (s = curvoice.last_sym; s; s = s.prev) {
switch (s.type) {
case C.NOTE: // insert a key
s = clone(curvoice.okey);
s.k_old_sf = curvoice.ckey.k_sf;
sym_link(s)
break
case C.KEY:
break
default:
continue
}
break
}
do_info('V', curvoice.id + ' score=' + param)
return
case "tune":
//fixme: to do
return
case "user":
set_user(param)
return
|
| ︙ | ︙ | |||
1065 1066 1067 1068 1069 1070 1071 |
return
case "vskip":
val = get_unit(param)
if (val < 0) {
syntax(1, "%%vskip cannot be negative")
return
}
| | > | > | | | | | 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 |
return
case "vskip":
val = get_unit(param)
if (val < 0) {
syntax(1, "%%vskip cannot be negative")
return
}
if (parse.state == 3) {
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 (parse.state == 2)
goto_tune()
s = new_block(cmd);
s.param = param
return
}
if (cmd == "newpage") {
blk_flush();
block.newpage = true;
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
switch (type) {
case "js":
js_inject(text)
break
case "ml":
if (parse.state == 3) {
s = new_block(type);
s.text = text
} else {
svg_flush();
if (user.img_out)
user.img_out(text)
}
|
| ︙ | ︙ | |||
1146 1147 1148 1149 1150 1151 1152 1153 1154 |
defs_add(text.slice(i + 6, j))
}
break
case "text":
action = get_textopt(opt);
if (!action)
action = cfmt.textoption
if (parse.state >= 2) {
s = new_block(type);
| > > > > > | | | | > > > > > > > > | | < | > > > | | > < < < | < < | < < < | < < < < < < < < < < | < < < < < < | | < < < < < < < < < < | | < < < | < | | < < | < < | < | < < < | < > | < < | < | < | < < < < < < < < > | | < < < < < | | | | | | | | | | 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 |
defs_add(text.slice(i + 6, j))
}
break
case "text":
action = get_textopt(opt);
if (!action)
action = cfmt.textoption
if (text.indexOf('\\') >= 0) // convert the escape sequences
text = cnv_escape(text)
if (parse.state >= 2) {
if (parse.state == 2)
goto_tune()
s = new_block(type);
s.text = text
s.opt = action
break
}
write_text(text, action)
break
}
}
/* -- generate a piece of tune -- */
function generate(in_mc) {
var s, v, p_voice;
if (parse.tp) {
syntax(1, "No end of tuplet")
s = parse.tps
if (s)
delete s.tp
delete parse.tp
}
if (vover) {
syntax(1, "No end of voice overlay");
get_vover(vover.bar ? '|' : ')')
}
if (!voice_tb.length)
return
voice_adj();
dupl_voice();
sort_all() /* define the time / vertical sequences */
if (!tsfirst)
return
self.set_bar_num()
pit_adj()
// give the parser result to the application
if (user.get_abcmodel)
user.get_abcmodel(tsfirst, voice_tb, anno_type, info)
if (user.img_out) // if SVG generation
self.output_music()
// if inside multicol, reset the parser
if (!in_mc)
return
voice_tb = Object.create(voice_tb)
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v];
p_voice.time = 0;
p_voice.sym = p_voice.last_sym = null;
// p_voice.st = cur_sy.voices[v].st;
// p_voice.second = cur_sy.voices[v].second;
// p_voice.clef.time = 0;
delete p_voice.have_ly;
p_voice.sls = [];
p_voice.hy_st = 0;
delete p_voice.bar_start
}
staves_found = 0 // (for compress/dup the voices)
}
// transpose a key
//fixme: transpose of the accidental list is not done
function key_transp(sk) {
if (sk.k_a_acc || sk.k_none) // same displayed key
return
var d,
k_b40 = sk.k_b40,
n_b40 = (k_b40 + 200 + sk.k_transp) % 40
d = abc2svg.b40k[n_b40] - n_b40
if (d) {
if (sk.k_transp > 0)
sk.k_transp += d
else
sk.k_transp -= d
n_b40 += d
}
sk.k_b40 = n_b40
var sf = abc2svg.b40sf[n_b40]
sk.k_old_sf = sk.k_sf
sk.k_sf = sf
sk.k_map = abc2svg.keys[sf + 7] // map of the notes with accidentals
}
/*
* for transpose purpose, check if a pitch is already in the measure or
* if it is tied from a previous note, and return the associated accidental
*/
function acc_same_pitch(s, pit) {
var i,
time = s.time
for (s = s.prev; s; s = s.prev) {
switch (s.type) {
case C.BAR:
if (s.time < time)
return //undefined // no same pitch
while (1) {
s = s.prev
if (!s)
return //undefined
if (s.type == C.NOTE) {
if (s.time + s.dur == time)
break
return //undefined
}
if (s.time < time)
return //undefined
}
for (i = 0; i <= s.nhd; i++) {
if (s.notes[i].pit == pit
&& s.notes[i].tie_ty)
return s.notes[i].acc
}
return //undefined
case C.NOTE:
for (i = 0; i <= s.nhd; i++) {
if (s.notes[i].pit == pit)
return s.notes[i].acc
}
break
}
}
return //undefined
}
/* -- get staves definition (%%staves / %%score) -- */
function get_staves(cmd, parm) {
var s, p_voice, p_voice2, i, flags, v, vid,
st, range,
a_vf = parse_staves(parm) // array of [vid, flags]
if (!a_vf)
return
if (voice_tb.length) {
voice_adj(true);
dupl_voice()
}
/* create a new staff system */
var maxtime = 0,
no_sym = true
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (p_voice.time > maxtime)
maxtime = p_voice.time
if (p_voice.sym)
no_sym = false
}
if (no_sym /* if first %%staves */
|| (maxtime == 0 && staves_found < 0)) {
par_sy.staves = []
par_sy.voices = []
} else {
/*
* create a new staff system and
* link the 'staves' symbol in a voice which is seen from
* the previous system - see sort_all
*/
for (v = 0; v < par_sy.voices.length; v++) {
if (par_sy.voices[v]) {
curvoice = voice_tb[v]
break
}
}
curvoice.time = maxtime;
s = {
type: C.STAVES,
|
| ︙ | ︙ | |||
1401 1402 1403 1404 1405 1406 1407 | p_voice = new_voice(vid); p_voice.time = maxtime; v = p_voice.v if (i == 0) par_sy.top_voice = p_voice.v // if the voice is already here, clone it | | > > > | 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 |
p_voice = new_voice(vid);
p_voice.time = maxtime;
v = p_voice.v
if (i == 0)
par_sy.top_voice = p_voice.v
// if the voice is already here, clone it
if (par_sy.voices[v]) {
p_voice2 = clone(p_voice);
// p_voice2.id += "_c" // for tests
par_sy.voices[voice_tb.length] = clone(par_sy.voices[v]);
v = voice_tb.length;
p_voice2.v = v;
p_voice2.sym = p_voice2.last_sym = null;
p_voice2.time = maxtime;
voice_tb.push(p_voice2)
delete p_voice2.clone
while (p_voice.clone)
p_voice = p_voice.clone;
p_voice.clone = p_voice2;
p_voice = p_voice2
} else {
par_sy.voices[v] = {}
}
a_vf[i][0] = p_voice;
par_sy.voices[v].range = range++
}
/* change the behavior from %%staves to %%score */
if (cmd[1] == 't') { /* if %%staves */
|
| ︙ | ︙ | |||
1511 1512 1513 1514 1515 1516 1517 |
if (cmd[1] == 'c') { /* if %%score */
for (st = 0; st < nstaff; st++)
par_sy.staves[st].flags ^= STOP_BAR
}
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
| | < < < < < > > > > > > > | 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 |
if (cmd[1] == 'c') { /* if %%score */
for (st = 0; st < nstaff; st++)
par_sy.staves[st].flags ^= STOP_BAR
}
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (!par_sy.voices[v]) {
p_voice.ignore = true
continue
}
par_sy.voices[v].second = p_voice.second;
st = p_voice.st
if (st > 0 && !p_voice.norepbra
&& !(par_sy.staves[st - 1].flags & STOP_BAR))
p_voice.norepbra = true
}
curvoice = parse.state >= 2 ? voice_tb[par_sy.top_voice] : null
}
// get a voice or create a clone of the current voice
function clone_voice(id) {
var v, p_voice
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v]
if (p_voice.id == id)
return p_voice // found
}
p_voice = clone(curvoice);
p_voice.v = voice_tb.length;
p_voice.id = id;
p_voice.sym = p_voice.last_sym = null;
p_voice.key = clone(curvoice.key)
delete p_voice.nm
delete p_voice.snm
delete p_voice.new_name
delete p_voice.lyric_restart
delete p_voice.lyric_cont
delete p_voice.ly_a_h;
delete p_voice.sym_restart
delete p_voice.sym_cont
delete p_voice.have_ly
voice_tb.push(p_voice)
return p_voice
} // clone_voice()
/* -- get a voice overlay -- */
function get_vover(type) {
var p_voice2, p_voice3, range, s, time, v, v2, v3,
line = parse.line
/* treat the end of overlay */
if (curvoice.ignore)
return
if (type == '|'
|| type == ')') {
if (!curvoice.last_note) {
|
| ︙ | ︙ | |||
1616 1617 1618 1619 1620 1621 1622 |
par_sy.voices[v2] = {
st: curvoice.st,
second: true
}
var f_clone = curvoice.clone != undefined ? 1 : 0;
range = par_sy.voices[curvoice.v].range
for (v = 0; v < par_sy.voices.length; v++) {
| | > | 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 |
par_sy.voices[v2] = {
st: curvoice.st,
second: true
}
var f_clone = curvoice.clone != undefined ? 1 : 0;
range = par_sy.voices[curvoice.v].range
for (v = 0; v < par_sy.voices.length; v++) {
if (par_sy.voices[v]
&& par_sy.voices[v].range > range)
par_sy.voices[v].range += f_clone + 1
}
par_sy.voices[v2].range = range + 1
if (f_clone) {
p_voice3 = clone_voice(p_voice2.id + 'c');
p_voice3.second = true;
v3 = p_voice3.v;
|
| ︙ | ︙ | |||
1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 |
syntax(1, "Wrong duration in voice overlay")
if (curvoice.time > vover.p_voice.time)
vover.p_voice.time = curvoice.time
}
}
p_voice2.time = vover.time;
curvoice = p_voice2
}
// check if a clef, key or time signature may go at start of the current voice
function is_voice_sig() {
var s
if (!curvoice.sym)
| > > > > > > > > > > > | 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 |
syntax(1, "Wrong duration in voice overlay")
if (curvoice.time > vover.p_voice.time)
vover.p_voice.time = curvoice.time
}
}
p_voice2.time = vover.time;
curvoice = p_voice2
// add a bar at start of the measure overlay
// (needed for sort_all() in case of spaces - 'y')
if (vover.bar) {
sym_link({
type: C.BAR,
bar_type: type,
dur: 0,
multi: 0
})
}
}
// check if a clef, key or time signature may go at start of the current voice
function is_voice_sig() {
var s
if (!curvoice.sym)
|
| ︙ | ︙ | |||
1690 1691 1692 1693 1694 1695 1696 |
// clef change
sym_link(s);
s.clef_small = true
}
// treat K: (kp = key signature + parameters)
function get_key(parm) {
| | < < < < > | < < < < < | | > > > > > > > | > | > > | | > > > > < < < < < < < < < < < < < | | 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 |
// clef change
sym_link(s);
s.clef_small = true
}
// treat K: (kp = key signature + parameters)
function get_key(parm) {
var v, p_voice, s, transp, sndtran,
// [s_key, a] = new_key(parm) // KO with nodejs
a = new_key(parm),
s_key = a[0];
a = a[1]
switch (parse.state) {
case 1: // in tune header (first K:)
if (s_key.k_sf == undefined && !s_key.k_a_acc) { // empty K:
s_key.k_sf = 0;
s_key.k_none = true
s_key.k_map = abc2svg.keys[7]
}
for (v = 0; v < voice_tb.length; v++) {
p_voice = voice_tb[v];
p_voice.key = clone(s_key);
p_voice.okey = clone(s_key);
p_voice.ckey = clone(s_key)
}
parse.ckey = s_key
if (a.length)
memo_kv_parm('*', a)
if (!glovar.ulen)
glovar.ulen = C.BLEN / 8;
parse.state = 2; // in tune header after K:
return
case 2: // K: at start of tune body
goto_tune(true)
break
}
if (a.length)
set_kv_parm(a);
if (!curvoice.ckey.k_bagpipe && !curvoice.ckey.k_drum
&& (cfmt.transp != undefined
|| curvoice.transp != undefined
|| curvoice.shift != undefined))
transp = (cfmt.transp || 0) +
(curvoice.transp || 0) +
(curvoice.shift || 0)
if (curvoice.sndtran != undefined
|| curvoice.sndsh != undefined)
sndtran = (curvoice.sndtran || 0) +
(curvoice.sndsh || 0)
if (s_key.k_sf == undefined) {
if (!s_key.k_a_acc
&& transp == undefined) {
if (sndtran == undefined)
return // not a key signature
s_key.k_play = true // play only
}
s_key.k_sf = curvoice.okey.k_sf
}
curvoice.okey = clone(s_key)
if (transp != undefined) {
curvoice.vtransp = transp;
s_key.k_transp = transp
}
if (sndtran != undefined)
s_key.k_sndtran = sndtran
s_key.k_old_sf = curvoice.ckey.k_sf; // memorize the key changes
if (!s_key.k_b40)
s_key.k_b40 = curvoice.ckey.k_b40
curvoice.ckey = s_key
if (is_voice_sig()) {
curvoice.key = clone(s_key)
if (s_key.k_none)
curvoice.key.k_sf = 0
} else {
sym_link(s_key) // (don't move the key)
}
}
// get / create a new voice
function new_voice(id) {
var p_voice, v, p_v_sav,
n = voice_tb.length
|
| ︙ | ︙ | |||
1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 |
wmeasure: glovar.meter.wmeasure,
clef: {
type: C.CLEF,
clef_auto: true,
clef_type: "a", // auto
time: 0
},
hy_st: 0
}
voice_tb.push(p_voice);
| > > | | < > | 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 |
wmeasure: glovar.meter.wmeasure,
clef: {
type: C.CLEF,
clef_auto: true,
clef_type: "a", // auto
time: 0
},
acc: [], // accidentals of the measure (parse)
sls: [], // slurs - used in parsing and in generation
hy_st: 0
}
voice_tb.push(p_voice);
// par_sy.voices[v] = {
// range: -1
// }
return p_voice
}
// this function is called at program start and on end of tune
function init_tune() {
nstaff = -1;
|
| ︙ | ︙ | |||
1890 1891 1892 1893 1894 1895 1896 |
tosvg(parse.fname, file, start, eol)
}
include--
}
// treat a 'V:' info
function get_voice(parm) {
| | | | | | | > | > | | > > > > > > > > > > > | | 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 |
tosvg(parse.fname, file, start, eol)
}
include--
}
// treat a 'V:' info
function get_voice(parm) {
var v, vs,
a = info_split(parm),
vid = a.shift()
if (!vid)
return // empty V:
if (vid.indexOf(',') > 0) { // if many voices
vs = vid.split(',');
vid = vs.shift()
}
if (parse.state < 2) {
if (a.length)
memo_kv_parm(vid, a)
if (vid != '*' && parse.state == 1)
curvoice = new_voice(vid)
return
}
if (vid == '*') {
syntax(1, "Cannot have V:* in tune body")
return
}
curvoice = new_voice(vid);
set_kv_parm(a)
if (parse.state == 2) // if first voice
goto_tune();
set_transp();
v = curvoice.v
if (curvoice.new) { // if new voice
delete curvoice.new
if (staves_found < 0) { // if no %%score/%%staves
curvoice.st = curvoice.cst = ++nstaff;
par_sy.nstaff = nstaff;
par_sy.voices[v] = {
st: nstaff,
range: v
}
par_sy.staves[nstaff] = {
stafflines: curvoice.stafflines || "|||||",
staffscale: 1
}
}
if (!par_sy.voices[v]) {
// if (cfmt.alignbars)
// syntax(1, "V: does not work with %%alignbars")
if (staves_found >= 0)
curvoice.ignore = true
}
}
if (!curvoice.filtered
&& !curvoice.ignore
&& (parse.voice_opts
|| parse.tune_v_opts)) {
curvoice.filtered = true;
voice_filter()
}
if (vs)
do_cloning(vs)
}
// change state from 'tune header after K:' to 'in tune body'
// curvoice is defined when called from get_voice()
function goto_tune(is_K) {
var v, p_voice,
s = {
type: C.STAVES,
dur: 0,
sy: par_sy
}
set_page();
write_heading();
reset_gen();
if (glovar.new_nbar) {
gene.nbar = glovar.new_nbar // measure numbering
glovar.new_nbar = 0
} else {
gene.nbar = 1
}
parse.state = 3; // in tune body
// if no voice yet, create the default voice
if (!voice_tb.length) {
get_voice("1");
curvoice.clef.istart = curvoice.key.istart;
curvoice.clef.iend = curvoice.key.iend;
// nstaff = 0;
curvoice.default = true
} else if (!curvoice) {
curvoice = voice_tb[staves_found < 0 ? 0 : par_sy.top_voice]
|
| ︙ | ︙ | |||
1998 1999 2000 2001 2002 2003 2004 |
// initialize the voices when no %%staves/score
if (staves_found < 0) {
nstaff = voice_tb.length - 1
for (v = 0; v <= nstaff; v++) {
p_voice = voice_tb[v];
delete p_voice.new; // old voice
| | | > | > | 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 |
// initialize the voices when no %%staves/score
if (staves_found < 0) {
nstaff = voice_tb.length - 1
for (v = 0; v <= nstaff; v++) {
p_voice = voice_tb[v];
delete p_voice.new; // old voice
p_voice.st = p_voice.cst = v;
par_sy.voices[v] = {
st: v,
range: v
}
par_sy.staves[v] = {
stafflines: p_voice.stafflines || "|||||",
staffscale: 1
}
}
par_sy.nstaff = nstaff
}
|
| ︙ | ︙ |
Changes to editor/edit.js.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 34 |
else
alert("window error: " + msg)
return false
}
var abc_images, // image buffer
abc_fname = ["noname.abc", ""], // file names
abc, // Abc object
| > | > | > > | > > | | | | < | | | | 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 |
else
alert("window error: " + msg)
return false
}
var abc_images, // image buffer
abc_fname = ["noname.abc", ""], // file names
abc_mtime = [], // associated last modification time
abc, // Abc object
syms, // music symbol at source index
ctxMenu, // context menu for play
elt_ref = {}, // pointers to page HTML elements
selx = [0, 0], // selected source indexes
selx_sav = [], // (saved while playing/printing)
play = {}, // play data
pop, // current popup message
texts = {}, // language specific texts
jsdir = document.currentScript ?
document.currentScript.src.match(/.*\//) :
(function() {
var s_a = document.getElementsByTagName('script')
for (var k = 0; k < s_a.length; k++) {
if (s_a[k].src.indexOf('edit-') >= 0)
return s_a[k].src.match(/.*\//) || ''
}
return "" // ??
})()
// -- Abc create argument
var user = {
// -- required methods
// include a file (%%abc-include - only one)
read_file: function(fn) {
elt_ref["s" + srcidx].style.display = "inline"
return elt_ref.src1.value
},
// insert the errors
errbld: function(sev, txt, fn, idx) {
var msg = sev + ' ' + clean_txt(txt)
if (idx >= 0)
elt_ref.diverr.innerHTML += '<b onclick="gotoabc(-1,' + idx +
')" style="cursor: pointer; display: inline-block">' +
msg + "</b><br/>\n"
else
elt_ref.diverr.innerHTML += msg + "<br/>\n"
},
// image output
img_out: function(str) {
abc_images += str
},
// -- optional methods
// annotations
anno_stop: function(type, start, stop, x, y, w, h, s) {
if (["beam", "slur", "tuplet"].indexOf(type) >= 0)
return
syms[start] = s // music symbol
// create a rectangle
abc.out_svg('<rect class="abcr _' + start +
'_" x="');
abc.out_sxsy(x, '" y="', y);
abc.out_svg('" width="' + w.toFixed(2) +
'" height="' + abc.sh(h).toFixed(2) + '"/>\n')
|
| ︙ | ︙ | |||
155 156 157 158 159 160 161 |
// }
abc_fname[srcidx] = files[0].name
var reader = new FileReader();
// Closure to capture the file information
reader.onloadend = function(evt) {
| < < | > | | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
// }
abc_fname[srcidx] = files[0].name
var reader = new FileReader();
// Closure to capture the file information
reader.onloadend = function(evt) {
var s = srcidx == 0 ? "source" : "src1";
elt_ref[s].value = evt.target.result;
elt_ref["s" + srcidx].value = abc_fname[srcidx];
src_change()
}
// Read the file as text
reader.readAsText(files[0], "UTF-8")
}
|
| ︙ | ︙ | |||
185 186 187 188 189 190 191 |
}
// render the textarea content to the right side
function render() {
var i, j,
content = elt_ref.source.value;
| < | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
}
// render the textarea content to the right side
function render() {
var i, j,
content = elt_ref.source.value;
if (!content)
return // empty source
// if include file not loaded yet, ask it
i = content.indexOf('%%abc-include ')
if (i >= 0) {
var sl = elt_ref.s1
|
| ︙ | ︙ | |||
213 214 215 216 217 218 219 |
function render2() {
var content = elt_ref.source.value
// load the required modules
if (!abc2svg.modules.load(content + elt_ref.src1.value, render2))
return
| | > | > > > > > > | | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
function render2() {
var content = elt_ref.source.value
// load the required modules
if (!abc2svg.modules.load(content + elt_ref.src1.value, render2))
return
// if page formatting, define a function to get the modification date
if (abc2svg.modules.pageheight.loaded) {
abc2svg.get_mtime = function(fn) {
var files = document.getElementById("abcfile").files
if (files && files[0].lastModified)
return new Date(files[0].lastModified)
return new Date()
}
}
abc = new abc2svg.Abc(user);
abc_images = '';
abc.tosvg('edit', '%%bgcolor white');
// document.body.style.cursor = "wait";
syms = []
try {
abc.tosvg(abc_fname[0], content)
} catch(e) {
alert(e.message + '\nabc2svg tosvg bug - stack:\n' + e.stack)
return
}
abc2svg.abc_end() // close the page if %%pageheight
|
| ︙ | ︙ | |||
260 261 262 263 264 265 266 | idx = s.value.length - 1; c = 0 break } } c = Number(c) + idx; s.focus(); | | | < | 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
idx = s.value.length - 1;
c = 0
break
}
}
c = Number(c) + idx;
s.focus();
s.setSelectionRange(c, syms[c].iend || c + 1)
}
// click in the target
function selsvg(evt) {
var v,
elt = evt.target,
cl = elt.getAttribute('class')
play.loop = false;
evt.stopImmediatePropagation();
evt.preventDefault()
// remove the context menu if active
|
| ︙ | ︙ | |||
292 293 294 295 296 297 298 |
return false
}
// highlight the clicked element or clear the selection start
s = elt_ref.source;
if (cl && cl.substr(0, 4) == 'abcr') {
v = Number(cl.slice(6, -1));
| | | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
return false
}
// highlight the clicked element or clear the selection start
s = elt_ref.source;
if (cl && cl.substr(0, 4) == 'abcr') {
v = Number(cl.slice(6, -1));
s.setSelectionRange(v, syms[v].iend)
} else {
s.setSelectionRange(0, 0)
}
s.blur();
s.focus()
}
|
| ︙ | ︙ | |||
360 361 362 363 364 365 366 | if (end == elt.value.length) return // select all setsel(0, 0); // clear selection setsel(1, 0) return } | | | | < < > | < | | | | > | | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 |
if (end == elt.value.length)
return // select all
setsel(0, 0); // clear selection
setsel(1, 0)
return
}
if (syms) {
syms.forEach(function(sym, is) {
if (!s) {
if (is >= start)
s = is
} else if (sym.iend <= end) {
e = is
}
})
}
if (!s)
return
if (selx[0] != s)
setsel(0, s)
if (selx[1] != e)
setsel(1, e);
elts = document.getElementsByClassName('_' + s + '_')
if (elts[0])
do_scroll(elts[0]) // move the element in the screen
}
// open a new window for file save
function saveas() {
var s = srcidx == 0 ? "source" : "src1",
source = elt_ref[s].value,
// create a link for our script to 'click'
link = document.createElement("a");
if (abc_fname[srcidx] == "noname.abc")
elt_ref["s" + srcidx].value =
abc_fname[srcidx] = prompt(texts.fn, abc_fname[srcidx])
link.download = abc_fname[srcidx];
// link.innerHTML = "Hidden Link";
link.href = "data:text/plain;charset=utf-8," +
encodeURIComponent(source);
// open in a new tab
// link.target = '_blank';
// when link is clicked call a function to remove it from
// the DOM in case user wants to save a second file.
link.onclick = destroyClickedElement;
// make sure the link is hidden.
link.style.display = "none";
|
| ︙ | ︙ | |||
465 466 467 468 469 470 471 |
var elts = document.getElementsByClassName('_' + i + '_');
if (elts && elts[0]) {
if (on)
do_scroll(elts[0]);
elts[0].style.fillOpacity = on ? 0.4 : 0
}
}
| | | > | > > > > > | | > | > | > | | > > | | | > > > > > > > > > > > > > | > | | > > | | > > > > > > > > | | < | < < < | | | | > > > | > > > > > | < < < < < < < | < > > | < | < < < < < | < | < < | | | < < < < < < < | < < > | | > > | | < < | < < | > | > > | > > | > > | < < < < < < < < < < < < < < < | < < > > | | > | < < < < < < < < < | | < < < < | < < < < > | | < | < | < | | < < < < < < < < < < < < < < < < < < < < < < < < < | | | | > | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 |
var elts = document.getElementsByClassName('_' + i + '_');
if (elts && elts[0]) {
if (on)
do_scroll(elts[0]);
elts[0].style.fillOpacity = on ? 0.4 : 0
}
}
function endplay(repv) {
if (play.loop) {
play.abcplay.play(play.si, play.ei)
return
}
play.playing = false;
play.repv = repv // repeat variant number for continue
// redisplay the selection
selx[0] = selx[1] = 0;
setsel(0, selx_sav[0]);
setsel(1, selx_sav[1])
}
// start playing
// -1: All (removed)
// 0: Tune
// 1: Selection
// 2: Loop
// 3: Continue
function play_tune(what) {
var i, si, ei, elt,
C = abc2svg.C,
tunes = abc.tunes,
s = elt_ref.source.value
if (play.playing) {
if (!play.stop) {
play.stop = -1;
play.abcplay.stop()
}
return
}
// search a symbol to play
function gnrn(sym, loop) { // go to the next real note (not tied)
var i
while (1) {
switch (sym.type) {
case C.NOTE:
i = sym.nhd + 1
while (--i >= 0) {
if (sym.notes[i].ti2)
break
}
if (i < 0)
return sym
break
case C.REST:
case C.GRACE:
return sym
case C.BLOCK:
switch (sym.subtype) {
case "midictl":
case "midiprog":
return sym
}
break
}
if (!sym.ts_next) {
if (!loop)
return gprn(sym, 1)
return sym
}
sym = sym.ts_next
}
// not reached
}
function gprn(sym, loop) { // go to the previous real note (not tied)
var i
while (1) {
switch (sym.type) {
// case C.BAR:
//fixme: there may be a right repeat!
// break
case C.NOTE:
i = sym.nhd + 1
while (--i >= 0) {
if (sym.notes[i].ti2)
break
}
if (i < 0)
return sym
break
case C.REST:
case C.GRACE:
return sym
case C.BLOCK:
switch (sym.subtype) {
case "midictl":
case "midiprog":
return sym
}
break
}
if (!sym.ts_prev) {
if (!loop)
return gnrn(sym, 1)
return sym
}
sym = sym.ts_prev
}
// not reached
}
function gsot(si) { // go to the first playable symbol of a tune
return gnrn(syms[si].p_v.sym)
}
function get_se(si) { // get the starting symbol
var sym = syms[si]
while (!sym.seqst)
sym = sym.ts_prev
return sym
} // get_se()
function get_ee(si) { // get the ending symbol
var sym = syms[si]
while (sym.ts_next && !sym.ts_next.seqst)
sym = sym.ts_next
return sym
} // get_ee()
// start playing
function play_start(si, ei) {
if (!si)
return
selx_sav[0] = selx[0]; // remove the colors
selx_sav[1] = selx[1];
setsel(0, 0);
setsel(1, 0);
play.stop = 0;
play.abcplay.play(si, ei, play.repv)
}
// play tune()
ctxMenu.style.display = "none"; // remove the play menu
play.playing = true;
if (tunes.length) { // if new display
// generate the play data of all tunes
while (1) {
elt = tunes.shift()
if (!elt)
break
play.abcplay.add(elt[0], elt[1])
}
play.si = play.ei = null
play.stop = 0
play.loop = false
}
// if loop again
if (what == 2 && play.loop) {
play_start(play.si, play.ei)
return
}
// get the starting and ending play indexes, and start playing
if (what == 3 && play.stop > 0) { // if stopped and continue
play_start(get_se(play.stop), play.ei)
return
}
if (what != 0 && selx[0] && selx[1]) { // if full selection
si = get_se(selx[0]);
ei = get_ee(selx[1])
} else if (what != 0 && selx[0]) { // if selection without end
si = get_se(selx[0]);
ei = null
} else if (what != 0 && selx[1]) { // if selection without start
si = gsot(selx[1])
ei = get_ee(selx[1])
} else { // no selection => tune
elt = play.click.svg // (dummy)
si = elt.getElementsByClassName('abcr') // symbols in the SVG
if (!si.length) {
play.playing = false
return // not in a tune!
}
i = Number(si[0].getAttribute('class').slice(6, -1))
si = gsot(i)
ei = null
}
if (what != 3) { // if not continue
play.si = si;
play.ei = ei;
play.loop = what == 2
play.repv = 0
}
play_start(si, ei)
}
// set the version and initialize the playing engine
function edit_init() {
|
| ︙ | ︙ | |||
739 740 741 742 743 744 745 746 |
if (v) {
elt_ref.source.style.fontSize =
elt_ref.src1.style.fontSize =
v + "px";
document.getElementById("fontsize").value =
Number(v)
}
v = storage(true, "lang");
| > > > > > > > > > > > > > > > > | | 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 |
if (v) {
elt_ref.source.style.fontSize =
elt_ref.src1.style.fontSize =
v + "px";
document.getElementById("fontsize").value =
Number(v)
}
// set the language
// if not defined, get the one of the navigator
v = storage(true, "lang");
if (!v) {
v = (navigator.languages ?
navigator.languages[0] :
navigator.language).split('-')[0]
switch (v) {
case "de":
case "en":
case "fr":
case "it": break
case "pt": v = "pt_BR"; break
default: v = "en"; break
}
}
loadlang(v, true)
}
document.getElementById("abc2svg").innerHTML =
'abc2svg-' + abc2svg.version + ' (' + abc2svg.vdate + ')'
// keep references on the page elements
var a = ["diverr", "source", "src1", "s0", "s1", "target"]
|
| ︙ | ︙ | |||
775 776 777 778 779 780 781 |
setsel(0, selx_sav[0]);
setsel(1, selx_sav[1])
}
// if playing is possible, load the playing script
if (window.AudioContext || window.webkitAudioContext
|| navigator.requestMIDIAccess) {
| | | 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 |
setsel(0, selx_sav[0]);
setsel(1, selx_sav[1])
}
// if playing is possible, load the playing script
if (window.AudioContext || window.webkitAudioContext
|| navigator.requestMIDIAccess) {
abc2svg.loadjs("snd-@MAJOR@.js", function() {
play.abcplay = AbcPlay({
onend: endplay,
onnote:notehlight,
});
document.getElementById("playdiv1").style.display =
document.getElementById("playdiv3").style.display =
document.getElementById("playdiv4").style.display =
|
| ︙ | ︙ | |||
815 816 817 818 819 820 821 |
// otherwise, display the play menu
play.click = { // keep the click references for 'play tune'
svg: elt,
Y: evt.pageY
}
| | | 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 |
// otherwise, display the play menu
play.click = { // keep the click references for 'play tune'
svg: elt,
Y: evt.pageY
}
ctxMenu = document.getElementById("ctxMenu");
ctxMenu.style.display = "block";
x = evt.pageX - elt_ref.target.parentNode.offsetLeft
+ elt_ref.target.parentNode.scrollLeft;
y = evt.pageY + elt_ref.target.parentNode.scrollTop;
ctxMenu.style.left = (x - 30) + "px";
ctxMenu.style.top = (y - 10) + "px"
return false
|
| ︙ | ︙ |
Changes to editor/edit.xhtml.
| ︙ | ︙ | |||
14 15 16 17 18 19 20 |
<!-- left -->
<div id="dleft">
<!-- menu bar -->
<ul id="nav">
<li class="dropbutton"><label id="f">File</label>
<ul class="droplinks">
| | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<!-- left -->
<div id="dleft">
<!-- menu bar -->
<ul id="nav">
<li class="dropbutton"><label id="f">File</label>
<ul class="droplinks">
<li><input type="file" id="abcfile" accept="*"
style="display:none" onchange="loadtune()"/>
<label id="fl" for="abcfile">Load file</label>
</li>
<li><label id="saveas">Save file</label></li>
</ul>
</li>
<li class="dropbutton"><label id="pr">Preferences</label>
|
| ︙ | ︙ | |||
100 101 102 103 104 105 106 | <!-- right - needed for the scrollbars --> <div id="dright"> <!-- context menu --> <div id="ctxMenu" title="Play"> <ul class="droplinks"> | > | | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | <!-- right - needed for the scrollbars --> <div id="dright"> <!-- context menu --> <div id="ctxMenu" title="Play"> <ul class="droplinks"> <!-- 'All' does not work anymore --> <li id="cmpa" onclick="play_tune(-1)" style="display:none">All</li> <li id="cmpt" onclick="play_tune(0)">Tune</li> <li id="cmps" onclick="play_tune(1)">Selection</li> <li id="cmpl" onclick="play_tune(2)">Loop</li> <li id="cmpc" onclick="play_tune(3)">Continue</li> </ul> </div> |
| ︙ | ︙ | |||
138 139 140 141 142 143 144 |
</ul>
</div>
<!-- about popup window -->
<div id="about" class="popup" style="width: 350px">
<div class="close" onclick="popshow('about')">x</div>
<p id="abc2svg">abc2svg</p>
| | > | < < | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
</ul>
</div>
<!-- about popup window -->
<div id="about" class="popup" style="width: 350px">
<div class="close" onclick="popshow('about')">x</div>
<p id="abc2svg">abc2svg</p>
<p>Copyright © 2016-2019 Jean-François Moine</p>
</div>
<!-- javascript must be enabled -->
<noscript>
<div id="okjs" class="popup" style="width:50%;background:#ff8080;visibility:visible">
Please enable Javascript.
</div>
</noscript>
</body>
</html>
|
Changes to err-de.js.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 |
user.textrans = {
"+: lyric without music": "+: Liedtext ohne Musik",
"+: symbol line without music": "+: Symbolzeile ohne Musik",
"+: without previous info field": "+: ohne vorhergehends Info-Feld",
"'{' in grace note": "'{' in Verzierungsnote",
| | < < > > > | | | | | > < | 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 107 108 109 110 111 112 113 114 115 116 117 |
user.textrans = {
"+: lyric without music": "+: Liedtext ohne Musik",
"+: symbol line without music": "+: Symbolzeile ohne Musik",
"+: without previous info field": "+: ohne vorhergehends Info-Feld",
"'{' in grace note": "'{' in Verzierungsnote",
"'}', ')' or ']' missing in %%score": "'}', ')' oder ']' fehlt in %%score",
"',' lacking in annotation '@x,y'": "',' fehlt in Beschriftung '@x,y'",
"'$1' is not a note": "'$1' is keine Note",
"'$1:' line ignored": "'$1:' Zeile ignoreirt",
"$1: inside tune - ignored": "$1: innerhalb der Stimme ignoriert",
"!$1! must be on a note": "!$1! muss an einer Note stehen",
"!$1! must be on a note or a rest": "!$1! muss an einer Note oder Pause stehen",
"!$1! must be on the last of a couple of notes": "!$1! muss an der letzten Notengruppe stehen",
"!beamon! must be on a bar": "!beamon! muss an einem Taktstrich stehen",
"!xstem! must be on a note": "!xstem! muss an einer Note stehen",
"%%deco: abnormal h/wl/wr value '$1'": "%%deco: falscher Wert '$1' für h/wl/wr",
"%%deco: bad C function index '$1'": "%%deco: falscher C Funktionsindex '$1'",
"%%deco: bad C function value '$1'": "%%deco: falscher C Funtionswert '$1'",
"%%deco: cannot have a negative value '$1'": "%%deco: '$1' kann keinen egativen Wert haben",
"%%multicol end without start": "%%multicol end ohne start",
"%%multicol new without start": "%%multicol new ohne stand",
"%%repeat cannot start a tune": "%%repeat kann nicht am Anfang einer Stimme stehen",
"%%staffwidth too big": "%%staffwidth zu groß",
"%%staffwidth too small": "%%staffwidth zu klein",
"%%tune not treated yet": "%%tune noch nicht behandelt",
"%%vskip cannot be negative": "%%vskip kann nicht negativ sein",
"Bad !xstem!": "!xstem! fehlerhaft",
"Bad %%setbarnb value": "fehlerhaft Wert für %%setbarnb",
"Bad %%staff number $1 (cur $2, max $3)": "falsche %%staff Nummer $1 (cur $2, max $3)",
"Bad %%staff value '$1'": "fehlerhafte %%staff Nummer '$1'",
"Bad %%stafflines value": "fehlerhafter Wert für %%stafflines",
"Bad %%staffscale value": "fehlerhafter Wert für %%staffscale",
"Bad char '$1' in M:": "fehlerhaftes Zeichen '$1' in M:",
"Bad character '$1'": "fehlerhaftes Zeichen '$1'",
"Bad character in grace note sequence":
"fehlerhaftes Zeichen in Sequenz von Vorschlagnoten",
"Bad controller number in %%MIDI": "Bad controller number in %%MIDI",
"Bad controller value in %%MIDI": "Bad controller value in %%MIDI",
"Bad duration '$1' in M:": "fehlerhafte Dauer '$1' in M:",
"Bad integer value": "fehlerhafte Ganzzahl",
"Bad instr= value": "fehlerhafter Wert für instr=",
"Bad L: value": "Fehlerhafter Wert für L:",
"Bad note in %%map": "fehlerhafte Note in %%map",
"Bad page width": "fehlerhafte Seitenbreite",
"Bad program in %%MIDI": "falsches Program in %%MIDI",
"Bad scale value in %%font": "fehlerhafter Wert für scale in %%font",
"Bad tempo value": "Bad tempo value",
"Bad tie": "fehlerhafter Haltebogen",
"Bad transpose value": "fehlerhafter Wert für transpose",
"Bad user character '$1'": "falsches benutzerdefiniertes Zeichen '$1' in U:/%%user",
"Bad value '$1' in %%linebreak - ignored": "fehlerhafter Wert '$1' in %%linebreak - ignoriert",
"Bad value in $1": "fehlerhafter Wert in $1",
"Bad voice ID in %%score": "Fehlerhafte ID für Stimme in %%score",
"Bar in repeat sequence": "Taktstrich in Wiederholungssequenz",
"Cannot have !$1! on a head": "!$1! im Kopfbereich nicht erlaubt",
"Cannot have '$1' inside a tune": "'$1' innerhalb einer Stimme nicht erlaubt",
"Cannot have a bar in grace notes": "Taktstrich in Vorschlagnote nicht erlaubt",
"Cannot have a broken rhythm in grace notes": "gebrochener Rythmus in Ziernoten nicht erlaubt ",
"Cannot have V:* in tune body": "V:* im Notenbereich nicht erlaubt",
"Cannot read file '$1'": "File '$1' kann nicht gelesen werden",
"Decoration ignored": "Dekoration ignoriert",
"Empty line in tune header - ignored": "Leerzeile in Kopfbereich - ignoriert",
"Erroneous end of voice overlay": "Fehlerhaftes Ende einer Stimme in überlagerten Stimmen",
"Incorrect 1st value in %%repeat": "erster Wert fehlerhaft in %%repeat",
"Incorrect 2nd value in %%repeat": "zweiter Wert fehlerhaft in %%repeat",
"Invalid 'r' in tuplet": "'r' fehlerhaft in Tuplet",
"Invalid decoration '$1'": "fehlerhafte Dekoration '$1'",
"Invalid note duration $1": "Fehlerhafte Notendekoration '$1'",
"Lack of ']'": "']' fehlt",
"Lack of starting [, ! or \" in U: / %%user":
"[, ! or \" fehlt in U: / %%user",
"Line split problem - adjust maxshrink and/or breaklimit": "Probleme beim Aufteilen der Zeile - justiere maxshrink und/oder breaklimit",
"Line too much shrunk $1 $2 $3": "Zeile zu stark geschrumpft $1 $2 $3",
"Line underfull ($1pt of $2pt)": "Zeile nicht voll genug ($1pt of $2pt)",
"Misplaced '$1' in %%score": "'$1' fehlerhaft platziert in %%score",
"Misplaced dot": "fehlerhaft platzierter Punkt",
"Mix of old and new transposition syntaxes":
"Mix von alter und neuer Transponierungs-syntax",
"No $1 after %%$2": "kein $1 nach %%$2",
"No </defs> in %%beginsvg sequence": "kein </defs> in %%beginsvg squenz",
"No </style> in %%beginsvg sequence": "kein </style> in %%beginsvg sequenz",
"No accidental after 'exp'": "kein Vorzeichen nach 'exp'",
"No end of decoration": "kein Ende der Dekoration",
"No end of grace note sequence": "kein ende der Vorschlagnoten",
"No end of guitar chord": "kein Ende des Akkordsymbols",
"No end of repeat string": "kein Ende des Wiederholungszeichens",
"No end of tuplet": "kein Ende des Tuplets",
"No end of tuplet in this music line":
"Kein ende des Tuplets in dieser Zeile",
"No end of voice overlay": "kein Ende der Stimmüberlagerung",
"No function for decoration '$1'": "keine Funktion für Dekoration '$1'",
"No note before '-'": "keine Note vor '-'",
"No note before '<'": "keine Note vor '<'",
"No note in voice overlay": "keine Note in Stimmüberlagerung",
// "Non standard note duration $1": "??",
"No read_file support": "Einlesen von Files nicht unterstützt",
"No start of !$1!": "kein Start von !$1!",
"Not an ASCII character": "kein ASCII - Zeichen",
"Not enough measure bars for lyric line": "nicht genug Takte für Liedtextzeile",
"Not enough measure bars for symbol line":
"Nicht genügend Takte für eine Symbolzeile",
"Not enough measures for %%repeat": "nicht genug Takte für %%repeat",
"Not enough parameters in %%map": "nicht genug Parameter in %%map",
"Not enough symbols after repeat sequence": "nicht genug Symbole nach einer Wiederholungssequenz",
|
| ︙ | ︙ |
Changes to err-fr.js.
1 2 3 4 5 6 7 8 9 10 11 12 |
//JS abc2svg - french translation of the error codes
// traduction des codes d'erreur en français
// par Jean-François Moine
// Appelez ce fichier dans la ligne de commande pour avoir
// les messages d'erreur en français
user.textrans = {
"+: lyric without music": "+: paroles sans musique",
"+: symbol line without music":
"+: plus de musique pour s:",
"+: without previous info field": "Pas de ligne info avant +:",
"'{' in grace note": "'{' dans notes d'agrément",
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//JS abc2svg - french translation of the error codes
// traduction des codes d'erreur en français
// par Jean-François Moine
// Appelez ce fichier dans la ligne de commande pour avoir
// les messages d'erreur en français
user.textrans = {
"+: lyric without music": "+: paroles sans musique",
"+: symbol line without music":
"+: plus de musique pour s:",
"+: without previous info field": "Pas de ligne info avant +:",
"'{' in grace note": "'{' dans notes d'agrément",
"'}', ')' or ']' missing in %%score":
"Il manque '}', ')' ou ']' dans %%score",
"',' lacking in annotation '@x,y'":
"Il manque une ',' dans l'annotation '@x,y'",
"'$1' is not a note": "'$1' n'est pas une note",
"'$1:' line ignored": "'$1:' ligne ignorée",
"$1: inside tune - ignored": "$1: en milieu de morceau - ignoré",
"!$1! must be on a note": "!$1! doit être sur une note",
"!$1! must be on a note or a rest":
|
| ︙ | ︙ | |||
31 32 33 34 35 36 37 | "%%deco: bad C function value '$1'": "%%deco: mauvaise valeur de fonction '$1'", "%%deco: cannot have a negative value '$1'": "%%deco: '$1' ne peut pas avoir de valeur négative", "%%multicol end without start": "%%multicol end sans start", "%%multicol new without start": "%%multicol new sans start", "%%repeat cannot start a tune": "%%repeat ne peut pas être en début de morceau", | < < | > > > | < | < | | | | 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 | "%%deco: bad C function value '$1'": "%%deco: mauvaise valeur de fonction '$1'", "%%deco: cannot have a negative value '$1'": "%%deco: '$1' ne peut pas avoir de valeur négative", "%%multicol end without start": "%%multicol end sans start", "%%multicol new without start": "%%multicol new sans start", "%%repeat cannot start a tune": "%%repeat ne peut pas être en début de morceau", "%%staffwidth too big": "%%staffwidth trop grand", "%%staffwidth too small": "%%staffwidth trop petit", "%%tune not treated yet": "%%tune n'est pas encore traité", "%%vskip cannot be negative": "%%vskip ne peut pas être négatif", "Bad !xstem!": "!xstem! erroné", "Bad %%setbarnb value": "Valeur incorrecte dans %%setbarnb", "Bad %%staff number $1 (cur $2, max $3)": "Numéro %%staff $1 incorrect (cur $2, max $3)", "Bad %%staff value '$1'": "Valeur incorrecte '$1' dans %%staff", "Bad %%stafflines value": "Valeur incorrecte dans %%stafflines", "Bad %%staffscale value": "Valeur incorrecte dans %%staffscale", "Bad char '$1' in M:": "Mauvais caractère '$1' dans M:", "Bad character '$1'": "Mauvais caractère '$1'", "Bad character in grace note sequence": "Caractère incorrect dans notes d'agrément", "Bad controller number in %%MIDI": "Mauvais numéro de controleur dans %%MIDI", "Bad controller value in %%MIDI": "Mauvaise valeur de controle dans %%MIDI", "Bad duration '$1' in M:": "Durée '$1' incorrecte dans M:", "Bad integer value": "Mauvaise valeur entière", "Bad instr= value": "Mauvaise valeur de instr=", "Bad L: value": "Mauvaise valeur pour L:", "Bad note in %%map": "Note incorrecte dans %%map", "Bad page width": "Mauvaise largeur de page", "Bad program in %%MIDI": "Mauvais 'program' dans %%MIDI", "Bad scale value in %%font": "Mauvaise échelle dans %%font", "Bad tempo value": "Mauvaise valeur de tempo", "Bad tie": "Mauvaise liaison de prolongation", "Bad transpose value": "Mauvaise valeur de transposition", "Bad user character '$1'": "Caractère illégal '$1' dans U:/%%user", "Bad value '$1' in %%linebreak - ignored": "Valeur incorrecte '$1' dans %%linebreak - ignorée", "Bad value in $1": "Mauvaise valeur dans $1", "Bad voice ID in %%score": "Mauvaise identité de voix dans %%score", "Bar in repeat sequence": "Barre dans la séquence à répéter", "Cannot have !$1! on a head": "!$1! ne peut pas être sur une tête de note", "Cannot have '$1' inside a tune": "'$1' ne peut pas être dans un morceau", "Cannot have a bar in grace notes": "Il ne peut pas y avoir de barre dans les notes d'agrément", "Cannot have a broken rhythm in grace notes": "Il ne peut pas y avoir '<' ou '>' dans les notes d'agrément", "Cannot have V:* in tune body": "Il ne peut pas y avoir V:* dans le corps du morceau", "Cannot read file '$1'": "Fichier '$1' inexistant", "Decoration ignored": "Décoration ignorée", "Empty line in tune header - ignored": "Ligne vide dans en-tête de morceau - ignorée", "Erroneous end of voice overlay": "Fin de superposition de voix erronée", "Incorrect 1st value in %%repeat": "Première valeur incorrecte dans %%repeat", "Incorrect 2nd value in %%repeat": "Deuxième valeur incorrecte dans %%repeat", "Invalid 'r' in tuplet": "'r' invalide dans le tuplet", "Invalid decoration '$1'": "Décoration '$1' invalide", "Invalid note duration $1": "Durée de note $1 invalide", "Lack of ']'": "']' manquant", 'Lack of starting [, ! or " in U: / %%user': 'U: / %%user ne commence pas par [, ! ou "', "Line split problem - adjust maxshrink and/or breaklimit": "Problème de découpe en lignes - ajuster maxshrink et/ou breaklimit", "Line too much shrunk $1 $2 $3": "Ligne trop compressée $1 $2 $3", "Line underfull ($1pt of $2pt)": "Trop d'espacement ($1pt of $2pt)", "Misplaced '$1' in %%score": "'$1' mal placé dans %%score", "Misplaced dot": "Point mal placé", "Mix of old and new transposition syntaxes": "Mélange des syntaxes de transposition ancienne et nouvelle", "No $1 after %%$2": "Pas de $1 après %%$2", "No </defs> in %%beginsvg sequence": "Pas de </defs> dans séquence %%beginsvg", "No </style> in %%beginsvg sequence": |
| ︙ | ︙ | |||
113 114 115 116 117 118 119 120 121 | "No end of tuplet in this music line": "Pas de fin de tuplet dans cette ligne de musique", "No end of voice overlay": "Pas de fin de superposition de voix", "No function for decoration '$1'": "Pas de fonction pour décoration '$1'", "No note before '-'": "Pas de note devant '-'", "No note before '<'": "Pas de note devant '<'", "No note in voice overlay": "Pas de note dans voix superposée", "No read_file support": "La fonction read_file n'existe pas", "No start of !$1!": "Pas de début pour !$1!", | > < < | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | "No end of tuplet in this music line": "Pas de fin de tuplet dans cette ligne de musique", "No end of voice overlay": "Pas de fin de superposition de voix", "No function for decoration '$1'": "Pas de fonction pour décoration '$1'", "No note before '-'": "Pas de note devant '-'", "No note before '<'": "Pas de note devant '<'", "No note in voice overlay": "Pas de note dans voix superposée", "Non standard note duration $1": "Durée de note $1 non standard" "No read_file support": "La fonction read_file n'existe pas", "No start of !$1!": "Pas de début pour !$1!", "Not an ASCII character": "Ce n'est pas un caractère ASCII", "Not enough measure bars for lyric line": "Pas assez de barres pour la ligne de paroles", "Not enough measure bars for symbol line": "Pas assez de barres pour ligne s:", "Not enough measures for %%repeat": "Pas assez de mesures pour %%repeat", |
| ︙ | ︙ |
Changes to err-it.js.
1 2 3 4 5 6 7 8 9 10 11 12 |
//JS abc2svg - Italian translation of the error codes
// Traduzione dei codici di errore in italiano
// di Guido Gonzato, guido . gonzato at gmail . com
// Richiamare questo file da linea di comando per avere
// i messaggi di errore in italiano.
user.textrans = {
"+: lyric without music": "+: parole senza musica",
"+: symbol line without music":
"+: linea di simboli senza musica",
"+: without previous info field": "Nessun campo di informazioni prima di +:",
"'{' in grace note": "'{' in nota di abbellimento",
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//JS abc2svg - Italian translation of the error codes
// Traduzione dei codici di errore in italiano
// di Guido Gonzato, guido . gonzato at gmail . com
// Richiamare questo file da linea di comando per avere
// i messaggi di errore in italiano.
user.textrans = {
"+: lyric without music": "+: parole senza musica",
"+: symbol line without music":
"+: linea di simboli senza musica",
"+: without previous info field": "Nessun campo di informazioni prima di +:",
"'{' in grace note": "'{' in nota di abbellimento",
"'}', ')' or ']' missing in %%score":
"'}', ')' o ']' mancanti in %%score",
"',' lacking in annotation '@x,y'":
"Manca una ',' nell'annotazione '@x,y'",
"'$1' is not a note": "'$1' non è una nota",
"'$1:' line ignored": "'$1:' linea ignorata",
"$1: inside tune - ignored": "$1: nel corpo del brano - ignorato",
"!$1! must be on a note": "!$1! deve stare su di una nota",
"!$1! must be on a note or a rest":
|
| ︙ | ︙ | |||
31 32 33 34 35 36 37 | "%%deco: bad C function value '$1'": "%%deco: valore errato per la funzione C '$1'", "%%deco: cannot have a negative value '$1'": "%%deco: '$1' non può avere un valore negativo", "%%multicol end without start": "%%multicol end senza start", "%%multicol new without start": "%%multicol new senza start", "%%repeat cannot start a tune": "%%repeat non può stare all'inizio del brano", | < < > > > | < | < | | | > < < | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | "%%deco: bad C function value '$1'": "%%deco: valore errato per la funzione C '$1'", "%%deco: cannot have a negative value '$1'": "%%deco: '$1' non può avere un valore negativo", "%%multicol end without start": "%%multicol end senza start", "%%multicol new without start": "%%multicol new senza start", "%%repeat cannot start a tune": "%%repeat non può stare all'inizio del brano", "%%staffwidth too big": "%%staffwidth troppo grande", "%%staffwidth too small": "%%staffwidth troppo piccolo", "%%tune not treated yet": "%%tune non ancora gestito", "%%vskip cannot be negative": "%%vskip non può essere negativo", "Bad !xstem!": "!xstem! errato", "Bad %%setbarnb value": "Valore errato in %%setbarnb", "Bad %%staff number $1 (cur $2, max $3)": "Numero $1 in %%staff errato (attuale $2, max $3)", "Bad %%staff value '$1'": "Valore errato '$1' in %%staff", "Bad %%stafflines value": "Valore errato in %%stafflines", "Bad %%staffscale value": "Valore errato in %%staffscale", "Bad char '$1' in M:": "Carattere errato '$1' in M:", "Bad character '$1'": "Carattere errato '$1'", "Bad character in grace note sequence": "Carattere errato nelle note di abbellimento", "Bad controller number in %%MIDI": "Numero errato del controller in %%MIDI", "Bad controller value in %%MIDI": "Valore errato del controller in %%MIDI", "Bad duration '$1' in M:": "Durata '$1' errata in M:", "Bad integer value": "Valore intero errato", "Bad instr= value": "Valore errato di instr=", "Bad L: value": "Valore errato per L:", "Bad note in %%map": "Nota errata in %%map", "Bad page width": "Larghezza di pagina errata", "Bad program in %%MIDI": "Numero di programma non valido in %%MIDI", "Bad scale value in %%font": "Valore di scala non valido in %%font", "Bad tempo value": "Bad tempo value", "Bad tie": "Legatura non valida", "Bad transpose value": "Valore non valido per la trasposizione", "Bad user character '$1'": "Carattere illegale '$1' in U:/%%user", "Bad value '$1' in %%linebreak - ignored": "Valore errato '$1' in %%linebreak - ignorato", "Bad value in $1": "Valore errato in $1", "Bad voice ID in %%score": "ID di voce non valido in %%score", "Bar in repeat sequence": "Stanghetta in sequenza ripetuta", "Cannot have !$1! on a head": "!$1! non è consentito su una nota", "Cannot have '$1' inside a tune": "'$1' non è consentito entro il brano", "Cannot have a bar in grace notes": "Stanghette non consentite nelle note di abbellimento", "Cannot have a broken rhythm in grace notes": "'Broken rhythm' non consentito nelle note di abbellimento", "Cannot have V:* in tune body": "V:* non consentito nel corpo del brano", "Cannot read file '$1'": "File '$1' inesistente", "Decoration ignored": "Decorazione ignorata", "Empty line in tune header - ignored": "Linea vuota nella testata - ignorata", "Erroneous end of voice overlap": "Fine di voice overlay errata", "Incorrect 1st value in %%repeat": "Primo valore in %%repeat errato", "Incorrect 2nd value in %%repeat": "Secondo valore in %%repeat errato", "Invalid 'r' in tuplet": "'r' non valido in gruppo irregolare", "Invalid decoration '$1'": "Decorazione '$1' non valida", "Invalid note duration $1": "Durée de note $1 non valida", "Lack of ']'": "']' mancante", 'Lack of starting [, ! or " in U: / %%user': 'U: / %%user non inizia con [, ! o "', "Line split problem - adjust maxshrink and/or breaklimit": "Problema di linea divisa - modificare maxshrink e/o breaklimit", "Line too much shrunk $1 $2 $3": "Linea troppo compressa $1 $2 $3", "Line underfull ($1pt of $2pt)": "Linea troppo vuota ($1pt di $2pt)", "Misplaced '$1' in %%score": "'$1' in posizione errata in %%score", "Misplaced dot": "Punto in posizione errata", "Mix of old and new transposition syntaxes": "Sintassi di trasposizione vecchia e nuova allo stesso tempo", "No $1 after %%$2": "Manca $1 dopo %%$2", "No </defs> in %%beginsvg sequence": "Manca </defs> nella sequenza %%beginsvg", "No </style> in %%beginsvg sequence": "manca </style> nella sequenza %%beginsvg", "No accidental after 'exp'": "Manca l'alterazione dopo 'exp'", "No end of decoration": "Decorazione non terminata", "No end of grace note sequence": "Sequenza di note di abbellimento non terminata", "No end of guitar chord": "Accordo di accompagnamento non terminato", "No end of repeat string": "Stringa di ripetizione non terminata", "No end of tuplet": "Gruppo irregolare non terminato", "No end of tuplet in this music line": "Gruppo irregolare non terminato in questa linea", "No function for decoration '$1'": "Funzione inesistente per la decorazione '$1'", "No note before '-'": "Nota mancante davanti a '-'", "No note before '<'": "Nota mancante davanti a '<'", "No note in voice overlay": "Nota mancante in voce sovrapposta (overlay)", // "Non standard note duration $1": "??", "No read_file support": "La funzione read_file non è supportata", "No start of !$1!": "Manca l'inizio di !$1!", "Not an ASCII character": "Non è un carattere ASCII", "Not enough measure bars for lyric line": "Battute insufficienti per le parole", "Not enough measure bars for symbol line": "Battute insufficienti per la linea s:", "Not enough measures for %%repeat": "Battute insufficienti per %%repeat", |
| ︙ | ︙ |
Changes to err-pt_BR.js.
1 2 3 4 5 6 7 8 9 10 11 |
//JS abc2svg - Brazilian Portuguese translation of the error codes:
// Tradução dos códigos de erro para português brasileiro
// Adicione este arquivo na linha de comando para obter as
// mensagens de erro em português do Brasil.
// (Hudson Lacerda - 11/dez/2016 - 22/jan/2018)
user.textrans = {
"+: lyric without music": "+: palavras sem música",
"+: symbol line without music": "+: linha de símbolos sem música",
"+: without previous info field": "+: continuação sem campo anterior",
"'{' in grace note": "'{' em notinha ornamental",
| | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//JS abc2svg - Brazilian Portuguese translation of the error codes:
// Tradução dos códigos de erro para português brasileiro
// Adicione este arquivo na linha de comando para obter as
// mensagens de erro em português do Brasil.
// (Hudson Lacerda - 11/dez/2016 - 22/jan/2018)
user.textrans = {
"+: lyric without music": "+: palavras sem música",
"+: symbol line without music": "+: linha de símbolos sem música",
"+: without previous info field": "+: continuação sem campo anterior",
"'{' in grace note": "'{' em notinha ornamental",
"'}', ')' or ']' missing in %%score":
"Falta '}', ')' ou ']' em %%score",
"',' lacking in annotation '@x,y'":
"Falta uma ',' na anotação '@x,y'",
"'$1' is not a note": "'$1' não é uma nota",
"'$1:' line ignored": "'$1:' linha ignorada",
"$1: inside tune - ignored": "$1: no meio da música - ignorando",
"!$1! must be on a note": "!$1! deveria estar em uma nota",
"!$1! must be on a note or a rest":
|
| ︙ | ︙ | |||
30 31 32 33 34 35 36 | "%%deco: bad C function value '$1'": "%%deco: valor de função '$1' incorreto", "%%deco: cannot have a negative value '$1'": "%%deco: valor '$1' não pode ser negativo", "%%multicol end without start": "%%multicol end sem 'start'", "%%multicol new without start": "%%multicol new sem 'start'", "%%repeat cannot start a tune": "%%repeat não pode estar no início de uma música", | < < | | > > > | | < | < | | | | 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 | "%%deco: bad C function value '$1'": "%%deco: valor de função '$1' incorreto", "%%deco: cannot have a negative value '$1'": "%%deco: valor '$1' não pode ser negativo", "%%multicol end without start": "%%multicol end sem 'start'", "%%multicol new without start": "%%multicol new sem 'start'", "%%repeat cannot start a tune": "%%repeat não pode estar no início de uma música", "%%staffwidth too big": "%%staffwidth muito grande", "%%staffwidth too small": "%%staffwidth muito pequeno", "%%tune not treated yet": "%%tune ainda não é tratado", "%%vskip cannot be negative": "%%vskip não pode ser negativo", "Bad !xstem!": "!xstem! incorreto", "Bad %%setbarnb value": "Valor incorreto para %%setbarnb", "Bad %%staff number $1 (cur $2, max $3)": "Número incorreto $1 em %%staff (atual $2, máximo $3)", "Bad %%staff value '$1'": "Valor incorreto '$1' em %%staff", "Bad %%stafflines value": "Valor incorreto em %%stafflines", "Bad %%staffscale value": "Valor incorreto em %%staffscale", "Bad char '$1' in M:": "Caráter inválido '$1' em M:", "Bad character '$1'": "Caráter inválido '$1'", "Bad character in grace note sequence": "Caráter inválido em grupo de notinhas ornamentais", "Bad controller number in %%MIDI": "Número inválido do controlador em %%MIDI", "Bad controller value in %%MIDI": "Valor incorreto para controlador em %%MIDI", "Bad duration '$1' in M:": "Duração '$1' incorreta em M:", "Bad integer value": "Número inteiro incorreto", "Bad instr= value": "Valor incorreto para instr=", "Bad L: value": "Valor incorreto de L:", "Bad note in %%map": "Nota incorreta em %%map", "Bad page width": "Largura de página incorreta", "Bad program in %%MIDI": "Valor incorreto de instrumento %%MIDI", "Bad scale value in %%font": "Tamanho incorreto em %%font", "Bad tempo value": "Bad tempo value", "Bad tie": "Ligadura de prolongamento incorreta", "Bad transpose value": "Valor incorreto de transposição", "Bad user character '$1'": "Caráter ilegal '$1' em U:/%%user", "Bad value '$1' in %%linebreak - ignored": "Valor incorreto '$1' em %%linebreak - ignorado", "Bad value in $1": "Valor incorreto em $1", "Bad voice ID in %%score": "Identificador de voz incorreto em %%score", "Bar in repeat sequence": "Barra de compasso em um fragmento %%repeat", "Cannot have !$1! on a head": "!$1! não pode estar em cabeça de nota", "Cannot have '$1' inside a tune": "'$1' não pode estar dentro de uma música", "Cannot have a bar in grace notes": "Não pode haver barra de compasso em grupo de notinhas ornamentais", "Cannot have a broken rhythm in grace notes": "Não pode haver ritmo quebrado em notinhas ornamentais", "Cannot have V:* in tune body": "Não pode haver V:* no corpo da música", "Cannot read file '$1'": "Arquivo '$1' não pôde ser aberto ou não existe", "Decoration ignored": "Decoração ignorada", "Empty line in tune header - ignored": "Linha em branco no cabeçalho da música - ignorada", "Erroneous end of voice overlay": "Terminação incorreta de superposição de vozes", "Incorrect 1st value in %%repeat": "Primeiro valor incorreto em %%repeat", "Incorrect 2nd value in %%repeat": "Segundo valor incorreto em %%repeat", "Invalid 'r' in tuplet": "'r' inválido em quiáltera", "Invalid decoration '$1'": "Decoração '$1' inválida", "Invalid note duration $1": "Duração de nota $1 inválida", "Lack of ']'": "']' faltando", 'Lack of starting [, ! or " in U: / %%user': 'U: / %%user não começou com [, ! ou "', "Line split problem - adjust maxshrink and/or breaklimit": "Problema de quebra de linha - ajuste maxshrink e/ou breaklimit", "Line too much shrunk $1 $2 $3": "Linha muito encolhida $1 $2 $3", "Line underfull ($1pt of $2pt)": "Linha muito espaçada ($1pt de $2pt)", "Misplaced '$1' in %%score": "'$1' deslocado em %%score", "Misplaced dot": "Ponto fora de lugar", "Mix of old and new transposition syntaxes": "Mistura de sintaxes de transposição antiga e nova", "No $1 after %%$2": "Falta $1 após %%$2", "No </defs> in %%beginsvg sequence": "Falta </defs> em bloco %%beginsvg", "No </style> in %%beginsvg sequence": |
| ︙ | ︙ | |||
112 113 114 115 116 117 118 119 120 | "Falta terminar quiáltera nesta linha de música", "No end of voice overlay": "Falta fim de divisão de vozes", "No function for decoration '$1'": "Falta função para decoração '$1'", "No note before '-'": "Falta nota antes de '-'", "No note before '<'": "Falta nota antes de '<'", "No note in voice overlay": "Falta nota em superposição de vozes", "No read_file support": "A função read_file não existe", "No start of !$1!": "Falta início de !$1!", | > < < | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | "Falta terminar quiáltera nesta linha de música", "No end of voice overlay": "Falta fim de divisão de vozes", "No function for decoration '$1'": "Falta função para decoração '$1'", "No note before '-'": "Falta nota antes de '-'", "No note before '<'": "Falta nota antes de '<'", "No note in voice overlay": "Falta nota em superposição de vozes", "Non standard note duration $1": "Duração não padronizada: $1", "No read_file support": "A função read_file não existe", "No start of !$1!": "Falta início de !$1!", "Not an ASCII character": "Não é um caráter ASCII", "Not enough measure bars for lyric line": "Faltam barras de compasso na linha de palavras (letra)", "Not enough measure bars for symbol line": "Faltam barras de compasso na linha de símbolos", "Not enough measures for %%repeat": "Faltam compassos para %%repeat", "Not enough parameters in %%map": "Parâmetros insuficientes para %%map", |
| ︙ | ︙ |
Changes to font.js.
1 | // abc2svg music font | | | | | | | | | | | | > | | | | | | < | > > | | | | | > | | < | | | | | | > | < | | | > > > > > | | < | | | < < | < | > | | | < | > | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > | | | < < < < | < > | < < > | | | < | < > | | < | | | > > | | | | | | | | < < | > > | > > | < < | | | | | | | | | | | | | | | > > > | | < | < < | | > > | > | > > > | < > | < | > | < > | < < > > | < > > > > | | < | > | | | | | < | | > > > > > > > > > | > | < > | < | < | | | < > | | < | | < < | | | < > > > | < > | > | < < < | < < > > | | | | | < | < > | > | | > > > | < | | > | | | < > | < < < < < < < < | | | | | | | | | < < | > > | | < < | > > | | | < | > | | > > | | | | | | | | | | | | | | | | | | | < | > | > > > | | | | | | | | | | | | | | | | | > > | | | | | | | | | | | | | | | > | | | | | | | > | | | | | | | > | | | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
// abc2svg music font
var musicfont = 'url("data:application/octet-stream;base64,\
AAEAAAAOAIAAAwBgRkZUTYTd79wAAFggAAAAHEdERUYAFQAUAABYBAAAABxPUy8yWLxdCwAAAWgA\
AABWY21hcFxKS5kAAAQIAAADemN2dCAAIgKIAAAHhAAAAARnYXNw//8AAwAAV/wAAAAIZ2x5Zp27\
6QgAAAiwAABGeGhlYWQPFh8MAAAA7AAAADZoaGVhCWn/GwAAASQAAAAkaG10eNzF+scAAAHAAAAC\
SGxvY2GpopfcAAAHiAAAASZtYXhwANkBPQAAAUgAAAAgbmFtZbni4sIAAE8oAAADG3Bvc3Qtfw6A\
AABSRAAABbUAAQAAAAEAAI87udRfDzz1AAsEAAAAAADRlyIXAAAAANncuoH/OPzvBUsEiAAAAAgA\
AgAAAAAAAAABAAAEiPzvAFwEJf84/XQFSwABAAAAAAAAAAAAAAAAAAAAkgABAAAAkgEMAAUAAAAA\
AAIAAAABAAEAAABAAC4AAAAAAAEBhgGQAAUACAKZAswAAACPApkCzAAAAesAMwEJAAACAAUDAAAA\
AAAAAAAAARAAAAAAAAAAAAAAAFBmRWQAQAAA7LcDM/8zAFwEiAMRAAAAAQAAAAAAAAF2ACIAAAAA\
AVUAAAGQAAACWAAAAFcAAAFK/7ACE/+wANL/sAAjAAAAIwAAACMAAABkAAAEIwAABCUAAAHg/9wD\
XgB6AwsAAALSAAACv/+6AdYAAAMLAAADDgAAAyf/yADIAAABrgAAASIAAAGQAAABfAAAAZAAAAGQ\
AAABgQAAAZAAAAGQAAABgQAAAZkACQGYAAkB9AAAAQQAFAEEAAoCawAkAhIAAAHCAAABSQAAAUAA\
AAFK//4BLAAAAjAAAAFKAAABSgAAAGQAAAFAAAABQAAAAUAAAAFAAAAAZAAAATYAAADmAAABNgAA\
ATsAAAE7AAABOwAAATsAAAE7AAABOwAAATsAAAE7AAABOwAAATsAAAENAAAAyAAAAP8AAAELABQB\
bgAAAQ0AMgFu//UAqQAAAToAAAFA//0AUAAAAUAAAABkAAABGAAAAlgAAAC2AAAAggAAAIIAAAEs\
AAABLAAAAO4AAAD/AAABSQAAAY8AAAHYAAAB2AAAA1MAAAIz//ADIP/hAXv/tAG4/9sBFv9+ARP/\
2wDcAAAA6P/kAr//tAIz/7QCv/+0Ayv/2wFf/9sCaf9+AV//fgJp/34BXwAAAf0ABQG1AAABtQAA\
AkQADQJEAA0BGAAAATYAAAEs//8BLAAAAPoAAADIAAABGP84APoAAADIAAAEDQAAAhwADAH0AAAB\
9AAAAfQAAAH0AAAB9AAAAfQAAAB4AAAALQAAAhwAAAD6AAAA+v/oAcIAAAFIAAABQAAAAgoAAAIK\
AAAAZAAAAAAAAwAAAAMAAAAcAAEAAAAAAnQAAwABAAAAHAAEAlgAAACSAIAABgASAAAAIOAA4CTg\
MOA54EPgSOBQ4FzgYuBp4H3gjOCV4KTgqeCz4QHhueG74efh8uH04ffh+eH84gDiSeJk4oPkoOSi\
5KTkqOSs5MDkzuTq5O7lAeUl5S3lMeU55WflaeVt5YLl0OXi5hDmEuYU5hjmJOYw5lDmVekS6RXp\
GOkg6SXpXeoC6qTso+yl7Kfsqey3//8AAAAAACDgAOAi4DDgOOBD4EXgUOBc4GLgaeB64IDglOCg\
4Kngs+EB4bnhu+Hn4fLh9OH34fnh/OH+4kDiYOKA5KDkouSk5KjkrOTA5M7k4eTu5QDlIOUp5S/l\
OeVm5WnlbOWC5dDl4uYQ5hLmFOYY5iTmMOZQ5lXpEOkU6RjpIOkl6V3qAuqk7KLspeyn7Knst///\
AAP/5CAFH+Qf2R/SH8kfyB/BH7YfsR+rH5sfmR+SH4gfhB97Hy4edx52HkseQR5AHj4ePR47Hjod\
+x3lHcobrhutG6wbqRumG5Mbhht0G3EbYBtCGz8bPhs3GwsbChsIGvQapxqWGmkaaBpnGmQaWRpO\
Gi8aKxdxF3AXbhdnF2MXLBaIFecT6hPpE+gT5xPaAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAQYAAAMAAAAAAAAAAQIAAAACAAAAAAAAAAAAAAAAAAAAAQAABAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiAogAAAAqACoAKgA2\
AD4AbgB8AIoAmACkALAAvgDcAVABrAIcAl4C6gN8A9wD8ASMBR4FdgW0BdYF6gY8BowGrAbyBzIH\
bAe4B/gIPgiYCKwI0gj4CSoJRgloCZQJqgnECfoKCAoUCiAKMgpOCnAKfgqSCqQKtAsACxALKgtE\
C3wLtAwCDE4MtA0WDZQODA4yDkwOfA6mDv4PJA9+D54P3BAEEBgQJBAyEEIQahCQEJwQqBC0EMAQ\
4hEIET4RjBHsEmASdhKcEsoTHhOSE+YUJhRqFMAWGhcmF+AYoBlwGgwa6hwGHQgdSh2OHdgd8h4W\
HioePh5uHn4ekB6sHsIe5h8WH/ggtCDcIPohLCFqIZwh3iHwIf4iGiI0IloifCKqIsQi7iMqIzwA\
AAACACIAAAEyAqoAAwAHAC6xAQAvPLIHBADtMrEGBdw8sgMCAO0yALEDAC88sgUEAO0ysgcGAfw8\
sgECAO0yMxEhESczESMiARDuzMwCqv1WIgJmAAABAAAAAAGRAZAAAwAAMREhEQGRAZD+cAABAAAA\
AAAAAAAAAAAAMQAAAQAAAAAAVwQDACAAABE1NjU0JyY1NDcGFRQXFhUUBxYVFAcGFRQXJjU0NzY1\
NDUjElc/FSVNTSUVP1cSIwIDAhhDNmA5NGY6MksiOWFNYRgYZkxgOSVKMjpmNDlgNkgAAf+w/+wB\
mgAUAAMAACchFSFQAer+FhQoAAAAAAH/sP/sAmIAFAADAAAnIRUhUAKy/U4UKAAAAAAB/7D/7AEi\
ABQAAwAAJyEVIVABcv6OFCgAAAAAAQAAAAAAIwPoAAMAABEzESMjIwPo/BgAAQAAAfQAIwPoAAMA\
ABEzESMjIwPo/gwAAQAAAvgAIwRWAAMAABE3ESMjIwRMCv6iAAAAAAIAAAFAAGQCngAHAA8AABIi\
JjQ2MhYUAiImNDYyFhRHKh0dKh0dKh0dKh0COh0qHR0q/ukdKh0dKgAAAAUAAAAABCQBrgAvADcA\
PwBHAFMAACE1Mx4BMzI2NTQnLgQ1NDYzMhYXNzMXIy4BIyIGFRQeAxceARUUBiMiJwcgIiY0NjIW\
FAQiJjQ2MhYUAREzMjY0JiMDNTMRIzUzMhYVFCMCTh4VTzIpO5QZGioWEVk9JCcZHh4HHg9KMB85\
ECIZMghOTVtPRS4jAZsqHR0qHf3qKh0dKh3+iSg8RkY83EZG3HGJ+qA8SyAhLSgHCBQUIxVDTQsO\
GZs6SCgbDxcPCQsCFTczOk4gIB0qHR0qHR0qHR0qAWn+mGGmYf56HgFoHmdr0gAFAAAAAAQkAa4A\
GgAiACoAMgA+AAAhIiY1NDYzMhYXNzMXByYjIgYUFjMyNjcXDgEyIiY0NjIWFAQiJjQ2MhYUAREz\
MjY0JiMDNTMRIzUzMhYVFCMDAmd1glolKRseHgghJF44NjY4Nk0RIxRZsSodHSod/eoqHR0qHf6J\
KDxGRjzcRkbccYn6a2dldwwSHqYEjG2YbUk+CkpRHSodHSodHSodHSoBaf6YYaZh/noeAWgeZ2vS\
AAAAA//cAAIB3gKzAAcADwBNAAAAIiY0NjIWFAQiJjQ2MhYUFzQ2MzIWFRQHFjMyNjU0LwEDJxMu\
ATU0PgE3NjMyFhUUBiMiJjU0NyYjIgYVFB8BExcDHgEVFA4BBwYjIiYBniAYGCAY/n4gGBggGFsb\
FBMeLBcpJjYme88r0VpIHBMUJjMwOBsUEx4sFykmNiZ61CvVWkgcExQmMzA4AVIYIBgYIFQYIBgY\
INMSHBoRHQ4XLSYtJmX+3iABJUdxOBYtERETOCESHBoRHQ4XLSYtJmUBJh/+10dyOBYtERETOAAF\
AHr/NANeAlQAFwAbAB8AIwAnAAABMxUeARczFSMOAQcVIzUuAScjNTM+ATcRIxYXNxU2NyczJicH\
NQYHAdgoVXgHiooHeFUoVXgHiooHeFVwBWsoawVwcAVrKGsFAlSJCItgKGCLCImJCItgKGKJCP7l\
ug7IyA66KLoOyMkOuwAAAAAEAAD9bwKnBIgACwBEAE4AYwAAAQYVFBc+ATU0Jw4BExcVFAYjIiY1\
NDYzMhYUBgcWMzI2PQEnBiMiJjU0Nz4GPwEmNTQ2NxYVFAYHFzYzMhYVFCc0JiMiBiMTPgEnDgEV\
FBYXLgE1NDcnDgEHHgEzMjcBbAcFSHU2OUJLF09NUl9AMi9BPy8tGC9AFxwNmNs6DSQgLh0xEhcW\
DWxJYlx5FBQLcYhOYlACBwIhW0HiNkYnHT0/phGPbAECoXkKFgNTNy0jWjGVSHINB177bOwDTFxT\
QS1IO1g3ARk8RgPpAsedhWYXMCUtGicOERCWZoyhBzrliKlfzwKcc866PmYB/p0SXfILRjEgQhIO\
RUepLr1yl2eNowIAAgAA/fwC0gIAAGQAaAAAATI2NTQnJiMiBw4CByYnJicRIxEzETY3NjceAxcW\
MzI2NTQnJiMiBxYXFBYVFAYrASY1NDc2NzYzMhcWFxUUBgcGIyInBxc2MzIWFxYdAQYHBiMiJjU0\
NzMyFhUUBhUGBxYBMxEjAd4+Sg0aSUY8AgYKBCIaHi4cHC4eGiIGFAwZDyclMT0SJFIvMTINAjMh\
BUQFGlUnI15VNwhaSB8tND8iIj80QmYeKAg3Vl1MckQFITMCDzA1/k17e/4geEotLWxJBQ4bCmIn\
Kx/+BAQA/hEfKydiCyoXHQkbe0IxNmIaECgDDQQeKxkyFAtEGQ1PNFMSTm8cDRdLShc+LDlDElM0\
UE48MhkrHgQOBCYQHAPe/AAAAAP/uv2lAsMA/wAqADYAQgAANzQ2MzIWFxYVFAYHDgEHNjc+ATc2\
NTQmJy4BIyIGBz4BMzIWFRQHBiMiJgUiJjU0NjMyFhUUBiciJjU0NjMyFhUUBhOLZ1VrKy9GVWbP\
leWFMTQTChEdHDQzO2EWGCMbLj0nITEzRQKCFh0aFBUeGhoXGxwVFBwbHWKANDk+cn+6T2BNCD2F\
MWNQK2ZHUCMiF09GHhdBLzIgHlGKHBcWHB0VFh3yHhkVGhsUGR4AAAIAAP8GAXIA+gADAAcAADcz\
EyMDMxMj3JQCltyUApb6/gwB9P4MAAAEAAD+CgIfA6oACQAgAGIAbQAAJRYXPgE1NCYjIgMCJw4B\
FRQXLgE1NDY3JicOAQceATMyFx4BHwEdARQjIiY1NDYzMhYVFAYHFjMyNjU0LwEGIyImNTQ3PgE3\
PgI3JjU0NjceARUUBgceARc2MzIXFhUUBwYDBhUUFz4BNTQnBgFJEwZNR1ZCDg0YASw5HyAqTDsF\
CXFVAQVtggMiAwYCAno2UzMoJTUxJxUiIywBDQkVjZkuDkweBSMnEg5ZQC8ZSWECCAQSCFw5MmM2\
ZAMGN14pX3XEWxJPMzZW/uABCxAJNCcpJhJBKThOED5aWnlTcX4aIEAXFxsHf0gxJDM3JCIoAQwz\
NQ8JjQGSimpRHFAYBCAhDcIHbn8TM2JbbYdMEW4kAkM2YncwGwNWHiI5JCV7M0YmJgACAAD+YwJC\
AZoAYwBnAAABMjY1NCcmIyIHDgEHJicmJxEjETMRNjc2Nx4DFxYzMjY1NCcmIyIHFhcUFhUUBisB\
JjU0NzY3NjMyFxYXFRQGBwYjIicHFzYzMhYXFh0BBgcGIyImNTQ3MzIWFRQGFQYHFgEzESMBfjI7\
ChU6ODACDAQdExglFhYlGBMdBBEKEwwgHScxDhxDJScoCgIqGgQ2BBVEIxhJRi0GSDoYJSsxGxs0\
KDVSGCAGLUZJPVs2BBoqAgwmK/6jYmL+gGA7JCRXOwUdC1IcIhn+agMz/nQZIhxSCCISFwgWYjUr\
KE4VDSACCwMYIhQoEAk1FQtAK0EOPloWChI8OxMyIy41D0ErQD8wKBQjGAMLAx8NFgMY/M0AAAAA\
A//I/h4CNgDMACYALwA7AAA3NDYzMhcWFRQHDgEHNjc2NzY1NCcuASMiBgc+ATMyFhUUBwYjIiYF\
IiY0NjIWFAYnIiY1NDYzMhYVFAYPcFKCPCN4Q8ZpwF5HHgktGC0gMFIKEhYWJTkgGSUsOQICEhcU\
IhgVFRIWFRIRFhUhTV5XM1rGbDtXBjNkSowvKWYzGhRCNhcNPCYoGhhTdRckFhciGMIYFBEUFRAT\
GQAAAAADAAAAAADIAPAACQATACkAADcGFRQWMzI2NTQnIgYVFBc2NTQmByImNTQ2Ny4BNTQ2MzIW\
FRQHFhUUBlAjGxARFAIOEyAjEzAlNSMiEQwoHiQ2PCg0dxQdFB4bERaGEQ4XGQshDxTcKB4XGgsP\
ExAaIiAcIxAgGyAmAAAAAgAA/wYBrgD6AAsAFAAAMxQWMzI2NTQmIyIGBzQ2MhYUBiImiiojIisn\
JiUoin20fX20fWJ4eWFldXZhZ5CR0pGSAAABAAD/BgEiAPoACQAAMTczERcVIzU3EWR9QfBB+v4+\
HhQUHgEsAAAAAQAA/wYBjwD6ADwAADcyFRQHDgMHNjMyFjMyNz4CMw4CBwYHBiMiJiMiBiMiNTQn\
PgU1NCciBzIWFRQGIyI1ND4Bx8gFDTZAbzYTIBtkHBgeBRAMAQEFBQEHEBopGnQVH1YCBwECLD5H\
PChTThocKTceTDxY+n4aDiEuHUQtDCMOAw0LBRYWAykOGCcmEAECIUU4PDI4GGIBNSUeHylnKDkZ\
AAABAAD/BgF1APoAOQAANzIWFRQGIyImNTQ3NjMyFxYVFAYHHgEVFAcGIyImJyY0NjMyFhUUBiMW\
MzI2NTQmJyY0Nz4BNCYjImYbIichGzIfM1lGJkRGPT5RSyRNJ1cYIzIgIiolGww/JCtILhYWL0sp\
JDyqHBcbIysjLxoqEyJILkQLC0UtQycTFhQdTC4hGxkeKTEnJjoIBCIECTdQMAAAAQAA/wYBkAD6\
ABEAAAUXIzc1IzU2NTMBMz8BETMVIwFFMsgy4ZOj/vuwAWNLS9EpKTEo8oD+jpaR/tkoAAAAAAEA\
AP8HAX4A+gAvAAAXNjMyFhUUBiMWMzI3PgE1NCcmIyIHEyEOASsBBzYzMhceARUUBw4CIyInLgE1\
NBIcIRsqIBwaJDEcEwkeHChOSAoBYgs1JdUGOUJTMSErQxZAKyU8KxAeXyAgFxwgIR4UHyA5HBo1\
ASIkOnkeHxVBJU8vEBACFAkyEiMAAAAAAgAA/wYBgQD6AAkALAAAFzI2NTQmIyIHFhMWFRQGIyIm\
NTQ2MyYjIgYVPgIzMhYVFAYjIiYnPgEzMhbIKS0qKCwwB90bIxgeIhsQFjc1LxUYLR5MT3FIYWYB\
AWxbMD/SRSwiMCWeAZ8aJhkoHhsMHiN4XwsKCUA2RFmCeGmREgABAAD/BgGQAPsAKAAANyIOAwc3\
PggzMhYzMjY3DgQVIzY3Njc2NwYjIiZhFBoUCREFCgEMAgsFCwkNEAkvdSMaOxEbRRoeCIIBCBFo\
Hi0RHiVgoQUOCRsGdAELAgkBBgEDASYXDkOnQVxCK0UbNocnOQooAAMAAP8GAYQA+gAOABwANAAA\
Fw4BFRQWMzI2NTQuAzc+ATU0JiIGFRQeAwcuATU0NjcyFhUUBgceARUUBiMiJjU0Npo2LFgsKj8P\
IB0xPjMjRFIzChwSMXAxKWZKS2UqMDoydU1MdjkqGSQbHTApHw4XEg0TWhoiHB0wKCAPFxMKFT8Y\
PDUzTQFGMic0Fxo6NTdKSDAkNQAAAgAA/wYBgQD6AAkALAAANyIGFRQWMzI3JgMmNTQ2MzIWFRQG\
IxYzMjY1DgIjIiY1NDYzMhYXDgEjIia5KS0qKCwwB90bIxgeIhsQFjc1LxUYLR5MT3FIYWYBAWxb\
MD/SRSwiMCWe/mEaJhkoHhsMHiN4XwsKCUA2RFmCeGmREgABAAn/CgGZAPkAMAAAJTAXNjU0JiMO\
ARUUFxYzMjc2NxQeARUOAQciJyYnNCY1NDcyFhcWFRQGIyImNT4BMwEvEgQ8HzNAJyEwKygcKgkI\
G1VWTzs7BAHbJEARIiQcICkCIBqkAwUIFB4CYmqOMyoiGFgBBAMBVVABOTlmAisC5gIeFCckJTku\
HBYmAAIACf6iAZkBXgA4AD8AACUwFzY1NCYjIgcRFjMyNzY3FB4BFQ4BByMVIzUmJyYnNCY1NDc1\
MxUyNjMyFhcWFRQGIyImNT4BMwMRBhUUFxYBLxIEPB8DEAwMKygcKgkIG1FVASM9LjsEAasjAwcD\
JEARIiQcICkCIBp6PScKpAMFCBQiBP5LBCIYWAEEAwFUUQFoawktOWYCKwLLGWlmAR4UJyQlOS4c\
Fib+lwGWLpGOMw0AAAEAAP8GAfQA+gALAAA1MzUzFTMVIxUjNSPXRtfXRtcj19dG19cAAAABABT+\
BgDjAgAAEwAAExYHBicmAjU0Ejc2FxYHBgIVFBLcBw0JBUlra0kJCwYGPEZH/hYIBQMGVwEgfXwB\
IlYLBwYISf7niIb+5QAAAQAK/gIA3AH9ABMAABM2EjU0AicmNzYXFhIVFAIHBicmFDtHRjwJDAoH\
SWtrSQgLBv4WSQEbhogBGUkLBAQJVv7efH3+4FcJCQQAAAQAJP9WAkwAqgALAA8AEwAeAAAFNCYj\
IgYVFBYzMjY3MxEjATMRIyQUBiMiJjU0NjMyAahUPCA0Vz0hL3IyMv4KMjIB9XtmZXx5aGYgNU4n\
HzVLI+r+rAFU/qzmeEZJOT9DAAACAAD/JAISANwAAwAPAAA3FSE1JTMVITUzESM1IRUjHgHW/gwe\
AdYeHv4qHkGCgps3N/5INzcAAAIAAP9/AcIAgQALABMAAAU0JiMiBhUUFjMyPgEUBiImNDYyAVFa\
NiA0XTchL3F9yH19yB40TycfNEwjdGxLS2xLAAAAAgAA/2wBSACUAA0AGwAAJSYjIgYVFBcWMzI2\
NTQ3FhUUBiMiJyY1NDYzMgEkDSU8lwYLJjyXEA9+SE8kD35IT0QXYSsKCRdhKwkXHh1DZ0MeHUNn\
AAAAAAEAAP95AUAAhwALAAAlFAYjIiY1NDYzMhYBQHlZMjx6WDI8KEZpOCdFajgAAf/+/28BTACR\
AAsAACc3FzcXBxcHJwcnNwIbjIwbhoYci4schnEgdnUgcHAhdXUhcAAAAAUAAP9qASwAlgAFAAsA\
EQAXAB8AABcHFjMyNy8BBhUUFz8BJiMiBx8BNjU0JwY0NjIWFAYilkcdKikfXUcdHVxIHykqHVxH\
HR3yWHxYWHwSSB0dWkkfKSodWEgdHVpIHykqHYV8WFh8WAAAAAEAAP8GAjAA+gADAAAVATMBAbh4\
/kf6AfT+DAABAAD/dAFKAIwAAwAAMTcXB6WlpYyMjAABAAD/dAFKAIwAAgAAFRsBpaWMARj+6AAB\
AAD/zgBkADIABwAAFiImNDYyFhRHKh0dKh0yHSodHSoAAAABAAD/eQFAAqgADwAAESERFAYjIiY1\
NDYzMhcRIQFAeVkyPHpYMR/+3gKo/YBGaTgnRWocAcUAAAEAAP95AUACqAATAAARIREUBiMiJjU0\
NjMyFxEhNSE1IQFAeVkyPHpYMR/+3gEi/t4CqP2ARmk4J0VqHAEReDwAAAAAAQAAAjABQAKoAAMA\
ABEhFSEBQP7AAqh4AAAAAAIAAAF8AUACqAADAAcAABEhFSERIRUhAUD+wAFA/sAB9HgBLHgAAAAB\
AAD/2gBkAD4ABwAAFiImNDYyFhRHKh0dKh0mHSodHSoAAAABAAADAgE2A8AABQAAESEVIRUjATb+\
6B4DwB6gAAAAAAEAAAMqAOYEOAA5AAATIiY1NDYzMhYVFA8BFDMyNjU0JisBIjU0OwEyNjU0JiMi\
FRQWFRQjIiY1NDYzMhYVFA4BFRQWFRQGUCcpEA4PEgsMIRUkEQ8SFBQoFyUODhUCIQwSJSsjLSMj\
FDMDKh4YDhYQDBIHBw0qHw8ZDhAlFQ0TDQMICBwRDBUeIhoYIxMCASIPIy0AAAAAAQAAAwIBNgPA\
AAUAAAEVIzUhNQE2Hv7oA8C+oB4AAAABAAD87wE7AAAADwAAFTUzHgQVFAc2NTQmJx4GP1FQNy4S\
kXDv7zVwZWyJSWBpQUmP3yoAAQAAAAABOwMRAA8AADE1Mz4BNTQnFhUUDgMHHnCSEy43UFE/Bu8f\
4ZNHSGdeSIptZ3E1AAIAAP1EATwAAAAYACYAABkBMx4GFRQHFhUUBzY1NC4DIzUeAxc0NjU0LgMe\
BiczOzguHBITHgUpPkhAFglETVYVASk+SEH+qQFXGzkzNzo9SCUsKykrNjkZITdkRTQYqyRUQ10p\
BAwEN2VFMxkAAAACAAD//wE8ArwAGAAmAAAVETMyPgM1NCcWFRQHFhUUDgUHNTI+AzU0JjUOAx4W\
QEg+KQUeExIcLjg7MycGFkFIPikBFVZNRAEBVxg0RWQ3IRk5NispKywlSD06NzM5G6sZM0VlNwQM\
AyldQ1MAAAAAAwAA/SoBPACRABsAKQA3AAAZATMeBhUUBxYVFAcWFRQHNjU0LgIjNR4DFzQ2NTQu\
AiMnHgMXNDY1NC4CIx4GJzM7OC4cEhISEx4FPVdVHAlETVYVATxWVR0CCURNVhUBPFZVHf6QAgEb\
OTM3Oj1IJSwrJy0sKykrNjkZIUR3SCmpJFRBXSkEDQNEdkgpqyRTQl0pBA0DRHZIKQAAAwAA/1YB\
PAK9ABwAKQA2AAARMzI+AzU0JxYVFAcWFRQHFhUUDgUHIzcyPgI1NCY1DgMnMj4CNTQmNQ4DHhZA\
SD4pBR4TEhISHC44OzMnBh4eHVVXPQEVVk1ECR1VVz0BFVZNRAFXGDRFZDchGTk2KykrLC0nKywl\
SD06NzM5G6opSXhEBAwEKV1DVIYpSXhEAw0EKV1DVAAEAAD9QgE8AVQAIAAuADwASgAAGQEzHgYV\
FAcWFRQHFhUUBxYVFAc2NTQuAyM1HgMXNDY1NC4DJx4DFzQ2NTQuAyceAxc0NjU0LgMeBiczOzgu\
HBISEhISEx4FKT5IQBYJRE1WFQEpPkhBFglETVYVASk+SEEWCURNVhUBKT5IQf6oAqwbOTM3Oj1I\
JSwrJy0sKyctLCspKzY5GSE3ZEU0GKskVENdKQQMBDdlRTMZqyRUQ10pAw4DN2VFMxmrJFRDXSkE\
DAQ3ZUUzGQAEAAD+jgE8AqAAHwAsADkARgAAGQEzMj4CNTQnFhUUBxYVFAcWFRQHFhUUDgUHNTI+\
AjU0JjUOAycyPgI1NCY1DgMnMj4CNTQmNQ4DHhxVVz0FHhMSEhISEhwuODszJwYdVVc9ARVWTUQJ\
HVVXPQEVVk1ECR1VVz0BFVZNRP6OAqwpSHdEIRk5NispKywtJyssLScrLCVIPTo3MzkbqilJeEQD\
DQQpXUNUhilJeEQDDQQpXUNUhilJeEQDDQQpXUNUAAAABQAA/VUBPAISACQAMgBAAE4AXAAAGQEz\
HgYVFAcWFRQHFhUUBxYVFAcWFRQHNjU0LgMjNR4DFzQ2NTQuAyceAxc0NjU0LgMnHgMXNDY1NC4D\
Jx4DFzQ2NTQuAx4GJzM7OC4cEhISEhISEhMeBSk+SEAWCURNVhUBKT5IQRYJRE1WFQEpPkhBFglE\
TVYVASk+SEEWCURNVhUBKT5IQf67A1cbOTM3Oj1IJSwrJy0sKyctLCsnLSwrKSs2ORkhN2RFNBir\
JFRDXSkDDQQ3ZUUzGaskVENdKQQMBDdlRTMZqyRUQ10pAw4DN2VFMxmrJFRDXSkEDAQ3ZUUzGQAA\
BQAA/bwBPAJ5ACMAMAA9AEoAVwAAGQEzMj4CNTQnFhUUBxYVFAcWFRQHFhUUBxYVFA4FBzUyPgI1\
NCY1DgMnMj4CNTQmNQ4DJzI+AjU0JjUOAycyPgI1NCY1DgMeHFVXPQUeExISEhISEhIcLjg7MycG\
HVVXPQEVVk1ECR1VVz0BFVZNRAkdVVc9ARVWTUQJHVVXPQEVVk1E/bwDVylId0QhGTk2KykrLC0n\
KywtJyssLScrLCVIPTo3MzkbqilJeEQDDQQpXUNUhilJeEQDDQQpXUNUhilJeEQDDQQpXUNUhilJ\
eEQDDQQpXUNUAAAAAgAA/2QA4QGwAAoAFgAANyIGHQE2NzY1NCY3MhYVFAcGIxEzETZnFCsiJisd\
ByM5S1JEKCN6JhO5Dzg7LxsmJjIjSUxSAkz+vDQAAAIAAP6GAMUBegADAAwAABc3NQcRFTcRIzUH\
ETcckJCpGawBZS2WLQFJ6DT9wOIzAkMBAAACAAD+mAD/AWgAAwAfAAA3FTc1AyM1BzU3NQc1NzUz\
FTc1MxU3FQcVNxUHFSM1B1NaWh41NTU1HlodNTU1NR1aRqcbp/43ow9cD6cPWg+onxyrow9cD6cP\
Wg+onxwAAAABABT/hAELAHoAHgAAFzUmJwcwFSM1MzcnMCM1MxUWFzcwNTMVIwYHFzAzFcMoDDNI\
OTMzOUghEjRIOSETNDl8OyYNMztKMjJIOSIRMzlHIhE0SAAEAAD/agFsAbAADgAcACsAOgAANw4B\
HQEyNzY3NjU0JyYjNzIWFRQHBgcGIxEzETYXDgEdATI3Njc2NTQnJiM3MhYVFAcGBw4BIxEzETZO\
ER4OHh8MBAoQERkdKwkYKzUvHxnRER0QHh0LBgsQDxYfKgsZKBY3Fh4bfQEeEMYpKzQNGR4UFSY5\
IRIgOTRAAkb+wTImAR0RxikvMBMTHBYVJjYkFhw+LxslAkb+wTIAAAIAMv9kAQ0BsAAKABYAADci\
BhUUFxYXNTQmJzIXETMRIicmNTQ2qxcgLi4aKjM6IyM6Uk85eiYbMEVCA8sSHiY0AUT9tFJQRSMy\
AAAE//X/agFsAbAADgAdACwAOwAANyMiBwYVFBcWFxYzNTQmJzIXETMRIiYnJicmNTQ2Fw4BHQEy\
NzY3NjU0JyYjNzIWFRQHBgcOASMRMxE2VwEREAoEDB8eDh4rMBkfFjcXKxgJK+kRHRAeHQsGCxAP\
Fh8qCxkoFjcWHht9FRQeGQ00KynGEB4nMgE//bolGzQ5IBIhOSYBHRHGKS8wExMcFhUmNiQWHD4v\
GyUCRv7BMgAAAAABAAD+wACpAUAAEwAAEzMVNxUHFTcVBxUjNQc1NzUHNTdEHkdHR0ceRERERAFA\
og5cDn8OWg+oog5cDn8OWg8AAwAA/pgBOgFoACMAJwArAAA3NTMVNxUHFTcVBxUjNQcVIzUPASM1\
BzU3NQc1NzUzFTc1MxUDNQcVNxU3NekeMzMzMx49HjwBHjMzMzMePR4ePVs9wKieD1wPnw9aD7Wq\
EqykEKieD1wPnw9aD7WqEqyk/v2eEZ+4nhGfAAH//QAAAT8A9AAYAAA3BiMiJjU0PwE2LwEmNTQ2\
MzIxFwUWFRQHEgIDBwkGzw4OzQgLBwECAR8ODgEBEAgKA0kHBk8DCwoSAWsGDg0FAAAAAQAAAAAA\
UABQAAkAADU0NjIWFAYjIiYXIhcXERAYKBEXFyIXGAAAAAEAAAAAAUAAKAADAAAxNSEVAUAoKAAA\
AAEAAAAAAGQBGAADAAAzAzMDKChkKAEY/ugAAAABAAAAAAEYATUABQAAMRsBIycHjIxBWFoBNf7L\
xsYAAAIAAAAAAlgBSgAOABkAADE0NjMyHgIVIy4BIgYHISImNDYzMhYVFAazeTlrVTMPC6LgogsB\
HBclJRcZIyOYsixRgE1uhoZuJDAkJBgZIwAAAQAAAAAAtgEtABcAABMyFhcWFRQHDgEjJyY1NDY1\
NCMuATU0NlYbGxAaMhlEEAYBRxQbKC0BLQwRHTA9PB0tAwECCGsTDwEmHB4xAAEAAP8GAIIA+gAD\
AAA1MxEjgoL6/gwAAAEAAAAAAIIA+gADAAA1MxUjgoL6+gAAAAEAAP+DASwAAAADAAAxIRUhASz+\
1H0AAAEAAAAAASwAfQADAAA1IRUhASz+1H19AAEAAP5+AOsBhwATAAATFwcXJiMiBhUUFyY1NDYz\
MhcnNym9Z2wyNB8mOHg0JSIih2QBh+XZzy4kHTU0S00jLRW8tAAAAQAA/w0BAADAABYAADcOAiMi\
JjU0NjIWFRQHMjY3NjIXAyerAxkaEys3JjgpFyIzIQIVA5YwPAEHBCkoHyAeGR0bISwCAv5vEAAA\
AAEAAP4MAUgAwAAkAAAXBiMiJjU0NjMyFhUUBzI/AQYjIiY1NDYzMhYVFAcyNzYyFwMnqyghKzcn\
GxwpF0ELPDYYKzcnGxwpF0guAhUDxS3EDCgoICAfGR0bIsoMKSgfIB4ZHRtNAgL9bgwAAAEAAP4M\
AY8BwAA2AAA3BiMiJjU0NjMyFhUUBzI/ASIOASMiJjU0NjMyFhUUBzI3NjIXAScTBiMiJjU0NjMy\
FhUUBzI39igfKzcnGxwpFz8LOgEgHBMrNycbHCkXSC4BFgP+9C1VKCErNycbHCkXQQs8DCgoICAf\
GR0bIssJBCkoHyAeGR0bTQIC/G4MASQMKCggIB8ZHRsiAAAAAAEAAP0MAdoBwABFAAATBiMiJjU0\
NjMyFhUUBzI/AQYjIiY1NDYzMhYVFAcyPwEGIyImNTQ2MzIWFRQHMj8BIg4BIyImNTQ2MhYVFAcy\
NzYyFwEnqyghKzcnGxwpF0ELOighKzcnGxwpF0ELOigfKzcnGxwpFz8LOgEgHBMrNyY4KRdILgIV\
A/6pLf48DCgoICAfGR0bIsoMKCggIB8ZHRsiygwoKCAgHxkdGyLLCQQpKB8gHhkdG00CAvtuDAAA\
AAEAAP0MAhkCrgBWAAAlBiMiJjU0NjMyFhUUBzI/AQYjIiY1NDYzMhYVFAcyPwEiDgEjIiY1NDYz\
MhYVFAcyNzYyFwEnEwYjIiY1NDYzMhYVFAcyPwEGIyImNTQ2MzIWFRQHMjcBPyghKzcnGxwpF0EL\
NigfKzcnGxwpFz8LNAEgHBMrNycbHCkXSC4BFgP+ai1VKCErNycbHCkXQQs6KCErNycbHCkXQQs0\
DCgoICAfGR0bIsQMKCggIB8ZHRsixwkEKSgfIB4ZHRtNAgL6gAwBJAwoKCAgHxkdGyLIDCgoICAf\
GR0bIgABAAD/GgNSAOYACwAANTMVITUzESM1IRUjGQMgGRn84BnmfX3+NH19AAAAAAP/8P8GAiYA\
+gAHAA8AEwAANiImNDYyFhQAIiY0NjIWFAUBMwFQMiMjMiMBiDIjIzIj/dIBuH7+R0sjMiMjMv7P\
IzIjIzJaAfT+DAAE/+H/BgMHAPoABwAPABMAFwAANiImNDYyFhQAIiY0NjIWFAUBMwEzATMBQTIj\
IzIjAncyIyMyI/zjAbh7/kd5Abh7/kdLIzIjIzL+zyMyIyMyWgH0/gwB9P4MAAL/tP+IAXwBGAAR\
ADsAADcWMzI2NzY1NCcmIyIGBwYVFBciJwczMhQrASI0OwETNjU0IyIOAwcGJjc2NzYzMhYXPgEz\
MhYVFAbFAgUSMg4NDwIEEjULDycqGS00CwvhCwtLaAYLCAwPCxkKBRsFMQ8YJCMkBx0mIx4tWSgB\
NSQgJiUFATMcJyQpLiB6Hh4BHRIMDwcUEiwQCA8JWBAZExoeDzQwSWsAAAH/2//2Ab4BGABTAAA3\
BgcGKwEiPwE2JiMiBgcGJjc+AzMyFzYzMhc+ATMyFhUUDwEGFRQzMjc+BTc2FgcOAiMiJjU0PwE2\
NTQjIg8BBgcnBiY/ATY1NCMiB1AHCAQENQ0NQgQGCA0WJAUVBBQQIh8SNwskJC0JCykTGSQFLwQI\
AQQFCwcMAw0BBhUGEhctHxUZBTQBFRsIQQgPJg0IBEMBFRsIFREDARqnDQ8aOQgMCSUaMBIoKCgQ\
GCMaCw99CwkOAgMJBg8FEgEJDQsfHxoWEw0NiAIEDhSrFgEBAQ8IqwIEDhQAAAAB/37/YAFeAbgA\
QQAAByImNTQ2MzIWFRQHBhUUMzI+BzcjIjU0OwE+ATMyFhUUBiMiJjU0NzY0IyIOBwczMhQrAQ4B\
MiAwFxMSFxIKGQsQDwsNCg4NFAo1ExFBFGk0IDAXExIXEgoZBwwKBwgFBgMGATYTEz8hdqAmIBoi\
FA8OCwcNDgYREyUkPDdVJxUTS18mIBoiFA8OCwYcBQsKFA0aDR4GKMXBAAAB/9sAAAETARMAKgAA\
Nz4BJiMiBg8BBgcGKwEiPwE2JiMiBgcGJjc+ATMyFhc2MzIWFRQjIiY1NNAFAwMFFCQJPwcIBAQ1\
DQ1CBAYIDhciBRUEITgiGx0EHyQaICsPG+cDBwQsGJwRAwEaow0PGjUIDAk8QBoNJx4ZNxYNFAAA\
AAEAAAAAANwBGAAxAAAzIiY1NDYyFhUUBxYzMjY1NC4CJyY1NDYzMhYVFAYjIiY1NDcmIyIGFRQe\
AhcWFRRQHjIVGhcQDBMWIQkLGAY6Ny0iNhYQDRYHDxEPGRESHgUwKxsQFhAMEhAQFhILDwcNBCUw\
IygkGBAYFA4DDhMRDQkTDBEDICtVAAAB/+T//ADnAQ8APAAAJwYuAT8BIgYjIiYOAQcGJyY3PgE3\
HgEzMjYzMhcWFA8BBhUUMzI2MzIXFjc2JyI1NDYzMhUUBisBLgEjIgoGCwEFsAUfDAMUDB8FDwQD\
CAwLAQ4vFSIrBAgFCweeAgIBDQYaIw0IBQckEg0mKB4dGCUIDgMECA0GwQYGAjIFDQsJEh4wAgEG\
CwEBEQenBgIDAxoKDg0DHQ4VNx4vAxgABf+0/4gFSwEYABsANQDZAPABCwAAJRYzMj4BNz4GNTQm\
JyYjIgYHDgIVFAUWMzI2Nz4FNTQmJyYjIgYHBhUUHgEXIicHMzIUKwEiNDsBEz4CNTQuAiMiDgMH\
BiY3Njc2MzIWFz4BMzIXPgEzMhYXPgEzMhc+ATMyFhc+ATMyFz4BMzIWFz4BMzIWFRQGIyInBzMy\
FCsBIjQ7ARM+AjU0JiMiBgcVFAYjIicHMzIUKwEiNDsBEz4CNTQmIyIGBxUUBiMiJwczMhQrASI0\
OwETND4DNDU0JiMiBgcVFAYlFjMyNjc+BDU0JicmIyIGBwYVFAUWMzI2Nz4GNTQmJyYjIg4BBwYV\
FBYCCgMEDB8eCQIDAgICAQEHCAMDEzQLBQcD/ssDBBIyDgIDAwMBAQcIAwMTNAsPBAcIFhktNAsL\
4QsLS2gBAwIBAgUDCAwPCxkKBRsFMQ8YJCMkBx0mIy8TEiIbIyQHHSYjLxMSIhsjJAcdJiMvExIi\
GyMkBx0mIx4ta0kWGS00CwvhCwtLaAEDAgUGDhQUa0kWGS00CwvhCwtLaAEDAgUGDhQUa0kWGS00\
CwvhCwtLaAECAQIFBg4UFGsDgwMEEjIOAgQDAwEHCAMDEzQLD/7LAwQSMg4CAwICAgEBBwgDAwwh\
HgcPCSgBGCoXBAoJCwoKCwUQFwMBMxwNGxgLKAcBNSQFCwwMDAwGEBcDATMcJiUMFA0qIHoeHgEd\
AggOBgMFBQIHFBIsEAgPCVgQGRMaHg8yHBYTGh4PMhwWExoeDzIcFhMaHg80MEdtIHoeHgEdAggO\
BgcIGCMBR20geh4eAR0CCA4GBwgYIwFHbSB6Hh4BHQEDBQUGBwMHCBgjAUdtKAE1JAYNDw4PBxAX\
AwEzHCYlKAcBNSQECgkLCgoLBRAXAwEYJRImJRIaAAAE/7T/iAQGARgAfQCYALQAzgAAISInBzMy\
FCsBIjQ7ARM+AjU0JiMiBgcVFAYjIicHMzIUKwEiNDsBEzQ+AzQ1NCYjIgYHFRQGIyInBzMyFCsB\
IjQ7ARM+AjU0LgIjIg4DBwYmNzY3NjMyFhc+ATMyFz4BMzIWFz4BMzIXPgEzMhYXPgEzMhYVFAYn\
FjMyNjc+BjU0JicmIyIOAQcGFRQWBRYzMj4BNz4GNTQmJyYjIgYHDgIVFAUWMzI2Nz4FNTQmJyYj\
IgYHBhUUHgEDUhYZLTQLC+ELC0toAQMCBQYOFBRrSRYZLTQLC+ELC0toAQIBAgUGDhQUa0kWGS00\
CwvhCwtLaAEDAgECBQMIDA8LGQoFGwUxDxgkIyQHHSYjLxMSIhsjJAcdJiMvExIiGyMkBx0mIx4t\
a0wDBBIyDgIDAgICAQEHCAMDDCEeBw8J/sIDBAwfHgkCAwICAgEBBwgDAxM0CwUHA/7LAwQSMg4C\
AwMDAQEHCAMDEzQLDwQHIHoeHgEdAggOBgcIGCMBR20geh4eAR0BAwUFBgcDBwgYIwFHbSB6Hh4B\
HQIIDgYDBQUCBxQSLBAIDwlYEBkTGh4PMhwWExoeDzIcFhMaHg80MEdtKAE1JAQKCQsKCgsFEBcD\
ARglEiYlEhoDARgqFwQKCQsKCgsFEBcDATMcDRsYCygHATUkBQsMDAwMBhAXAwEzHCYlDBQNAAP/\
tP+IAsEBGABXAHEAjQAAMyInBzMyFCsBIjQ7ARM+AjU0LgIjIg4DBwYmNzY3NjMyFhc+ATMyFz4B\
MzIWFz4BMzIWFRQGIyInBzMyFCsBIjQ7ARM0PgM0NTQmIyIGBxUUBicWMzI2Nz4FNTQmJyYjIgYH\
BhUUHgEFFjMyPgE3PgY1NCYnJiMiBgcOAhUUyBYZLTQLC+ELC0toAQMCAQIFAwgMDwsZCgUbBTEP\
GCQjJAcdJiMvExIiGyMkBx0mIx4ta0kWGS00CwvhCwtLaAECAQIFBg4UFGtMAwQSMg4CAwMDAQEH\
CAMDEzQLDwQHAUoDBAwfHgkCAwICAgEBBwgDAxM0CwUHAyB6Hh4BHQIIDgYDBQUCBxQSLBAIDwlY\
EBkTGh4PMhwWExoeDzQwR20geh4eAR0BAwUFBgcDBwgYIwFHbSgBNSQFCwwMDAwGEBcDATMcJiUM\
FA0CARgqFwQKCQsKCgsFEBcDATMcDRsYCygAAAL/2/+IAysBGAB6AI8AACU2NzYzMhYXPgEzMhYV\
FAYjIicHMzIUKwEiNDsBEz4DNTQmIyIOAwcOASMiJjU0Nj8CNCMiDwEGBycGJj8BNjU0JiMiDwEG\
BwYrASI/ATYmIyIGBwYmNz4DMzIXNjMyFz4BMzIeAxUUDwEGFRQzMjc+ARcWMzI2Nz4BNTQmJyYj\
IgYHBhUUFgGtMRQYIiMkBx0mIx4ta0kWGS00CwvhCwtLaAEBAwEFBgcPEg4YCBo8LRUZAgM0ARUb\
CEEIDyYNCARDAQwJGwhEBwgEBDUNDUIEBggNFiQFFQQUECIfEjcLJCQtCQspEwoSDwsHBS8ECAID\
DyXRAwQSMg4GBwcIAwMTNAsPCXdsGB0TGh4PNDBHbSB6Hh4BHQIFCQkFBwgNHxs1EDY4FRQGDQeI\
Bg4UqxYBAQEPCKsDAwYIFKwRAwEapw0PGjkIDAklGjASKCgoEBgGCw8TCg0NfQsJDgIINTkBNSQP\
JhEQFwMBMxwmJRIaAAL/2/9gAxkBuABXAJ8AADcGBwYrASI/ATYmIyIGBwYmNz4DMzIXNjMyFz4B\
MzIeAxUUDwEGFRQzMjc+BTc2FgcOAiMiJjU0Nj8CNCMiDwEGBycGJj8BNjU0JiMiBxMiJjU0NjMy\
FhUUBwYVFDMyPgc3IyImNTQ2OwE+ATMyFhUUBiMiJjU0NzY0IyIOBwczMhYVFA4BKwEOAVAHCAQE\
NQ0NQgQGCA0WJAUVBBQQIh8SNwskJC0JCykTChIPCwcFLwQIAgMFCwcMAw0BBhUGEhctHxUZAgM0\
ARUbCEEIDyYNCARDAQwJGwj1IDAXExIXEgoZCxAPCw0KDg0UCjUJCgkIQRRpNCAwFxMSFxIKGQcM\
CgcIBQYDBgE2CQsFCQY/IXYVEQMBGqcNDxo5CAwJJRowEigoKBAYBgsPEwoNDX0LCQ4CAwkGDwUS\
AQkNCx8fGhUUBg0HiAYOFKsWAQEBDwirAwMGCBT+nyYgGiIUDw4LBw0OBhETJSQ8N1UnDAkIC0tf\
JiAaIhQPDgsGHAULChQNGg0eBgwIBQkGxcEAAAAAAf9+/2ACaQG4AHsAACUjDgEjIiY1NDYzMhYV\
FAcGFRQzMj4HNyMiJjU0PgM7AT4BMzIWFRQGIyImNTQ3NjQjIgcGBxc+ATMyFhUUBiMiJjU0NzY0\
IyIOBwczMhYUBisBDgEjIiY1NDYzMhYVFAcGFRQzMj4HAV+bIXZfIDAXExIXEgoZCxAPCw0KDg0U\
CjUJCgEDBAYDQRRpNCAwFxMSFxIKGSYXAwGbFGk0IDAXExIXEgoZBwwKBwgFBgMGATYJCwsJPyF2\
XyAwFxMSFxIKGQsQDwsNCg8NFObFwSYgGiIUDw4LBw0OBhETJSQ8N1UnDAkDBQUEAktfJiAaIhQP\
DgsGHHMMBgFLXyYgGiIUDw4LBhwFCwoUDRoNHgYMEAzFwSYgGiIUDw4LBw0OBhETJSQ8N1UAAAAA\
Af9+/2ADdAG4ALMAABMzPgEzMhYVFAYjIiY1NDc2NCMiBwYHFz4BMzIWFRQGIyImNTQ3NjQjIg4H\
BzMyFhUUDgErAQ4BIyImNTQ2MzIWFRQHBhUUMzI+BzcjDgEjIiY1NDYzMhYVFAcGFRQzMj4HNyMO\
ASMiJjU0NjMyFhUUBwYVFDMyPgc3IyImNTQ+AzsBPgEzMhYVFAYjIiY1NDc2NCMiDgIHBsycFGk0\
IDAXExIXEgoZJhcDAZsUaTQgMBcTEhcSChkHDAoHCAUGAwYBNgkKBAkGPyF2XyAwFxMSFxIKGQsQ\
DwsNCg8NFAqbIXZfIDAXExIXEgoZCxAPCw0KDg0VCpshdl8gMBcTEhcSChkLEA8LDQoODRQKNQkK\
AQMEBgNBFGk0IDAXExIXEgoZDhUOCAYCAQ5LXyYgGiIUDw4LBhxzDAYBS18mIBoiFA8OCwYcBQsK\
FA0aDR4GDAgFCQbFwSYgGiIUDw4LBw0OBhETJSQ8N1UnxcEmIBoiFA8OCwcNDgYREyUkOzhVJ8XB\
JiAaIhQPDgsHDQ4GERMlJDw3VScMCQMFBQQCS18mIBoiFA8OCwYcEyciGwoAAf9+/2AEgAG4AOcA\
AAEXPgEzMhYVFAYjIiY1NDc2NCMiBwYHFz4BMzIWFRQGIyImNTQ3NjQjIg4HBzMyFhQGKwEOASMi\
JjU0NjMyFhUUBwYVFDMyPgc3Iw4BIyImNTQ2MzIWFRQHBhUUMzI+BzcjDgEjIiY1NDYzMhYVFAcG\
FRQzMj4HNyMOASMiJjU0NjMyFhUUBwYVFDMyPgc3IyImNTQ+AzsBPgEzMhYVFAYjIiY1NDc2NCMi\
BwYHFz4BMzIWFRQGIyImNTQ3NjQjIg4HAdicFGk0IDAXExIXEgoZJhcDAZsUaTQgMBcTEhcSChkH\
DAoHCAUGAwYBNgkKCgk/IXZfIDAXExIXEgoZCxAPCw0KDw0UCpshdl8gMBcTEhcSChkLEA8LDQoO\
DRQKmyF2XyAwFxMSFxIKGQsQDwsNCg8NFAqbIXZfIDAXExIXEgoZCxAPCw0KDg0UCjUJCgEDBAYD\
QRRpNCAwFxMSFxIKGSYXAwGbFGk0IDAXExIXEgoZBwwKBwgFBgMGAQ8BS18mIBoiFA8OCwYccwwG\
AUtfJiAaIhQPDgsGHAULChQNGg0eBgwQDMXBJiAaIhQPDgsHDQ4GERMlJDw3VSfFwSYgGiIUDw4L\
Bw0OBhETJSM8N1YnxcEmIBoiFA8OCwcNDgYREyUkPDdVJ8XBJiAaIhQPDgsHDQ4GERMlJDw3VScM\
CQMFBQQCS18mIBoiFA8OCwYccwwGAUtfJiAaIhQPDgsGHAUKCxMOGQ4dAAMAAP9gAt8BuAA3AHsA\
xQAAMyImNTQ2MzIWFRQHFjMyNjU0LgMnLgI1NDYzMhYVFAYjIi4BNTQ3JiMiBhUUHgIXHgEVFCUG\
LgE/AS4CIyIGIyIOAQcGJyY3PgE3HgEzMjYzMhYXFhQPAQ4BFRQeARcWPgEnLgE1NDYzMhUUBwYj\
IiMuAiMiBgUiJjU0NjMyFhUUBw4BHgEVFBYyPgc3IyIuATU0NjsBPgEzMhYVFAYjIiY1NDc2NCMi\
DgcHMzIWFAYrAQ4BUB4yEgwOFwwGGBYhAwwFFwMUGBQ3LSI2FhAIEAsFEA4PGRESHgUbFwEmBgsB\
Ba4ECQoHBhwGBRASBRAFAwcLDAEYJQ4gKAcECwcLB5oCAhoqDQUJBQIDJBQMJiYSEwMDEiMYCAoS\
/r0gMBcTEhcSBAEBAgYWEA8LDQoODRQKNQYJBAkIQRRpNCAwFxMSFxIKGQcMCgcIBQYDBgE2CQoK\
CT8hdisbEBYNCxgMEhYSCQwNBA4CDRIeDyMtJBgQGAkPCggIFBENCRMMEQMSHxVaAwQIDQa/AgIB\
ARgfBA0LCBMeLgQCAQgBAQERB6MDBQIHAwcLAwQNBggIFAsTNysUCQEIBgerJiAaIhQPDgsCBQQG\
AwgGBhETJSQ8N1UnBgkGCAtLXyYgGiIUDw4LBhwFCwoUDRoNHgYMEAzFwQAAAAIABf/7AfwBmgAJ\
ACwAAAEPAQYVFDMyNjcHDgEjIiY1ND8BIzUzPwEHNzIVNjMyFhUUBiImNTQ3Bg8BIwE2fzkCFBhE\
EgwpMh8iIgM3aXMWWSaYGSA1GB0YIBYJNxBCSAEJB7gIAxUXDygZFCQaCwuzIEoueAotKRwVEhsR\
DhITDyfYAAEAAP/9AbUA1AAvAAAlMjU0JwYiJjU+ATMyFhUUBwYjIi8BJiMiFRQXNjMyFhUUBgci\
JyY1NDc2MxYfARYBcC0aEBwUARcJJC0pFx4mHqIaES4ZEA8NFRQNHRgcKBYiKheiHDE5IBMQFg0O\
FjM1MyQVFXoSOiASEBcODxICGiItMyQTAhB6EwABAAD/zQG1AQMANgAAFyImNTQ3NjMWHwE1MxUX\
FjMyNjU0JwYjIjU+ATMyFhUUBwYjIi8BFSM1JyYjIgYVFBc2MzIVFE0gLSgWICgXLh5cIg8VHBYU\
EhwBDwkgLSkXHCQeLh5cIA8WHBUUExwDQyYzJBMCECRpgEcXKRwnEAwbDxVCJjMkFRUkbINHFige\
Jw8MHSAAAQANAAACRQDgAAsAADcnNxc3FzcXBycHJyIVjmV4ak0Wkml0aS4ZmXx8fFQXoXx8fAAA\
AAEADf/LAkUBEQATAAAlBycHJzcXNzUzFzcXNxcHJwcVIwEWQGlLFY5lFhsBRmpPFJJpGRtGRnxO\
GZl8F5Z7SnxVGKF8G5YAAAEAAAAAARgBGAALAAAzNSM1MzUzFTMVIxV7e3sie3t7Int7InsAAAAB\
AAAAAAE2AXIACgAAMTU+BDczFAYkMUw0NA8ewDwHDys9b0mO2gAAAf//AAABLQCgAB0AADc+AjMy\
HgEXFjMyNzYWBw4CIyIuAScmIyIHBiYBCRApHBgmJg8JCh4YBA4CCBEpHBgkJRIHCB0dBQ1GGSEg\
ITEKBiQGBwcZIh8hMQoEIwYIAAAAAQAAAAABLAEsAAcAADERIREjNSMVASwj5gEs/tS0tAABAAAA\
AAD6AcIABgAAMwMzGwEzA2lpKFVVKGkBwv6YAWj+PgACAAAAAADIAMgABwAPAAA2MjY0JiIGFBYi\
JjQ2MhYURT4sLD4sdFI7O1I7GSw+LCw+RTtSOztSAAH/OAAAAMgAyAALAAAjNDYyFhUjNCYiBhXI\
dqR2HmCUYFJ2dlJKYGBKAAAAAgAAAAAAtAEsAAcAFQAANjI2NCYiBhQXNS4BNTQ2MhYVFAYHFUse\
GxseGxgdKzdGNysdeDU2NTU2rWQINScoPDwoJzUIZAAAAgAAAAAAyAEsAA8AHwAANy4BNTQ2MhYV\
FAYHHQEjNTc+ATU0JiIGFRQWFz0BMxVUJDA7UjswJCAgGSIsPiwiGSBmBTglKTs7KSU4BQFlZRkG\
KRsfLCwfGykGAUlJAAAABAAA//wD9AJ/AIcAkQCdAKcAADc+ATU0LgEnLgE1ND4CPwIOARUUMzI3\
Fw4BIyImNTQ+AjMyFhUUBiMiJic3HgEzMjU0LgInBwYVFB4CFRQGDwEeAjM6ATMyNyY1NDc2MzIW\
FRQHBgceATMyNjU0NjcuAj0BHgEVFAYjIicGIyIuAScOASImJyYjIg4BBwYjIjU0NgUiJjQ2MzIW\
FAYlPgE1NCcmIyIGFRQFNjU0JicOARUUmDZFAQICA1IDBAUBAj1iaiAeHRoVKSUeLR8+cEh9cjIu\
HDYSGBEUFDMMHEAtGwkdIh0fEBAOKR8MAwgCECMhHCJMGyMKHTwTIBsWMUNdIIFeurRRQkEjJDwh\
MxYOLCggGxwaEgoUGQZaIQowA1wLExMLDBIR/g8zJAQFFRwuATxaFxI/MFoYPyAEBwcECHQiBQ4O\
DAQEpQRjLCM8DUIvJhohR0QsUTcwNTArDh4RMgoaIhoCQiQbHjYhLBUmTxQUCikaHjUoNSUuKyAh\
EzkwFxIqGVJfGSxZNAYBPLFrRl85OhUUEiYZFiAtCxUEOgcNOE8SGBISGBKALy8bBw4SOSsedAWB\
IkkVHVhEPwAAAAACAAwACgHTAc8ACgCPAAAlNCYjIgYUFjMyNicOASMiJjQ2MzIWFzY1NCcmIyIm\
NDYzMhceARcWMzI1NCcuATU0NjMyFhUUBgcUMzI3PgE3NjMyFhUUBiMiBgcGFRQzMjYzMhYUBiMi\
JiMiBhUUFx4BFxYVFAYjIicuAScmIyIVFBYVFAYjIiY0NjU0IyIHDgEHBiMiJjU0NzYzMjc2NTQB\
FhgPEBUWDxAXiRkmDhkbGhkNKhglDBQYHRwZFxIQCwMUCxIUAQInHhQSGyMBFhANEQENDBoTHhsS\
GxUNECEbKw4cGx0ZDycUFxILFDgNDhkXExQMARMRChIqIBMSHSYXDQ4SAxESDBQaDQwWIxIN7hAU\
EyIWFQoBJRkqGyUCAxYOChMcKB0MCz4WDRgNCBcnDxcaGxYRIxkqEBM4Dw4bFBEjBgsODxYnHSga\
JggKFgoSAwsNGRMbDgs5FQ8fHjATFBgaJDEXJA4SPQwHFhQYDg0SDQwaAAAAAwAA/wYB9AD6AAcA\
DwAXAAA2FBYyNjQmIgI0NjIWFAYiNiImNDYyFhQteKp4eKqlktCSktCBMiMjMiNVqnh4qnj+y9CS\
ktCSviMyIyMyAAACAAD/BgH0APoABwAPAAA2FBYyNjQmIgI0NjIWFAYiLXiqeHiqpZLQkpLQVap4\
eKp4/svQkpLQkgAAAAADAAD+ogH0AV4AEQAXAB0AABMzFR4BFRQGBxUjNS4BNTQ2NxkBDgEUFhc+\
ATQmJ+QtYIODYC1ghINhTmlpe01paU0BXmQKjmJhjwpkZQiPYmOOCP47AZgIdZ51CAh2nHYIAAAA\
AgAA/wYB0gD6ACEAKQAAJRYVFAcGIyInJiMiBhQWMzI3NjMyFxYVFAcGIyImNDYzMgIiJjQ2MhYU\
Ac8CCwUGDQozd1V4eFV4MgYSBwMMA0CVaJKSaJR7MiMjMiOCBgQPBgMOX3iqeF8NAgcMBgZ4ktCS\
/sojMiMjMgAAAAEAAP8GAdIA+gAhAAAlFhUUBwYjIicmIyIGFBYzMjc2MzIXFhUUBwYjIiY0NjMy\
Ac8CCwUGDQozd1V4eFV4MgYSBwMMA0CVaJKSaJSCBgQPBgMOX3iqeF8NAgcMBgZ4ktCSAAACAAD+\
ogHSAV4AJAAqAAAlFhcWFRQHBiMiJyYnETY3NjMyFxYVFAcGBxUjNS4BNTQ2NzUzAxEOARQWARGE\
OgILBQYNCi1mZS4GEgcDDAM8gi1ghINhLS1OaWn5Cm0GBA8GAw5UCv5oB1cNAgcMBgZwB2VlCI9i\
Y44IZf3WAZgIdZ51AAABAAD/xAB4ADwABwAAFiImNDYyFhRVMiMjMiM8IzIjIzIAAAABAAD+ogAt\
AV4AAwAAExEjES0tAV79RAK8AAAAAgAA/RIBSgC+AAMADwAANxUhNSUzFSE1MxEjESEVIx4BDv7U\
HgEOHh7+8h5GjIx4MjL8VAJiMgABAAAAAAJWAXIACwAANTcXNxc3FwEnBycHiVRWUq8i/vxUVlM1\
Qblzc3HpFv6kdHRwRwAAAf/oAL0BEgE3ABcAACY+ATMyFjI3NjMyFRQOASMiJiIHBiMiNRgwIRwU\
VSgUAwcOMCEcFFUoFAQHDfYwET0UAwcMMBE9FAQIAAAAAAIAAP+JAcIAiwALABMAAAU0JiMiBhUU\
FjMyPgEUBiImNDYyAVFaNiA0XTchL3F9yH19yBQ0TycfNEwjdGxLS2xLAAAAAgAA/2wBSAKoAA0A\
HAAAJSYjIgYVFBcWMzI2NTQTMxEUBiMiJyY1NDYzMhcBJA0lPJcGCyY8lwIdfkhPJA9+SEAkRBdh\
KwoJF2ErCQJu/W5DZ0MeHUNnLQAAAAABAAD/eQFAAqgADQAAATMRFAYjIiY1NDYzMhcBIh55WTI8\
elgxHwKo/YBGaTgnRWocAAAAAQAA/3kCCgKoABoAAAERFAYjIiY1NDYzMhcRNTMeBBUUBzY1NAFA\
eVkyPHpYMR8eBi45OCUyEgG5/m9GaTgnRWocAU7vNVxHTnVJSHJBSe8AAAAAAgAA/3kCCwKoAB8A\
KAAAJTURMx4EFRQHFhUUBzY1NCYjERQGIyImNTQ2MzITHgEXNDY1NCYBIh4JMDg2IxUWIgV2OHlZ\
Mjx6WDE9DoUbAXZr5gFXJEc7QlgzJTIwJC5BGSFfnv7WRmk4J0VqAXY7ojUDDgNfnwAAAQAA/84A\
ZAAyAAcAABYiJjQ2MhYURyodHSodMh0qHR0qAAAAAAAOAK4AAQAAAAAAAACDAQgAAQAAAAAAAQAH\
AZwAAQAAAAAAAgAHAbQAAQAAAAAAAwAgAf4AAQAAAAAABAAHAi8AAQAAAAAABQAJAksAAQAAAAAA\
BgAHAmUAAwABBAkAAAEGAAAAAwABBAkAAQAOAYwAAwABBAkAAgAOAaQAAwABBAkAAwBAAbwAAwAB\
BAkABAAOAh8AAwABBAkABQASAjcAAwABBAkABgAOAlUAQwBvAHAAeQByAGkAZwBoAHQAIABcADIA\
NQAxACAAMgAwADEAOAAtADIAMAAxADkAIABKAGUAYQBuAC0ARgByAGEAbgBjAG8AaQBzACAATQBv\
AGkAbgBlAC4AIABUAGgAaQBzACAAZgBvAG4AdAAgAGkAcwAgAGwAaQBjAGUAbgBzAGUAZAAgAHUA\
bgBkAGUAcgAgAHQAaABlACAAUwBJAEwAIABPAHAAZQBuACAARgBvAG4AdAAgAEwAaQBjAGUAbgBz\
AGUAIABcACgAaAB0AHQAcAA6AC8ALwBzAGMAcgBpAHAAdABzAC4AcwBpAGwALgBvAHIAZwAvAE8A\
RgBMAFwAKQAuAABDb3B5cmlnaHQgXDI1MSAyMDE4LTIwMTkgSmVhbi1GcmFuY29pcyBNb2luZS4g\
VGhpcyBmb250IGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBTSUwgT3BlbiBGb250IExpY2Vuc2UgXCho\
dHRwOi8vc2NyaXB0cy5zaWwub3JnL09GTFwpLgAAYQBiAGMAMgBzAHYAZwAAYWJjMnN2ZwAAUgBl\
AGcAdQBsAGEAcgAAUmVndWxhcgAARgBvAG4AdABGAG8AcgBnAGUAIAA6ACAAYQBiAGMAMgBzAHYA\
ZwAgADoAIAAyADgALQAxADAALQAyADAAMQA5AABGb250Rm9yZ2UgOiBhYmMyc3ZnIDogMjgtMTAt\
MjAxOQAAYQBiAGMAMgBzAHYAZwAAYWJjMnN2ZwAAVgBlAHIAcwBpAG8AbgAgACAAAFZlcnNpb24g\
IAAAYQBiAGMAMgBzAHYAZwAAYWJjMnN2ZwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAkgAAAAEAAgECAAMBAwEEAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwEQAREBEgETARQBFQEWARcB\
GAEZARoBGwEcAR0BHgEfASABIQEiASMBJAElASYBJwEoASkBKgErASwBLQEuAS8BMAExATIBMwE0\
ATUBNgE3ATgBOQE6ATsBPAE9AT4BPwFAAUEBQgFDAUQBRQFGAUcBSAFJAUoBSwFMAU0BTgFPAVAB\
UQFSAVMBVAFVAVYBVwFYAVkBWgFbAVwBXQFeAV8BYAFhAWIBYwFkAWUBZgFnAWgBaQFqAWsBbAFt\
AW4BbwFwAXEBcgFzAXQBdQF2AXcBeAF5AXoBewF8AX0BfgF/AYABgQGCAYMBhAGFAYYBhwGIAYkB\
igGLAYwBjQGOAY8GLm5vZGVmB3VuaUUwMDAHdW5pRTAyMgd1bmlFMDIzB3VuaUUwMjQHdW5pRTAz\
MAd1bmlFMDM4B3VuaUUwMzkHdW5pRTA0Mwd1bmlFMDQ1B3VuaUUwNDYHdW5pRTA0Nwd1bmlFMDQ4\
B3VuaUUwNTAHdW5pRTA1Qwd1bmlFMDYyB3VuaUUwNjkHdW5pRTA3QQd1bmlFMDdCB3VuaUUwN0MH\
dW5pRTA3RAd1bmlFMDgwB3VuaUUwODEHdW5pRTA4Mgd1bmlFMDgzB3VuaUUwODQHdW5pRTA4NQd1\
bmlFMDg2B3VuaUUwODcHdW5pRTA4OAd1bmlFMDg5B3VuaUUwOEEHdW5pRTA4Qgd1bmlFMDhDB3Vu\
aUUwOTQHdW5pRTA5NQd1bmlFMEEwB3VuaUUwQTEHdW5pRTBBMgd1bmlFMEEzB3VuaUUwQTQHdW5p\
RTBBOQd1bmlFMEIzB3VuaUUxMDEHdW5pRTFCOQd1bmlFMUJCB3VuaUUxRTcHdW5pRTFGMgd1bmlF\
MUY0B3VuaUUxRjcHdW5pRTFGOQd1bmlFMUZDB3VuaUUxRkUHdW5pRTFGRgd1bmlFMjAwB3VuaUUy\
NDAHdW5pRTI0MQd1bmlFMjQyB3VuaUUyNDMHdW5pRTI0NAd1bmlFMjQ1B3VuaUUyNDYHdW5pRTI0\
Nwd1bmlFMjQ4B3VuaUUyNDkHdW5pRTI2MAd1bmlFMjYxB3VuaUUyNjIHdW5pRTI2Mwd1bmlFMjY0\
B3VuaUUyODAHdW5pRTI4MQd1bmlFMjgyB3VuaUUyODMHdW5pRTRBMAd1bmlFNEEyB3VuaUU0QTQH\
dW5pRTRBOAd1bmlFNEFDB3VuaUU0QzAHdW5pRTRDRQd1bmlFNEUxB3VuaUU0RTIHdW5pRTRFMwd1\
bmlFNEU0B3VuaUU0RTUHdW5pRTRFNgd1bmlFNEU3B3VuaUU0RTgHdW5pRTRFOQd1bmlFNEVBB3Vu\
aUU0RUUHdW5pRTUwMAd1bmlFNTAxB3VuaUU1MjAHdW5pRTUyMQd1bmlFNTIyB3VuaUU1MjMHdW5p\
RTUyNAd1bmlFNTI1B3VuaUU1MjkHdW5pRTUyQQd1bmlFNTJCB3VuaUU1MkMHdW5pRTUyRAd1bmlF\
NTJGB3VuaUU1MzAHdW5pRTUzMQd1bmlFNTM5B3VuaUU1NjYHdW5pRTU2Nwd1bmlFNTY5B3VuaUU1\
NkMHdW5pRTU2RAd1bmlFNTgyB3VuaUU1RDAHdW5pRTVFMgd1bmlFNjEwB3VuaUU2MTIHdW5pRTYx\
NAd1bmlFNjE4B3VuaUU2MjQHdW5pRTYzMAd1bmlFNjUwB3VuaUU2NTUHdW5pRTkxMAd1bmlFOTEx\
B3VuaUU5MTIHdW5pRTkxNAd1bmlFOTE1B3VuaUU5MTgHdW5pRTkyMAd1bmlFOTI1B3VuaUU5NUQH\
dW5pRUEwMgd1bmlFQUE0B3VuaUVDQTIHdW5pRUNBMwd1bmlFQ0E1B3VuaUVDQTcHdW5pRUNBOQd1\
bmlFQ0I3AAAAAAAAAf//AAIAAQAAAAAAAAAMABQABAAAAAIAAAABAAAAAQAAAAAAAQAAAADZahND\
AAAAANGXIhcAAAAA2dy6gQ==\
") format("truetype")'
|
Changes to font/abc2svg.sfd.
|
| | | | | 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 | SplineFontDB: 3.2 FontName: abc2svg FullName: abc2svg FamilyName: abc2svg Weight: Regular Copyright: Copyright \\251 2018-2019 Jean-Francois Moine. This font is licensed under the SIL Open Font License \\(http://scripts.sil.org/OFL\\). Version: ItalicAngle: 0 UnderlinePosition: 0 UnderlineWidth: 0 Ascent: 819 Descent: 205 InvalidEm: 0 LayerCount: 2 Layer: 0 1 "Back" 1 Layer: 1 0 "Fore" 0 XUID: [1021 296 1430826605 13506888] OS2Version: 0 OS2_WeightWidthSlopeOnly: 0 OS2_UseTypoMetrics: 0 CreationTime: 1433498007 ModificationTime: 1572276737 PfmFamily: 17 TTFWeight: 400 TTFWidth: 5 LineGap: 92 VLineGap: 92 Panose: 2 0 5 3 0 0 0 0 0 0 OS2TypoAscent: 0 |
| ︙ | ︙ | |||
46 47 48 49 50 51 52 | Encoding: Custom Compacted: 1 UnicodeInterp: none NameList: Adobe Glyph List DisplaySize: -96 AntiAlias: 1 FitToEm: 1 | | | | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | Encoding: Custom Compacted: 1 UnicodeInterp: none NameList: Adobe Glyph List DisplaySize: -96 AntiAlias: 1 FitToEm: 1 WinInfo: 128 8 2 BeginPrivate: 0 EndPrivate TeXData: 1 0 0 346030 173015 115343 0 1048576 115343 783286 444596 497025 792723 393216 433062 380633 303038 157286 324010 404750 52429 2506097 1059062 262144 BeginChars: 143 143 StartChar: .nodef Encoding: 0 0 0 Width: 400 Flags: M LayerCount: 2 Fore |
| ︙ | ︙ | |||
208 209 210 211 212 213 214 | EndSplineSet Validated: 1 EndChar StartChar: uniE043 Encoding: 9 57411 9 Width: 100 | | < < | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | EndSplineSet Validated: 1 EndChar StartChar: uniE043 Encoding: 9 57411 9 Width: 100 Flags: MW LayerCount: 2 Fore SplineSet 50 570 m 3 22 570 0 592 0 620 c 3 0 648 22 670 50 670 c 3 78 670 100 648 100 620 c 3 |
| ︙ | ︙ | |||
390 391 392 393 394 395 396 | EndSplineSet Validated: 1 EndChar StartChar: uniE048 Encoding: 13 57416 13 Width: 862 | | < < < | 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 | EndSplineSet Validated: 1 EndChar StartChar: uniE048 Encoding: 13 57416 13 Width: 862 Flags: MW LayerCount: 2 Fore SplineSet 472 596 m 1 512 596 l 1 512 459 l 1 625 448 715 344 724 216 c 1 |
| ︙ | ︙ | |||
442 443 444 445 446 447 448 | Encoding: 14 57424 14 Width: 779 Flags: HMW LayerCount: 2 Fore SplineSet 364 851 m 0 | | | | | | | | | | | | | | | | | | < < | 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 | Encoding: 14 57424 14 Width: 779 Flags: HMW LayerCount: 2 Fore SplineSet 364 851 m 0 359 812 357 782 357 751 c 0 357 716 359 680 362 626 c 1 443 681 551 791 551 896 c 0 551 942 546 1011 497 1023 c 1 417 1013 376 939 364 851 c 0 449 -250 m 9 472 -486 l 0 472 -487 472 -488 472 -489 c 0 472 -586 423 -657 316 -657 c 0 204 -657 139 -593 139 -509 c 0 139 -452 184 -392 253 -392 c 0 315 -392 365 -436 365 -495 c 0 365 -554 317 -594 255 -595 c 1 275 -606 298 -620 324 -620 c 0 377 -620 435 -592 435 -490 c 0 435 -489 435 -488 435 -487 c 0 412 -254 l 17 398 -255 385 -256 371 -256 c 0 176 -256 0 -116 0 100 c 0 0 188 25 277 58 335 c 8 131 463 275 562 326 600 c 1 317 704 313 787 313 852 c 0 313 1052 406 1152 494 1160 c 1 570 1115 592 1005 592 873 c 0 592 688 538 598 379 473 c 1 399 266 l 0 409 267 420 268 430 268 c 0 585 268 679 145 679 -3 c 0 679 -124 618 -220 449 -250 c 9 601 -23 m 0 601 52 536 141 423 141 c 0 419 141 416 140 412 140 c 1 445 -215 l 1 575 -189 601 -121 601 -23 c 0 375 138 m 1 306 124 251 75 251 8 c 0 251 -35 281 -84 319 -108 c 1 246 -91 195 -56 195 46 c 0 195 176 270 236 361 261 c 1 344 450 l 1 164 306 93 226 92 82 c 1 95 -111 219 -222 376 -222 c 0 387 -222 397 -221 408 -220 c 0 375 138 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE05C Encoding: 15 57436 15 Width: 722 Flags: MW LayerCount: 2 Fore SplineSet 478 -480 m 0 567 -480 614 -375 614 -286 c 0 614 -257 610 -227 601 -196 c 0 584 -125 550 -88 502 -88 c 0 |
| ︙ | ︙ | |||
561 562 563 564 565 566 567 | EndSplineSet Validated: 1 EndChar StartChar: uniE062 Encoding: 16 57442 16 Width: 703 | | < < | | | | | | | | | | | | | | | | | | 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | EndSplineSet Validated: 1 EndChar StartChar: uniE062 Encoding: 16 57442 16 Width: 703 Flags: HMW LayerCount: 2 Fore SplineSet 19 29 m 0 19 161 125 255 261 255 c 0 378 255 440 220 496 146 c 0 528 104 543 31 543 -30 c 0 543 -193 505 -313 388 -422 c 24 246 -555 118 -593 -70 -603 c 1 72 -565 189 -512 292 -409 c 0 358 -343 387 -287 412 -181 c 0 421 -142 422 -69 422 -36 c 0 422 48 418 100 376 150 c 0 339 194 314 207 245 207 c 0 168 207 97 154 67 58 c 1 97 96 116 111 153 111 c 0 214 111 260 62 260 -1 c 0 260 -33 248 -61 221 -83 c 1 198 -104 166 -113 139 -113 c 0 71 -113 19 -52 19 29 c 0 661 -170 m 0 632 -170 610 -150 610 -119 c 0 610 -90 629 -69 656 -69 c 0 683 -69 707 -90 707 -119 c 0 707 -148 687 -170 661 -170 c 0 655 72 m 0 625 72 605 94 605 127 c 0 605 156 626 174 654 174 c 0 681 174 702 153 702 127 c 0 702 94 682 72 655 72 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE069 Encoding: 17 57449 17 Width: 470 |
| ︙ | ︙ | |||
623 624 625 626 627 628 629 | EndSplineSet Validated: 1 EndChar StartChar: uniE07A Encoding: 18 57466 18 Width: 779 | | < < | | | | | | | < < | 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 | EndSplineSet Validated: 1 EndChar StartChar: uniE07A Encoding: 18 57466 18 Width: 779 Flags: MW LayerCount: 2 Fore SplineSet 329 117 m 1 329 117 348 -79 354 -170 c 1 464 -145 502 -83 502 -22 c 0 502 46 442 118 350 118 c 0 343 118 336 118 329 117 c 1 323 -170 m 2 323 -170 299 97 298 113 c 1 243 102 197 67 197 13 c 0 197 -13 207 -40 228 -66 c 1 188 -44 154 0 154 58 c 0 154 137 216 188 289 208 c 1 284 266 280 308 275 360 c 1 131 245 77 181 76 66 c 1 82 -68 133 -173 320 -173 c 0 323 -173 323 -172 323 -170 c 2 357 -199 m 1 363 -271 369 -330 370 -341 c 0 371 -351 370 -359 370 -368 c 0 370 -370 370 -373 370 -375 c 0 370 -462 329 -502 248 -502 c 0 178 -502 111 -448 111 -381 c 0 111 -335 147 -294 202 -294 c 0 252 -294 292 -338 292 -385 c 0 292 -432 254 -459 204 -460 c 1 220 -469 238 -472 259 -472 c 0 303 -472 338 -442 338 -368 c 0 338 -361 338 -353 337 -344 c 2 324 -203 l 1 315 -204 303 -204 294 -204 c 0 108 -204 0 -105 0 80 c 0 0 150 20 221 46 267 c 1 67 308 132 372 166 399 c 0 185 415 222 451 263 481 c 1 257 564 249 630 249 682 c 0 249 842 328 916 402 938 c 1 470 864 474 804 474 698 c 0 474 550 431 478 304 378 c 1 309 324 311 278 318 215 c 1 327 216 335 217 344 217 c 0 398 217 453 197 493 150 c 1 534 106 543 55 543 -2 c 0 543 -76 514 -135 444 -169 c 1 414 -184 391 -196 357 -199 c 1 290 658 m 0 288 638 287 615 287 594 c 0 287 552 291 513 293 501 c 1 358 545 442 639 442 712 c 0 442 749 433 790 401 820 c 1 331 792 299 728 290 658 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE07B Encoding: 19 57467 19 Width: 782 Flags: MW LayerCount: 2 Fore SplineSet 382 -384 m 0 453 -384 491 -300 491 -229 c 0 491 -206 488 -182 481 -157 c 0 467 -100 440 -70 402 -70 c 0 |
| ︙ | ︙ | |||
753 754 755 756 757 758 759 | EndSplineSet Validated: 1 EndChar StartChar: uniE07C Encoding: 20 57468 20 Width: 807 | | < < | | | | | | | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 | EndSplineSet Validated: 1 EndChar StartChar: uniE07C Encoding: 20 57468 20 Width: 807 Flags: MW LayerCount: 2 Fore SplineSet 15 33 m 0 15 139 104 204 209 204 c 0 299 204 358 176 399 117 c 0 423 82 434 25 434 -24 c 0 434 -154 394 -258 314 -330 c 1 233 -401 94 -474 -56 -482 c 1 58 -452 160 -406 230 -331 c 1 278 -281 313 -202 331 -117 c 0 337 -86 340 -55 340 -29 c 0 340 38 325 90 295 124 c 1 262 160 236 170 194 170 c 0 133 170 68 125 54 50 c 1 78 80 86 86 116 86 c 0 165 86 210 38 210 -12 c 0 210 -38 200 -60 178 -78 c 1 160 -95 138 -102 116 -102 c 0 54 -102 15 -32 15 33 c 0 529 -136 m 0 506 -136 488 -120 488 -95 c 0 488 -72 502 -55 525 -55 c 0 547 -55 566 -72 566 -95 c 0 566 -118 550 -136 529 -136 c 0 524 58 m 0 500 58 484 76 484 102 c 0 484 125 499 139 523 139 c 0 545 139 562 123 562 102 c 0 562 76 546 58 524 58 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE07D Encoding: 21 57469 21 Width: 200 |
| ︙ | ︙ | |||
1118 1119 1120 1121 1122 1123 1124 | EndSplineSet Validated: 1 EndChar StartChar: uniE08A Encoding: 32 57482 32 Width: 409 | | < < | | | 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 | EndSplineSet Validated: 1 EndChar StartChar: uniE08A Encoding: 32 57482 32 Width: 409 Flags: HMW LayerCount: 2 Fore SplineSet 303 164 m 1 311 163 315 162 321 161 c 1 324 165 325 170 325 174 c 0 325 202 273 224 234 224 c 5 173 222 119 170 119 18 c 0 119 -58 126 -133 158 -175 c 0 181 -204 207 -217 239 -217 c 0 265 -217 294 -207 322 -183 c 0 350 -159 369 -119 392 -71 c 1 392 -74 410 -77 409 -80 c 0 376 -183 333 -244 211 -246 c 0 161 -246 111 -226 73 -189 c 0 |
| ︙ | ︙ | |||
1152 1153 1154 1155 1156 1157 1158 | EndSplineSet Validated: 1 EndChar StartChar: uniE08B Encoding: 33 57483 33 Width: 408 | | < < | 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 | EndSplineSet Validated: 1 EndChar StartChar: uniE08B Encoding: 33 57483 33 Width: 408 Flags: MW LayerCount: 2 Fore SplineSet 303 164 m 1 311 163 315 162 321 161 c 1 324 165 325 170 325 174 c 0 325 202 273 228 234 228 c 0 |
| ︙ | ︙ | |||
1330 1331 1332 1333 1334 1335 1336 | Fore SplineSet 337 -30 m 4 337 40 264 101 193 101 c 4 154 101 109 75 109 31 c 4 109 -40 186 -97 257 -97 c 4 298 -97 337 -75 337 -30 c 4 | | | | | | | < < | | | | | | | | | | | | | | | | | | | | 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 | Fore SplineSet 337 -30 m 4 337 40 264 101 193 101 c 4 154 101 109 75 109 31 c 4 109 -40 186 -97 257 -97 c 4 298 -97 337 -75 337 -30 c 4 450 0 m 4 450 -70 361 -129 225 -129 c 4 89 -129 0 -70 0 0 c 4 0 70 89 129 225 129 c 4 361 129 450 70 450 0 c 4 EndSplineSet Validated: 1 EndChar StartChar: uniE0A3 Encoding: 40 57507 40 Width: 329 Flags: MW LayerCount: 2 Fore SplineSet 292 68 m 4 283 84 264 91 242 91 c 4 164 91 31 10 31 -49 c 4 31 -56 33 -62 37 -68 c 4 45 -84 64 -91 86 -91 c 4 164 -91 297 -10 297 49 c 4 297 56 295 62 292 68 c 4 313 81 m 4 323 61 328 41 328 22 c 4 328 -70 223 -148 130 -148 c 4 83 -148 40 -128 15 -81 c 4 5 -61 0 -41 0 -22 c 4 0 70 105 148 198 148 c 4 245 148 288 128 313 81 c 4 EndSplineSet Validated: 1 EndChar StartChar: uniE0A4 Encoding: 41 57508 41 Width: 320 Flags: HMW LayerCount: 2 Fore SplineSet 320 40 m 4 320 -51 231 -135 110 -135 c 4 40 -135 0 -90 0 -40 c 4 0 50 90 135 210 135 c 4 280 135 320 90 320 40 c 4 EndSplineSet Validated: 1 EndChar StartChar: uniE0A9 Encoding: 42 57513 42 Width: 330 |
| ︙ | ︙ | |||
1508 1509 1510 1511 1512 1513 1514 1515 | 22 -50 0 -28 0 0 c 3 0 28 22 50 50 50 c 3 78 50 100 28 100 0 c 3 100 -28 78 -50 50 -50 c 3 EndSplineSet Validated: 1 EndChar | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 | 22 -50 0 -28 0 0 c 3 0 28 22 50 50 50 c 3 78 50 100 28 100 0 c 3 100 -28 78 -50 50 -50 c 3 EndSplineSet Validated: 1 EndChar StartChar: uniE1F2 Encoding: 48 57842 48 Width: 320 Flags: HMW LayerCount: 2 Fore SplineSet 0 680 m 1 320 680 l 1 320 40 l 2 320 -51 231 -135 110 -135 c 0 40 -135 0 -90 0 -40 c 0 0 50 90 135 210 135 c 0 244 135 271 124 290 107 c 1 290 560 l 1 0 560 l 1 0 680 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE1F4 Encoding: 49 57844 49 Width: 320 Flags: HMW LayerCount: 2 Fore SplineSet 0 680 m 1 320 680 l 1 320 40 l 2 320 -51 231 -135 110 -135 c 0 40 -135 0 -90 0 -40 c 0 0 50 90 135 210 135 c 0 244 135 271 124 290 107 c 1 290 380 l 1 0 380 l 1 0 500 l 1 290 500 l 1 290 560 l 1 0 560 l 1 0 680 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE1F7 Encoding: 50 57847 50 Width: 320 Flags: HMW LayerCount: 2 Fore SplineSet 0 680 m 25 320 680 l 29 320 560 l 25 0 560 l 25 0 680 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE1F9 Encoding: 51 57849 51 Width: 320 Flags: HMW LayerCount: 2 Fore SplineSet 0 500 m 25 320 500 l 25 320 380 l 25 0 380 l 29 0 500 l 25 0 680 m 25 320 680 l 25 320 560 l 25 0 560 l 25 0 680 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE1FC Encoding: 52 57852 52 Width: 100 Flags: HMW LayerCount: 2 Fore SplineSet 50 -38 m 7 22 -38 0 -16 0 12 c 7 0 40 22 62 50 62 c 7 78 62 100 40 100 12 c 7 100 -16 78 -38 50 -38 c 7 EndSplineSet Validated: 1 EndChar StartChar: uniE1FE Encoding: 53 57854 53 Width: 310 Flags: HMW LayerCount: 2 Fore SplineSet 0 960 m 29 310 960 l 29 310 930 l 29 30 930 l 29 30 770 l 29 0 770 l 29 0 960 l 29 EndSplineSet Validated: 1 EndChar StartChar: uniE1FF Encoding: 54 57855 54 Width: 230 Flags: HMW LayerCount: 2 Fore SplineSet 80 810 m 0 27 810 0 833 0 864 c 0 0 882 11 900 30 900 c 0 51 900 63 888 63 872 c 0 63 842 40 846 40 840 c 0 40 831 59 827 73 827 c 0 100 827 130 857 130 900 c 0 130 918 120 940 98 940 c 0 88 940 90 940 80 940 c 0 70 940 60 943 60 954 c 24 60 965 69 970 80 970 c 0 95 970 105 970 120 970 c 0 151 970 180 1001 180 1028 c 0 180 1043 172 1060 152 1060 c 0 141 1060 131 1056 131 1047 c 0 131 1040 133 1043 133 1028 c 0 133 1014 124 1000 100 1000 c 0 84 1000 70 1013 70 1029 c 0 70 1052 86 1080 150 1080 c 0 197 1080 230 1055 230 1020 c 0 230 966 160 949 160 940 c 0 160 933 180 916 180 890 c 0 180 847 149 810 80 810 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE200 Encoding: 55 57856 55 Width: 310 Flags: HMW LayerCount: 2 Fore SplineSet 310 960 m 25 310 770 l 25 280 770 l 25 280 930 l 25 0 930 l 25 0 960 l 25 310 960 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE240 Encoding: 56 57920 56 Width: 315 Flags: HMW LayerCount: 2 Fore SplineSet 0 -239 m 13 0 0 l 5 30 0 l 5 51 -195 315 -321 315 -584 c 4 315 -643 302 -710 269 -785 c 5 282 -738 287 -691 287 -647 c 4 287 -452 175 -294 30 -239 c 5 0 -239 l 13 EndSplineSet Validated: 1 EndChar StartChar: uniE241 Encoding: 57 57921 57 Width: 315 Flags: HMW LayerCount: 2 Fore SplineSet 0 0 m 1 0 239 l 1 30 239 l 1 178 280 288 445 288 642 c 0 288 688 282 736 269 785 c 1 302 711 315 647 315 588 c 0 315 328 51 195 30 0 c 0 0 0 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE242 Encoding: 58 57922 58 Width: 315 Flags: HMW LayerCount: 2 Fore SplineSet 0 -343 m 13 0 0 l 5 30 0 l 5 62 -133 315 -236 315 -418 c 4 315 -445 310 -474 297 -505 c 5 309 -531 316 -559 316 -589 c 4 316 -623 307 -660 286 -700 c 5 290 -680 291 -660 291 -642 c 4 291 -448 100 -342 30 -342 c 5 0 -343 l 13 30 -171 m 5 56 -278 226 -366 291 -492 c 5 291 -485 292 -479 292 -472 c 4 292 -278 101 -171 30 -171 c 5 EndSplineSet Validated: 1 EndChar StartChar: uniE243 Encoding: 59 57923 59 Width: 315 Flags: HMW LayerCount: 2 Fore SplineSet 0 -1 m 9 0 342 l 1 30 342 l 1 100 342 291 448 291 642 c 0 291 660 290 680 286 700 c 1 307 660 316 623 316 589 c 0 316 559 309 531 297 505 c 1 310 474 315 445 315 418 c 0 315 236 62 133 30 0 c 1 0 -1 l 9 30 171 m 1 101 171 292 278 292 472 c 0 292 479 291 484 291 491 c 1 226 365 56 278 30 171 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE244 Encoding: 60 57924 60 Width: 315 Flags: HMW LayerCount: 2 Fore SplineSet 0 -368 m 9 0 145 l 1 30 145 l 1 62 12 315 -91 315 -273 c 0 315 -300 310 -329 297 -360 c 1 309 -386 315 -414 315 -444 c 0 315 -471 310 -500 297 -531 c 1 309 -557 316 -585 316 -615 c 0 316 -649 307 -686 286 -726 c 1 290 -706 291 -687 291 -668 c 0 291 -475 100 -368 30 -368 c 1 0 -368 l 9 30 -199 m 1 56 -307 226 -392 291 -518 c 1 291 -511 292 -504 292 -498 c 0 292 -306 105 -199 32 -199 c 0 31 -199 31 -199 30 -199 c 1 30 -28 m 1 56 -135 226 -221 291 -347 c 1 291 -340 292 -333 292 -327 c 0 292 -135 105 -28 32 -28 c 0 31 -28 31 -28 30 -28 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE245 Encoding: 61 57925 61 Width: 315 Flags: HMW LayerCount: 2 Fore SplineSet 0 343 m 17 30 343 l 1 100 343 291 449 291 643 c 0 291 661 290 681 286 701 c 1 307 661 316 624 316 590 c 0 316 560 309 532 297 506 c 1 310 475 315 446 315 419 c 0 315 389 309 361 297 335 c 1 310 304 315 275 315 248 c 0 315 66 62 -37 30 -170 c 1 0 -170 l 1 0 343 l 17 30 0 m 1 101 0 292 108 292 302 c 0 292 309 291 315 291 322 c 1 226 196 56 109 30 0 c 1 30 171 m 1 101 171 292 279 292 473 c 0 292 480 291 486 291 493 c 1 226 367 56 280 30 171 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE246 Encoding: 62 57926 62 Width: 315 Flags: HMW LayerCount: 2 Fore SplineSet 0 -344 m 9 0 340 l 1 30 340 l 1 62 207 315 104 315 -78 c 0 315 -105 310 -134 297 -165 c 1 309 -191 315 -219 315 -249 c 0 315 -276 310 -305 297 -336 c 1 309 -362 315 -390 315 -420 c 0 315 -447 310 -476 297 -507 c 1 309 -533 316 -561 316 -591 c 0 316 -625 307 -662 286 -702 c 1 290 -682 291 -662 291 -644 c 0 291 -450 100 -344 30 -344 c 1 0 -344 l 9 30 -173 m 1 56 -281 226 -368 291 -494 c 1 291 -487 292 -481 292 -474 c 0 292 -280 101 -173 30 -173 c 1 30 -2 m 1 56 -110 226 -197 291 -323 c 1 291 -316 292 -310 292 -303 c 0 292 -109 101 -2 30 -2 c 1 30 169 m 1 56 62 226 -26 291 -152 c 1 291 -145 292 -139 292 -132 c 0 292 62 101 169 30 169 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE247 Encoding: 63 57927 63 Width: 315 Flags: HMW LayerCount: 2 Fore SplineSet 0 -370 m 9 0 314 l 1 30 314 l 1 100 314 291 421 291 614 c 0 291 633 290 652 286 672 c 1 307 632 316 595 316 561 c 0 316 531 309 503 297 477 c 1 310 446 315 417 315 390 c 0 315 360 309 332 297 306 c 1 310 275 315 246 315 219 c 0 315 189 309 161 297 135 c 1 310 104 315 75 315 48 c 0 315 -134 62 -237 30 -370 c 1 0 -370 l 9 30 -200 m 1 101 -200 292 -92 292 102 c 0 292 108 291 115 291 122 c 1 226 -4 56 -91 30 -200 c 1 30 -29 m 1 101 -29 292 79 292 273 c 0 292 279 291 286 291 293 c 1 226 167 56 81 30 -29 c 1 30 142 m 1 101 142 292 250 292 444 c 0 292 450 291 457 291 464 c 1 226 338 56 251 30 142 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE248 Encoding: 64 57928 64 Width: 315 Flags: HMW LayerCount: 2 Fore SplineSet 0 -325 m 9 0 530 l 1 30 530 l 1 62 397 315 294 315 112 c 0 315 85 310 56 297 25 c 1 309 -1 315 -29 315 -59 c 0 315 -86 310 -115 297 -146 c 1 309 -172 315 -200 315 -230 c 0 315 -257 310 -286 297 -317 c 1 309 -343 315 -371 315 -401 c 0 315 -428 310 -457 297 -488 c 1 309 -514 316 -542 316 -572 c 0 316 -606 307 -643 286 -683 c 1 290 -663 291 -643 291 -625 c 0 291 -431 100 -325 30 -325 c 1 0 -325 l 9 30 -154 m 1 56 -262 226 -349 291 -475 c 1 291 -468 292 -462 292 -455 c 0 292 -261 101 -154 30 -154 c 1 30 17 m 1 56 -91 226 -178 291 -304 c 1 291 -297 292 -291 292 -284 c 0 292 -90 101 17 30 17 c 1 30 188 m 1 56 80 226 -7 291 -133 c 1 291 -126 292 -120 292 -113 c 0 292 81 101 188 30 188 c 1 30 359 m 1 56 252 226 164 291 38 c 1 291 45 292 51 292 58 c 0 292 252 101 359 30 359 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE249 Encoding: 65 57929 65 Width: 315 Flags: HMW LayerCount: 2 Fore SplineSet 0 -580 m 9 0 275 l 1 30 275 l 1 100 275 291 382 291 575 c 0 291 594 290 613 286 633 c 1 307 593 316 556 316 522 c 0 316 492 309 464 297 438 c 1 310 407 315 378 315 351 c 0 315 321 309 293 297 267 c 1 310 236 315 207 315 180 c 0 315 150 309 122 297 96 c 1 310 65 315 36 315 9 c 0 315 -21 309 -49 297 -75 c 1 310 -106 315 -135 315 -162 c 0 315 -344 62 -447 30 -580 c 1 0 -580 l 9 30 -410 m 1 101 -410 292 -302 292 -108 c 0 292 -102 291 -95 291 -88 c 1 226 -214 56 -301 30 -410 c 1 30 -239 m 1 101 -239 292 -131 292 63 c 0 292 69 291 76 291 83 c 1 226 -43 56 -129 30 -239 c 1 30 -68 m 1 101 -68 292 40 292 234 c 0 292 240 291 247 291 254 c 1 226 128 56 41 30 -68 c 1 30 103 m 1 101 103 292 211 292 405 c 0 292 411 291 418 291 425 c 1 226 299 56 213 30 103 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE260 Encoding: 66 57952 66 Width: 269 Flags: HMW LayerCount: 2 Fore SplineSet 103 122 m 0 77 122 40 90 40 65 c 2 |
| ︙ | ︙ | |||
1847 1848 1849 1850 1851 1852 1853 | 40 108 l 1 63 142 93 160 133 160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE261 | | | < | 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 | 40 108 l 1 63 142 93 160 133 160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE261 Encoding: 67 57953 67 Width: 200 Flags: MW LayerCount: 2 Fore SplineSet 28 -101 m 1 172 -56 l 1 172 94 l 1 28 49 l 1 |
| ︙ | ︙ | |||
1874 1875 1876 1877 1878 1879 1880 | 1 377 l 1 28 378 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE262 | | | 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 | 1 377 l 1 28 378 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE262 Encoding: 68 57954 68 Width: 255 Flags: HMW LayerCount: 2 Fore SplineSet 83 70 m 21 83 -97 l 5 |
| ︙ | ︙ | |||
1919 1920 1921 1922 1923 1924 1925 | 83 -189 l 5 83 -360 l 5 EndSplineSet Validated: 1 EndChar StartChar: uniE263 | | | < < | 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 | 83 -189 l 5 83 -360 l 5 EndSplineSet Validated: 1 EndChar StartChar: uniE263 Encoding: 69 57955 69 Width: 267 Flags: MW LayerCount: 2 Fore SplineSet 195 -124 m 9 195 -65 l 25 195 -65 155 -27 143 -14 c 9 92 -65 l 25 |
| ︙ | ︙ | |||
1957 1958 1959 1960 1961 1962 1963 | 267 -124 l 1 195 -124 l 9 EndSplineSet Validated: 1 EndChar StartChar: uniE264 | | | 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 | 267 -124 l 1 195 -124 l 9 EndSplineSet Validated: 1 EndChar StartChar: uniE264 Encoding: 70 57956 70 Width: 366 Flags: HMW LayerCount: 2 Fore SplineSet 78 125 m 1 55 124 31 100 31 78 c 2 |
| ︙ | ︙ | |||
2004 2005 2006 2007 2008 2009 2010 | 219 113 l 1 235 143 256 163 291 163 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE280 | | | 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 | 219 113 l 1 235 143 256 163 291 163 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE280 Encoding: 71 57984 71 Width: 269 Flags: HMW LayerCount: 2 Fore SplineSet 171 122 m 0 140 122 116 92 116 57 c 0 |
| ︙ | ︙ | |||
2029 2030 2031 2032 2033 2034 2035 | 76 -20 50 28 50 75 c 0 50 124 97 160 141 160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE281 | | | 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 | 76 -20 50 28 50 75 c 0 50 124 97 160 141 160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE281 Encoding: 72 57985 72 Width: 366 Flags: HMW LayerCount: 2 Fore SplineSet 87 125 m 1 86 125 l 2 |
| ︙ | ︙ | |||
2076 2077 2078 2079 2080 2081 2082 | 219 113 l 1 235 143 256 163 291 163 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE282 | | | 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 | 219 113 l 1 235 143 256 163 291 163 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE282 Encoding: 73 57986 73 Width: 169 Flags: HMW LayerCount: 2 Fore SplineSet 68 320 m 8 98 320 l 1 |
| ︙ | ︙ | |||
2108 2109 2110 2111 2112 2113 2114 | 68 152 l 1 68 320 l 8 EndSplineSet Validated: 1 EndChar StartChar: uniE283 | | | 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 | 68 152 l 1 68 320 l 8 EndSplineSet Validated: 1 EndChar StartChar: uniE283 Encoding: 74 57987 74 Width: 314 Flags: HMW LayerCount: 2 Fore SplineSet 233 192 m 17 233 360 l 1 |
| ︙ | ︙ | |||
2166 2167 2168 2169 2170 2171 2172 | 233 101 l 1 172 83 l 9 EndSplineSet Validated: 1 EndChar StartChar: uniE4A0 | | | 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 | 233 101 l 1 172 83 l 9 EndSplineSet Validated: 1 EndChar StartChar: uniE4A0 Encoding: 75 58528 75 Width: 320 Flags: W HStem: 0 244<5 15> VStem: -3 322 LayerCount: 2 Fore SplineSet |
| ︙ | ︙ | |||
2193 2194 2195 2196 2197 2198 2199 | 319 109 314 101 305 98 c 1 18 1 l 0 EndSplineSet Validated: 1 EndChar StartChar: uniE4A2 | | | | | | | | | | 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 | 319 109 314 101 305 98 c 1 18 1 l 0 EndSplineSet Validated: 1 EndChar StartChar: uniE4A2 Encoding: 76 58530 76 Width: 80 Flags: HMW LayerCount: 2 Fore SplineSet 0 40 m 24 0 63 17 80 40 80 c 24 62 80 80 63 80 40 c 24 80 18 63 0 40 0 c 24 18 0 0 18 0 40 c 24 EndSplineSet Validated: 1 EndChar StartChar: uniE4A4 Encoding: 77 58532 77 Width: 320 Flags: HMW LayerCount: 2 Fore SplineSet 0 0 m 25 0 40 l 25 320 40 l 25 320 0 l 25 0 0 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE4A8 Encoding: 78 58536 78 Width: 100 Flags: HMW LayerCount: 2 Fore SplineSet 40 0 m 25 0 280 l 25 100 280 l 25 60 0 l 25 40 0 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE4AC Encoding: 79 58540 79 Width: 280 Flags: W HStem: 0 309 VStem: 0 280 LayerCount: 2 Fore SplineSet 0 0 m 1 140 309 l 25 280 0 l 1 215 0 l 1 127 198 l 25 37 0 l 1 0 0 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4C0 Encoding: 80 58560 80 Width: 600 Flags: HMW LayerCount: 2 Fore SplineSet 0 0 m 1 0 214 150 330 300 330 c 3 |
| ︙ | ︙ | |||
2284 2285 2286 2287 2288 2289 2290 | 332 120 359 92 359 60 c 3 359 27 333 0 299 0 c 3 EndSplineSet Validated: 1 EndChar StartChar: uniE4CE | | | 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 | 332 120 359 92 359 60 c 3 359 27 333 0 299 0 c 3 EndSplineSet Validated: 1 EndChar StartChar: uniE4CE Encoding: 81 58574 81 Width: 182 Flags: HMW LayerCount: 2 Fore SplineSet 86 301 m 0 123 301 136 294 156 272 c 0 |
| ︙ | ︙ | |||
2306 2307 2308 2309 2310 2311 2312 | 32 156 -0 184 -0 222 c 0 -0 258 27 301 86 301 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE4E1 | | | | | | | 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 | 32 156 -0 184 -0 222 c 0 -0 258 27 301 86 301 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE4E1 Encoding: 82 58593 82 Width: 130 Flags: HMW LayerCount: 2 Fore SplineSet 0 250 m 1 130 250 l 1 130 -250 l 5 0 -250 l 1 0 250 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4E2 Encoding: 83 58594 83 Width: 130 Flags: MW LayerCount: 2 Fore SplineSet 0 250 m 1 130 250 l 1 130 0 l 1 0 0 l 1 0 250 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4E3 Encoding: 84 58595 84 Width: 300 Flags: MW LayerCount: 2 Fore SplineSet 0 0 m 1 300 0 l 1 300 -125 l 1 0 -125 l 1 0 0 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4E4 Encoding: 85 58596 85 Width: 300 Flags: MW LayerCount: 2 Fore SplineSet 0 125 m 1 300 125 l 1 300 0 l 1 0 0 l 1 0 125 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4E5 Encoding: 86 58597 86 Width: 238 Flags: MW LayerCount: 2 Fore SplineSet 41 391 m 1 230 162 l 1 |
| ︙ | ︙ | |||
2394 2395 2396 2397 2398 2399 2400 | 122 193 l 1 41 391 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4E6 | | | 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 | 122 193 l 1 41 391 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4E6 Encoding: 87 58598 87 Width: 255 Flags: W HStem: 48 33<112 170.038> VStem: 0 135<81.9955 177.625> LayerCount: 2 Fore SplineSet |
| ︙ | ︙ | |||
2418 2419 2420 2421 2422 2423 2424 | 58 -227 l 1 171 60 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4E7 | | | < < | | | | | < < | | | | | | | < < | | | | | | | | | < < | | | | | | | 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 | 58 -227 l 1 171 60 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4E7 Encoding: 88 58599 88 Width: 329 Flags: MW LayerCount: 2 Fore SplineSet 171 -196 m 1 151 -202 140 -208 98 -208 c 0 45 -208 0 -184 0 -128 c 0 0 -83 33 -64 66 -64 c 0 101 -64 135 -85 135 -120 c 0 135 -136 130 -155 112 -176 c 1 158 -176 182 -160 188 -142 c 1 248 60 l 1 230 56 212 48 170 48 c 0 117 48 72 73 72 129 c 0 72 174 105 192 138 192 c 0 173 192 207 172 207 137 c 0 207 121 202 102 184 81 c 1 230 81 272 108 302 158 c 1 304 160 324 160 328 158 c 1 131 -500 l 1 86 -488 l 1 171 -196 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4E8 Encoding: 89 58600 89 Width: 399 Flags: MW LayerCount: 2 Fore SplineSet 246 60 m 1 226 54 217 48 175 48 c 0 122 48 77 72 77 128 c 0 77 173 110 192 143 192 c 0 178 192 212 171 212 136 c 0 212 120 207 101 189 80 c 1 235 80 257 96 263 114 c 1 321 317 l 1 303 313 283 304 241 304 c 0 188 304 143 329 143 385 c 0 143 430 176 448 209 448 c 0 244 448 278 428 278 393 c 0 278 377 273 358 255 337 c 1 301 337 343 364 373 414 c 1 375 416 395 416 399 414 c 1 131 -500 l 1 86 -488 l 1 171 -196 l 1 151 -202 140 -208 98 -208 c 0 45 -208 0 -184 0 -128 c 0 0 -83 33 -64 66 -64 c 0 101 -64 135 -85 135 -120 c 0 135 -136 130 -155 112 -176 c 1 158 -176 182 -160 188 -142 c 1 246 60 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4E9 Encoding: 90 58601 90 Width: 472 Flags: MW LayerCount: 2 Fore SplineSet 171 -452 m 1 151 -458 140 -464 98 -464 c 0 45 -464 0 -440 0 -384 c 0 0 -339 33 -320 66 -320 c 0 101 -320 135 -341 135 -376 c 0 135 -392 130 -411 112 -432 c 1 158 -432 182 -416 188 -398 c 1 246 -196 l 1 226 -202 215 -208 173 -208 c 0 120 -208 75 -184 75 -128 c 0 75 -83 108 -64 141 -64 c 0 176 -64 210 -85 210 -120 c 0 210 -136 205 -155 187 -176 c 1 233 -176 257 -160 263 -142 c 1 321 60 l 1 301 54 292 48 250 48 c 0 197 48 152 72 152 128 c 0 152 173 185 192 218 192 c 0 253 192 287 171 287 136 c 0 287 120 282 101 264 80 c 1 310 80 332 96 338 114 c 1 396 317 l 1 378 313 358 304 316 304 c 0 263 304 218 329 218 385 c 0 218 430 251 448 284 448 c 0 319 448 353 428 353 393 c 0 353 377 348 358 330 337 c 1 376 337 418 364 448 414 c 1 450 416 470 416 474 414 c 1 131 -756 l 1 86 -744 l 1 171 -452 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4EA Encoding: 91 58602 91 Width: 472 Flags: MW LayerCount: 2 Fore SplineSet 319 52 m 1 299 46 288 40 246 40 c 0 193 40 148 64 148 120 c 0 148 165 181 184 214 184 c 0 249 184 283 163 283 128 c 0 283 112 278 93 260 72 c 1 306 72 330 88 336 106 c 1 390 302 l 1 370 296 361 290 319 290 c 0 266 290 221 314 221 370 c 0 221 415 254 434 287 434 c 0 322 434 356 413 356 378 c 0 356 362 351 343 333 322 c 1 379 322 401 338 407 356 c 1 459 555 l 1 441 551 421 542 379 542 c 0 326 542 281 567 281 623 c 0 281 668 314 686 347 686 c 0 382 686 416 666 416 631 c 0 416 615 411 596 393 575 c 1 439 575 481 602 511 652 c 1 513 654 533 654 537 652 c 1 131 -756 l 1 86 -744 l 1 171 -452 l 1 151 -458 140 -464 98 -464 c 0 45 -464 0 -440 0 -384 c 0 0 -339 33 -320 66 -320 c 0 101 -320 135 -341 135 -376 c 0 135 -392 130 -411 112 -432 c 1 158 -432 182 -416 188 -398 c 1 246 -198 l 1 226 -204 215 -210 173 -210 c 0 120 -210 75 -186 75 -130 c 0 75 -85 108 -66 141 -66 c 0 176 -66 210 -87 210 -122 c 0 210 -138 205 -157 187 -178 c 1 233 -178 257 -162 263 -144 c 1 319 52 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE4EE Encoding: 92 58606 92 Width: 851 Flags: W HStem: -105 210<25 825> VStem: 0 25<-230 -105 105 230> 825 25<-230 -105 105 230> LayerCount: 2 Fore SplineSet |
| ︙ | ︙ | |||
2610 2611 2612 2613 2614 2615 2616 | 0 -230 l 25 0 230 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE500 | | | < < | 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 | 0 -230 l 25 0 230 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE500 Encoding: 93 58624 93 Width: 563 Flags: MW LayerCount: 2 Fore SplineSet 55 75 m 3 22 75 -5 102 -5 135 c 3 -5 169 22 195 55 195 c 3 88 195 115 168 115 135 c 3 |
| ︙ | ︙ | |||
2638 2639 2640 2641 2642 2643 2644 | 109 -250 l 1 -16 -250 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE501 | | | 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 | 109 -250 l 1 -16 -250 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE501 Encoding: 94 58625 94 Width: 800 Flags: W HStem: -195 120<659.745 752.255> 75 120<-6.25464 86.2546> VStem: -20 120<88.7454 181.255> 646 120<-181.255 -88.7454> LayerCount: 2 Fore SplineSet |
| ︙ | ︙ | |||
2671 2672 2673 2674 2675 2676 2677 | 334 -250 l 5 212 -250 l 5 EndSplineSet Validated: 1 EndChar StartChar: uniE520 | | | | | | | | | | | | | | | | | | < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > | > > > > > > > > > > > > > > > > > > > > | > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | > | | | | > > | | | 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 | 334 -250 l 5 212 -250 l 5 EndSplineSet Validated: 1 EndChar StartChar: uniE520 Encoding: 95 58656 95 Width: 379 Flags: HMW LayerCount: 2 Fore SplineSet 197 40 m 0 199 39 201 39 204 39 c 0 228 39 267 80 286 128 c 0 294 148 299 175 299 198 c 0 299 219 295 236 284 240 c 0 282 241 280 241 278 241 c 0 253 241 211 199 196 162 c 0 186 136 181 109 181 87 c 0 181 62 187 44 197 40 c 0 220 0 m 4 203 0 173 6 153 32 c 1 108 -90 l 1 160 -90 l 2 175 -90 175 -120 160 -120 c 0 -65 -120 l 0 -79 -120 -80 -90 -65 -90 c 2 10 -90 l 1 114 195 l 0 115 198 120 213 120 225 c 0 120 233 118 240 109 240 c 0 83 240 72 207 28 135 c 0 21 124 -6 139 1 151 c 0 56 249 69 280 125 280 c 0 170 280 193 271 203 235 c 1 244 278 263 280 305 280 c 0 341 280 380 248 380 180 c 0 380 87 319 0 220 0 c 4 EndSplineSet Validated: 1 EndChar StartChar: uniE521 Encoding: 96 58657 96 Width: 440 Flags: MW LayerCount: 2 Fore SplineSet 80 21 m 4 76 11 74 1 57 0 c 4 4 0 l 4 -6 0 0 18 4 26 c 5 70 193 l 4 77 211 69 221 60 221 c 4 42 221 35 210 -11 138 c 4 -18 127 -39 139 -33 151 c 4 3 216 36 280 86 280 c 4 128 280 145 266 152 240 c 5 170 260 194 280 224 280 c 4 254 280 273 263 278 240 c 5 292 259 322 280 349 280 c 4 382 280 410 254 410 219 c 4 410 211 408 202 405 193 c 4 358 68 l 4 355 60 354 54 354 48 c 4 354 40 357 34 362 34 c 4 364 34 365 35 367 36 c 4 389 48 404 72 419 93 c 4 427 104 449 93 440 78 c 4 411 27 388 -10 323 -10 c 4 296 -10 277 5 277 31 c 4 277 39 278 47 282 57 c 4 334 193 l 4 335 195 335 197 335 199 c 4 335 209 325 213 314 213 c 4 300 213 284 206 279 193 c 4 214 22 l 4 211 14 207 0 191 -1 c 5 153 0 l 20 134 -2 132 12 136 22 c 4 203 193 l 4 204 195 204 197 204 199 c 4 204 208 195 213 183 213 c 4 170 213 153 206 148 193 c 4 80 21 l 4 EndSplineSet Validated: 1 EndChar StartChar: uniE522 Encoding: 97 58658 97 Width: 278 Flags: HMW LayerCount: 2 Fore SplineSet -50 -160 m 0 -90 -160 -130 -135 -130 -90 c 0 -130 -55 -113 -30 -88 -30 c 0 -63 -30 -47 -45 -47 -65 c 0 -47 -75 -54 -83 -65 -90 c 0 -75 -97 -75 -100 -75 -110 c 0 -75 -120 -65 -124 -50 -124 c 0 13 -124 16 -35 83 230 c 1 64 230 65 230 30 230 c 0 17 230 11 241 11 251 c 0 11 261 17 270 28 270 c 0 59 270 61 270 93 270 c 1 121 374 204 440 270 440 c 0 310 440 350 415 350 370 c 0 350 335 333 310 308 310 c 0 283 310 267 325 267 345 c 0 267 355 274 363 285 370 c 0 296 377 295 380 295 390 c 0 295 400 285 404 270 404 c 0 228 404 218 332 205 270 c 1 232 270 229 270 259 270 c 0 272 270 278 260 278 250 c 0 278 240 272 230 259 230 c 0 233 230 229 230 196 230 c 1 153 -26 80 -160 -50 -160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE523 Encoding: 98 58659 98 Width: 275 Flags: HMW LayerCount: 2 Fore SplineSet 208 231 m 0 218 237 218 245 208 245 c 0 179 245 153 203 143 177 c 0 80 21 l 0 76 11 74 1 57 0 c 0 4 0 l 0 -6 0 0 18 4 26 c 1 70 189 l 0 77 207 69 217 60 217 c 0 42 217 35 210 -11 138 c 0 -18 127 -39 139 -33 151 c 0 3 216 40 275 90 275 c 0 132 275 147 246 150 236 c 1 162 251 182 275 217 275 c 0 252 275 275 254 275 220 c 0 275 181 256 165 232 165 c 0 212 165 190 182 190 200 c 0 190 216 196 224 208 231 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE524 Encoding: 99 58660 99 Width: 220 Flags: HMW LayerCount: 2 Fore SplineSet 80 0 m 0 41 0 0 33 0 70 c 0 0 92 18 108 34 108 c 0 51 108 70 96 70 80 c 0 70 65 61 53 54 46 c 1 62 35 69 30 85 30 c 0 113 30 140 45 140 70 c 0 140 100 116 103 90 120 c 0 57 141 32 172 32 205 c 0 32 252 72 280 132 280 c 0 177 280 220 253 220 220 c 0 220 199 204 180 182 180 c 0 166 180 147 195 147 214 c 0 147 219 151 225 154 231 c 1 146 241 135 250 122 250 c 0 103 250 82 239 82 220 c 0 82 193 129 175 152 160 c 0 186 137 200 115 200 85 c 0 200 26 156 0 80 0 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE525 Encoding: 100 58661 100 Width: 232 Flags: HMW LayerCount: 2 Fore SplineSet -10 3 m 0 -22 -6 -34 16 -23 26 c 0 153 219 l 0 138 218 126 213 105 213 c 0 98 213 86 219 76 218 c 0 65 217 47 173 34 162 c 0 20 150 6 154 20 187 c 0 41 238 38 251 44 267 c 1 79 265 89 260 126 260 c 0 184 260 189 271 207 271 c 0 211 271 215 271 220 270 c 0 235 268 233 254 224 245 c 0 66 78 l 0 65 75 64 72 64 70 c 0 64 68 65 67 66 67 c 0 69 67 76 70 86 70 c 0 99 70 119 65 147 44 c 0 166 29 179 64 166 64 c 0 148 64 130 72 130 93 c 0 130 111 143 128 161 128 c 0 181 128 199 115 199 73 c 0 199 35 170 -4 129 -4 c 0 126 -4 103 -4 100 -4 c 0 56 2 50 23 31 23 c 0 19 23 6 15 -10 3 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE529 Encoding: 101 58665 101 Width: 703 Flags: HMW LayerCount: 2 Fore SplineSet 522 40 m 0 524.179123831 39.0525548563 526.555731167 38.5988184777 529.0907001 38.5988184777 c 0 |
| ︙ | ︙ | |||
2977 2978 2979 2980 2981 2982 2983 | 835.665333312 135.693575703 831.068143327 108.945807045 831.068143327 87.1471403297 c 0 831.068143327 62.5417301443 836.925393958 44.2419393862 847 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52A | | | 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 | 835.665333312 135.693575703 831.068143327 108.945807045 831.068143327 87.1471403297 c 0 831.068143327 62.5417301443 836.925393958 44.2419393862 847 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52A Encoding: 102 58666 102 Width: 563 Flags: W HStem: -120 30<-74.2249 10 108 169.668 250.775 335 433 494.668 575.775 660 758 819.668> 0 38.5988<191.014 237.319 516.014 562.319 841.014 887.319> 240 40<80.1149 147.5 239.117 318 404.386 472.5 564.117 643 729.386 797.5 889.117 973> VStem: 120.421 60.6474<87.1471 224.606> 298.898 81.1023<108.679 217.246> 445.421 60.6474<87.1471 224.606> 623.898 81.1023<108.679 217.246> 770.421 60.6474<87.1471 224.606> 948.898 81.1023<108.462 239.669> LayerCount: 2 Fore SplineSet |
| ︙ | ︙ | |||
3069 3070 3071 3072 3073 3074 3075 | 185.665333312 135.693575703 181.068143327 108.945807045 181.068143327 87.1471403297 c 0 181.068143327 62.5417301443 186.925393958 44.2419393862 197 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52B | | | 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 | 185.665333312 135.693575703 181.068143327 108.945807045 181.068143327 87.1471403297 c 0 181.068143327 62.5417301443 186.925393958 44.2419393862 197 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52B Encoding: 103 58667 103 Width: 703 Flags: HMW LayerCount: 2 Fore SplineSet 200 0 m 0 183 0 173 6 153 32 c 1 |
| ︙ | ︙ | |||
3133 3134 3135 3136 3137 3138 3139 | 510.665333312 135.693575703 506.068143327 108.945807045 506.068143327 87.1471403297 c 0 506.068143327 62.5417301443 511.925393958 44.2419393862 522 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52C | | | 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 | 510.665333312 135.693575703 506.068143327 108.945807045 506.068143327 87.1471403297 c 0 506.068143327 62.5417301443 511.925393958 44.2419393862 522 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52C Encoding: 104 58668 104 Width: 811 Flags: HMW LayerCount: 2 Fore SplineSet 429 119 m 0 480 232 500 280 556 280 c 0 |
| ︙ | ︙ | |||
3205 3206 3207 3208 3209 3210 3211 | 616.665333312 135.693575703 612.068143327 108.945807045 612.068143327 87.1471403297 c 0 612.068143327 62.5417301443 617.925393958 44.2419393862 628 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52D | | | 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 | 616.665333312 135.693575703 612.068143327 108.945807045 612.068143327 87.1471403297 c 0 612.068143327 62.5417301443 617.925393958 44.2419393862 628 40 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52D Encoding: 105 58669 105 Width: 351 Flags: HMW LayerCount: 2 Fore SplineSet 80 21 m 0 76 11 74 1 57 0 c 0 |
| ︙ | ︙ | |||
3278 3279 3280 3281 3282 3283 3284 | 676 230 672 230 639 230 c 1 596 -26 523 -160 393 -160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52F | | | 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 | 676 230 672 230 639 230 c 1 596 -26 523 -160 393 -160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE52F Encoding: 106 58671 106 Width: 617 Flags: HMW LayerCount: 2 Fore SplineSet 351 230 m 9 196 230 l 1 |
| ︙ | ︙ | |||
3332 3333 3334 3335 3336 3337 3338 | 192 -120 202 -124 217 -124 c 0 280 -124 284 -35 351 230 c 9 EndSplineSet Validated: 1 EndChar StartChar: uniE530 | | | 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 | 192 -120 202 -124 217 -124 c 0 280 -124 284 -35 351 230 c 9 EndSplineSet Validated: 1 EndChar StartChar: uniE530 Encoding: 107 58672 107 Width: 351 Flags: HMW LayerCount: 2 Fore SplineSet 204 270 m 9 360 270 l 1 |
| ︙ | ︙ | |||
3404 3405 3406 3407 3408 3409 3410 | 295 400 285 404 270 404 c 0 228 404 217 332 204 270 c 9 EndSplineSet Validated: 1 EndChar StartChar: uniE531 | | | 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 | 295 400 285 404 270 404 c 0 228 404 217 332 204 270 c 9 EndSplineSet Validated: 1 EndChar StartChar: uniE531 Encoding: 108 58673 108 Width: 617 Flags: HMW LayerCount: 2 Fore SplineSet 472 271 m 9 628 270 l 1 |
| ︙ | ︙ | |||
3494 3495 3496 3497 3498 3499 3500 | 562 400 552 404 537 404 c 0 495 404 485 332 472 271 c 9 EndSplineSet Validated: 1 EndChar StartChar: uniE539 | | | 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 | 562 400 552 404 537 404 c 0 495 404 485 332 472 271 c 9 EndSplineSet Validated: 1 EndChar StartChar: uniE539 Encoding: 109 58681 109 Width: 351 Flags: HMW LayerCount: 2 Fore SplineSet 80 0 m 0xd8 41 0 0 33 0 70 c 0xe8 |
| ︙ | ︙ | |||
3572 3573 3574 3575 3576 3577 3578 | 465 230 461 230 428 230 c 1 385 -26 312 -160 182 -160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE566 | | | 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 | 465 230 461 230 428 230 c 1 385 -26 312 -160 182 -160 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE566 Encoding: 110 58726 110 Width: 509 Flags: HMW LayerCount: 2 Fore SplineSet 310 265 m 1 183 258 l 1 |
| ︙ | ︙ | |||
3612 3613 3614 3615 3616 3617 3618 | 230 0 l 1 242 40 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE567 | | | 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 | 230 0 l 1 242 40 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE567 Encoding: 111 58727 111 Width: 437 Flags: W HStem: -3 72<49.5596 110.739> 0 49<319.775 397.094> 141 71<327.059 386.441> 161 47<36.904 118.027> VStem: 0 24<64.6579 145.71> 413 24<63.9568 143.617> LayerCount: 2 Fore SplineSet |
| ︙ | ︙ | |||
3649 3650 3651 3652 3653 3654 3655 | 323 68 l 1 342 55 353 49 368 49 c 0x5c EndSplineSet Validated: 1 EndChar StartChar: uniE569 | | | 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 | 323 68 l 1 342 55 353 49 368 49 c 0x5c EndSplineSet Validated: 1 EndChar StartChar: uniE569 Encoding: 112 58729 112 Width: 437 Flags: HMW LayerCount: 2 Fore SplineSet 77 -3 m 0 33 -3 0 54 0 102 c 0 |
| ︙ | ︙ | |||
3691 3692 3693 3694 3695 3696 3697 | 92 61 102 51 102 32 c 0 102 11 93 -1 77 -3 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE56C | | | 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 | 92 61 102 51 102 32 c 0 102 11 93 -1 77 -3 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE56C Encoding: 113 58732 113 Width: 580 Flags: W HStem: 0 224 LayerCount: 2 Fore SplineSet 34 46 m 13 |
| ︙ | ︙ | |||
3716 3717 3718 3719 3720 3721 3722 | 109 124 l 5 34 46 l 13 EndSplineSet Validated: 1 EndChar StartChar: uniE56D | | | 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 | 109 124 l 5 34 46 l 13 EndSplineSet Validated: 1 EndChar StartChar: uniE56D Encoding: 114 58733 114 Width: 580 Flags: W HStem: -53 326<278 305> 0 21G<197.065 232.286 418.065 453.137> VStem: 278 27<-53 70 150 273> LayerCount: 2 Fore SplineSet |
| ︙ | ︙ | |||
3750 3751 3752 3753 3754 3755 3756 | 278 -53 l 25 278 70 l 1xa0 EndSplineSet Validated: 1 EndChar StartChar: uniE582 | | | 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 | 278 -53 l 25 278 70 l 1xa0 EndSplineSet Validated: 1 EndChar StartChar: uniE582 Encoding: 115 58754 115 Width: 280 Flags: HMW LayerCount: 2 Fore SplineSet 123 0 m 25 123 123 l 25 |
| ︙ | ︙ | |||
3774 3775 3776 3777 3778 3779 3780 | 157 0 l 25 123 0 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE5D0 | | | | 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 | 157 0 l 25 123 0 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE5D0 Encoding: 116 58832 116 Width: 310 Flags: HMW LayerCount: 2 Fore SplineSet 0 0 m 1 0 60 l 1 93 79 229 114 280 370 c 1 310 370 l 1 310 175 152 13 0 0 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE5E2 Encoding: 117 58850 117 Width: 300 Flags: W HStem: 0 62<198.921 262.211> 96 64<38.8054 112.592> VStem: 283 16<88.1179 101.401> LayerCount: 2 Fore SplineSet |
| ︙ | ︙ | |||
3814 3815 3816 3817 3818 3819 3820 | 55 96 32 79 17 61 c 0 10 53 -2 61 1 70 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE610 | | | | | | | | | | | | | 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 | 55 96 32 79 17 61 c 0 10 53 -2 61 1 70 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE610 Encoding: 118 58896 118 Width: 300 Flags: HMW LayerCount: 2 Fore SplineSet 0 0 m 25 0 300 l 25 300 300 l 25 300 0 l 25 265 0 l 25 265 180 l 25 35 180 l 29 35 0 l 29 0 0 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE612 Encoding: 119 58898 119 Width: 250 Flags: HMW LayerCount: 2 Fore SplineSet 105 0 m 29 0 450 l 25 40 450 l 25 125 90 l 25 210 450 l 25 250 450 l 25 145 0 l 25 105 0 l 29 EndSplineSet Validated: 1 EndChar StartChar: uniE614 Encoding: 120 58900 120 Width: 200 Flags: HMW LayerCount: 2 Fore SplineSet 100 25 m 28 141 25 175 59 175 100 c 28 175 141 141 175 100 175 c 28 59 175 25 141 25 100 c 28 25 59 59 25 100 25 c 28 100 0 m 28 45 0 0 45 0 100 c 28 0 155 45 200 100 200 c 28 155 200 200 155 200 100 c 28 200 45 155 0 100 0 c 28 EndSplineSet Validated: 1 EndChar StartChar: uniE618 Encoding: 121 58904 121 Width: 280 Flags: HMW LayerCount: 2 Fore SplineSet -200 0 m 1 -200 110 -110 200 0 200 c 24 110 200 200 110 200 0 c 1 170 0 l 1 170 99 99 170 0 170 c 24 -99 170 -170 99 -170 0 c 1 -200 0 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE624 Encoding: 122 58916 122 Width: 250 Flags: HMW LayerCount: 2 Fore SplineSet 90 120 m 0 110 120 132 165 132 200 c 28 |
| ︙ | ︙ | |||
3916 3917 3918 3919 3920 3921 3922 | 108 0 l 25 72 0 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE630 | | | | | | | | | | | | | | 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 | 108 0 l 25 72 0 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniE630 Encoding: 123 58928 123 Width: 200 Flags: HMW LayerCount: 2 Fore SplineSet 84 102 m 1 37 109 -0 150 0 200 c 24 0 255 45 300 100 300 c 24 155 300 200 255 200 200 c 24 200 150 163 109 116 102 c 1 116 101 l 1 116 0 l 25 84 0 l 25 84 101 l 1 84 102 l 1 116 126 m 1 149 134 175 164 175 200 c 24 175 241 141 275 100 275 c 24 59 275 25 241 25 200 c 24 25 164 51 134 84 126 c 1 84 127 l 1 84 200 l 25 116 200 l 25 116 127 l 1 116 126 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniE650 Encoding: 124 58960 124 Width: 1037 Flags: W HStem: -2 60<361.035 435.033 953.253 1010.82> 0 49<543.265 652.027> 286 36<514.943 580.797> 359 66<58.4784 125.129> 402 58<367.211 444.917> 607 32<177.106 261> VStem: 0 57<406 505.924> 148 26<463.933 475.584> 200 67<410.241 442> 274.641 84.3586<205.588 329> 425 56<126.64 255.856> 452 64<466.983 558.522> 585 40<194.878 284.873> 675 60<72.5613 225.441> 887 59<79.8865 267.532> 952 60<-0.820206 56.8202> LayerCount: 2 Fore SplineSet |
| ︙ | ︙ | |||
4026 4027 4028 4029 4030 4031 4032 | 758 262 735 202 735 117 c 0 735 73 753 50 797 40 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE655 | | | 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 | 758 262 735 202 735 117 c 0 735 73 753 50 797 40 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE655 Encoding: 125 58965 125 Width: 540 Flags: W HStem: 68 93<79.5149 155.133> 182 17<220 222.173 252.655 264.303> 192 94<18.5323 100.176 375.888 460.387> 230 56<60.9363 133.273> 230 18<300.618 361.695> 274 18<213.64 227.572 256.894 258> 315 97<73.5817 155.121 322.704 406.413> VStem: 179 23<209.875 223.47 254.181 264.625> 192 98<17.9339 97.9009 381.276 451.65> 230 18<113.95 174.519 300.936 363.797> 278 17<212.458 224.186 254.5 261> LayerCount: 2 Fore SplineSet |
| ︙ | ︙ | |||
4099 4100 4101 4102 4103 4104 4105 | 173 186 179 196 179 204 c 0 179 219 166 230 141 230 c 0xcb40 EndSplineSet Validated: 1 EndChar StartChar: uniE910 | | | 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 | 173 186 179 196 179 204 c 0 179 219 166 230 141 230 c 0xcb40 EndSplineSet Validated: 1 EndChar StartChar: uniE910 Encoding: 126 59664 126 Width: 500 Flags: HMW LayerCount: 2 Fore SplineSet 45 0 m 28 45 -113 137 -205 250 -205 c 28 |
| ︙ | ︙ | |||
4125 4126 4127 4128 4129 4130 4131 | 283 60 310 33 310 0 c 7 310 -33 283 -60 250 -60 c 7 EndSplineSet Validated: 1 EndChar StartChar: uniE911 | | | | | | | | | | | | | | | | | | | | | | 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 | 283 60 310 33 310 0 c 7 310 -33 283 -60 250 -60 c 7 EndSplineSet Validated: 1 EndChar StartChar: uniE911 Encoding: 127 59665 127 Width: 500 Flags: HMW LayerCount: 2 Fore SplineSet 45 0 m 24 45 -113 137 -205 250 -205 c 24 363 -205 455 -113 455 0 c 24 455 113 363 205 250 205 c 24 137 205 45 113 45 0 c 24 0 0 m 24 0 139 111 250 250 250 c 24 388 250 500 139 500 0 c 24 500 -138 389 -250 250 -250 c 24 112 -250 0 -138 0 0 c 24 EndSplineSet Validated: 1 EndChar StartChar: uniE912 Encoding: 128 59666 128 Width: 500 Flags: HMW LayerCount: 2 Fore SplineSet 228 350 m 5 273 350 l 5 273 250 l 5 400 237 500 131 500 0 c 4 500 -130 401 -237 273 -250 c 5 273 -350 l 5 228 -350 l 5 228 -249 l 5 100 -238 0 -131 0 0 c 4 0 132 99 238 228 249 c 5 228 350 l 5 228 -204 m 5 228 204 l 5 125 193 45 106 45 0 c 4 45 -106 125 -193 228 -204 c 5 273 -204 m 5 375 -193 455 -105 455 0 c 4 455 105 375 193 273 204 c 5 273 -204 l 5 EndSplineSet Validated: 1 EndChar StartChar: uniE914 Encoding: 129 59668 129 Width: 500 Flags: HMW LayerCount: 2 Fore SplineSet 463 130 m 0 464 127 465 123 465 120 c 0 |
| ︙ | ︙ | |||
4209 4210 4211 4212 4213 4214 4215 | 283 60 310 33 310 0 c 3 310 -33 283 -60 250 -60 c 3 EndSplineSet Validated: 1 EndChar StartChar: uniE915 | | | 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 | 283 60 310 33 310 0 c 3 310 -33 283 -60 250 -60 c 3 EndSplineSet Validated: 1 EndChar StartChar: uniE915 Encoding: 130 59669 130 Width: 500 Flags: HMW LayerCount: 2 Fore SplineSet 463 130 m 0 464 127 465 123 465 120 c 0 |
| ︙ | ︙ | |||
4237 4238 4239 4240 4241 4242 4243 | 0 139 111 250 250 250 c 0 344 250 420 210 463 130 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE918 | | | 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 | 0 139 111 250 250 250 c 0 344 250 420 210 463 130 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniE918 Encoding: 131 59672 131 Width: 500 Flags: HMW LayerCount: 2 Fore SplineSet 273 249 m 1 356 243 424 203 463 130 c 0 |
| ︙ | ︙ | |||
4274 4275 4276 4277 4278 4279 4280 | 125 193 45 106 45 0 c 0 45 -106 125 -193 228 -204 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE920 | | | | | 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 | 125 193 45 106 45 0 c 0 45 -106 125 -193 228 -204 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniE920 Encoding: 132 59680 132 Width: 120 Flags: HMW LayerCount: 2 Fore SplineSet 60 -60 m 3 27 -60 0 -33 0 0 c 3 0 33 27 60 60 60 c 3 93 60 120 33 120 0 c 3 120 -33 93 -60 60 -60 c 3 EndSplineSet Validated: 1 EndChar StartChar: uniE925 Encoding: 133 59685 133 Width: 45 Flags: HMW LayerCount: 2 Fore SplineSet 45 350 m 9 45 -350 l 1 0 -350 l 9 0 350 l 1 45 350 l 9 EndSplineSet Validated: 1 EndChar StartChar: uniE95D Encoding: 134 59741 134 Width: 540 Flags: HMW LayerCount: 2 Fore SplineSet 30 70 m 25 30 -70 l 25 |
| ︙ | ︙ | |||
4335 4336 4337 4338 4339 4340 4341 | 0 -190 l 25 0 190 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniEA02 | | | 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 | 0 -190 l 25 0 190 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniEA02 Encoding: 135 59906 135 Width: 250 Flags: HMW LayerCount: 2 Fore SplineSet 0 65 m 25 137 250 l 25 |
| ︙ | ︙ | |||
4359 4360 4361 4362 4363 4364 4365 | 32 41 l 25 0 65 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniEAA4 | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 | 32 41 l 25 0 65 l 25 EndSplineSet Validated: 1 EndChar StartChar: uniEAA4 Encoding: 136 60068 136 Width: 250 Flags: HMW LayerCount: 2 Fore SplineSet 0 270 m 0 30 300 45 311 85 311 c 0 125 311 170 250 210 250 c 0 222 250 230 250 250 270 c 0 252 272 256 273 260 273 c 0 266 273 274 273 274 266 c 0 274 259 266 246 250 230 c 0 220 200 205 189 165 189 c 0 125 189 80 250 40 250 c 0 28 250 20 250 0 230 c 0 -2 228 -7 226 -11 226 c 0 -17 226 -24 227 -24 234 c 0 -24 241 -17 253 0 270 c 0 EndSplineSet Validated: 1 EndChar StartChar: uniECA2 Encoding: 137 60578 137 Width: 450 Flags: HMW LayerCount: 2 Fore SplineSet 337 -20 m 4 337 50 264 111 193 111 c 4 154 111 109 85 109 41 c 4 109 -30 186 -87 257 -87 c 4 298 -87 337 -65 337 -20 c 4 450 10 m 4 450 -60 361 -119 225 -119 c 4 89 -119 0 -60 0 10 c 4 0 80 89 139 225 139 c 4 361 139 450 80 450 10 c 4 EndSplineSet Validated: 1 EndChar StartChar: uniECA3 Encoding: 138 60579 138 Width: 328 Flags: HMW LayerCount: 2 Fore SplineSet 292 68 m 0 283 84 264 91 242 91 c 0 164 91 31 10 31 -49 c 0 31 -56 33 -62 37 -68 c 0 45 -84 64 -91 86 -91 c 0 164 -91 297 -10 297 49 c 0 297 56 295 62 292 68 c 0 299 680 m 1 328 680 l 1 328 22 l 2 328 -70 223 -148 130 -148 c 0 83 -148 40 -128 15 -81 c 0 5 -61 0 -41 0 -22 c 0 0 70 105 148 198 148 c 0 237 148 273 134 298 103 c 1 299 680 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniECA5 Encoding: 139 60581 139 Width: 320 Flags: HMW LayerCount: 2 Fore SplineSet 290 680 m 1 320 680 l 1 320 40 l 2 320 -51 231 -135 110 -135 c 0 40 -135 0 -90 0 -40 c 0 0 50 90 135 210 135 c 0 244 135 271 124 290 107 c 1 290 680 l 1 EndSplineSet Validated: 1 EndChar StartChar: uniECA7 Encoding: 140 60583 140 Width: 522 Flags: HMW LayerCount: 2 Fore SplineSet 320 441 m 1 320 40 l 2 320 -51 231 -135 110 -135 c 0 40 -135 0 -90 0 -40 c 0 0 50 90 135 210 135 c 0 244 135 271 124 290 107 c 1 290 441 l 1 290 680 l 1 320 680 l 1 341 485 522 459 522 196 c 0 522 137 505 85 472 10 c 1 485 57 490 104 490 148 c 0 490 258 462 396 320 441 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniECA9 Encoding: 141 60585 141 Width: 522 Flags: HMW LayerCount: 2 Fore SplineSet 290 107 m 1 290 337 l 1 290 680 l 1 320 680 l 1 352 547 522 491 522 309 c 0 522 282 514 253 501 222 c 1 513 196 523 168 523 138 c 0 523 104 510 67 489 27 c 1 493 47 494 67 494 85 c 0 494 219 390 338 320 338 c 1 320 40 l 2 320 -51 231 -135 110 -135 c 0 40 -135 0 -90 0 -40 c 0 0 50 90 135 210 135 c 0 244 135 271 124 290 107 c 1 320 509 m 1 346 402 429 361 494 235 c 1 494 242 495 248 495 255 c 0 495 388 391 509 320 509 c 1 EndSplineSet Validated: 1 EndChar StartChar: uniECB7 Encoding: 142 60599 142 Width: 100 Flags: HMW LayerCount: 2 Fore SplineSet 50 -50 m 3 22 -50 0 -28 0 0 c 3 0 28 22 50 50 50 c 3 78 50 100 28 100 0 c 3 100 -28 78 -50 50 -50 c 3 EndSplineSet EndChar EndChars EndSplineFont |
Changes to modules/MIDI.js.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// MIDI.js - module to handle the %%MIDI parameters
//
// Copyright (C) 2019 Jean-Francois Moine - GPL3+
//
// This module is loaded when "%%MIDI" appears in a ABC source.
//
// Parameters (see abcMIDI for details)
// %%MIDI channel n
// %%MIDI program n
// %%MIDI control k v
// %%MIDI drummap ABC_note MIDI_pitch
abc2svg.MIDI = {
// parse %%MIDI commands
do_midi: function(parm) {
| > > > > > > > > | > > > > > | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | < < < < < < | | < < < < < < < < < < < < < < | | < | | | < > > < < | | > > | > > > > > > | > < < | > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
// MIDI.js - module to handle the %%MIDI parameters
//
// Copyright (C) 2019 Jean-Francois Moine - GPL3+
//
// This module is loaded when "%%MIDI" appears in a ABC source.
//
// Parameters (see abcMIDI for details)
// %%MIDI channel n
// %%MIDI program n
// %%MIDI control k v
// %%MIDI drummap ABC_note MIDI_pitch
// Using %%MIDI drummap creates a voicemap named "MIDIdrum".
// This name must be used if some print map is required:
// %%MIDI drummap g 42
// %%map MIDIdrum g heads=x
// A same effect may be done by
// %%percmap g 42 x
// but this is not abcMIDI compatible!
abc2svg.MIDI = {
// parse %%MIDI commands
do_midi: function(parm) {
// convert a ABC note to b40 (string)
function abc_b40(p) {
var pit,
acc = 0,
i = 0
switch (p[0]) {
case '^':
if (p[++i] == '^') {
acc = 2
i++
} else {
acc = 1
}
break
case '=':
i++
break
case '_':
if (p[++i] == '_') {
acc = -2
i++
} else {
acc = -1
}
break
}
pit = 'CDEFGABcdefgab'.indexOf(p[i++]) + 16
if (pit < 16)
return
while (p[i] == "'") {
pit += 7
i++
}
while (p[i] == ",") {
pit -= 7
i++
}
return abc2svg.pab40(pit, acc).toString()
} // abc_b40()
// convert a MIDI pitch to b40
function mid_b40(p) {
var pit = Number(p)
if (isNaN(pit))
return
p = (pit / 12) | 0 // octave
pit = pit % 12; // in octave
return p * 40 + abc2svg.isb40[pit] + 2
} // mid_b40()
// do_midi()
var n, v, s, maps,
a = parm.split(/\s+/)
switch (a[1]) {
case "channel": // channel 10 is bank 128
if (a[2] != "10")
break // other channel values are ignored
abc2svg.MIDI.do_midi.call(this, "MIDI control 0 1") // MSB bank
abc2svg.MIDI.do_midi.call(this, "MIDI control 32 0") // LSB bank
break
case "drummap":
//fixme: should have a 'MIDIdrum' per voice?
n = abc_b40(a[2])
v = mid_b40(a[3])
if (!n || !v) {
this.syntax(1, this.errs.bad_val, "%%MIDI drummap")
break
}
maps = this.get_maps()
if (!maps.MIDIdrum)
maps.MIDIdrum = {}
if (!maps.MIDIdrum[n])
maps.MIDIdrum[n] = []
maps.MIDIdrum[n][3] = v
this.set_v_param("mididrum", "MIDIdrum")
break
case "program":
if (a[3] != undefined) // the channel is unused
v = a[3]
else
v = a[2];
v = parseInt(v)
if (isNaN(v) || v < 0 || v > 127) {
this.syntax(1, "Bad program in %%MIDI")
return
}
if (this.parse.state == 3) {
s = this.new_block("midiprog");
s.play = true
s.instr = v
} else {
this.set_v_param("instr", v)
}
break
case "control":
n = parseInt(a[2])
if (isNaN(n) || n < 0 || n > 127) {
this.syntax(1, "Bad controller number in %%MIDI")
return
}
v = parseInt(a[3])
if (isNaN(v) || v < 0 || v > 127) {
this.syntax(1, "Bad controller value in %%MIDI")
return
}
if (this.parse.state == 3) {
s = this.new_block("midictl");
s.play = true
s.ctrl = n;
s.val = v
} else {
this.set_v_param("midictl", a[2] + ' ' + a[3])
}
break
}
}, // do_midi()
// set the MIDI parameters in the current voice
set_midi: function(a) {
|
| ︙ | ︙ |
Changes to modules/ambitus.js.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
if (s.notes[1].pit - s.notes[0].pit > 4) {
this.xypath(s.x, 3 * (s.notes[1].pit - 18) + staff_tb[s.st].y);
this.out_svg('v' +
((s.notes[1].pit - s.notes[0].pit) * 3).toFixed(1) +
'" stroke-width=".6"/>\n');
}
s.x += 26;
p_voice.clef.nhd = 0
}
of(p_voice)
}, // draw_symbols()
set_pitch: function(of, last_s) {
of(last_s)
if (!last_s && this.cfmt().ambitus)
abc2svg.ambitus.do_ambitus.call(this)
},
| > | | | 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 |
if (s.notes[1].pit - s.notes[0].pit > 4) {
this.xypath(s.x, 3 * (s.notes[1].pit - 18) + staff_tb[s.st].y);
this.out_svg('v' +
((s.notes[1].pit - s.notes[0].pit) * 3).toFixed(1) +
'" stroke-width=".6"/>\n');
}
s.x += 26;
s.nhd = 0
p_voice.clef.nhd = 0
}
of(p_voice)
}, // draw_symbols()
set_pitch: function(of, last_s) {
of(last_s)
if (!last_s && this.cfmt().ambitus)
abc2svg.ambitus.do_ambitus.call(this)
},
set_fmt: function(of, cmd, param) {
if (cmd == "ambitus") {
this.cfmt().ambitus = param
return
}
of(cmd, param)
},
set_width: function(of, s) {
if (s.clef_type != undefined && s.nhd > 0) {
s.wl = 40;
s.wr = 12
} else {
|
| ︙ | ︙ |
Changes to modules/capo.js.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 | if (!gch) return if (gch.type == 'g') break } gch2 = Object.create(gch); gch2.capo = false; // (would be erased when setting gch) | | < | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
if (!gch)
return
if (gch.type == 'g')
break
}
gch2 = Object.create(gch);
gch2.capo = false; // (would be erased when setting gch)
gch2.text = this.gch_tr1(gch2.text, -abc2svg.ifb40[transp % 12])
if (!this.capo_first) { // if new tune
this.capo_first = true;
gch2.text += " (capo: " + transp.toString() + ")"
}
gch2.font = this.get_font(cfmt.capofont ? "capo" : "annotation");
a_gch.splice(i, 0, gch2)
|
| ︙ | ︙ | |||
47 48 49 50 51 52 53 |
},
output_music: function(of) {
this.capo_first = false;
of()
},
| | | | 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 |
},
output_music: function(of) {
this.capo_first = false;
of()
},
set_fmt: function(of, cmd, param) {
if (cmd == "capo") {
this.cfmt().capo = param
return
}
of(cmd, param)
},
set_hooks: function(abc) {
abc.gch_build = abc2svg.capo.gch_build.bind(abc, abc.gch_build);
abc.output_music = abc2svg.capo.output_music.bind(abc, abc.output_music);
abc.set_format = abc2svg.capo.set_fmt.bind(abc, abc.set_format)
}
} // capo
abc2svg.modules.hooks.push(abc2svg.capo.set_hooks);
// the module is loaded
abc2svg.modules.capo.loaded = true
|
Added modules/clair.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
// clair.js - module to output Clairnote sheets (https:clairnote.org)
//
// Copyright (C) 2019 Jean-Francois Moine - GPL3+
//
// This module is loaded when "%%clairnote" appears in a ABC source.
//
// Parameters (none)
// %%clairnote 1
abc2svg.clair = {
// table for helper lines (from C, to c'')
// index = (note pitch + 16)
// value = array of staff offsets / null
hl_tb: [
new Int8Array([-20,-16,-12,-8,-4]), // _B,, -18
new Int8Array([-20,-18,-16,-12,-8,-4]), // B,, -17
new Int8Array([-16,-12,-8,-4]), // C, -16
new Int8Array([-16,-12,-8,-4]), // ^C, -15
new Int8Array([-16,-14,-12,-8,-4]), // D, -14
new Int8Array([-12,-8,-4]), // ^D, -13
new Int8Array([-12,-8,-4]), // E, -12
new Int8Array([-12,-8,-4]), // F, -11
new Int8Array([-12,-10,-8,-4]), // ^F, -10
new Int8Array([-8,-4]), // G, -9
new Int8Array([-8,-4]), // ^G, -8
new Int8Array([-8,-4]), // A, -7
new Int8Array([-8,-6,-4]), // _B, -6
new Int8Array([-4]), // B, -5
new Int8Array([-4]), // C -4
new Int8Array([-4]), // ^C -3
new Int8Array([-4,-2]), // D -2
null, // ^D -1
null, // E 0
null, // F 1
new Int8Array([2]), // ^F 2
null, // G 3
null, // ^G 4
null, // A 5
new Int8Array([6,8]), // _B 6
new Int8Array([8]), // B 7
new Int8Array([8]), // c 8
new Int8Array([8]), // ^c 9
new Int8Array([8,10]), // d 10
null, // _e 11
null, // e 12
null, // f 13
new Int8Array([14]), // ^f 14
null, // g 15
null, // ^g 16
null, // a 17
new Int8Array([18,20]), // _b 18
new Int8Array([20]), // b 19
new Int8Array([20]), // c' 20
new Int8Array([20]), // ^c' 21
new Int8Array([20,22]), // d' 22
new Int8Array([20,22]), // _e' 23
new Int8Array([20,24]), // e' 24
new Int8Array([20,24]), // f' 25
new Int8Array([20,24,26]), // ^f' 26
new Int8Array([20,24,26]), // g' 27
new Int8Array([20,24,28]), // ^g' 28
new Int8Array([20,24,28]), // a' 29
new Int8Array([20,24,28,30]), // _b' 30
new Int8Array([20,24,28,30]), // b' 31
new Int8Array([20,24,28,32]) // c'' 32
],
// draw the helper lines
draw_hl: function(of, x, s, hltype) {
if (!s.p_v.clair) {
of(x, s, hltype)
return
}
var i, m, hl,
staffb = this.get_staff_tb()[s.st].y
for (m = 0; m <= s.nhd; m++) {
hl = abc2svg.clair.hl_tb[s.notes[m].pit]
if (!hl)
continue
for (i = 0; i < hl.length; i++)
this.xygl(x, staffb + hl[i] * 3, hltype)
}
}, // draw_hl()
// draw the key signature
draw_keysig: function(of, x, s) {
if (!s.p_v.clair) {
of(x, s)
return
}
var i,
staffb = this.get_staff_tb()[s.st].y,
a_tb = new Int8Array(24),
sc = [0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19, 21, 23],
// major scale (2 octaves)
bn_tb = [7, 2, -3, 4, -1, 6, 1, 8, 3, -2, 5, 0, 7, 2, -3],
// #sf -> (major) base note
bn = bn_tb[s.k_sf + 7] // base note
if (!s.k_a_acc) {
if (s.k_sf > 0) {
for (i = 1; i <= s.k_sf; i++) {
a_tb[bn_tb[i] + 3] = 1; // index = y + 3
a_tb[bn_tb[i] + 12 + 3] = 1
}
if (bn + sc[s.k_mode] > 8)
bn -= 12
for (i = 7; --i >= 0; ) {
y = bn + sc[s.k_mode + i]
this.xygl(x, staffb + y * 3, (y & 1) ? "wk" : "bk");
if (a_tb[y + 3])
this.xygl(x,
staffb + y * 3,
"sht");
switch (s.k_mode + i) {
case 3:
case 7:
case 10:
x += 4.5
break
}
}
} else {
for (i = s.k_sf; i < 0; i++) {
a_tb[bn_tb[i + 6] + 3] = 1; // index = y + 3
a_tb[bn_tb[i + 6] + 12 + 3 ] = 1
}
if (bn + sc[s.k_mode] > 8)
bn -= 12
for (i = 0; i < 7; i++) { // down top
y = bn + sc[s.k_mode + i]
this.xygl(x, staffb + y * 3, (y & 1) ? "wk" : "bk");
if (a_tb[y + 3])
this.xygl(x,
staffb + y * 3,
"flt");
switch (s.k_mode + i) {
case 2:
case 6:
case 9:
x += 4.5
break
}
}
}
} else if (s.k_a_acc.length) {
for (i = 0; i < s.k_a_acc.length; i++) {
var acc = s.k_a_acc[i];
j = sc[(acc.pit + 3) % 7];
a_tb[j] = acc.acc;
a_tb[j + 12] = acc.acc
}
// todo
}
}, // draw_keysig()
// update a clef
new_clef: function(s) {
switch (s.clef_type) {
case 't':
s.clef_line = 3;
s.clefpit = -2;
s.clef_name = "cl4"
break
case 'c':
s.clef_line = 3;
s.clefpit = 6;
s.clef_name = "cl3"
break
case 'b':
s.clef_line = 3;
s.clefpit = 14;
s.clef_name = "cl2"
break
}
}, // new_clef()
// function called before SVG generation
output_music: function(of) {
var s, m, mp, p_v, v,
cfmt = this.cfmt(),
tsfirst = this.get_tsfirst(),
voice_tb = this.get_voice_tb(),
abcmidi = new AbcMIDI();
abcmidi.add(tsfirst, voice_tb); // get the MIDI pitches
// define the new clefs and key signatures
// (clefs converted from clairnote.ly)
this.do_begin_end("svg", null, '<defs>\n\
<g id="cl2">\n\
<path transform="translate(-9,-27) scale(8)" d="m0.2656 -0.78107\n\
C0.3775 -0.79547 0.4351 -0.84567 0.7003 -0.85587\n\
C0.9459 -0.86587 1.0531 -0.85987 1.1805 -0.83797\n\
C1.6967 -0.74937 2.1173 -0.13032 2.1173 0.64059\n\
C2.1173 2.10531 0.9987 3.04975 0.019 3.8078\n\
C0 3.8345 0 3.846 0 3.8652\n\
C0 3.9101 0.022 3.94 0.056 3.94\n\
C0.071 3.94 0.079 3.93904 0.107 3.9231\n\
C1.3341 3.23572 2.6095 2.2656 2.6095 0.57604\n\
C2.6095 -0.4711 2.0006 -1.05061 1.1664 -1.05061\n\
C0.9058 -1.05561 0.7658 -1.05861 0.5568 -1.02591\n\
C0.4588 -1.01061 0.248 -0.97281 0.219 -0.92831\n\
C0.165 -0.89151 0.162 -0.77308 0.266 -0.78129"/>\n\
<text x="-5" y="-24" font-size="28px"></text>\n\
</g>\n\
<g id="cl3">\n\
<path transform="translate(-9,-12) scale(8)" d="m1.0406 -2.93878\n\
C0.9606 -2.93578 0.8881 -2.93178 0.8237 -2.92878\n\
L0.8237 -2.92846\n\
C0.6586 -2.92046 0.4659 -2.89806 0.3697 -2.87906\n\
C0.1409 -2.83386 0.0236 -2.78916 0 -2.75937\n\
C-0.018 -2.73927 -0.015 -2.71087 0 -2.69037\n\
C0.023 -2.64587 0.145 -2.67017 0.4188 -2.72887\n\
C0.5108 -2.74867 0.6924 -2.76597 0.8607 -2.77257\n\
C1.0868 -2.78157 1.2883 -2.70417 1.3194 -2.69167\n\
C1.7053 -2.53668 2.0444 -2.24033 2.0444 -1.46855\n\
C2.0444 -0.8488 1.8942 -0.04261 1.4629 -0.04261\n\
C1.4489 -0.04061 1.4419 -0.03861 1.4289 -0.02891\n\
C1.4149 -0.01311 1.4179 -0.00091 1.4169 0.01179\n\
C1.4169 0.01193 1.4169 0.01195 1.4169 0.01211\n\
C1.4169 0.01225 1.4169 0.01227 1.4169 0.01243\n\
C1.4169 0.02513 1.4169 0.03723 1.4289 0.05313\n\
C1.4389 0.06213 1.4479 0.06493 1.4629 0.06683\n\
C1.8942 0.06683 2.0444 0.87302 2.0444 1.49278\n\
C2.0444 2.26455 1.7053 2.56059 1.3194 2.71559\n\
C1.2884 2.72799 1.0868 2.80579 0.8607 2.79679\n\
C0.6924 2.78979 0.5113 2.77259 0.4188 2.75279\n\
C0.145 2.69409 0.0231 2.66979 0 2.71429\n\
C-0.011 2.73479 -0.014 2.76349 0 2.78359\n\
C0.024 2.81339 0.1409 2.85799 0.3697 2.90328\n\
C0.4657 2.92228 0.6586 2.94468 0.8237 2.95268\n\
L0.8237 2.953\n\
C0.9525 2.958 1.1126 2.9714 1.305 2.96\n\
C1.9479 2.916 2.5587 2.47655 2.5587 1.48844\n\
C2.5587 0.89409 2.1807 0.20184 1.7065 0.01218\n\
C2.1807 -0.17748 2.5587 -0.86972 2.5587 -1.46406\n\
C2.5587 -2.45218 1.9479 -2.89194 1.305 -2.93594\n\
C1.209 -2.94194 1.1207 -2.94094 1.0406 -2.93794"/>\n\
<text x="-5,-5" y="0,-24" font-size="28px"></text>\n\
</g>\n\
<g id="cl4">\n\
<path transform="translate(-9,3) scale(8)" d="m1.5506 -4.76844\n\
C1.5376 -4.76844 1.5066 -4.75114 1.5136 -4.73384\n\
L1.7544 -4.17292\n\
C1.8234 -3.97367 1.8444 -3.88334 1.8444 -3.66416\n\
C1.8444 -3.16204 1.5635 -2.76967 1.2174 -2.38312\n\
L1.0789 -2.2278\n\
C0.5727 -1.68982 0 -1.16441 0 -0.45906\n\
C0 -0.36713 -0.6414 1.05 1.4549 1.05\n\
C1.5319 1.05 1.6984 1.0492 1.8799 1.0372\n\
C2.0139 1.0282 2.1594 0.9969 2.2732 0.9744\n\
C2.3771 0.9538 2.5752 0.8757 2.5752 0.8757\n\
C2.7512 0.8152 2.6612 0.62915 2.5442 0.6835\n\
C2.5442 0.6835 2.3481 0.7626 2.2449 0.7822\n\
C2.1355 0.803 1.9939 0.8319 1.8645 0.8382\n\
C1.6935 0.8462 1.5257 0.8402 1.4569 0.8352\n\
C1.1541 0.8139 0.8667 0.67432 0.6558 0.48763\n\
C0.5148 0.36284 0.3782 0.17408 0.3582 -0.12709\n\
C0.3582 -0.76471 0.792 -1.23147 1.255 -1.71365\n\
L1.3978 -1.86523\n\
C1.8046 -2.29959 2.185 -2.75829 2.185 -3.32815\n\
C2.185 -3.77846 1.9185 -4.42204 1.6113 -4.75678\n\
C1.5983 -4.76858 1.5713 -4.77188 1.5513 -4.76828"/>\n\
<text x="-3" y="0" font-size="28px"></text>\n\
</g>\n\
<ellipse id="bk" class="fill" rx="2.9" ry="2.4"/>\n\
<ellipse id="wk" class="stroke" stroke-width="1" rx="2.5" ry="2"/>\n\
<path id="flt" class="stroke" stroke-width="1.5" d="m-2.5 -1l-7 -7"/>\n\
<path id="sht" class="stroke" stroke-width="1.5" d="m-2.5 1l-7 7"/>\n\
</defs>')
// change the pitches of all notes
// (pitch + accidental => offset)
for (v = 0; v < voice_tb.length; v++) {
p_v = voice_tb[v]
if (!p_v.clair)
continue
p_v.scale = 1.3;
for (s = p_v.sym; s; s = s.next) {
if (!s.dur)
continue
for (m = 0; m <= s.nhd; m++) {
mp = s.notes[m].midi
if (mp) {
mp -= 46;
s.notes[m].pit = mp
delete s.notes[m].acc
}
}
}
}
of()
},
// set a format parameter
set_fmt: function(of, cmd, param) {
if (cmd == "clairnote") {
this.set_v_param("clair", true);
this.set_v_param("stafflines", "|-|---|-|")
this.set_v_param("staffscale", .8)
return
}
of(cmd, param)
},
// set the pitches according to the clefs
set_pitch: function(of, last_s) {
if (last_s) {
of(last_s)
return // not the 1st time
}
var p_v, s, v,
voice_tb = this.get_voice_tb(),
staff_tb = this.get_staff_tb()
for (v = 0; v < voice_tb.length; v++) {
p_v = voice_tb[v]
if (!p_v.clair)
continue
abc2svg.clair.new_clef(staff_tb[p_v.st].clef)
for (s = p_v.sym; s; s = s.next) {
if (s.clef_type)
abc2svg.clair.new_clef(s)
}
}
of(last_s)
},
// set the clairnote flag in the current voice
set_vp: function(of, a) {
var i,
curvoice = this.get_curvoice()
for (i = 0; i < a.length; i++) {
if (a[i] == "clair=") {
curvoice.clair = a[i + 1]
break
}
}
of(a)
},
// set the width of the clairnote key signatures
set_width: function(of, s) {
if (s.k_sf && s.p_v && s.p_v.clair) {
s.wl = 8;
s.wr = 10
} else {
of(s)
}
},
set_hooks: function(abc) {
abc.draw_hl = abc2svg.clair.draw_hl.bind(abc, abc.draw_hl);
abc.draw_keysig = abc2svg.clair.draw_keysig.bind(abc, abc.draw_keysig);
abc.output_music = abc2svg.clair.output_music.bind(abc, abc.output_music);
abc.set_format = abc2svg.clair.set_fmt.bind(abc, abc.set_format);
abc.set_pitch = abc2svg.clair.set_pitch.bind(abc, abc.set_pitch);
abc.set_vp = abc2svg.clair.set_vp.bind(abc, abc.set_vp);
abc.set_width = abc2svg.clair.set_width.bind(abc, abc.set_width)
}
} // clair
abc2svg.modules.hooks.push(abc2svg.clair.set_hooks);
// the module is loaded
abc2svg.modules.clairnote.loaded = true
|
Changes to modules/combine.js.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// combine.js - module to add a combine chord line
//
// Copyright (C) 2018-2019 Jean-Francois Moine - GPL3+
//
// This module is loaded when "%%voicecombine" appears in a ABC source.
//
// Parameters
// %%voicecombine n 'n' is the combine level
abc2svg.combine = {
// function called at start of the generation when multi-voices
comb_v: function() {
| | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// combine.js - module to add a combine chord line
//
// Copyright (C) 2018-2019 Jean-Francois Moine - GPL3+
//
// This module is loaded when "%%voicecombine" appears in a ABC source.
//
// Parameters
// %%voicecombine n 'n' is the combine level
abc2svg.combine = {
// function called at start of the generation when multi-voices
comb_v: function() {
var C = abc2svg.C,
delsym = [] // deleted symbols for slurs and ties
// check if voice combine may occur
function may_combine(s) {
var nhd2,
s2 = s.ts_next
if (!s2 || (s2.type != C.NOTE && s2.type != C.REST))
|
| ︙ | ︙ | |||
34 35 36 37 38 39 40 |
if (s.a_gch && s2.a_gch)
return false
if (s.type == C.REST) {
if (s.type == s2.type && s.invis && !s2.invis)
return false
return true
}
| | < < > | > | | | | | | | | 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 |
if (s.a_gch && s2.a_gch)
return false
if (s.type == C.REST) {
if (s.type == s2.type && s.invis && !s2.invis)
return false
return true
}
if (s2.a_ly)
return false
if (s2.beam_st != s.beam_st
|| s2.beam_end != s.beam_end)
return false;
nhd2 = s2.nhd
if (s.combine <= 1
&& s.notes[0].pit <= s2.notes[nhd2].pit + 1)
return false
return true
} // may_combine()
// combine two notes
function combine_notes(s, s2) {
var nhd, type, m;
for (m = 0; m <= s2.nhd; m++) // change the container of the notes
s2.notes[m].s = s
Array.prototype.push.apply(s.notes, s2.notes);
s.nhd = nhd = s.notes.length - 1;
s.notes.sort(abc2svg.pitcmp) // sort the notes by pitch
if (s.combine >= 3) { // remove unison heads
for (m = nhd; m > 0; m--) {
if (s.notes[m].pit == s.notes[m - 1].pit
&& s.notes[m].acc == s.notes[m - 1].acc)
s.notes.splice(m, 1)
}
s.nhd = nhd = s.notes.length - 1
}
s.ymx = 3 * (s.notes[nhd].pit - 18) + 4;
s.ymn = 3 * (s.notes[0].pit - 18) - 4;
// force the tie directions
type = s.notes[0].tie_ty
if ((type & 0x07) == C.SL_AUTO)
s.notes[0].tie_ty = C.SL_BELOW | (type & C.SL_DOTTED);
type = s.notes[nhd].tie_ty
if ((type & 0x07) == C.SL_AUTO)
s.notes[nhd].tie_ty = C.SL_ABOVE | (type & C.SL_DOTTED)
} // combine_notes()
// combine 2 voices
function do_combine(s) {
var s2, nhd, nhd2, type
while (1) {
|
| ︙ | ︙ | |||
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
}
} else if (s.type == C.REST) {
if (s.invis
&& !s2.invis)
delete s.invis
} else {
combine_notes.call(this, s, s2)
}
if (s2.a_gch)
s.a_gch = s2.a_gch
if (s2.a_dd) {
if (!s.a_dd)
s.a_dd = s2.a_dd
else
| > > > > > > > > > > > > | > > | > > > > > > > > > > > > > > | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
}
} else if (s.type == C.REST) {
if (s.invis
&& !s2.invis)
delete s.invis
} else {
combine_notes.call(this, s, s2)
if (s2.tie_s)
s.tie_s = s2.tie_s
}
if (s2.sls) {
if (s.sls)
Array.prototype.push.apply(s.sls, s2.sls)
else
s.sls = s2.sls
}
if (s2.sl1)
s.sl1 = true
if (s2.a_gch)
s.a_gch = s2.a_gch
if (s2.a_dd) {
if (!s.a_dd)
s.a_dd = s2.a_dd
else
Array.prototype.push.apply(s.a_dd, s2.a_dd)
}
// memorize the deleted symbol: it may support slur or tie endings
delsym.push({s: s2, r: s});
this.unlksym(s2) // remove the next symbol
// there may be more voices
if (s.in_tuplet || !may_combine.call(this, s))
break
}
} // do_combine()
// replace tie endings
function tie_repl(s) {
var s1 = s.tie_s,
i = delsym.length
while (--i >= 0) {
if (delsym[i].s == s1) {
s.tie_s = delsym[i].r
break
}
}
} // tie_repl()
// code of comb_v()
var s, s2, g, i, r
for (s = this.get_tsfirst(); s; s = s.ts_next) {
switch (s.type) {
case C.REST:
if (s.combine == undefined || s.combine < 0)
continue
|
| ︙ | ︙ | |||
166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
if (s2.beam_end)
break
do {
s2 = s2.next
} while (s2.type != C.NOTE && s2.type != C.REST)
}
}
}, // comb_v()
do_pscom: function(of, text) {
if (text.slice(0, 13) == "voicecombine ")
this.set_v_param("combine", text.split(/[ \t]/)[1])
else
of(text)
| > > > > > > | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
if (s2.beam_end)
break
do {
s2 = s2.next
} while (s2.type != C.NOTE && s2.type != C.REST)
}
}
// replace the tie endings
for (s = this.get_tsfirst(); s; s = s.ts_next) {
if (s.tie_s)
tie_repl(s)
}
}, // comb_v()
do_pscom: function(of, text) {
if (text.slice(0, 13) == "voicecombine ")
this.set_v_param("combine", text.split(/[ \t]/)[1])
else
of(text)
|
| ︙ | ︙ |
Changes to modules/diag.js.
| ︙ | ︙ | |||
478 479 480 481 482 483 484 |
output_music: function(of) {
if (this.cfmt().diag)
abc2svg.diag.do_diag.call(this)
of()
},
| | | | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 |
output_music: function(of) {
if (this.cfmt().diag)
abc2svg.diag.do_diag.call(this)
of()
},
set_fmt: function(of, cmd, param) {
if (cmd == "diagram") {
this.cfmt().diag = param
return
}
of(cmd, param)
},
set_hooks: function(abc) {
abc.output_music = abc2svg.diag.output_music.bind(abc, abc.output_music);
abc.set_format = abc2svg.diag.set_fmt.bind(abc, abc.set_format)
}
} // diag
|
| ︙ | ︙ |
Changes to modules/equalbars.js.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 |
// new tune - clear the width of the start of the staff
output_music: function(of) {
this.equalbars_d = 0;
of()
},
// get the equalbars parameter
| | | | < < | 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 |
// new tune - clear the width of the start of the staff
output_music: function(of) {
this.equalbars_d = 0;
of()
},
// get the equalbars parameter
set_fmt: function(of, cmd, param) {
if (cmd == "equalbars")
this.cfmt().equalbars = this.get_bool(param)
else
of(cmd, param)
},
// adjust the symbol offsets of a music line
set_sym_glue: function(of, width) {
var C = abc2svg.C,
s, s2, w, i, n, x, g, t, t0,
bars = [],
tsfirst = this.get_tsfirst();
of(width) // compute the x offset of the symbols
if (!this.cfmt().equalbars)
return
// search the first note/rest/space
for (s2 = tsfirst; s2; s2 = s2.ts_next) {
switch (s2.type) {
default:
continue
case C.GRACE:
case C.MREST:
case C.NOTE:
case C.REST:
|
| ︙ | ︙ | |||
57 58 59 60 61 62 63 |
t0 = t = s2.time
for (s = s2; s.ts_next; s = s.ts_next) {
if (s.type == C.BAR && s.seqst) {
bars.push([s, s.time - t]);
t = s.time
}
}
| > > > | > > > | < | > | 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 |
t0 = t = s2.time
for (s = s2; s.ts_next; s = s.ts_next) {
if (s.type == C.BAR && s.seqst) {
bars.push([s, s.time - t]);
t = s.time
}
}
// push the last bar if it is not the invisible bar after a key change
if (!s.invis || s.prev.type != C.KEY)
bars.push([s, s.time - t])
else
bars[bars.length - 1][0] = s // replace the last bar
width = s.x
t = s.time
if (s.dur)
t += s.dur;
n = bars.length
if (n <= 1)
return // one or no bar
// set the measure parameters
x = s2.type == C.GRACE ? s2.extra.x : s2.x;
if (this.equalbars_d < x)
this.equalbars_d = x // new offset of the first note/rest
d = this.equalbars_d
w = (width - d) / (t - t0) // width per time unit
// loop on the bars
for (i = 0; i < n; i++) {
s = bars[i][0]; // next bar
f = w * bars[i][1] / (s.x - x)
|
| ︙ | ︙ |
Changes to modules/grid.js.
1 2 3 4 5 6 7 | // grid.js - module to insert a chord grid before or after a tune // // Copyright (C) 2018-2019 Jean-Francois Moine - GPL3+ // // This module is loaded when "%%grid" appears in a ABC source. // // Parameters | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// grid.js - module to insert a chord grid before or after a tune
//
// Copyright (C) 2018-2019 Jean-Francois Moine - GPL3+
//
// This module is loaded when "%%grid" appears in a ABC source.
//
// Parameters
// %%grid <n> [include=<list>] [nomusic] [norepeat] [repbrk]
// <n> = number of columns (1: auto)
// > 0: above the tune, < 0: under the tune
// <list> = comma separated list of (continuous) measure numbers
// 'nomusic' displays only the grid
// 'norepeat' omits the ':' indications
// 'repbrk' starts a new grid line on start/stop repeat
// %%gridfont font_name size (default: 'serif 16')
abc2svg.grid = {
// function called before tune generation
do_grid: function() {
var C = abc2svg.C,
|
| ︙ | ︙ | |||
34 35 36 37 38 39 40 |
&& s.a_meter[0].top[0] % 3 == 0)
beat = C.BLEN / 8 * 3
return beat
} // get_beat()
// generate the grid
function build_grid(chords, bars, font, wmx) {
| | | < | > > | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
&& s.a_meter[0].top[0] % 3 == 0)
beat = C.BLEN / 8 * 3
return beat
} // get_beat()
// generate the grid
function build_grid(chords, bars, font, wmx) {
var i, k, l, nr, line, bar, w, hr, x0, x, y, yl,
lc = '',
cells = [],
nc = grid.n,
sf = '" style="font-size:' + (font.size * .72).toFixed(1)
// small font
// set some chord(s) in each cell
function set_chords() {
var i, ch,
pch = '-'
for (i = 0; i < chords.length; i++) {
|
| ︙ | ︙ | |||
70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
continue
}
if (!ch[2])
ch[2] = ch[1] || ch[0];
pch = ch[3]
}
} // set_chords()
// set some chords in each cell
set_chords()
// build the content of the cells
if (!grid.ls) {
cells = chords
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
continue
}
if (!ch[2])
ch[2] = ch[1] || ch[0];
pch = ch[3]
}
} // set_chords()
function build_cell(cell, x, y, yl, hr) {
var line = ''
if (cell.length > 1) {
line += '<path class="stroke" stroke-width="1" d="M' +
(x - wmx / 2).toFixed(1) + ' ' +
yl.toFixed(1) + 'l' +
wmx.toFixed(1) + ' -' + hr.toFixed(1) +
'"/>\n'
if (cell[1]) {
line += '<path class="stroke" stroke-width="1" d="M' +
(x - wmx / 2).toFixed(1) + ' ' +
(yl - hr).toFixed(1) + 'l' +
(wmx / 2).toFixed(1) + ' ' + (hr / 2).toFixed(1) +
'"/>\n'
line += '<text class="' + cls + sf + '" x="' +
(x - wmx / 3).toFixed(1) + '" y="' +
y.toFixed(1) + '">' +
cell[0] + '</text>\n'
line += '<text class="' + cls + sf + '" x="' +
x.toFixed(1) + '" y="' +
(y - hr / 3).toFixed(1) + '">' +
cell[1] + '</text>\n'
} else {
line += '<text class="' + cls + sf + '" x="' +
(x - wmx * .2).toFixed(1) + '" y="' +
(y - hr / 4).toFixed(1) + '">' +
cell[0] + '</text>\n'
}
if (cell.length >= 3) {
if (cell[3]) {
line += '<path class="stroke" stroke-width="1" d="M' +
x.toFixed(1) + ' ' +
(yl - hr / 2).toFixed(1) + 'l' +
(wmx / 2).toFixed(1) + ' ' + (hr / 2).toFixed(1) +
'"/>\n'
line += '<text class="' + cls + sf + '" x="' +
x.toFixed(1) + '" y="' +
(y + hr / 3).toFixed(1) + '">' +
cell[2] + '</text>\n'
line += '<text class="' + cls + sf + '" x="' +
(x + wmx / 3).toFixed(1) + '" y="' +
y.toFixed(1) + '">' +
cell[3] + '</text>\n'
} else {
line += '<text class="' + cls + sf + '" x="' +
(x + wmx * .2).toFixed(1) + '" y="' +
(y + hr / 4).toFixed(1) + '">' +
cell[2] + '</text>\n'
}
}
} else {
line += '<text class="' + cls + '" x="' +
x.toFixed(1) + '" y="' + y.toFixed(1) + '">' +
cell[0] + '</text>\n'
}
return line
} // build_cell()
// build_grid()
// set some chords in each cell
set_chords()
// build the content of the cells
if (!grid.ls) {
cells = chords
|
| ︙ | ︙ | |||
95 96 97 98 99 100 101 | break cells.push(chords[k]); bars.push(bar[k]) } } } | | < < > > > > > > > > > > > > > > > > > > > > > < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | > > > > > | | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
break
cells.push(chords[k]);
bars.push(bar[k])
}
}
}
// get the number of columns
if (nc < 0)
nc = -nc
if (nc < 3) // auto
nc = cells.length % 6 == 0 ? 6 : 8
if (nc > cells.length)
nc = cells.length;
hr = font.size * 2
if (wmx < hr * 1.4)
wmx = hr * 1.4; // cell width
w = wmx * nc
if (w > img.width) {
nc /= 2;
w /= 2
}
// generate the cells
yl = 1
y = 1 - hr / 2 + font.size * .3
nr = 0
x0 = (img.width - w) / 2
for (i = 0; i < cells.length; i++) {
if (i == 0
|| (grid.repbrk
&& (bars[i].slice(-1) == ':' || bars[i][0] == ':'))
|| k >= nc) {
y += hr // new row
yl += hr
x = x0 + wmx / 2
k = 0
nr++
}
k++
lc += build_cell(cells[i], x, y, yl, hr)
x += wmx
}
// build the SVG image
line = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
color="black" width="' + img.width.toFixed(0) +
'px" height="' + (hr * nr + 6).toFixed(0) + 'px"';
i = cfmt.bgcolor
if (i)
line += ' style="background-color: ' + i + '"';
line += '>\n<style type="text/css">\n\
.mid {text-anchor:middle}\n'
if (cfmt.fullsvg || grid.nomusic)
line += '\
.stroke {stroke: currentColor; fill: none}\n\
.' + font_cl + ' {' + this.style_font(font) + '}\n';
line += '</style>\n'
// draw the lines
line += '<path class="stroke" d="\n';
y = 1
for (i = 0; i <= nr; i++) {
line += 'M' + x0.toFixed(1) + ' ' + y.toFixed(1) +
'h' + w.toFixed(1)+ '\n';
y += hr
}
x = x0
for (i = 0; i <= nc; i++) {
line += 'M' + x.toFixed(1) + ' 1v' + (hr * nr).toFixed(1) + '\n';
x += wmx
}
line += '"/>\n';
// insert the cells
line += lc
// show the repeat signs
y = 1 - hr / 2 + font.size * .3;
x = x0
for (i = 0; i < bars.length; i++) {
bar = bars[i]
if (bar[0] == ':')
line += '<text class="' + cls + '" x="' +
(x - 5).toFixed(1) +
'" y="' + y.toFixed(1) +
'" style="font-weight:bold;font-size:' +
(font.size + 2).toFixed(1) + '">:</text>\n'
if (i == 0
|| (grid.repbrk
&& (bars[i].slice(-1) == ':' || bars[i][0] == ':'))
|| k >= nc) {
y += hr; // new row
x = x0
k = 0
}
k++
if (bar.slice(-1) == ':')
line += '<text class="' + cls + '" x="' +
(x + 5).toFixed(1) +
'" y="' + y.toFixed(1) +
'" style="font-weight:bold;font-size:' +
(font.size + 2).toFixed(1) + '">:</text>\n'
x += wmx
}
|
| ︙ | ︙ | |||
269 270 271 272 273 274 275 |
font_cl = this.font_class(font)
cls = font_cl + " mid";
this.set_font('grid'); // (for strwh())
// scan the first voice of the tune
cur_beat = beat_i = n = wmx = 0;
bars.push('|')
| | | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
font_cl = this.font_class(font)
cls = font_cl + " mid";
this.set_font('grid'); // (for strwh())
// scan the first voice of the tune
cur_beat = beat_i = n = wmx = 0;
bars.push('|')
for (s = tsfirst; s; s = s.ts_next) {
while (s.time > cur_beat) {
if (beat_i < 3) // only 2, 3 or 4 beats / measure...
beat_i++;
cur_beat += beat
}
switch (s.type) {
case C.NOTE:
|
| ︙ | ︙ | |||
311 312 313 314 315 316 317 | break chords.push(chord); bars.push(bt) } chord = []; cur_beat = s.time; // synchronize in case of error beat_i = 0 | | > > | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
break
chords.push(chord);
bars.push(bt)
}
chord = [];
cur_beat = s.time; // synchronize in case of error
beat_i = 0
if (bt.indexOf(':') >= 0)
rep = true // some repeat
while (s.ts_next && s.ts_next.type == C.BAR)
s = s.ts_next
break
case C.METER:
beat = get_beat(s)
wm = s.wmeasure
break
}
}
|
| ︙ | ︙ | |||
338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
s = {
type: C.BLOCK,
subtype: 'ml',
dur: 0,
time: 0,
p_v: p_voice,
v: p_voice.v,
text: build_grid.call(this, chords, bars, font, wmx)
}
if (grid.nomusic) { // if no music
this.set_tsfirst(s)
return
}
| > | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
s = {
type: C.BLOCK,
subtype: 'ml',
dur: 0,
time: 0,
p_v: p_voice,
v: p_voice.v,
st: p_voice.st,
text: build_grid.call(this, chords, bars, font, wmx)
}
if (grid.nomusic) { // if no music
this.set_tsfirst(s)
return
}
|
| ︙ | ︙ | |||
372 373 374 375 376 377 378 |
output_music: function(of) {
if (this.cfmt().grid)
abc2svg.grid.do_grid.call(this);
of()
},
| | > > | | 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
output_music: function(of) {
if (this.cfmt().grid)
abc2svg.grid.do_grid.call(this);
of()
},
set_fmt: function(of, cmd, parm) {
if (cmd == "grid") {
if (!parm)
parm = "1";
parm = parm.split(/\s+/)
var grid = {n: Number(parm.shift())}
if (isNaN(grid.n)) {
if (parm.length) {
this.syntax(1, this.errs.bad_val, "%%grid")
return
}
grid.n = 1
}
while (parm.length) {
var item = parm.shift()
if (item == "norepeat")
grid.norep = true
else if (item == "nomusic")
grid.nomusic = true
else if (item == "repbrk")
grid.repbrk = true
else if (item.slice(0, 8) == "include=")
grid.ls = item.slice(8).split(',')
}
this.cfmt().grid = grid
return
}
of(cmd, parm)
},
set_hooks: function(abc) {
abc.output_music = abc2svg.grid.output_music.bind(abc, abc.output_music);
abc.set_format = abc2svg.grid.set_fmt.bind(abc, abc.set_format)
}
} // grid
abc2svg.modules.hooks.push(abc2svg.grid.set_hooks);
// the module is loaded
abc2svg.modules.grid.loaded = true
|
Changes to modules/grid2.js.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 |
// %%grid2 y
// This command must appear in a voice.
abc2svg.grid2 = {
// function called before tune generation
do_grid: function() {
| | > > > > > > > | | > > > > | > > > > > > > | 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 |
// %%grid2 y
// This command must appear in a voice.
abc2svg.grid2 = {
// function called before tune generation
do_grid: function() {
var s, v, p_v, ix, cs, c_a_cs, bt,
voice_tb = this.get_voice_tb()
for (v = 0; v < voice_tb.length; v++) {
p_v = voice_tb[v]
if (!p_v.grid2)
continue
p_v.clef.invis = true; // no clef
p_v.key.k_sf = p_v.key.k_a_acc = 0; // no key signature
p_v.staffnonote = 2 // draw the staff
for (s = p_v.sym; s; s = s.next) {
delete s.a_dd // no decoration
if (!s.dur) {
if (s.bar_type)
bt = s.time
continue
}
// set all notes
s.invis = true; // as invisible
delete s.sl1; // with no slur
delete s.tie_s // and no tie
if (s.tf) // don't show the tuplets
s.tf[0] = 1
if (!s.a_gch) {
if (s.time == bt)
s.a_gch = c_a_cs
continue
}
for (ix = 0; ix < s.a_gch.length; ix++) {
gch = s.a_gch[ix]
if (gch.type == 'g') {
c_a_cs = s.a_gch
break
}
}
}
}
}, // do_grid()
// draw the chord symbol in the middle of the staff
draw_chosym: function(s) {
var ix, gch;
|
| ︙ | ︙ | |||
57 58 59 60 61 62 63 |
},
output_music: function(of) {
abc2svg.grid2.do_grid.call(this);
of()
},
| | | | 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 |
},
output_music: function(of) {
abc2svg.grid2.do_grid.call(this);
of()
},
set_fmt: function(of, cmd, param) {
if (cmd == "grid2") {
var curvoice = this.get_curvoice()
if (curvoice) {
this.set_v_param("stafflines", "..."); // no staff lines
curvoice.grid2 = param
}
return
}
of(cmd, param)
},
set_hooks: function(abc) {
abc.draw_gchord = abc2svg.grid2.draw_gchord.bind(abc, abc.draw_gchord);
abc.output_music = abc2svg.grid2.output_music.bind(abc, abc.output_music);
abc.set_format = abc2svg.grid2.set_fmt.bind(abc, abc.set_format)
}
} // grid2
abc2svg.modules.hooks.push(abc2svg.grid2.set_hooks);
// the module is loaded
abc2svg.modules.grid2.loaded = true
|
Changes to modules/page.js.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 |
page.img_out_sav = user.img_out // keep our reference
} else {
user.img_out = cur_img_out // .. by an other extension
}
}
},
| | | | < | < | < < < < < < < < < < | < | | | > > > > > | | > > > > > > > > > > > > > > > > > > > | > > > > | | | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
page.img_out_sav = user.img_out // keep our reference
} else {
user.img_out = cur_img_out // .. by an other extension
}
}
},
// function called at end of generation
abc_end: function(of) {
var page = this.page
if (page && page.in_page) {
abc2svg.page.close_page(page)
if (user.img_out == page.img_out_sav)
user.img_out = page.user_out
}
of()
}, // abc_end()
// generate a header or a footer in page.hf and return its height
gen_hf: function(page, up, font, str) {
var a, i, j, k, x, y, y0, s,
cfmt = page.abc.cfmt(),
fh = font.size * 1.1,
pos = [ '">',
'" text-anchor="middle">',
'" text-anchor="end">' ]
// create the text of a header or a footer
function header_footer(o_font, str) {
var c, i, k, t, n_font,
c_font = o_font,
nl = 1,
j = 0,
r = ["", "", ""]
if (str[0] == '"')
str = str.slice(1, -1)
if (str.indexOf('\t') < 0) // if no TAB
str = '\t' + str // center
for (i = 0; i < str.length; i++) {
c = str[i]
switch (c) {
case '>':
r[j] += ">"
continue
case '<':
r[j] += "<"
continue
case '&':
for (k = i + 1; k < i + 8; k++) {
if (!str[k] || str[k] == '&'
|| str[k] == ';')
break
}
r[j] += str[k] == ';' ? "&" : "&"
continue
case '\t':
if (j < 2)
j++ // next column
continue
case '\\': // hope '\n'
if (c_font != o_font) {
r[j] += "</tspan>"
// c_font = o_font
}
for (j = 0; j < 3; j++)
r[j] += '\n';
nl++;
j = 0;
i++
continue
default:
r[j] += c
continue
case '$':
break
}
c = str[++i]
switch (c) {
case 'd':
if (!abc2svg.get_mtime)
break // cannot know the change time of the file
r[j] += strftime(cfmt.dateformat,
abc2svg.get_mtime(page.abc.parse.fname))
break
case 'D':
r[j] += strftime(cfmt.dateformat)
break
case 'F':
r[j] += page.abc.parse.fname
break
case 'I':
c = str[++i]
case 'T':
t = abc.info()[c]
if (t)
r[j] += t.split('\n', 1)[0]
|
| ︙ | ︙ | |||
122 123 124 125 126 127 128 | r[j] += t break } break case 'V': r[j] += "abc2svg-" + abc2svg.version break | > > > > > > > > | > > > > > > > > > > > > > | < < < < < < | | | | | | < | < < | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | < | | > > > > > > > > | > > | > > > > > > > | > > > < | < < < > | > > > > > > > > > | > > > > > > > | > | > | > | > > > > > > > > > > > > > > > > > > > | | | | | | | | | < < < < < < | | < < < < < < < < < < < < < < < < < < < < | | < < < < < < < < | | | < < < < < < < < | | < < | > > > > > | < | | | < < < < < < > | < < | | | < | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
r[j] += t
break
}
break
case 'V':
r[j] += "abc2svg-" + abc2svg.version
break
default:
if (c == '0')
n_font = o_font
else if (c >= '1' && c < '9')
n_font = page.abc.get_font("u" + c)
else
break
// handle the font changes
if (n_font == c_font)
break
if (c_font != o_font)
r[j] += "</tspan>";
c_font = n_font
if (c_font == o_font)
break
r[j] += '<tspan class="' +
font_class(n_font) + '">'
break
}
}
if (c_font != o_font)
r[j] += "</tspan>";
r[4] = nl // number of lines
return r
} // header_footer()
function font_class(font) {
if (font.class)
return 'f' + font.fid + cfmt.fullsvg + ' ' + font.class
return 'f' + font.fid + cfmt.fullsvg
}
// gen_hf
if (str[0] == '-') { // not on 1st page
if (page.pn == 1)
return 0
str = str.slice(1)
}
a = header_footer(font, str)
y0 = font.size * .8
for (i = 0; i < 3; i++) {
str = a[i]
if (!str)
continue
if (i == 0)
x = cfmt.leftmargin
else if (i == 1)
x = cfmt.pagewidth / 2
else
x = cfmt.pagewidth - cfmt.rightmargin
y = y0
k = 0
while (1) {
j = str.indexOf('\n', k)
if (j >= 0)
s = str.slice(k, j)
else
s = str.slice(k)
if (s)
page.hf += '<text class="' +
font_class(font) +
'" x="' + x.toFixed(1) +
'" y="' + y.toFixed(1) +
pos[i] +
s + '</text>\n'
if (j < 0)
break
k = j + 1
y += fh
}
}
return fh * a[4]
}, // gen_hf()
// start a new page
open_page: function(page,
ht) { // spacing under the header
var h, o_font,
// font_style,
abc = page.abc,
cfmt = abc.cfmt(),
sty = ""
page.pn++
page.pna++
// start a new page
if (page.first)
page.first = false
else
sty = "page-break-before:always"
if (page.gutter)
sty += (sty ? ";" : "") + "margin-left:" +
((page.pn & 1) ? page.gutter : -page.gutter).toFixed(1) + "px"
abc2svg.page.img_out(page, sty ?
'<div style="' + sty + '">' :
'<div>')
page.in_page = true
page.hmax = cfmt.pageheight - page.topmargin - page.botmargin - ht
// define the header/footer
page.hf = ''
if (page.header) {
h = abc2svg.page.gen_hf(page, true,
abc.get_font("header"), page.header)
abc2svg.page.img_out(page,
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
width="' + cfmt.pagewidth.toFixed(0) +
'px" height="' + (page.topmargin + ht + h).toFixed(0) +
'px">\n' +
'<g transform="translate(0,' +
page.topmargin.toFixed(1) + ')">' +
page.hf + '</g>\n</svg>')
page.hmax -= h;
page.hf = ''
} else {
abc2svg.page.img_out(page,
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
width="' + cfmt.pagewidth.toFixed(0) +
'px" height="' + ht.toFixed(0) +
'px">\n</svg>')
}
if (page.footer) {
page.fh = abc2svg.page.gen_hf(page, false,
abc.get_font("footer"), page.footer)
page.hmax -= page.fh
}
page.h = 0
}, // open_page()
close_page: function(page) {
var h,
cfmt = page.abc.cfmt()
page.in_page = false
if (page.footer) {
h = page.hmax + page.fh - page.h
abc2svg.page.img_out(page,
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1"\n\
xmlns:xlink="http://www.w3.org/1999/xlink"\n\
width="' + cfmt.pagewidth.toFixed(0) +
'px" height="' + h.toFixed(0) +
'px">\n<g transform="translate(0,' +
(h - page.fh).toFixed(1) + ')">' +
page.hf + '</g>\n</svg>')
}
abc2svg.page.img_out(page, '</div>')
page.h = 0
}, // close_page()
// handle the output flow of the abc2svg generator
img_in: function(p) {
var h, ht,
page = this.page
// copy a block
function blkcpy(page) {
var b
if (!page.blk.length) {
page.blk = null
return
}
page.h = page.hb
while (page.blk.length) {
b = page.blk.shift()
abc2svg.page.img_out(page, b.p)
page.h += b.h
}
page.blk = null // direct output
} // blkcpy()
// img_in()
switch (p.slice(0, 4)) {
case "<div": // new block (tune / paragraph)
if (p.indexOf('newpage') > 0
|| (page.oneperpage && this.info().X)
|| !page.h) // empty page
abc2svg.page.open_page(page, 0)
page.blk = [] // in block
page.hb = page.h // keep the offset of the start of tune
break
case "<svg": // SVG image
h = Number(p.match(/height="(\d+)px"/)[1])
if (h + page.h >= page.hmax) { // if page overflow
if (page.blk) // if inside a block
blkcpy(page) // output the beginning of the tune
ht = page.blk ? 0 :
this.cfmt().topspace // tune continuation
// if (page.in_page)
abc2svg.page.close_page(page)
abc2svg.page.open_page(page, ht)
}
// if no overflow yet, keep the block
if (page.blk)
page.blk.push({p: p, h: h})
else
abc2svg.page.img_out(page, p)
page.h += h
break
case "</di": // end of block
if (page.blk)
blkcpy(page)
break
// default:
////fixme: %%beginml cannot be treated (no information about its height)
// break
}
}, // img_in()
// handle the page related parameters
set_fmt: function(of, cmd, parm) {
var v,
cfmt = this.cfmt(),
page = this.page
if (cmd == "pageheight") {
v = this.get_unit(parm)
if (isNaN(v)) {
this.syntax(1, errs.bad_val, '%%' + cmd)
return
}
cfmt.pageheight = v
// if first definition, install the hook
if (!page && user.img_out && abc2svg.abc_end) {
this.page = page = {
abc: this,
topmargin: 38, // 1cm
botmargin: 38, // 1cm
// gutter: 0,
h: 0, // current page height
pn: 0, // page number
pna: 0, // absolute page number
first: true, // no skip to next page
user_out: user.img_out
}
// don't let the backend handle the header/footer
if (cfmt.header) {
page.header = cfmt.header;
cfmt.header = null
|
| ︙ | ︙ | |||
377 378 379 380 381 382 383 |
v = this.get_unit(cfmt.topmargin)
if (!isNaN(v))
page.topmargin = v
}
if (cfmt.gutter) {
v = this.get_unit(cfmt.gutter)
if (!isNaN(v))
| | > > | 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 |
v = this.get_unit(cfmt.topmargin)
if (!isNaN(v))
page.topmargin = v
}
if (cfmt.gutter) {
v = this.get_unit(cfmt.gutter)
if (!isNaN(v))
page.gutter = v
}
if (cfmt.oneperpage)
page.oneperpage = this.get_bool(cfmt.oneperpage)
if (!cfmt.dateformat)
cfmt.dateformat = "%b %e, %Y %H:%M"
// set the hooks
user.img_out = abc2svg.page.img_in.bind(this);
page.img_out_sav = user.img_out;
abc2svg.abc_end = abc2svg.page.abc_end.bind(this,
abc2svg.abc_end)
}
|
| ︙ | ︙ | |||
415 416 417 418 419 420 421 |
case "topmargin":
v = this.get_unit(parm)
if (isNaN(v)) {
this.syntax(1, errs.bad_val, '%%' + cmd)
return
}
page[cmd] = v
| < < | < < < < < < < < | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 |
case "topmargin":
v = this.get_unit(parm)
if (isNaN(v)) {
this.syntax(1, errs.bad_val, '%%' + cmd)
return
}
page[cmd] = v
return
case "oneperpage":
page[cmd] = this.get_bool(parm)
return
}
}
of(cmd, parm)
}, // set_fmt()
set_hooks: function(abc) {
abc.set_format = abc2svg.page.set_fmt.bind(abc, abc.set_format)
}
} // page
abc2svg.modules.hooks.push(abc2svg.page.set_hooks);
// the module is loaded
abc2svg.modules.pageheight.loaded = true
|
Changes to modules/perc.js.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// perc.js - module to handle %%percmap
//
// Copyright (C) 2018-2019 Jean-Francois Moine - GPL3+
//
// This module is loaded when "%%percmap" appears in a ABC source.
//
// Parameters (from W. Vree)
// %%percmap ABC_note percussion [note_head]
// The percussion may be a number (MIDI percussion number range 35..81),
// a ABC note or a possibly abbreviated percussion name.
// See https://wim.vree.org/js2/tabDrumDoc.html for more information.
abc2svg.perc = {
// parse %%percmap
do_perc: function(parm) {
var pits = new Int8Array([0, 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6]),
| > > | | 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 |
// perc.js - module to handle %%percmap
//
// Copyright (C) 2018-2019 Jean-Francois Moine - GPL3+
//
// This module is loaded when "%%percmap" appears in a ABC source.
//
// Parameters (from W. Vree)
// %%percmap ABC_note percussion [note_head]
// The percussion may be a number (MIDI percussion number range 35..81),
// a ABC note or a possibly abbreviated percussion name.
// See https://wim.vree.org/js2/tabDrumDoc.html for more information.
// Using this command creates a voicemap named "MIDIdrum".
abc2svg.perc = {
// parse %%percmap
do_perc: function(parm) {
var pits = new Int8Array([0, 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6]),
accs = new Int8Array([3, 1, 3, -1, 3, 3, 1, 3, -1, 3, -1, 3])
// GM drum
// 35 B,,, Acoustic Bass Drum a-b-d
// 36 C,, Bass Drum 1 b-d-1
// 37 ^C,, Side Stick s-s
// 38 D,, Acoustic Snare a-s
// 39 ^D,, Hand Clap h-c
|
| ︙ | ︙ | |||
113 114 115 116 117 118 119 | "s-g": 73, "s-s": 37, "s-w": 71, "t": 54, "v": 58 } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | < < < < < < < < < < < < < < < < | | < | | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
"s-g": 73,
"s-s": 37,
"s-w": 71,
"t": 54,
"v": 58
}
// convert a ABC note to b40
function abc_b40(p) {
var pit,
acc = 0,
i = 0
switch (p[0]) {
case '^':
if (p[++i] == '^') {
acc = 2
i++
} else {
acc = 1
}
break
case '=':
i++
break
case '_':
if (p[++i] == '_') {
acc = -2
i++
} else {
acc = -1
}
break
}
pit = 'CDEFGABcdefgab'.indexOf(p[i++]) + 16
if (pit < 16)
return
while (p[i] == "'") {
pit += 7
i++
}
while (p[i] == ",") {
pit -= 7
i++
}
if (p[i]) // if some extra character
return
return abc2svg.pab40(pit, acc)
} // abc_b40()
// convert a MIDI pitch to b40
function mid_b40(pit) {
var o = (pit / 12) | 0 // octave
pit = pit % 12; // in octave
return o * 40 + abc2svg.isb40[pit] + 2
} // mid_b40()
// convert a drum instrument to b40
function tob40(p) {
var i, j, s,
pit = Number(p)
if (isNaN(pit)) { // not a MIDI pitch
s = abc_b40(p) // try a ABC note
if (s)
return s
// try a drum instrument name
p = p.toLowerCase(p);
s = p[0]; // get the 1st letters after '-'
i = 0
while (1) {
j = p.indexOf('-', i)
if (j < 0)
break
|
| ︙ | ︙ | |||
176 177 178 179 180 181 182 | case 'i': case 'o': pit = prn[s + p[1]] break } break } | < < | | | < < < < < < < | | < < < < < < < < < < < < < < | | | > < | | | | > | | | | | | < > > > > > | > | < | < < < > | | | > | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
case 'i':
case 'o':
pit = prn[s + p[1]]
break
}
break
}
if (!pit)
return
}
}
return mid_b40(pit)
} // tob40()
// do_perc()
var vpr, vpl,
maps = this.get_maps(),
a = parm.split(/\s+/),
n = abc_b40(a[1]) // note as b40
if (!n) {
this.syntax(1, this.errs.bad_val, "%%percmap")
return
}
vpr = { // print
pit: abc2svg.b40p(n),
acc: 0
}
vpl = tob40(a[2]) // play
if (!vpl) {
this.syntax(1, this.errs.bad_val, "%%percmap")
return
}
a = a[3] ? [a[3]] : null // head
if (!maps.MIDIdrum)
maps.MIDIdrum = {}
n = n.toString()
if (!maps.MIDIdrum[n]) {
maps.MIDIdrum[n] =
[a, vpr, null, vpl] // [heads, print, color, play]
} else {
if (a)
maps.MIDIdrum[n][0] = a
if (!maps.MIDIdrum[n][1])
maps.MIDIdrum[n][1] = vpr
maps.MIDIdrum[n][3] = vpl
}
this.set_v_param("perc", "MIDIdrum")
}, // do_perc()
// set the MIDI parameters in the current voice
set_perc: function(a) {
var i, item,
curvoice = this.get_curvoice()
for (i = 0; i < a.length; i++) {
switch (a[i]) {
case "perc=": // %%percmap
if (!curvoice.map)
curvoice.map = {}
curvoice.map = a[i + 1];
if (!curvoice.midictl)
curvoice.midictl = []
curvoice.midictl[0] = 1 // bank 128
break
}
}
}, // set_perc()
do_pscom: function(of, text) {
|
| ︙ | ︙ |
Changes to modules/psvg.js.
| ︙ | ︙ | |||
543 544 545 546 547 548 549 |
svgbuf = ''
}
Psvg.prototype.ps_flush = ps_flush
// evaluate a PS user sequence (%beginps .. %%endps)
Psvg.prototype.ps_eval = function(txt) {
wps.parse(txt);
| | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 |
svgbuf = ''
}
Psvg.prototype.ps_flush = ps_flush
// evaluate a PS user sequence (%beginps .. %%endps)
Psvg.prototype.ps_eval = function(txt) {
wps.parse(txt);
ps_flush(true)
}
// ------ output builtin decorations
// common part
function pscall(f, x, y, script) {
gcur.xorig = gcur.xoffs = abcobj.sx(0);
gcur.yorig = gcur.yoffs = abcobj.sy(0);
|
| ︙ | ︙ |
Changes to modules/soloffs.js.
1 2 3 4 5 6 7 8 9 10 11 |
// soloffs.js - module to set the X offset of some elements at start of music line
//
// Copyright (C) 2018-2019 Jean-Francois Moine - GPL3+
//
// Parameters
// %%soloffs <type>=<offset> [<type>=<offset>]*
// <type> is one of 'part', 'tempo' or 'space'
// <offset> is the X offset from the start of staff
abc2svg.soloffs = {
| | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// soloffs.js - module to set the X offset of some elements at start of music line
//
// Copyright (C) 2018-2019 Jean-Francois Moine - GPL3+
//
// Parameters
// %%soloffs <type>=<offset> [<type>=<offset>]*
// <type> is one of 'part', 'tempo' or 'space'
// <offset> is the X offset from the start of staff
abc2svg.soloffs = {
set_fmt: function(of, cmd, parm) {
if (cmd == "soloffs") {
var i, v,
C = abc2svg.C,
soloffs = this.cfmt().soloffs = {}
parm = parm.split(/\s+/)
while (parm.length) {
|
| ︙ | ︙ | |||
37 38 39 40 41 42 43 | // default: // // error // break } } return } | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
// default:
// // error
// break
}
}
return
}
of(cmd, parm)
},
set_sym_glue: function(of, width) {
var s,
C = abc2svg.C,
tsfirst = this.get_tsfirst(),
soloffs = this.cfmt().soloffs;
|
| ︙ | ︙ |
Changes to modules/sth.js.
| ︙ | ︙ | |||
96 97 98 99 100 101 102 |
if (curvoice.sth && s && s.type == C.NOTE) {
s.sth = curvoice.sth;
curvoice.sth = null // some stem widths in this voice
}
return s
},
| | | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
if (curvoice.sth && s && s.type == C.NOTE) {
s.sth = curvoice.sth;
curvoice.sth = null // some stem widths in this voice
}
return s
},
set_fmt: function(of, cmd, param) {
if (cmd == "sth") {
var curvoice = this.get_curvoice()
if (this.parse.state == 2)
this.goto_tune()
if (curvoice)
curvoice.sth = param.split(/[ \t;-]+/)
return
}
of(cmd, param)
},
set_stems: function(of) {
of();
abc2svg.sth.set_sth.call(this)
},
set_hooks: function(abc) {
abc.calculate_beam = abc2svg.sth.calculate_beam.bind(abc, abc.calculate_beam);
abc.new_note = abc2svg.sth.new_note.bind(abc, abc.new_note);
abc.set_format = abc2svg.sth.set_fmt.bind(abc, abc.set_format);
abc.set_stems = abc2svg.sth.set_stems.bind(abc, abc.set_stems)
}
} // sth
abc2svg.modules.hooks.push(abc2svg.sth.set_hooks);
// the module is loaded
|
| ︙ | ︙ |
Added modules/strftime.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
/* Port of strftime() by T. H. Doan (https://thdoan.github.io/strftime/)
*
* Day of year (%j) code based on Joe Orost's answer:
* http://stackoverflow.com/questions/8619879/javascript-calculate-the-day-of-the-year-1-366
*
* Week number (%V) code based on Taco van den Broek's prototype:
* http://techblog.procurios.nl/k/news/view/33796/14863/calculate-iso-8601-week-and-year-in-javascript.html
*/
function strftime(sFormat, date) {
if (!(date instanceof Date)) date = new Date();
var nDay = date.getDay(),
nDate = date.getDate(),
nMonth = date.getMonth(),
nYear = date.getFullYear(),
nHour = date.getHours(),
aDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
aMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
aDayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
isLeapYear = function() {
return (nYear%4===0 && nYear%100!==0) || nYear%400===0;
},
getThursday = function() {
var target = new Date(date);
target.setDate(nDate - ((nDay+6)%7) + 3);
return target;
},
zeroPad = function(nNum, nPad) {
return ((Math.pow(10, nPad) + nNum) + '').slice(1);
};
return sFormat.replace(/%[a-z]/gi, function(sMatch) {
return (({
'%a': aDays[nDay].slice(0,3),
'%A': aDays[nDay],
'%b': aMonths[nMonth].slice(0,3),
'%B': aMonths[nMonth],
'%c': date.toUTCString(),
'%C': Math.floor(nYear/100),
'%d': zeroPad(nDate, 2),
'%e': nDate,
'%F': date.toISOString().slice(0,10),
'%G': getThursday().getFullYear(),
'%g': (getThursday().getFullYear() + '').slice(2),
'%H': zeroPad(nHour, 2),
'%I': zeroPad((nHour+11)%12 + 1, 2),
'%j': zeroPad(aDayCount[nMonth] + nDate + ((nMonth>1 && isLeapYear()) ? 1 : 0), 3),
'%k': nHour,
'%l': (nHour+11)%12 + 1,
'%m': zeroPad(nMonth + 1, 2),
'%n': nMonth + 1,
'%M': zeroPad(date.getMinutes(), 2),
'%p': (nHour<12) ? 'AM' : 'PM',
'%P': (nHour<12) ? 'am' : 'pm',
'%s': Math.round(date.getTime()/1000),
'%S': zeroPad(date.getSeconds(), 2),
'%u': nDay || 7,
'%V': (function() {
var target = getThursday(),
n1stThu = target.valueOf();
target.setMonth(0, 1);
var nJan1 = target.getDay();
if (nJan1!==4) target.setMonth(0, 1 + ((4-nJan1)+7)%7);
return zeroPad(1 + Math.ceil((n1stThu-target)/604800000), 2);
})(),
'%w': nDay,
'%x': date.toLocaleDateString(),
'%X': date.toLocaleTimeString(),
'%y': (nYear + '').slice(2),
'%Y': nYear,
'%z': date.toTimeString().replace(/.+GMT([+-]\d+).+/, '$1'),
'%Z': date.toTimeString().replace(/.+\((.+?)\)$/, '$1')
}[sMatch] || '') + '') || sMatch;
});
}
|
Changes to modules/temper.js.
| ︙ | ︙ | |||
36 37 38 39 40 41 42 |
v0.temper = new Float32Array(12)
for (var i = 0; i < 12; i++)
v0.temper[i] = this.cfmt().temper[i] / 100
}
},
// get the temperament
| | | | 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 |
v0.temper = new Float32Array(12)
for (var i = 0; i < 12; i++)
v0.temper[i] = this.cfmt().temper[i] / 100
}
},
// get the temperament
set_fmt: function(of, cmd, param) {
if (cmd == "temperament") {
var ls = new Float32Array(param.split(/ +/)),
i = ls.length
if (i == 12) {
while (--i >= 0) {
if (isNaN(parseInt(ls[i])))
break
}
if (i < 0) {
this.cfmt().temper = ls
return
}
}
this.syntax(1, this.errs.bad_val, "%%temperament")
return
}
of(cmd, param)
},
set_hooks: function(abc) {
abc.set_bar_num = abc2svg.temper.set_bar_num.bind(abc, abc.set_bar_num);
abc.set_format = abc2svg.temper.set_fmt.bind(abc, abc.set_format)
}
} // temper
abc2svg.modules.hooks.push(abc2svg.temper.set_hooks);
// the module is loaded
abc2svg.modules.temperament.loaded = true
|
Changes to package.json.
1 2 |
{
"name": "abc2svg",
| | > > > > | 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 |
{
"name": "abc2svg",
"version": "1.20.7",
"description": "ABC music notation translator",
"devDependencies": {
"uglify-js": "^2.5.0"
},
"files": [
"COPYING",
"COPYING.LESSER",
"MIDI-1.js",
"Scc1t2/",
"abc2odt",
"abc2svg",
"abc2svg-1.js",
"abc2svg.ttf",
"abcdoc-1.js",
"abcemb-1.js",
"abcemb1-1.js",
"abcemb2-1.js",
"abctopdf",
"abcweb2-1.js",
"ambitus-1.js",
"break-1.js",
"capo-1.js",
"clair-1.js",
"clip-1.js",
"cmdline.js",
"combine-1.js",
"diag-1.js",
"edit-1.css",
"edit-1.js",
"edit-1.xhtml",
|
| ︙ | ︙ | |||
43 44 45 46 47 48 49 |
"grid2-1.js",
"json-1.js",
"page-1.js",
"perc-1.js",
"play-1.js",
"psvg-1.js",
"setmidi-1.js",
| | > > > | > | > > | > | 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 |
"grid2-1.js",
"json-1.js",
"page-1.js",
"perc-1.js",
"play-1.js",
"psvg-1.js",
"setmidi-1.js",
"snd-1.js",
"soloffs-1.js",
"sth-1.js",
"temper-1.js",
"toabc.js",
"toaudio-1.js",
"toabw.js",
"tomei.js",
"toodt.js",
"toparam.js",
"toxhtml.js"
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"bin": {
"abc2odt": "./abc2odt",
"abc2svg": "./abc2svg",
"abctopdf": "./abctopdf"
},
"repository": {
"type": "fossil",
"url": "https://chiselapp.com/user/moinejf/repository/abc2svg"
},
"keywords": [
"ABC",
"music",
"SVG"
],
"author": "Jean-François Moine",
"license": "LGPL-3.0",
"bugs": {
"url": "https://chiselapp.com/user/moinejf/repository/abc2svg/reportlist"
},
"homepage": "https://chiselapp.com/user/moinejf/repository/abc2svg",
"dependencies": {
"npm": "^6.10.1"
}
}
|
Changes to toabc.js.
| ︙ | ︙ | |||
43 44 45 46 47 48 49 50 51 52 53 54 55 56 | uppermordent: 'P', segno: 'S', trill: 'T', upbow: 'u', downbow: 'v', roll: '~' }, mode_tb = [ // key modes [0, ""], [2, "dor"], [4, "phr"], [-1, "lyd"], [1, "mix"], [3, "m"], | > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | uppermordent: 'P', segno: 'S', trill: 'T', upbow: 'u', downbow: 'v', roll: '~' }, old_font = [], mode_tb = [ // key modes [0, ""], [2, "dor"], [4, "phr"], [-1, "lyd"], [1, "mix"], [3, "m"], |
| ︙ | ︙ | |||
80 81 82 83 84 85 86 |
ln = 'V:' + p_voice.id
if (!vold[v]) {
vold[v] = true
if (p_voice.clef
&& p_voice.clef.clef_type != 'a')
ln += ' ' + clef_dump(p_voice.clef)
| | > > < > > > > > > > > | < < < < < > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
ln = 'V:' + p_voice.id
if (!vold[v]) {
vold[v] = true
if (p_voice.clef
&& p_voice.clef.clef_type != 'a')
ln += ' ' + clef_dump(p_voice.clef)
if (p_voice.nm) {
ln += ' nm="' + p_voice.nm + '"'
font_def("voice", p_voice.nm)
}
if (p_voice.snm)
ln += ' snm="' + p_voice.snm + '"';
if (p_voice.scale != 1)
ln += ' scale=' + p_voice.scale
if (p_voice.uscale)
ln += ' microscale=' + p_voice.uscale
}
abc2svg.print(ln)
} // vi_out()
if (nv == 1) {
if (vo[0].length == 0)
return
if (!vold[0]
&& (voice_tb[0].nm || voice_tb[0].snm
|| voice_tb[0].scale != 1 || voice_tb[0].uscale))
vi_out(0);
if (eoln) {
eoln = false
vo[0][vo[0].length - 1] += "$"
}
abc2svg.print(vo[0].join(''));
vo[0] = []
return
}
for (var v = 0; v < nv; v++) {
if (vo[v].length == 0)
continue
vi_out(v);
if (eoln) {
eoln = false
vo[v][vo[v].length - 1] += "$"
}
abc2svg.print(vo[v].join(''));
vo[v] = []
}
} // voice_out()
function block_dump(s) {
var ln = "%%" + s.subtype + ' '
switch (s.subtype) {
case "ml":
ln += s.text
break
default:
ln += s.param
break
case "sep":
ln += s.sk1.toFixed(1) + ' ' +
s.l.toFixed(1) + ' ' +
s.sk2.toFixed(1)
break
case "skip":
ln += s.sk
break
case "text":
font_def("text", s.text)
if (s.text.indexOf('\n') <= 0
&& (!s.opt || s.opt == 'c')) {
if (s.opt == 'c')
ln = "%%center " + s.text
else
ln += s.text
break
|
| ︙ | ︙ | |||
158 159 160 161 162 163 164 |
abc2svg.print(ln +
'\n%%' + s.text.replace(/\n/g, '\n%%') +
"\n%%endtext")
return
case "title":
abc2svg.print('T:' + s.text.replace(/\n/g, '\nT:'))
return
| < < < | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
abc2svg.print(ln +
'\n%%' + s.text.replace(/\n/g, '\n%%') +
"\n%%endtext")
return
case "title":
abc2svg.print('T:' + s.text.replace(/\n/g, '\nT:'))
return
}
abc2svg.print(ln)
} // block_dump()
function clef_dump(s) {
var ln
switch (s.clef_type) {
|
| ︙ | ︙ | |||
216 217 218 219 220 221 222 223 224 225 226 |
break
}
d++
}
if (d > 0)
line += "//////".slice(0, d)
} // dur_dump()
function gch_dump(a_gch) {
var i, j, gch
for (i = 0; i < a_gch.length; i++) {
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < > > | 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
break
}
d++
}
if (d > 0)
line += "//////".slice(0, d)
} // dur_dump()
function font_def(fn, p) {
var c, f,
i = p.indexOf('$')
abc.get_font(fn) // used font
// fixme: one '$' only
if (i >= 0) {
c = p[i + 1]
if (c >= '1' && c <= '9') {
c = "u" + c
f = abc.cfmt()[c + "font"] // user font
f.fid = abc.get_font(c).fid // dump it!
}
}
font_dump() // dump the new fonts
} // font_def()
function font_dump() {
var k, f, def,
cfmt = abc.cfmt()
// fs = abc.get_font_style().split("\n").shift()
for (k in cfmt) {
if (k.slice(-4) != "font")
continue
f = cfmt[k]
if (f.fid == undefined)
continue // not used
if (old_font[f.fid])
continue // already out
old_font[f.fid] = true
def = f.name || ""
if (f.weight)
def += f.weight
if (f.style)
def += f.style
if (!def)
def = "*"
if (k[0] == "u")
k = "setfont-" + k[1]
abc2svg.print('%%' + k + ' ' +
def + ' ' + (f.size || "*"))
}
} // font_dump()
function gch_dump(a_gch) {
var i, j, gch
for (i = 0; i < a_gch.length; i++) {
gch = a_gch[i]
font_def(gch.type == 'g' ? "gchord" : "annotation", gch.text)
line += '"';
switch (gch.type) {
case 'g':
for (j = 0; j < gch.text.length; j++) {
switch (gch.text.charCodeAt(j)) {
case 0x266d:
line += 'b'
break
|
| ︙ | ︙ | |||
299 300 301 302 303 304 305 |
if (clef && clef.clef_type != 'a')
ln += ' ' + clef_dump(clef)
//fixme: to continue
return ln
} // key_dump()
function lyric_dump() {
| | | > | < < | < < < < < < < < < < < < < < < < < < < | 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
if (clef && clef.clef_type != 'a')
ln += ' ' + clef_dump(clef)
//fixme: to continue
return ln
} // key_dump()
function lyric_dump() {
var v, s, i, ly, nly, t, w
font_def("vocal", "")
for (v = 0; v < nv; v++) {
nly = 0;
w = []
for (s = voice_tb[v].sym; s; s = s.next) {
ly = s.a_ly
if (ly)
while (nly < ly.length)
w[nly++] = ""
}
if (nly == 0)
continue
for (s = voice_tb[v].sym; s; s = s.next) {
if (s.type != C.NOTE)
continue
ly = s.a_ly
if (!ly) {
for (i = 0; i < nly; i++)
w[i] += "*"
continue
}
for (i = 0; i < nly; i++) {
|
| ︙ | ︙ | |||
362 363 364 365 366 367 368 | case '_\n': w[i] += '_' break default: t = t.replace(/ /g, '~') t = t.replace(/-/g, '\\-') t = t.replace(/\n/g, '-'); | > > | | | | > > | > > > > > > > | 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
case '_\n':
w[i] += '_'
break
default:
t = t.replace(/ /g, '~')
t = t.replace(/-/g, '\\-')
t = t.replace(/\n/g, '-');
if (t.slice(-1) != "-")
t += ' '
w[i] += t
break
}
}
}
if (w.length != 0) {
if (voice_tb.length > 1)
abc2svg.print("V:" + voice_tb[v].id)
for (i = 0; i < w.length; i++)
abc2svg.print("w:" + w[i].replace(/\*+$/,""))
}
}
} // lyric_dump()
function meter_dump(s) {
var i, ln
if (s.wmeasure == 1)
return "M:none"
ln = "M:"
for (i = 0; i < s.a_meter.length; i++) {
if (i != 0)
ln += ' ';
ln += s.a_meter[i].top
if (s.a_meter[i].bot)
ln += '/' + s.a_meter[i].bot
}
return ln
} // meter_dump()
function note_dump(s, note, tie_ch) {
var p, j, sl, s2
if (note.sls) {
for (j = 0; j < note.sls.length; j++) {
sl = note.sls[j];
slti_dump(sl.ty, '(');
s2 = sl.note.s
if (s2.sl2)
s2.sl2++
else
s2.sl2 = 1
}
}
if (note.a_dcn) {
for (j = 0; j < note.a_dcn.length; j++)
line += '!' + note.a_dcn[j] + '!'
}
if (note.color)
line += "!" + note.color + "!"
switch (note.acc) {
|
| ︙ | ︙ | |||
436 437 438 439 440 441 442 |
if (p < 16) {
line += ","
if (p < 9)
line += ","
}
}
}
| | | | | > > | 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 |
if (p < 16) {
line += ","
if (p < 9)
line += ","
}
}
}
if (!tie_ch && note.tie_ty)
slti_dump(note.tie_ty, '-')
while (note.sl2) {
line += ')';
note.sl2--
}
} // note_dump()
function slti_dump(fl, ty) {
if (fl & C.SL_DOTTED)
line += ".";
line += ty
switch (fl & 0x07) {
|
| ︙ | ︙ | |||
468 469 470 471 472 473 474 |
st = -1,
sy = s.sy;
curv = -1;
ln = "%%score "
for (v = 0; v < sy.voices.length; v++) {
p_v = sy.voices[v]
| | | 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 |
st = -1,
sy = s.sy;
curv = -1;
ln = "%%score "
for (v = 0; v < sy.voices.length; v++) {
p_v = sy.voices[v]
if (p_v)
vn[p_v.range] = v
}
for (v = 0; v < sy.voices.length; v++) {
if (vn[v] == undefined || vn[v] < 0)
continue
p_v = sy.voices[vn[v]]
if (p_v.st != st) {
|
| ︙ | ︙ | |||
587 588 589 590 591 592 593 |
}
if (s.tempo_str2)
ln += '"' + s.tempo_str2 + '"'
info_out(ln)
} // tempo_dump()
function tuplet_dump(s) {
| | < < < < < < < < < | < < < < < < < < | < | < | < < < | < > | | | | | | | > > | < | > > > > | > > > > > > > | 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 |
}
if (s.tempo_str2)
ln += '"' + s.tempo_str2 + '"'
info_out(ln)
} // tempo_dump()
function tuplet_dump(s) {
var tp
while (1) {
tp = s.tp.shift()
if (!tp)
break
line += '(' + tp.p
if (tp.ro == tp.p
&& ((tp.p == 2 && tp.q == 3)
|| (tp.p == 3 && tp.q == 2)
|| (tp.p == 4 && tp.q == 3)))
;
else
line += ':' + tp.q + ':' + tp.ro
}
} // tuplet_dump()
function sym_dump(s) {
var tie_ch, i, sl
if (s.repeat_n) {
if (s.repeat_n < 0)
line += "[I:repeat " + (-s.repeat_n).toString() +
' ' + s.repeat_k + ']'
else
line += "[I:repeat " + s.repeat_n +
' ' + s.repeat_k + ']'
}
if (s.tp)
tuplet_dump(s)
if (s.sls) {
for (i = 0; i < s.sls.length; i++) {
sl = s.sls[i];
slti_dump(sl.ty, '(');
if (sl.is_note) {
if (sl.note.sl2)
sl.note.sl2++
else
sl.note.sl2 = 1
} else {
if (sl.note.s.sl2)
sl.note.s.sl2++
else
sl.note.s.sl2 = 1
}
}
}
if (s.a_gch)
gch_dump(s.a_gch)
if (s.a_dd)
deco_dump(s.a_dd)
if (s.invis && s.type != C.REST && s.type != C.SPACE)
line += "!invisible!"
|
| ︙ | ︙ | |||
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 |
break
case C.MREST:
line += s.invis ? 'X' : 'Z'
if (s.nmes != 1)
line += s.nmes
break
case C.NOTE:
if (s.beam_br1)
line += "!beambr1!"
if (s.beam_br2)
line += "!beambr2!"
if (s.trem1)
line += '!' + "///".slice(0, s.ntrem) + '!'
if (s.xstem)
line += "!xstem!"
if (s.stemless
&& s.notes[0].dur < C.BLEN) // head duration
line += "!stemless!"
if (s.trem22)
line += "!trem" + s.ntrem + "!"
else if (s.trem2 && s.next && s.next.trem2)
s.next.trem22 = true
tie_ch = true
if (s.notes.length == 1) {
note_dump(s, s.notes[0], tie_ch)
} else {
for (i = 0; i < s.notes.length; i++) {
| > > > > > > > > > > > > > | | 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 |
break
case C.MREST:
line += s.invis ? 'X' : 'Z'
if (s.nmes != 1)
line += s.nmes
break
case C.NOTE:
if (s.stem) { // if forced stem direction
if (s.stem > 0) {
if (s.p_v.pos.stm != C.SL_ABOVE) {
s.p_v.pos.stm = C.SL_ABOVE
line += "[I:pos stem up]"
}
} else {
if (s.p_v.pos.stm != C.SL_BELOW) {
s.p_v.pos.stm = C.SL_BELOW
line += "[I:pos stem down]"
}
}
}
if (s.beam_br1)
line += "!beambr1!"
if (s.beam_br2)
line += "!beambr2!"
if (s.trem1)
line += '!' + "///".slice(0, s.ntrem) + '!'
if (s.xstem)
line += "!xstem!"
if (s.stemless
&& s.notes[0].dur < C.BLEN) // head duration
line += "!stemless!"
if (s.trem22)
line += "!trem" + s.ntrem + "!"
else if (s.trem2 && s.next && s.next.trem2)
s.next.trem22 = true
tie_ch = true
if (s.notes.length == 1) {
note_dump(s, s.notes[0], tie_ch)
} else {
for (i = 0; i < s.notes.length; i++) {
if (!s.notes[i].tie_n) {
tie_ch = false
break
}
}
line += '['
for (i = 0; i < s.notes.length; i++)
note_dump(s, s.notes[i], tie_ch);
|
| ︙ | ︙ | |||
740 741 742 743 744 745 746 |
dur_dump(tmp, true)
} else {
tmp = s.notes[0].dur // head duration
if (s.trem2)
tmp /= 2;
dur_dump(tmp)
}
| | | | > | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 |
dur_dump(tmp, true)
} else {
tmp = s.notes[0].dur // head duration
if (s.trem2)
tmp /= 2;
dur_dump(tmp)
}
if (s.tie_s && tie_ch)
slti_dump(s.notes[0].tie_ty, '-');
tmp = s.sl2
while (tmp) {
line += ')';
tmp--
}
break
case C.PART:
font_def("parts", s.text)
info_out('P:' + s.text)
break
case C.REST:
line += s.invis ? 'x' : 'z';
dur_dump(s.dur)
break
case C.SPACE:
|
| ︙ | ︙ | |||
786 787 788 789 790 791 792 793 794 795 796 797 798 799 |
break
default:
voice_out();
abc2svg.print('% ??sym: ' + music_types[s.type])
break
}
} // sym_dump()
abc2svg.print('\nX:' + info['X'])
header_dump("TC")
abc2svg.print(meter_dump(voice_tb[0].meter));
ulen = voice_tb[0].ulen < 0 ? C.BLEN / 4 : voice_tb[0].ulen;
| > > | 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 |
break
default:
voice_out();
abc2svg.print('% ??sym: ' + music_types[s.type])
break
}
} // sym_dump()
font_dump()
abc2svg.print('\nX:' + info['X'])
header_dump("TC")
abc2svg.print(meter_dump(voice_tb[0].meter));
ulen = voice_tb[0].ulen < 0 ? C.BLEN / 4 : voice_tb[0].ulen;
|
| ︙ | ︙ | |||
823 824 825 826 827 828 829 |
voice_out();
if (s.del)
continue
line = "";
// (all voices are synchronized on %%score)
if (s.type != C.STAVES && s.time > vti[s.v]) {
//fixme: put 'X' if more than one measure
| > | | > > | | | < | | | > | 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 |
voice_out();
if (s.del)
continue
line = "";
// (all voices are synchronized on %%score)
if (s.type != C.STAVES && s.time > vti[s.v]) {
//fixme: put 'X' if more than one measure
if (s.time > vti[s.v] + 2) {
line += 'x';
dur_dump(s.time - vti[s.v]);
}
vti[s.v] = s.time
}
sym_dump(s)
if (s.dur)
vti[s.v] = s.time + s.dur
if (s.next) {
if (s.beam_end && !s.beam_st && !s.next.beam_end)
line += ' '
if (s.eoln)
eoln = true
}
if (line)
vo[s.v].push(line)
}
voice_out();
lyric_dump();
header_dump("W")
} // abc_dump()
user.get_abcmodel = abc_dump
// -- local functions
abc2svg.abc_init = function(args) {
abc2svg.print('%abc-2.2\n\
% generated by abc2svg toabc from\n\
%\t' + args.join(' ') + '\n\
%%linebreak $')
}
abc2svg.abc_end = function() {
if (user.errtxt)
abc2svg.print("Errors:\n" + user.errtxt)
}
abc2svg.abort = function(e) {
abc2svg.print(e.message + "\n*** Abort ***\n" + e.stack);
abc2svg.abc_end();
abc2svg.quit()
}
|
Changes to toabw.js.
| ︙ | ︙ | |||
79 80 81 82 83 84 85 |
r[j] += c
continue
case '$':
break
}
c = str[++i]
switch (c) {
| > > | > | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
r[j] += c
continue
case '$':
break
}
c = str[++i]
switch (c) {
case 'd':
if (!abc2svg.get_mtime)
break // cannot know the modification date of the file
r[j] += abc2svg.get_mtime(abc.parse.fname)
break
case 'D':
r[j] += (new Date()).toUTCString()
break
case 'F':
r[j] += abc.parse.fname
break
case 'I':
c = str[++i]
case 'T':
t = abc.info()[c]
if (t)
r[j] += t.split('\n', 1)[0]
|
| ︙ | ︙ | |||
130 131 132 133 134 135 136 | res = '<section id="'+ (type[0] == 'h' ? '0' : '1') + '" listid="0" parentid="0" type="' + type + '" xid="' + (++seq).toString() + '">\n\ <table xid="' + (++seq).toString() + '"\ props="list-tag:1; table-column-props:6.00cm/6.00cm/6.00cm/;\ table-column-leftpos:' + (page_type[0] == 'L' ? '0.6in' : '1.5cm') + '">\n'; | | | 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
res = '<section id="'+ (type[0] == 'h' ? '0' : '1') +
'" listid="0" parentid="0" type="' + type +
'" xid="' + (++seq).toString() + '">\n\
<table xid="' + (++seq).toString() + '"\
props="list-tag:1; table-column-props:6.00cm/6.00cm/6.00cm/;\
table-column-leftpos:' + (page_type[0] == 'L' ? '0.6in' : '1.5cm') + '">\n';
a = header_footer(clean_txt(str))
for (i = 0; i < 3; i++) {
res += '<cell xid="' + (++seq).toString() + '"\
props="left-attach:' + i + '; right-attach:' + (i + 1).toString() +
'; bot-attach:1; top-attach:0;\
top-color:ffffff; right-color:ffffff; bg-style:1;\
left-color:ffffff; bot-color:ffffff">\n';
str = a[i]
|
| ︙ | ︙ | |||
222 223 224 225 226 227 228 229 |
// replace <>& by XML character references
function clean_txt(txt) {
return txt.replace(/<|>|&.*?;|&/g, function(c) {
switch (c) {
case '<': return "<"
case '>': return ">"
}
| > < < | 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
// replace <>& by XML character references
function clean_txt(txt) {
return txt.replace(/<|>|&.*?;|&/g, function(c) {
switch (c) {
case '<': return "<"
case '>': return ">"
case '&': return "&"
}
return c
})
}
abc2svg.abort = function(e) {
abc.blk_flush();
if (typeof abc2svg.printErr == 'function')
|
| ︙ | ︙ |
Added tomei.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 |
// abc2svg - tomei.js - convert ABC to MEI
//
// Copyright (C) 2019 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
// constants from core/abc2svg.js
var C = abc2svg.C,
OPEN_BRACE = 0x01,
CLOSE_BRACE = 0x02,
OPEN_BRACKET = 0x04,
CLOSE_BRACKET = 0x08,
OPEN_PARENTH = 0x10,
CLOSE_PARENTH = 0x20,
STOP_BAR = 0x40,
FL_VOICE = 0x80,
OPEN_BRACE2 = 0x0100,
CLOSE_BRACE2 = 0x0200,
OPEN_BRACKET2 = 0x0400,
CLOSE_BRACKET2 = 0x0800,
MASTER_VOICE = 0x1000
// generate a new reference
function new_ref(s) {
if (!s.ref) {
s.ref = ++meas.ref
if (!s.items)
s.items = ""
s.items += ' xml:id="a' + s.ref.toString() + '"'
}
}
// --- decorations
// decoration as text (dynam, fing) at end of measure
// d[1] = tag
// d[2] = item in the tag
// d[3] = optional 'place'
function decotxt1(s, d) {
new_ref(s)
var t = '\t <' + d[1] + ' startid="#a' + s.ref + '"'
//fixme: above or below
if (d[3]) // place
t += ' ' + d[3] + '="above"'
meas.tags.push(t + '>' + d[2] + '</' + d[1] + '>')
}
// decoration in a symbol
// d[1] = tag
// d[2] = item in the tag
// d[3] = optional 'place'
function decosym(s, d) {
//fixme: if no place
// if (1)
// return' ' + d[2]
var t = '\t\t<' + d[1]
if (d[2])
t += ' ' + d[2]
//fixme: above or below
if (d[3]) // place
t += ' ' + d[3] + '="above"'
if (!s.tags)
s.tags = []
s.tags.push(t + '/>')
}
// (decoration either in a symbol or at end of the measure)
// decoration at end of the measure
// d[1] = tag
// d[2] = item in the tag
// d[3] = optional 'place'
function decotag1(s, d) {
new_ref(s)
var t = '\t <' + d[1] + ' startid="#a' + s.ref + '"'
if (d[2])
t += ' ' + d[2]
//fixme: above or below
if (d[3]) // place
t += ' ' + d[3] + '="above"'
meas.tags.push(t + '/>')
}
var deco_l = {
// "-("
// "-)"
// "~("
// "~)"
//fixme: form=cres/dim, place=above/below and 2 references
// "<(": [null, "hairpin"], // "cres",
// "<)": [null, "hairpin"], // "cres",
// ">"
// ">(": [null, "hairpin"], // "dim",
// ">)": [null, "hairpin"], // "dim",
"^": [decosym, "artic", 'artic="marc"', "place"],
// "+":
"0": [decotxt1, "fing", "0", "place"],
"1": [decotxt1, "fing", "1", "place"],
// "15va("
// "15va)"
// "15vb("
// "15vb)"
"2": [decotxt1, "fing", "2", "place"],
"3": [decotxt1, "fing", "3", "place"],
"4": [decotxt1, "fing", "4", "place"],
"5": [decotxt1, "fing", "5", "place"],
// "8va("
// "8va)"
// "8vb("
// "8vb)"
accent: [decosym, "artic", 'artic="acc"', "place"],
//fixme: plist on notes
// arpeggio
breath: [decotag1, "breath"],
// coda: [null, "O"],
// crescendo(
// crescendo)
// dacapo
// dacoda
// "D.C."
// "D.C.alcoda"
// "D.C.alfine"
// diminuendo(
// diminuendo)
// "D.S."
// "D.S.alcoda"
// "D.S.alfine"
dot: [decosym, "artic", 'artic="stacc"', "place"],
downbow: [decosym, "artic", 'artic="dnbow"', "place"],
// emphasis: [null, "L"],
f: [decotxt1, "dynam", "f", "place"],
fermata: [decotag1, "fermata", null, "place"],
ff: [decotxt1, "dynam", "ff", "place"],
fff: [decotxt1, "dynam", "fff", "place"],
ffff: [decotxt1, "dynam", "ffff", "place"],
// fine
// gmark
invertedfermata: [decotag1, "fermata", 'form="inv"', "place"],
// invertedturn: [decotag1, "fermata", 'form="inv"', "place"],
// invertedturnx: [decotag1, "fermata", 'form="inv"', "place"],
// longphrase
lowermordent: [decotag1, "mordent", 'form="lower"'],
marcato: [decosym, "artic", 'artic="marc"', "place"],
// mediumphrase
mf: [decotxt1, "dynam", "mf", "place"],
mp: [decotxt1, "dynam", "mp", "place"],
open: [decosym, "artic", 'artic="open"', "place"],
p: [decotxt1, "dynam", "p", "place"],
pralltriller: [decotag1, "mordent", 'form="upper"'],
// ped
"ped)": [decotxt1, "pedal", dir="up"],
"ped(": [decotxt1, "pedal", dir="down"],
// ped-up
// plus
pp: [decotxt1, "dynam", "pp", "place"],
ppp: [decotxt1, "dynam", "ppp", "place"],
pppp: [decotxt1, "dynam", "pppp", "place"],
// rbstop
// roll: [null, '~'],
// segno: [null, 'S'],
sfz: [decotxt1, "dynam", "sfz", "place"],
// shortphrase
// slide
snap: [decosym, "artic", 'artic="snap"', "place"],
tenuto: [decosym, "artic", 'artic="ten"', "place"],
// thumb
trill: [decotag1, "trill", null, "place"],
//2 references
// "trill(": [null, "trill("], // place=above/below
// "trill)": [null, "trill)"],
turn: [decotag1, "turn", 'form="upper"'],
turnx: [decotag1, "turn", 'form="lower"'],
upbow: [decosym, "artic", 'artic="upbow"', "place"],
uppermordent: [decotag1, "mordent", 'form="upper"']
// wedge
}
// build the decorations of a symbol
// a decoration may be:
// - as an item in the symbol (in s.items)
// - as a tag in the symbol (in s.tags)
// - as a tag at the end of the measure (in meas.tags)
function deco_build(s) {
var i, n, d
for (i = 0; i < s.a_dd.length; i++) {
n = s.a_dd[i].name
d = deco_l[n]
//keep until all done
if (!d)
{
abc2svg.printErr('<!-- no conversion of '+n+'-->')
continue
}
d[0](s, d)
}
} // deco_build()
// global variables/constants
var mode_tb = ["major", "dor", "phr", "lyd", "mix", "minor", "loc"],
bar_ty = {".|": "dashed",
"||": "dbl",
".||": "dbldashed",
".||": "dbldotted",
".|": "dotted",
"|]": "end",
"": "invis",
"[|:": "rptstart",
":[]:": "rptboth",
":|]": "rptend",
"|": "single"
},
meas = { // measure
bar_num: 0,
no_head: true,
st: [],
vo: [],
ref: 100,
clefs: [], // clefs per staff
tags: []
}
// dump the staves at start of tune (no 's') and inside the tune
function staves_dump(s) {
var v, p_v, staff, in_parenth, ln, stop, s2,
voice_tb = abc.get_voice_tb(),
vn = [],
st = -1,
sy = s ? s.sy : abc.get_cur_sy()
// clef in staffDef
function clef_dump(s) {
var ln = ' clef.shape="'
switch (s.clef_type) {
case 't': ln += 'G"'; break
case 'c': ln += 'C"'; break
case 'b': ln += 'F"'; break
case 'p': ln += 'perc"'; break
//fixme: TAB
default: return ''
}
ln += ' clef.line="' + s.clef_line + '"'
if (s.clef_octave)
ln += ' clef.dis="8" clef.dis.place="' +
(s.clef_octave > 0 ? 'above"' : 'below"')
return ln
} // clef_dump()
// meas.sy = sy
for (v = 0; v < sy.voices.length; v++) {
p_v = sy.voices[v]
if (p_v)
vn[p_v.range] = v
}
for (v = 0; v < sy.voices.length; v++) {
if (vn[v] == undefined)
continue
p_v = sy.voices[vn[v]]
if (p_v.st == st)
continue
if (st >= 0) {
if (staff.flags & CLOSE_BRACE2)
abc2svg.print('\t </staffGrp>')
if (staff.flags & CLOSE_BRACE)
abc2svg.print('\t </staffGrp>')
if (staff.flags & CLOSE_BRACKET2)
abc2svg.print('\t </staffGrp>')
if (staff.flags & CLOSE_BRACKET)
abc2svg.print('\t </staffGrp>')
}
staff = sy.staves[++st]
stop = (staff.flags & STOP_BAR) ?
' bar.thru="false"' : ''
if (staff.flags & OPEN_BRACKET)
abc2svg.print('\t <staffGrp symbol="bracket"' +
stop + '>')
if (staff.flags & OPEN_BRACKET2)
abc2svg.print('\t <staffGrp symbol="bracket"' +
stop + '>')
if (staff.flags & OPEN_BRACE)
abc2svg.print('\t <staffGrp symbol="brace"' +
stop + '>')
if (staff.flags & OPEN_BRACE2)
abc2svg.print('\t <staffGrp symbol="brace"' +
stop + '>')
ln = '\t <staffDef n="' + (st + 1).toString() + '"'
for (s2 = voice_tb[vn[v]].sym; s2; s2 = s2.next) {
if (s2.dur)
break
if (s2.type == C.CLEF) {
if (!s2.invis)
ln += clef_dump(s2)
meas.clefs[st] = s2
break
}
}
abc2svg.print(ln + '/>')
}
if (staff.flags & CLOSE_BRACE2)
abc2svg.print('\t </staffGrp>')
if (staff.flags & CLOSE_BRACE)
abc2svg.print('\t </staffGrp>')
if (staff.flags & CLOSE_BRACKET2)
abc2svg.print('\t </staffGrp>')
if (staff.flags & CLOSE_BRACKET)
abc2svg.print('\t </staffGrp>')
} // staves_dump()
// dump the header
function head_dump() {
var i, v, s, g, line, ulen, tmp, tmp2, grace, bagpipe, eoln, curv,
info = abc.info(),
first = abc.get_tsfirst(),
voice_tb = abc.get_voice_tb(),
nv = voice_tb.length,
vo = [], // dump line per voice
vold = [], // false/true for voice name
vti = []
// -- main code of head_dump()
info.T = info.T ? info.T.replace(/\n/g,'<lb/>') : ''
abc2svg.print('\
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">\n\
<meiHead>\n\
<fileDesc>\n\
<titleStmt>\n\
<title>' + info.T + '</title>\n\
</titleStmt>\n\
<pubStmt />\n\
</fileDesc>\n\
<encodingDesc>\n\
<appInfo>\n\
<application version="' + abc2svg.version + '">\n\
<name>abc2svg</name>\n\
<p>Transcoded from ABC</p>\n\
</application>\n\
</appInfo>\n\
</encodingDesc>\n\
<workList>\n\
<work>\n' +
(info.T ? ('\
<title>\n\
' + info.T + '\n\
</title>\n') : '') +
(info.C ? ('\
<composer>\n\
' + info.C + '\n\
</composer>\n') : '') + '\
</work>\n\
</workList>\n\
</meiHead>\n\
<music>\n\
<body>\n\
<mdiv>\n\
<score>')
line = '\
<scoreDef'
s = voice_tb[0].meter
if (s.wmeasure != 1) {
meas.wmeasure = s.wmeasure
tmp = s.a_meter[0].top
tmp2 = s.a_meter[0].bot
if (tmp2)
line += ' meter.count="' + tmp + '" meter.unit="' + tmp2 + '"'
else if (tmp == "C")
line += ' meter.sym="common"'
else if (tmp == "C|")
line += ' meter.sym="cut"'
else
line += ' meter.count="' + tmp + '"'
}
s = voice_tb[0].key
tmp = s.k_sf
if (tmp > 0)
tmp = tmp.toString() + 's'
else if (tmp < 0)
tmp = (-tmp).toString() + 'f'
line += ' key.sig="' + tmp + '" key.mode="' +
mode_tb[s.k_mode] + '">'
abc2svg.print(line)
// output the staff system
staves_dump()
abc2svg.print('\
</scoreDef>\n\
<section>')
} // head_dump()
user.img_out = function() {} // do the generation with no output
// dump a whole measure
function meas_dump(s2) {
var ln, i, s, t, st, v, staff, voice, tim, g, s1
// clef in a measure
function clef_dump(s) {
if (!meas.clefs[s.st])
abc2svg.printErr('!! V:'+s.p_v.id+' '+s.time+' '+s.type+' st '+s.st)
if (s.clef_type == meas.clefs[s.st].clef_type)
return
meas.clefs[s.st] = s
var ln = '\t <clef shape="'
switch (s.clef_type) {
case 't': ln += 'G"'; break
case 'c': ln += 'C"'; break
case 'b': ln += 'F"'; break
case 'p': ln += 'perc"'; break
//fixme: TAB
default: return ''
}
ln += ' line="' + s.clef_line + '"'
if (s.clef_octave)
ln += ' dis="8" dis.place="' +
(s.clef_octave > 0 ? 'above"' : 'below"')
abc2svg.print(ln + '/>')
} // clef_dump()
// dump a duration
function dur_dump(dur, nflags) {
var t,
d = ' dur="'
if (nflags == undefined) {
//fixme: what if dur % 12 != 0 ?
t = (dur / 12) | 0
for (nflags = 5; t; t >>= 1, nflags--) {
if (t & 1)
break
}
}
if (nflags == -4)
d += "long"
else if (nflags == -3)
d += "breve"
else
d += (1 << (nflags + 2)).toString()
dur >>= (5 - nflags)
switch (dur) {
case 12: break
case 18: d += '" dots="1'; break
case 21: d += '" dots="2'; break
// case 22:
default: d += '" dots="3'; break
}
return d + '"'
} // dur_dump()
function gch_dump(s) {
new_ref(s)
var i, gch, t
for (i = 0; i < s.a_gch.length; i++) {
t = ' startid="#a' + s.ref
gch = s.a_gch[i]
// font_def(gch.type == 'g' ? "gchord" : "annotation", gch.text)
if (gch.type == 'g') {
t = '\t <harm' + t + '">' + gch.text + '</harm>'
} else {
if (gch.type == "^")
t += '" place="above"'
else if (gch.type == "_")
t += '" place="below"'
t = '\t <dir' + t + '>' + gch.text + '</dir>'
}
meas.tags.push(t)
}
} // gch_dump()
function note_dump(s) {
var m, note, t, item, s2, b_tp, i, r,
n = s.nhd,
line = ""
function ly_dump(s) {
var ly, i,
nly = s.a_ly.length
function ly_du1(t) {
var ln = '\t\t <syl'
switch (t) {
case '-\n':
case '_\n':
//fixme: no text...
return
default:
if (t.slice(-1) == "\n") {
t = t.slice(0, -1)
ln += ' con="d"'
}
break
}
abc2svg.print(ln + '>' + t + '</syl>')
}
if (nly == 1) {
ly_du1(s.a_ly[0].t)
return
}
for (i = 0; i < nly; i++) {
abc2svg.print('\t\t<verse n="' +
(i + 1).toString() + '">')
ly_du1(s.a_ly[i].t)
abc2svg.print('\t\t</verse>')
}
} // ly_dump()
function pit_dump(note) {
var pit = (note.opit || note.pit) + 12,
ln = ' pname="' +
"cdefgab"[pit % 7] + '" oct="' +
((pit / 7) | 0).toString() + '"'
switch (note.acc) {
case -2: ln += ' accid="ff"'; break
case -1: ln += ' accid="f"'; break
case 1: ln += ' accid="s"'; break
case 2: ln += ' accid="x"'; break
case 3: ln += ' accid="n"'; break
}
return ln
} // pit_dump()
// dump the starting beam and tuplets
function btps_dump(s) {
var i, tp, ln, st
function tp_dump(tp) {
var ln = '\t <tuplet num="' +
tp.p + '" numbase="' +
tp.q
if (Number(tp.f[0]) == 1) {
ln +=
'" num.visible="false" bracket.visible="false'
} else {
switch (Number(tp.f[2])) {
case 1: ln += '" bracket.visible="false'; break
case 2: ln += '" num.format="ratio'; break
}
switch (Number(tp.f[3])) {
case 1: ln += '" bracket.place="above'; break
case 2: ln += '" bracket.place="below'; break
}
}
abc2svg.print(ln + '">')
} // tp_dump()
// if start of a beam, check if crossing a measure bar
// // or with notes on different staves
if (s.beam_st && !s.beam_end) {
// st = s.st
for (s2 = s.next; ; s2 = s2.next) {
// if (s2.st != st || s2.type == C.BAR) {
if (s2.type == C.BAR) {
while (!s2.beam_end)
s2 = s2.next
new_ref(s)
new_ref(s2)
// if (s.st != s2.st)
// beam.with="above" or "below"
meas.tags.push(
'\t <beamSpan startid="#a' +
s.ref + '" endid="#a' +
s2.ref + '"/>')
s2 = null // the beam is treated
break
}
if (s2.beam_end)
break
}
}
if (!s2) { // if no beam
if (s.tp) { // but tuplets
i = s.tp.length
while (--i >= 0)
tp_dump(s.tp[i])
}
return
}
ln = '\t <beam>'
if (!s.tp) { // beam without any tuplet
abc2svg.print(ln)
return
}
// start of beam and tuplet(s)
i = 0
while (i < s.tp.length) {
tp = s.tp[i]
r = tp.ro
for (s2 = s; s2; s2 = s2.next) {
if (s2.dur)
r--
if (s2.beam_end || r < 0)
break
}
if (!s2.beam_end)
break
tp_dump(tp)
i++
}
abc2svg.print(ln)
while (i < s.tp.length)
tp_dump(s.tp[i++])
} // btps_dump()
// -- main of note_dump()
btps_dump(s)
if (s.beam_br1 || s.beam_br2) {
if (!s.items)
s.items = ""
s.items += s.beam_br1 ? ' breaksec="1"' :
' breaksec="2"'
}
if (n) { // chord
line = '\t <chord' + dur_dump(s.dur_orig, s.nflags)
if (s.grace)
line += ' grace="unknown"'
if (s.stem > 0)
line += ' stem.dir="up"'
else if (s.stem < 0)
line += ' stem.dir="down"'
if (s.st != s.p_v.st)
line += ' staff="' + (s.st + 1).toString() + '"'
if (s.items)
line += s.items
abc2svg.print(line + '>')
line = ""
for (m = 0; m <= n; m++) {
note = s.notes[m]
line = '\t <note' + pit_dump(note)
if (note.items)
line += note.items
abc2svg.print(line + '/>')
}
if (s.tags)
abc2svg.print(s.tags.join("\n"))
if (s.a_ly)
ly_dump(s)
abc2svg.print('\t </chord>')
} else { // single note
line = '\t <note' + dur_dump(s.dur_orig, s.nflags) +
pit_dump(s.notes[0])
if (s.stem > 0)
line += ' stem.dir="up"'
else if (s.stem < 0)
line += ' stem.dir="down"'
if (s.grace)
line += ' grace="unknown"'
if (s.st != s.p_v.st)
line += ' staff="' + (s.st + 1).toString() + '"'
if (s.items)
line += s.items
if (s.tags || s.a_ly) {
abc2svg.print(line + '>')
if (s.tags)
abc2svg.print(s.tags)
if (s.a_ly)
ly_dump(s)
abc2svg.print('\t </note>')
} else {
abc2svg.print(line + '/>')
}
}
n = s.tpe
if (s.beam_st || !s.beam_end) { // if no beam end
while (--n >= 0)
abc2svg.print('\t </tuplet>')
return
}
if (!n) { // beam end but no tuplet end
abc2svg.print('\t </beam>')
return
}
for (s2 = s.prev; s2; s2 = s2.prev) {
if (s2.beam_st) {
abc2svg.print('\t </beam>')
break
}
if (s2.tp) {
i = s2.tp.length
while (i > 0 && n > 0) {
abc2svg.print('\t </tuplet>')
i--
n--
}
}
}
while (--n >= 0)
abc2svg.print('\t </tuplet>')
} // note_dump()
function tempo_dump(s) {
if (s.del)
return
var v,
t = '\t <tempo place="above" startid="#a',
s2 = s.ts_next
while (!s2.dur && s2.type != C.SPACE)
s2 = s2.ts_next
new_ref(s2)
t += s2.ref + '"'
v = s.tempo
if (v) {
if (s.tempo_notes)
v *= s.tempo_notes[0] / C.BLEN * 4
t += ' mm="' + v + '"'
}
if (!s.tempo_str1 && !s.tempo_str2) {
meas.tags.push(t + '/>')
} else {
meas.tags.push(t + '>')
t = ''
if (s.tempo_str1)
t += s.tempo_str1
//fixme: note
if (!t)
t += ' '
t += 'fixme=' + s.tempo
if (s.tempo_str2) {
if (!t)
t += ' '
t += s.tempo_str2
}
meas.tags.push('\t </tempo>')
}
} // tempo_dump()
// -- main of meas_dump()
// get the start time
tim = 1000000
for (st = 0; st < meas.st.length; st++) {
staff = meas.st[st]
if (!staff)
continue
for (v = 0; v < staff.vo.length; v++) {
s = staff.vo[v].s[0]
if (s && s.time < tim) {
s1 = s
tim = s.time
}
}
}
if (!s1)
return // !
if (tim == 0 && s2.time < meas.wmeasure)
meas.bar_num = -1 // upbeat
ln = '\t <measure n="' + (++meas.bar_num).toString() +'"'
if (meas.bar_num == 0)
ln += ' metcon="false" type="upbeat"'
if (s1.type == C.BAR // if bar at start of tune
&& s1.time == 0) {
t = s1.bar_type
if (s1.bar_dotted)
t = '.' + t
t = bar_ty[t]
if (t)
ln += ' left="' + t + '"'
}
if (s2) {
t = s2.bar_type // bar at end of measure
if (s2.bar_dotted)
t = '.' + t
t = bar_ty[t]
if (t && t != "single")
ln += ' right="' + t + '"'
}
abc2svg.print(ln + '>')
for (st = 0; st < meas.st.length; st++) {
staff = meas.st[st]
if (!staff)
continue
ln = '\t <staff n="' + (st + 1).toString() + '"'
abc2svg.print(ln + '>')
for (v = 0; v < staff.vo.length; v++) {
voice = staff.vo[v]
// if (!voice)
// continue
ln = '\t <layer n="' + (v + 1).toString() + '"'
abc2svg.print(ln + '>')
tim = s1.time
for (i = 0; i < voice.s.length; i++) {
s = voice.s[i]
if (s.time > tim)
abc2svg.print('\t <space' +
dur_dump(s.time - tim) + '/>')
if (s.a_dd)
deco_build(s)
if (s.a_gch)
gch_dump(s)
//fixme:s.repeat_..
//fixme:s.invis
switch (s.type) {
case C.CLEF:
clef_dump(s)
break
case C.GRACE:
for (g = s.extra; g; g = g.next)
note_dump(g)
break
// case C.KEY:
// break
// case C.METER:
// break
// case C.MREST:
// break
case C.NOTE:
note_dump(s)
break
case C.REST:
//fixme: test if full measure
ln = '\t <' +
(s.invis ? 'space' : 'rest') +
dur_dump(s.dur_orig, s.nflags)
if (s.items)
ln += s.items
if (s.tags) {
abc2svg.print(ln + '>')
abc2svg.print(s.tags)
abc2svg.print('\t </rest>')
} else {
abc2svg.print(ln + '/>')
}
break
case C.TEMPO:
tempo_dump(s)
break
}
if (s.dur)
tim = s.time + s.dur
}
abc2svg.print('\t </layer>')
}
abc2svg.print('\t </staff>')
}
// output the decorations
if (meas.tags.length) {
abc2svg.print(meas.tags.join('\n'))
meas.tags = []
}
abc2svg.print('\t </measure>')
} // meas_dump()
// dump a music line (SVG image)
function glue(of, width) {
var s, staff, v, voice, ending,
tsfirst = this.get_tsfirst()
of(width)
function slur_dump(s) {
var i, m, note, note2, sl, refs, refs2, ref, ref2
function slur_out(ty, r1, r2) {
var line = '\t <slur startid="#a' + r1 +
'" endid="#a' + r2 + '"'
if (ty & C.SL_DOTTED)
line += ' lform="dotted"'
switch (ty & 0x07) {
case C.SL_ABOVE:
line += ' curvedir="above"'
break
case C.SL_BELOW:
line += ' curvedir="below"'
break
}
meas.tags.push(line + '/>')
} // slur_out()
if (s.sls) {
new_ref(s)
ref = s.ref
for (i = 0; i < s.sls.length; i++) {
sl = s.sls[i]
note = sl.note
if (sl.is_note) {
new_ref(note)
ref2 = note.ref
} else {
new_ref(note.s)
ref2 = note.s.ref
}
slur_out(sl.ty, ref, ref2)
}
}
if (s.sl1) {
for (m = 0; m <= s.nhd; m++) {
note = s.notes[m]
if (note.sls) {
new_ref(note)
ref = note.ref
for (i = 0; i < note.sls.length; i++) {
sl = note.sls[i]
note2 = sl.note
if (sl.is_note) {
new_ref(note2)
ref2 = note2.ref
} else {
new_ref(note2.s)
ref2 = note2.s.ref
}
slur_out(sl.ty, ref, ref2)
}
}
}
}
} // slur_dump()
function tie_dump(s) {
var m, note, note2, refs, refs2, ref, ref2,
s2 = s.tie_s
if (!s.nhd) {
new_ref(s)
refs = s.ref
}
if (!s2.nhd) {
new_ref(s2)
refs2 = s2.ref
}
for (m = 0; m <= s.nhd; m++) {
note = s.notes[m]
note2 = note.tie_n
if (refs) {
ref = refs
} else {
new_ref(note)
ref = note.ref
}
if (refs2) {
ref2 = refs2
} else {
new_ref(note2)
ref2 = note2.ref
}
line = '\t <tie startid="#a' + ref +
'" endid="#a' + ref2 + '"'
if (note.tie_ty & C.SL_DOTTED)
line += ' lform="dotted"'
switch (note.tie_ty & 0x07) {
case C.SL_ABOVE:
line += ' curvedir="above"'
break
case C.SL_BELOW:
line += ' curvedir="below"'
break
}
meas.tags.push(line + '/>')
}
} // tie_dump()
// main code of glue()
// output the MEI header if not done yet
if (meas.no_head) {
meas.no_head = false
head_dump()
}
// loop on the measures
for (s = tsfirst; s; s = s.ts_next) {
// if (abc.get_cur_sy() != meas.sy)
// staves_dump()
if (ending && s.rbstop)
ending = 2
if (s.type == C.BAR)
continue
// create the staves and voices if not done yet
staff = meas.st[s.st]
if (!staff) {
meas.st[s.st] = staff = {
vo: []
}
}
//other structure: voice sequences per staff
// v = staff.vo.length
// while (--v >= 0) {
// if (staff.vo[v].v == s.v)
// break
// }
// if (v < 0) { // new voice in this staff
// v = staff.vo.length
// staff.vo.push({
// v: s.v,
// s: [] // array of symbols
// })
// }
// voice = staff.vo[v]
//simple structure: use 'staff=' on staff changes
voice = meas.vo[s.v]
if (!voice) {
meas.vo[s.v] = voice = {
s: []
}
staff.vo.push(voice)
}
if (s.time == 0 && s.prev && s.prev == C.BAR
&& voice.s.length == 0) // start with a bar
voice.s.push(s.prev)
voice.s.push(s)
switch (s.type) {
case C.GRACE:
case C.NOTE:
if (s.sls || s.sl1)
slur_dump(s)
if (s.tie_s)
tie_dump(s)
break
case C.STAVES:
staves_dump(s)
break
}
if (!s.ts_next || s.ts_next.type == C.BAR) {
if (meas.eol) {
meas.eol = false
abc2svg.print('\t <sb/>')
}
meas_dump(s.ts_next)
if (ending == 2) { // if end of ending
abc2svg.print('\t</ending>')
ending = 0
}
if (s.ts_next && s.ts_next.text) { // if ending
abc2svg.print('\t<ending n="' +
s.ts_next.text + '">')
ending = 1
}
meas.st = []
meas.vo = []
}
}
meas.eol = true
} // glue()
// hook at tune generation start
function mei_output(of) {
if (meas.done) // do only one generation
return
meas.done = true
of()
}
// -- local functions
abc2svg.abc_init = function(args) {
abc.output_music = mei_output.bind(abc, abc.output_music)
abc.set_sym_glue = glue.bind(abc, abc.set_sym_glue)
abc2svg.print('<?xml version="1.0" encoding="UTF-8"?>\n\
<?xml-model href="http://music-encoding.org/schema/4.0.0/mei-all.rng"\n\
type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>\n\
<?xml-model href="http://music-encoding.org/schema/4.0.0/mei-all.rng"\n\
type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>')
}
abc2svg.abc_end = function() {
abc2svg.print('\
</section>\n\
</score>\n\
</mdiv>\n\
</body>\n\
</music>\n\
</mei>')
//fixme: terminer derniere mesure si pas barre de fin
//fixme: W: dans <section> - cf
// /home/jef/abc/mei/McFerrin_Don't_worry.mei
if (user.errtxt)
abc2svg.printErr("Errors:\n" + user.errtxt)
}
abc2svg.abort = function(e) {
abc2svg.printErr(e.message + "\n*** Abort ***\n" + e.stack)
abc2svg.abc_end()
abc2svg.quit()
}
|
Changes to toodt.js.
| ︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
function set_unit(p) {
if (typeof p == "string")
return p
if (page_type[0] == 'L')
return (p / 96).toFixed(1) + 'in'
return (p / 37.8).toFixed(1) + 'cm'
}
// output a header or a footer
function gen_hf(type, stype, str) {
var c, i, res_left,
j = 0,
res = '<style:' + type + '>\n\
<text:p text:style-name="' + stype + '\"><text:tab/>'
if (str[0] == '"')
str = str.slice(1, -1)
if (str.indexOf('\t') < 0) // if no TAB
str = '\t' + str // center
for (i = 0; i < str.length; i++) {
c = str[i]
switch (c) {
case '\t':
| > > > > > > > > > > > > > | 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 |
function set_unit(p) {
if (typeof p == "string")
return p
if (page_type[0] == 'L')
return (p / 96).toFixed(1) + 'in'
return (p / 37.8).toFixed(1) + 'cm'
}
// replace <>& by XML character references
function clean_txt(txt) {
return txt.replace(/<|>|&.*?;|&/g, function(c) {
switch (c) {
case '<': return "<"
case '>': return ">"
case '&': return "&"
}
return c
})
}
// output a header or a footer
function gen_hf(type, stype, str) {
var c, i, res_left,
j = 0,
res = '<style:' + type + '>\n\
<text:p text:style-name="' + stype + '\"><text:tab/>'
if (str[0] == '"')
str = str.slice(1, -1)
str = clean_txt(str)
if (str.indexOf('\t') < 0) // if no TAB
str = '\t' + str // center
for (i = 0; i < str.length; i++) {
c = str[i]
switch (c) {
case '\t':
|
| ︙ | ︙ | |||
100 101 102 103 104 105 106 |
continue
case '$':
break
}
c = str[++i]
switch (c) {
case 'd':
| | > | | | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
continue
case '$':
break
}
c = str[++i]
switch (c) {
case 'd':
if (!abc2svg.get_mtime)
break // cannot know the modification date of the file
res += abc2svg.get_mtime(abc.parse.fname).toLocaleString()
break
case 'D':
res += (new Date()).toLocaleString()
break
case 'F':
res += abc.parse.fname
break
case 'I':
c = str[++i]
case 'T':
t = abc.info()[c]
if (t) {
t_info = '\
|
| ︙ | ︙ |
Added toparam.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 |
// abc2svg - toparam - dump the abc2svg parameters
//
// Copyright (C) 2019 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
abc2svg.abort = function(e) {
abc2svg.quit()
}
abc2svg.abc_init = function() {
}
abc2svg.abc_end = function() {
var k, v, t,
cfmt = abc.cfmt()
if (user.errtxt)
abc2svg.print("Errors:\n" + user.errtxt)
abc2svg.print('% abc2svg default parameters\n')
for (k in cfmt) {
if (cfmt.hasOwnProperty(k)) {
v = cfmt[k]
if (k.slice(-4) == "font") {
t = v.name || ""
if (v.weight)
t += v.weight
if (v.style)
t += v.style
if (!t)
t = "*"
if (k[0] == "u")
k = "setfont-" + k[1]
v = t + ' ' + (v.size || "*")
} else if (k == "infoname") {
t = v.split("\n")
while (t.length)
abc2svg.print('%%' + k + ' ' + t.shift())
continue
} else if (k.slice(-6) == "margin"
|| k.slice(0, 4) == "page") {
v = (v / 37.8).toFixed(2).replace(/\.?0+$/,"") + "cm"
} else if (k == "writefields") {
v = v + " 1"
} else if (v === "") {
v = '""'
}
abc2svg.print('%%' + k + ' ' + v)
}
}
}
|
Changes to toxhtml.js.
| ︙ | ︙ | |||
74 75 76 77 78 79 80 |
r[j] += c
continue
case '$':
break
}
c = str[++i]
switch (c) {
| > > | > | | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
r[j] += c
continue
case '$':
break
}
c = str[++i]
switch (c) {
case 'd':
if (!abc2svg.get_mtime)
break // cannot know the modification date of the file
r[j] += abc2svg.get_mtime(abc.parse.fname)
break
case 'D':
r[j] += get_date()
break
case 'F':
r[j] += abc.parse.fname
break
case 'I':
c = str[++i]
case 'T':
t = abc.info()[c]
if (t)
r[j] += t.split('\n', 1)[0]
|
| ︙ | ︙ | |||
148 149 150 151 152 153 154 |
var cfmt = abc.cfmt()
// output a header or footer
function gen_hf(type, str) {
var a, i, page,
lcr = ["left", "center", "right"];
| | | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
var cfmt = abc.cfmt()
// output a header or footer
function gen_hf(type, str) {
var a, i, page,
lcr = ["left", "center", "right"];
a = header_footer(clean_txt(str))
for (i = 0; i < 3; i++) {
str = a[i]
if (!str)
continue
if (str.indexOf('\x0c') >= 0) {
str = str.replace('\x0c', '');
page = " page"
|
| ︙ | ︙ | |||
225 226 227 228 229 230 231 |
<meta name="generator" content="abc2svg-' + abc2svg.version + '"/>\n\
<!-- CreationDate: ' + get_date() + '-->\n\
<style type="text/css">\n\
svg {display:block}\n\
body {width:' + cfmt.pagewidth.toFixed(0) +'px}\n\
p {' + set_pstyle() + 'margin-top:0}\n\
p span {line-height:' + ((cfmt.lineskipfac * 100) | 0).toString() + '%}\n' +
| | > > > > > > > | | | 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
<meta name="generator" content="abc2svg-' + abc2svg.version + '"/>\n\
<!-- CreationDate: ' + get_date() + '-->\n\
<style type="text/css">\n\
svg {display:block}\n\
body {width:' + cfmt.pagewidth.toFixed(0) +'px}\n\
p {' + set_pstyle() + 'margin-top:0}\n\
p span {line-height:' + ((cfmt.lineskipfac * 100) | 0).toString() + '%}\n' +
((header || footer) ? media_f : media_s))
// works with chrome and --headless
if (abc.page)
abc2svg.print('@page{size:' +
(cfmt.pagewidth / 96).toFixed(2) + 'in ' +
(cfmt.pageheight / 96).toFixed(2) + 'in;margin:0}')
else
abc2svg.print('@page{margin:0' + topmargin + ' 0 ' +
botmargin + ' 0}')
abc2svg.print('</style>\n\
<title>abc2svg document</title>\n\
</head>\n\
<body>')
if (header)
gen_hf("header", header)
if (footer)
gen_hf("footer", footer);
|
| ︙ | ︙ |
Changes to util/abcdoc.js.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
window.onerror = function(msg, url, line) {
if (typeof msg == 'string')
alert("window error: " + msg +
"\nURL: " + url +
"\nLine: " + line)
else if (typeof msg == 'object')
alert("window error: " + msg.type + ' ' + msg.target.src)
else
alert("window error: " + msg)
return false
}
| > > > > | < > | | | > > | < | > > > | < | < < < < < < < < < < < < < < < < < < < | > | < > | 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 |
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
(function(){
window.onerror = function(msg, url, line) {
if (typeof msg == 'string')
alert("window error: " + msg +
"\nURL: " + url +
"\nLine: " + line)
else if (typeof msg == 'object')
alert("window error: " + msg.type + ' ' + msg.target.src)
else
alert("window error: " + msg)
return false
}
// function called when abc2svg is fully loaded
function abcdoc() {
var errtxt = '',
new_page = '',
page, // document source
jsdir = document.currentScript ?
document.currentScript.src.match(/.*\//) :
(function() {
var s_a = document.getElementsByTagName('script')
for (var k = 0; k < s_a.length; k++) {
if (s_a[k].src.indexOf('abcdoc-') >= 0)
return s_a[k].src.match(/.*\//) || ''
}
return "" // ??
})(),
user = { // -- abc2svg init argument
errmsg: function(msg, l, c) { // get the errors
errtxt += clean_txt(msg) + '\n'
},
img_out: function(str) { // image output
new_page += str
},
page_format: true // define the non-page-breakable blocks
}
// replace <>& by XML character references
function clean_txt(txt) {
return txt.replace(/<|>|&.*?;|&/g, function(c) {
switch (c) {
case '<': return "<"
case '>': return ">"
case '&': return "&"
}
return c
})
}
// function to load javascript files
abc2svg.loadjs = function(fn, relay, onerror) {
var s = document.createElement('script');
if (/:\/\//.test(fn))
s.src = fn // absolute URL
else
s.src = jsdir + fn;
s.type = 'text/javascript'
if (relay)
s.onload = relay;
s.onerror = onerror || function() {
alert('error loading ' + fn)
}
document.head.appendChild(s)
}
// search the ABC tunes and add their rendering as SVG images
function render() {
var i = 0, j, k, res,
re = /\n%abc|\nX:/g, // start on "%abc" or "X:"
re_stop = /\n<|\n%.begin/g, // stop on "<" and skip "%%begin"
abc = new abc2svg.Abc(user);
abc.tosvg('abcdoc', '%%bgcolor white\n\
%%rightmargin 0.8cm\n\
%%leftmargin 0.8cm\n\
%%topspace 0')
for (;;) {
// get the start of a ABC sequence
|
| ︙ | ︙ | |||
164 165 166 167 168 169 170 171 172 173 174 |
try {
document.body.innerHTML = new_page + page.slice(i)
} catch (e) {
alert("abc2svg bad generated SVG: " + e.message +
"\nStack:\n" + e.stack)
}
}
// wait for the page to be loaded
document.addEventListener("DOMContentLoaded", dom_loaded, false)
| > > > > > > > > > > > > > > > > > > > > > > > > | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
try {
document.body.innerHTML = new_page + page.slice(i)
} catch (e) {
alert("abc2svg bad generated SVG: " + e.message +
"\nStack:\n" + e.stack)
}
} // render()
// --- abcdoc() main code ---
// get the page content
page = document.body.innerHTML;
// accept page formatting
abc2svg.abc_end = function() {}
// load the required modules, then render the music
if (abc2svg.modules.load(page, render))
render()
} // abcdoc()
// loop until abc2svg is fully loaded
function dom_loaded() {
if (typeof abc2svg != "object"
|| !abc2svg.modules) {
setTimeout(dom_loaded, 500)
return
}
abcdoc()
}
// wait for the page to be loaded
document.addEventListener("DOMContentLoaded", dom_loaded, false)
})()
|
Changes to util/abcemb.js.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 33 34 |
else if (typeof msg == 'object')
alert("window error: " + msg.type + ' ' + msg.target.src)
else
alert("window error: " + msg)
return false
}
var errtxt = '',
new_page = '',
| > > > > < < < < | | | > > | > > | | > | > > > > > > | | | 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 |
else if (typeof msg == 'object')
alert("window error: " + msg.type + ' ' + msg.target.src)
else
alert("window error: " + msg)
return false
}
var abc2svg = {}
// function called when abc2svg is fully loaded
function dom_loaded() {
var errtxt = '',
new_page = '',
playing,
abcplay,
page, // document source
a_src = [], // index: #sequence,
// value: [start_idx, end_idx]
a_pe = [], // index: #sequence, value: playing events
glop, // global sequence for play
old_gm,
jsdir = document.currentScript ?
document.currentScript.src.match(/.*\//) :
(function() {
var s_a = document.getElementsByTagName('script')
for (var k = 0; k < s_a.length; k++) {
if (s_a[k].src.indexOf('abcemb-') >= 0)
return s_a[k].src.match(/.*\//) || ''
}
return "" // ??
})(),
// -- abc2svg init argument
user = {
errmsg: function(msg, l, c) { // get the errors
errtxt += clean_txt(msg) + '\n'
},
img_out: function(str) { // image output
new_page += str
},
page_format: true // define the non-page-breakable blocks
};
// play arguments
playconf = {
onend: function() {
playing = false
}
}
// replace <>& by XML character references
function clean_txt(txt) {
return txt.replace(/<|>|&.*?;|&/g, function(c) {
switch (c) {
case '<': return "<"
case '>': return ">"
case '&': return "&"
}
return c
})
}
function endplay() {
playing = false
}
// function called on click on the music
abc2svg.playseq = function(seq) {
var outputs
if (!abcplay) {
if (typeof AbcPlay == "undefined") { // as play-1.js not loaded,
abc2svg.playseq = function(){} // don't come here anymore
return
}
abcplay = AbcPlay(playconf);
}
if (playing) {
abcplay.stop();
return
|
| ︙ | ︙ | |||
110 111 112 113 114 115 116 | return } a_pe[seq] = abcplay.clear() // keep the playing events } abcplay.play(0, 100000, a_pe[seq]) } | < < < < < < < < < < < < < < < < < < < < < | > > > > > > > > > > > > > > > > > > > | 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
return
}
a_pe[seq] = abcplay.clear() // keep the playing events
}
abcplay.play(0, 100000, a_pe[seq])
}
// function to load javascript files
abc2svg.loadjs = function(fn, relay, onerror) {
var s = document.createElement('script');
if (/:\/\//.test(fn))
s.src = fn // absolute URL
else
s.src = jsdir + fn;
s.type = 'text/javascript'
if (relay)
s.onload = relay;
s.onerror = onerror || function() {
alert('error loading ' + fn)
}
document.head.appendChild(s)
}
function render() {
// search the ABC tunes,
// replace them by SVG images with play on click
var i = 0, j, k, res, abc,
seq = 0,
re = /\n%abc|\nX:/g,
re_stop = /\nX:|\n<|\n%.begin/g,
select = window.location.hash.slice(1);
// aweful hack: user.anno_stop must be defined before Abc creation
// for being set later by follow() !
if (typeof follow == "function")
user.anno_stop = function(){};
abc = new abc2svg.Abc(user)
// handle MEI files
j = page.indexOf("<mei ")
if (j >= 0) {
k = page.indexOf("</mei>") + 6
abc.mei2mus(page.slice(j, k))
document.body.innerHTML = new_page
// no play yet
return
}
// initialize the play follow function
if (typeof follow == "function")
follow(abc, user, playconf)
// check if a selection
if (select) {
select = decodeURIComponent(select);
select = page.search(select)
if (select < 0)
select = 0
}
|
| ︙ | ︙ | |||
199 200 201 202 203 204 205 |
k = re_stop.lastIndex - 2;
// selection
if (!select || page[j] != 'X' || (select >= j && select < k)) {
// clicking on the music plays this tune
if (page[j] == 'X') {
| | < < < < | | > | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
k = re_stop.lastIndex - 2;
// selection
if (!select || page[j] != 'X' || (select >= j && select < k)) {
// clicking on the music plays this tune
if (page[j] == 'X') {
new_page += '<div onclick="abc2svg.playseq(' +
a_src.length + ')">\n';
a_src.push([j, k])
} else if (!glop) {
glop = [j, k]
}
try {
abc.tosvg('abcemb', page, j, k)
} catch (e) {
alert("abc2svg javascript error: " + e.message +
"\nStack:\n" + e.stack)
}
if (errtxt) {
new_page += '<pre style="background:#ff8080">' +
errtxt + "</pre>\n";
errtxt = ""
}
abc2svg.abc_end() // close the page if %%pageheight
if (page[j] == 'X')
new_page += '</div>\n'
} // selection
i = k
if (i >= page.length)
break
|
| ︙ | ︙ | |||
249 250 251 252 253 254 255 256 257 |
delete user.img_out; // stop SVG generation
old_gm = user.get_abcmodel;
user.get_abcmodel = function(tsfirst, voice_tb, music_types, info) {
if (old_gm)
old_gm(tsfirst, voice_tb, music_types, info);
abcplay.add(tsfirst, voice_tb)
}
} // dom_loaded()
| > > > > > > > > > > > > > > > > > > > > > > | | | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
delete user.img_out; // stop SVG generation
old_gm = user.get_abcmodel;
user.get_abcmodel = function(tsfirst, voice_tb, music_types, info) {
if (old_gm)
old_gm(tsfirst, voice_tb, music_types, info);
abcplay.add(tsfirst, voice_tb)
}
} // render()
// --- dom_loaded() main code ---
// get the page content
page = document.body.innerHTML
// load the abc2svg core if not done by <script>
if (!abc2svg.Abc) {
abc2svg.loadjs(page.indexOf("<mei ") >= 0 ?
"mei2svg-1.js" :
"abc2svg-1.js",
dom_loaded)
return
}
// accept page formatting
abc2svg.abc_end = function() {}
// load the required modules, then render the music
if (abc2svg.modules.load(page, render))
render()
} // dom_loaded()
// wait for the scripts to be loaded
window.addEventListener("load", function() {setTimeout(dom_loaded, 500)})
|
Added util/abcemb1.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
//#javascript
// abcemb1-1.js file to include in html pages with abc2svg-1.js
//
// This script either:
// - builds a list of the tunes when there is no selection or
// - displays the selected tune.
//
// When the tune is displayed, if playing is not enabled,
// scrolling the music may be done by clicking/taping
// on the 'start scrolling' button.
//
// The header of the tune list ("Tunes:") may be set in a global
// javascript variable 'list_head'.
//
// Copyright (C) 2019 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
window.onerror = function(msg, url, line) {
if (typeof msg == 'string')
alert("window error: " + msg +
"\nURL: " + url +
"\nLine: " + line)
else if (typeof msg == 'object')
alert("window error: " + msg.type + ' ' + msg.target.src)
else
alert("window error: " + msg)
return false
}
// remove the menu button on print
window.onbeforeprint = function() {
var e = document.getElementById("dd")
if (e)
e.style.display = "none"
}
window.onafterprint = function() {
var e = document.getElementById("dd")
if (e)
e.style.display = "block"
}
var abc2svg = {}
// function called when abc2svg is fully loaded
function dom_loaded() {
var errtxt = '',
app = "abcemb",
new_page,
playing,
abcplay,
tune_dur, // scroll tune duration
scroll_to, // scroll timeout
dt, // scroll delta per timeout
sY, // current scroll Y
page, // document source
pe, // playing events
jsdir = document.currentScript ?
document.currentScript.src.match(/.*\//) :
(function() {
var s_a = document.getElementsByTagName('script')
for (var k = 0; k < s_a.length; k++) {
if (s_a[k].src.indexOf('abcemb1-') >= 0)
return s_a[k].src.match(/.*\//) || ''
}
return "" // ??
})(),
// -- abc2svg init argument
user = {
errmsg: function(msg, l, c) { // get the errors
errtxt += clean_txt(msg) + '\n'
},
// function called before SVG generation
get_abcmodel: function(tsfirst, voice_tb) {
var d, i, n, pf,
s = tsfirst
while (1) {
if (s.tempo && !pf) {
d = 0;
n = s.tempo_notes.length
for (i = 0; i < n; i++)
d += s.tempo_notes[i];
pf = d * s.tempo / 60
}
if (!s.ts_next)
break
s = s.ts_next
}
if (!pf)
pf = abc2svg.C.BLEN / 8; // default: Q:1/4=120
// abc2svg.C.BLEN / 4 * 120 / 60
tune_dur = s.time / pf
},
img_out: function(str) { // image output
new_page += str
},
page_format: true // define the non-page-breakable blocks
};
// play arguments
playconf = {
onend: function() {
playing = false
}
}
// replace <>& by XML character references
function clean_txt(txt) {
return txt.replace(/<|>|&.*?;|&/g, function(c) {
switch (c) {
case '<': return "<"
case '>': return ">"
case '&': return "&"
}
return c
})
}
// scroll the displayed music
function do_scroll(old) {
// if start, get the window parameters and delay the first scroll
if (!old) {
var d = document.documentElement;
// time for scrolling one pixel
dt = tune_dur / d.scrollHeight
// start scrolling at this time (1/4 of the first screen)
var ttop = dt * d.clientHeight / 4
document.getElementById("ss").style.display = "block"
scroll_to = setTimeout(do_scroll, ttop * 1000, 1)
// (in Android Browser, remove the address bar)
window.scrollTo(0, 8); // go to the top
sY = 0;
} else {
if (sY == window.pageYOffset) { // no scroll -> finished
document.getElementById("ss").style.display = "none"
scroll_to = null
return
}
sY = window.pageYOffset;
window.scrollTo(0, sY + 1);
scroll_to = setTimeout(do_scroll, dt * 1000, 1)
}
}
// menu functions
// click inside/outside of the menu button
window.onmouseup = function(event) {
var e = document.getElementById("dc")
if (e) {
if (event.target.className == "db")
e.classList.toggle("show")
else if (e.classList.contains("show"))
e.classList.remove("show")
}
}
// source edit
abc2svg.src_upd = function() {
page = document.getElementById('ta').value
abc2svg.get_sel()
} // src_upd()
abc2svg.src_edit = function() {
// offer a textarea with the ABC source and 2 buttons
document.body.innerHTML = '\
<textarea id="ta" rows="50" cols="80">' + page + '</textarea>\
<br/>\
<a href="#" onclick="abc2svg.src_upd()"> Apply </a> - \
<a href="#" onclick="abc2svg.get_sel()"> Cancel </a>'
} // src_edit()
// start/stop scrolling when no play
abc2svg.st_scroll = function() {
if (scroll_to) {
clearTimeout(scroll_to);
document.getElementById("ss").style.display = "none"
scroll_to = null
} else {
scroll_to = setTimeout(do_scroll, 500, 0) // scroll start
}
}
// function called on click in the music:
// start / stop playing and scrolling
abc2svg.playseq = function(select) {
var outputs
if (!abcplay) { // if first time
delete user.img_out; // stop SVG generation
user.get_abcmodel = function(tsfirst, voice_tb) {
abcplay.add(tsfirst, voice_tb)
}
abcplay = AbcPlay(playconf)
}
// stop
if (playing) {
if (scroll_to) { // if scrolling active
clearTimeout(scroll_to); // stop it
scroll_to = null
}
abcplay.stop();
return
}
playing = true
if (!pe) { // if no playing event
var abc = new abc2svg.Abc(user);
abcplay.clear();
abc.tosvg("play", "%%play")
if (select)
abc.tosvg(app, "%%select " + select)
try {
abc.tosvg(app, page)
} catch(e) {
alert(e.message + '\nabc2svg tosvg bug - stack:\n' + e.stack);
playing = false;
pe = null
return
}
pe = abcplay.clear() // keep the playing events
}
if (document.documentElement.scrollHeight > window.innerHeight)
scroll_to = setTimeout(do_scroll, 500, 0); // scroll start
abcplay.play(0, 100000, pe)
} // playseq()
// function to load javascript files
abc2svg.loadjs = function(fn, relay, onerror) {
var s = document.createElement('script');
if (/:\/\//.test(fn))
s.src = fn // absolute URL
else
s.src = jsdir + fn;
s.type = 'text/javascript'
if (relay)
s.onload = relay;
s.onerror = onerror || function() {
alert('error loading ' + fn)
}
document.head.appendChild(s)
} // loadjs()
// build a list of the tunes
abc2svg.get_sel = function() {
var j, k,
n = 0,
i = 0,
t = (typeof list_head == "undefined" ? "Tunes:" : list_head) + '<ul>\n'
// --- get_sel() main ---
for (;;) {
i = page.indexOf("\nX:", i)
if (i < 0)
break
j = page.indexOf("\nT:", ++i)
if (j < 0)
break
n++;
t += '<li><a \
style="cursor:pointer;color:blue;text-decoration:underline" \
onclick="abc2svg.do_render(\'' + page.slice(i, j) + '\')">'
k = page.indexOf("\n", j + 1);
t += page.slice(j + 3, k)
if (page[k + 1] == 'T' && page[k + 2] == ':') {
j = k + 3;
k = page.indexOf("\n", j)
if (k > 0)
t += " - " + page.slice(j, k)
}
t += '</a></li>\n';
i = k
}
if (n <= 1) {
abc2svg.do_render()
return
}
t += '</ul>';
document.body.innerHTML = t
} // get_sel()
// search/ask the tune to be rendered
function render() {
var select = window.location.hash.slice(1) // after '#'
// create styles for the menu
var sty = document.createElement('style')
sty.innerHTML = '\
.dd{position:fixed;top:0;bottom:0;right:0;height:40px;cursor:pointer;font-size:16px}\
#ss{display:none;background-color:red}\
.db{display:block;margin:5px; padding:5px;background-color:yellow}\
.db:hover,.db:focus{background-color:lightgreen}\
.dc{position:absolute;left:-70px;min-width:100px;display:none;background-color:yellow}\
.dc label{display:block;padding:0 5px 0 5px;margin:2px}\
.dc label:hover{outline:solid;outline-width:2px}\
.show{display:block}'
document.head.appendChild(sty)
// if no selection and many tunes, get the references of the tunes
// and ask which one to display
if (!select)
abc2svg.get_sel()
else
abc2svg.do_render(decodeURIComponent(select))
} // render()
// replace the (previous) body by the music
abc2svg.do_render = function(select) {
// aweful hack: user.anno_stop must be defined before Abc creation
// for being set later by follow() !
if (typeof follow == "function")
user.anno_stop = function(){};
abc = new abc2svg.Abc(user)
new_page = ""
// initialize the play follow function
if (typeof follow == "function")
follow(abc, user, playconf)
if (select) {
if (typeof AbcPlay != "undefined")
new_page += '<div onclick="abc2svg.playseq(\'' +
select + '\')">'
abc.tosvg(app, "%%select " + select)
} else if (typeof AbcPlay != "undefined") {
new_page += '<div onclick="abc2svg.playseq()">'
}
try {
abc.tosvg(app, page)
} catch (e) {
alert("abc2svg javascript error: " + e.message +
"\nStack:\n" + e.stack)
}
if (typeof AbcPlay != "undefined")
new_page += '</div>'
if (errtxt) {
new_page += '<pre style="background:#ff8080">' +
errtxt + "</pre>\n";
errtxt = ""
}
// add the menu
new_page += '\
<div id="dd" class="dd">\
<label class="db">|||</label>\
<div id="dc" class="dc">\
<label id="edit" onclick="abc2svg.src_edit()">Source edit</label>\
<label id="list" onclick="abc2svg.get_sel()">Tune list</label>\
<label id="play" onclick="abc2svg.st_scroll()">Scroll</label>\
</div>\
</div>\
<label id="ss" class="dd" onclick="abc2svg.st_scroll()">Scroll<br/>stop</label>'
// change the page
try {
document.body.innerHTML = new_page
} catch (e) {
alert("abc2svg bad generated SVG: " + e.message +
"\nStack:\n" + e.stack)
return
}
// update the menu
setTimeout(function() {
// remove scroll in menu if play or not a big tune
if (typeof AbcPlay != "undefined"
|| document.documentElement.scrollHeight <= window.innerHeight)
document.getElementById("play").style.display = "none"
}, 500)
} // render()
// --- dom_loaded() main code ---
// load the abc2svg core if not done by <script>
if (!abc2svg.Abc) {
abc2svg.loadjs("abc2svg-1.js", dom_loaded)
return
}
// get the page content
page = document.body.innerHTML;
// accept page formatting
abc2svg.abc_end = function() {}
// load the required modules, then render the music
if (abc2svg.modules.load(page, render))
render()
} // dom_loaded()
// wait for the scripts to be loaded
window.addEventListener("load", function() {setTimeout(dom_loaded, 500)})
|
Changes to util/abcemb2.js.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
alert("window error: " + msg.type + ' ' + msg.target.src)
else
alert("window error: " + msg)
return false
}
var errtxt = '',
| < | > > | > > | | | | 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 |
alert("window error: " + msg.type + ' ' + msg.target.src)
else
alert("window error: " + msg)
return false
}
var errtxt = '',
elts, // ABC HTML elements
tunes = '', // source of the ABC sequences
indx = [], // indexes of the tunes in tunes
select,
playing,
abcplay,
playconf = {
onend: endplay
},
a_pe = [], // index: #sequence, value: playing events
glop, // global sequence index for play
old_gm,
jsdir = document.currentScript ?
document.currentScript.src.match(/.*\//) :
(function() {
var s_a = document.getElementsByTagName('script')
for (var k = 0; k < s_a.length; k++) {
if (s_a[k].src.indexOf('abcemb2-') >= 0)
return s_a[k].src.match(/.*\//) || ''
}
return "" // ??
})(),
// -- abc2svg init argument
user = {
errmsg: function(msg, l, c) { // get the errors
errtxt += clean_txt(msg) + '\n'
},
img_out: function(str) { // image output
new_page += str
},
page_format: true // define the non-page-breakable blocks
}
// replace <>& by XML character references
function clean_txt(txt) {
return txt.replace(/<|>|&.*?;|&/g, function(c) {
switch (c) {
case '<': return "<"
case '>': return ">"
|
| ︙ | ︙ | |||
115 116 117 118 119 120 121 |
}
abcplay.play(0, 100000, a_pe[i])
}
// function called when the page is loaded
function dom_loaded() {
| < < < < < < < | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
}
abcplay.play(0, 100000, a_pe[i])
}
// function called when the page is loaded
function dom_loaded() {
// convert HTML to ABC
function toabc(s) {
return s.replace(/>/g, '>')
.replace(/</g, '<')
.replace(/&/g, '&')
.replace(/[ \t]+(%%)/g, '$1')
.replace(/[ \t]+(.:)/g, '$1')
|
| ︙ | ︙ | |||
159 160 161 162 163 164 165 |
tunes += toabc(elt.innerHTML) + '\n'
}
indx[i] = tunes.length;
ready()
}
function ready() {
| | > > > > > > > > > | | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
tunes += toabc(elt.innerHTML) + '\n'
}
indx[i] = tunes.length;
ready()
}
function ready() {
var i, j, abc
// load the required modules
if (!abc2svg.modules.load(tunes, ready))
return
// accept page formatting
abc2svg.abc_end = function() {}
var sel = window.location.hash.slice(1)
if (sel)
select = '%%select ' + decodeURIComponent(sel);
// aweful hack: user.anno_stop must be defined before Abc creation
// for being set later by follow() !
if (typeof follow == "function")
user.anno_stop = function(){};
abc = new abc2svg.Abc(user)
// initialize the play follow function
if (typeof follow == "function")
follow(abc, user, playconf)
// generate and replace
for (i = 0; i < elts.length; i++) {
new_page = ""
// set the playing callback
j = tunes.indexOf('X:', indx[i])
if (j >= 0 && j < indx[i + 1])
new_page += '<div onclick="playseq(' + i + ')">\n'
else if (glop == undefined)
|
| ︙ | ︙ | |||
197 198 199 200 201 202 203 |
try {
abc.tosvg('abcemb2', tunes, indx[i], indx[i + 1])
} catch (e) {
alert("abc2svg javascript error: " + e.message +
"\nStack:\n" + e.stack)
}
if (errtxt) {
| | | | 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
try {
abc.tosvg('abcemb2', tunes, indx[i], indx[i + 1])
} catch (e) {
alert("abc2svg javascript error: " + e.message +
"\nStack:\n" + e.stack)
}
if (errtxt) {
new_page += '<pre style="background:#ff8080">' +
errtxt + "</pre>\n";
errtxt = ""
}
try {
elts[i].innerHTML = new_page
} catch (e) {
alert("abc2svg bad generated SVG: " + e.message +
"\nStack:\n" + e.stack)
|
| ︙ | ︙ | |||
224 225 226 227 228 229 230 | if (old_gm) old_gm(tsfirst, voice_tb, music_types, info); abcplay.add(tsfirst, voice_tb) } } // dom_loaded() // wait for the page to be loaded | | | 229 230 231 232 233 234 235 236 |
if (old_gm)
old_gm(tsfirst, voice_tb, music_types, info);
abcplay.add(tsfirst, voice_tb)
}
} // dom_loaded()
// wait for the page to be loaded
window.addEventListener("load", function() {setTimeout(dom_loaded, 500)})
|
Added util/abcweb2.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
//#javascript
// abcemb2-1.js file to include in html pages with abc2svg-1.js
//
// Copyright (C) 2018-2019 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
window.onerror = function(msg, url, line) {
if (typeof msg == 'string')
alert("window error: " + msg +
"\nURL: " + url +
"\nLine: " + line)
else if (typeof msg == 'object')
alert("window error: " + msg.type + ' ' + msg.target.src)
else
alert("window error: " + msg)
return false
}
if (typeof abc2svg == "undefined")
var abc2svg = {}
// function called when abc2svg is fully loaded
function dom_loaded() {
var abc, i, elt,
errtxt = '',
elts, // ABC HTML elements
abcsrc = "", // ABC source
indx = [], // indexes of the tunes in abcsrc
select,
playing,
abcplay,
playconf = {
onend: function() {
playing = false
}
},
tune_lst, // array of [tsfirst, voice_tb] per tune
jsdir = document.currentScript ?
document.currentScript.src.match(/.*\//) :
(function() {
var s_a = document.getElementsByTagName('script')
for (var k = 0; k < s_a.length; k++) {
if (s_a[k].src.indexOf('abcweb2-') >= 0)
return s_a[k].src.match(/.*\//) || ''
}
return "" // ??
})(),
// abc2svg init argument
user = {
errmsg: function(msg, l, c) { // get the errors
errtxt += clean_txt(msg) + '\n'
},
img_out: function(str) { // image output
if (str.slice(0, 4) == "<svg")
new_page += '<svg class="abc' +
abc.tunes.length + '"' +
str.slice(4)
else
new_page += str
},
page_format: true // define the non-page-breakable blocks
} // user
// replace <>& by XML character references
function clean_txt(txt) {
return txt.replace(/<|>|&.*?;|&/g, function(c) {
switch (c) {
case '<': return "<"
case '>': return ">"
case '&': return "&"
}
return c
})
} // clean_txt()
// function called on click in the screen
abc2svg.playseq = function(evt) {
var outputs, e, i,
tunes = abc.tunes,
svg = evt.target
// search if click in a SVG image
while (svg.tagName != 'svg') {
svg = svg.parentNode
if (!svg)
return
}
i = svg.getAttribute('class').match(/abc(\d)/)
if (!i)
return
i = i[1] - 1 // tune number
// initialize the play object
if (!abcplay) {
// if play-1.js is not loaded, don't come here anymore
if (typeof AbcPlay == "undefined") {
abc2svg.playseq = function(){}
return
}
abcplay = AbcPlay(playconf)
}
if (playing) {
abcplay.stop()
return
}
// if first time, get the tunes references
// and generate the play data of all tunes
if (tunes.length) {
tune_lst = tunes.slice(0) // (array copy)
while (1) {
e = tunes.shift()
if (!e)
break
abcplay.add(e[0], e[1])
}
}
playing = true
abcplay.play(tune_lst[i][0], null)
} // playseq()
function render() {
var i, sel
// aweful hack: user.anno_stop must be defined before Abc creation
// for being set later by follow() !
if (typeof follow == "function")
user.anno_stop = function(){}
abc = new abc2svg.Abc(user)
// initialize the play follow function
if (typeof follow == "function")
follow(abc, user, playconf)
// do the selection
sel = window.location.hash.slice(1)
if (sel) {
select = '%%select ' + decodeURIComponent(sel)
abc.tosvg("abcemb2", select)
}
// generate and replace
for (i = 0; i < elts.length; i++) {
new_page = ""
try {
abc.tosvg('abcemb2', abcsrc, indx[i], indx[i + 1])
} catch (e) {
alert("abc2svg javascript error: " + e.message +
"\nStack:\n" + e.stack)
}
if (errtxt) {
new_page += '<pre style="background:#ff8080">' +
errtxt + "</pre>\n"
errtxt = ""
}
try {
elts[i].innerHTML = new_page
} catch (e) {
alert("abc2svg bad generated SVG: " + e.message +
"\nStack:\n" + e.stack)
}
}
abc2svg.abc_end() // close the page if %%pageheight
} // render()
// convert HTML to ABC
function toabc(s) {
return s.replace(/>/g, '>')
.replace(/</g, '<')
.replace(/&/g, '&')
.replace(/[ \t]+(%%)/g, '$1')
.replace(/[ \t]+(.:)/g, '$1')
} // toabc()
// function to load javascript files
abc2svg.loadjs = function(fn, relay, onerror) {
var s = document.createElement('script')
if (/:\/\//.test(fn))
s.src = fn // absolute URL
else
s.src = jsdir + fn
s.type = 'text/javascript'
if (relay)
s.onload = relay
s.onerror = onerror || function() {
alert('error loading ' + fn)
}
document.head.appendChild(s)
}
// accept page formatting
abc2svg.abc_end = function() {}
// prepare for play on click
window.onclick = abc2svg.playseq
// extract the ABC source
elts = document.getElementsByClassName('abc')
for (i = 0; i < elts.length; i++) {
elt = elts[i]
indx[i] = abcsrc.length
abcsrc += toabc(elt.innerHTML) + '\n'
}
indx[i] = abcsrc.length
// load the required modules
if (abc2svg.modules.load(abcsrc, render))
render()
} // dom_loaded()
// wait for the page to be loaded
window.addEventListener("load", dom_loaded)
|
Changes to util/follow.js.
| ︙ | ︙ | |||
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 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
var ref = [],
ignore_types = {
beam:true,
slur:true,
tuplet:true
}
user.anno_stop = function(type, start, stop, x, y, w, h) {
if (ignore_types[type])
return
ref[start] = stop; // keep the source reference
// create a rectangle
abc.out_svg('<rect class="abcr _' + start + '_" x="');
abc.out_sxsy(x, '" y="', y);
abc.out_svg('" width="' + w.toFixed(2) +
'" height="' + h.toFixed(2) + '"/>\n')
}
| > > | | | | | < < < < < < < < < < | < | < | 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 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
// init
function follow(abc, user, playconf) {
var ref = [],
ignore_types = {
beam:true,
slur:true,
tuplet:true
}
user.anno_stop = function(type, start, stop, x, y, w, h) {
if (ignore_types[type])
return
ref[start] = stop; // keep the source reference
// create a rectangle
abc.out_svg('<rect class="abcr _' + start + '_" x="');
abc.out_sxsy(x, '" y="', y);
abc.out_svg('" width="' + w.toFixed(2) +
'" height="' + h.toFixed(2) + '"/>\n')
}
playconf.onnote = function(i, on) {
var elts = document.getElementsByClassName('_' + i + '_')
if (elts && elts[0])
elts[0].style.fillOpacity = on ? 0.4 : 0
}
// create the style of the rectangles
var sty = document.createElement("style");
sty.innerHTML = ".abcr {fill: #d00000; fill-opacity: 0; z-index: 15}";
document.head.appendChild(sty)
} // follow()
|
Changes to util/json.js.
| ︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
links = {
next: true,
prev: true,
ts_next: true,
ts_prev: true,
extra: true,
p_v: true,
dd_st: true
}
// generate an attribute
function attr_gen(ind, attr, val) {
var i, e,
indn = ind + inb // next indentation
| > > > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
links = {
next: true,
prev: true,
ts_next: true,
ts_prev: true,
extra: true,
p_v: true,
s: true,
sn: true,
tie_s: true,
dd_st: true
}
// generate an attribute
function attr_gen(ind, attr, val) {
var i, e,
indn = ind + inb // next indentation
|
| ︙ | ︙ |
Changes to util/midi.js.
1 2 3 | //#javascript // Set the MIDI pitches in the notes // | | > > > < < < | > | | | | < < < < < < < < | < < < < < < | < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < | | > > > > > > > > > | > > | | > | < | | < | < < | | | < < | | | > | < < > > | | | | | < < | | < < < < < | < < < < < < < < < | | | | < < > < < | | < < | < < < < | | < < < < < < < < < < < < < < | > | 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 107 108 109 110 111 112 113 114 115 116 117 |
//#javascript
// Set the MIDI pitches in the notes
//
// Copyright (C) 2015-2019 Jean-Francois Moine
//
// This file is part of abc2svg-core.
//
// abc2svg-core is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg-core is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// Usage:
// // Create a AbcMIDI object
// var abcmidi = AbcMIDI()
//
// // Define a get_abcmodel() callback function
// // This one is called by abc2svg after ABC parsing
// user.get_abcmodel = my_midi_callback
//
// // In this function
// function my_midi_callback(tsfirst, voice_tb, music_types, info) {
//
// // set the MIDI pitches
// abcmidi.add(tsfirst, voice_tb);
//
// // The MIDI pitches are stored in the notes
// // s.notes[i].midi
// }
// AbcMIDI creation
function AbcMIDI() {
var C = abc2svg.C
return { // returned object
// add MIDI pitches
add: function(s, // starting symbol
voice_tb) { // voice table
var p_v, s,
temper = voice_tb[0].temper, // (set by the module temper.js)
v = voice_tb.length
// initialize the clefs and keys
while (--v >= 0) {
p_v = voice_tb[v]
if (!p_v.sym)
continue
if (p_v.key.k_bagpipe)
// detune in cents for just intonation in A
// C ^C D _E E F ^F G _A A _B B
// 15.3 -14.0 -2.0 -10.0 1.9 13.3 -16.0 -31.8 -12.0 0.0 11.4 3.8
// (C is ^C, F is ^F and G is =G)
// 86 84
// temp = [100-14, -14, -2, -10, 2, 100-16, -16, -32, -12, 0, 11, 4]
// but 'A' bagpipe = 480Hz => raise Math.log2(480/440)*1200 = 151
temper = new Float32Array([
2.37, 1.37, 1.49, 1.41, 1.53, 2.35, 1.35, 1.19, 1.39, 1.51, 1.62, 1.55
])
s = p_v.clef
vloop(p_v.sym,
p_v.key.k_sndtran || 0,
s.clef_octave && !s.clef_oct_transp ?
(s.clef_octave / 7 * 40) : 0)
}
function vloop(s, sndtran, ctrans) {
var i, g, note,
transp = sndtran + ctrans
function midi_set(note) {
var m = abc2svg.b40m(note.b40 + transp)
if (temper // if not equal temperament
&& (!note.acc
|| note.acc | 0 == note.acc)) // and not micro-tone
m += temper[m % 12]
note.midi = m
}
while (s) {
switch (s.type) {
case C.CLEF:
ctrans = (s.clef_octave && !s.clef_oct_transp) ?
(s.clef_octave / 7 * 40) : 0
transp = ctrans + sndtran
break
case C.KEY:
if (s.k_sndtran != undefined) {
sndtran = s.k_sndtran
transp = ctrans + sndtran
}
break
case C.GRACE:
for (g = s.extra; g; g = g.next) {
for (i = 0; i <= g.nhd; i++)
midi_set(g.notes[i])
}
break
case C.NOTE:
for (i = 0; i <= s.nhd; i++)
midi_set(s.notes[i])
break
}
s = s.next
}
} // vloop()
} // add()
} // returned object
} // end AbcMidi
|
Changes to util/play.js.
| ︙ | ︙ | |||
80 81 82 83 84 85 86 |
function play2(out) {
var o
if (!out)
out = []
o = audio5.get_outputs() // get the HTML5 audio port
if (o)
| | > | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
function play2(out) {
var o
if (!out)
out = []
o = audio5.get_outputs() // get the HTML5 audio port
if (o)
Array.prototype.push.apply(out, o)
if (out.length == 0) {
if (conf.onend) // no output port
conf.onend()
return
}
if (out.length == 1) {
o = 0 // only one port
} else {
o = -1 // ask which port?
var pr = "Use"
for (var i = 0; i < out.length; i++)
|
| ︙ | ︙ | |||
143 144 145 146 147 148 149 | if (typeof Midi5 == "function") midi5 = Midi5(conf) if (typeof Audio5 == "function") audio5 = Audio5(conf); return abcplay } // AbcPlay | > > > > | 144 145 146 147 148 149 150 151 152 153 154 | if (typeof Midi5 == "function") midi5 = Midi5(conf) if (typeof Audio5 == "function") audio5 = Audio5(conf); return abcplay } // AbcPlay // nodejs if (typeof module == 'object' && typeof exports == 'object') exports.AbcPlay = AbcPlay |
Added util/sndaud.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 |
// sndaud5.js - audio output using HTML5 audio
//
// Copyright (C) 2019 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
// Audio5 creation
// @conf: configuration object - all items are optional:
// ac: audio context - (default: created on play start)
// sfu: soundfont URL (sf2 base64 encoded - default: "Scc1t2")
// onend: callback function called at end of playing
// Argument:
// repv: last repeat variant number
// onnote: callback function called on note start/stop playing
// Arguments:
// i: start index of the note in the ABC source
// on: true on note start, false on note stop
// instr_load: function to load the sound font of an instrument
// (optional)
// Arguments:
// instr: MIDI instrument number
// done: callback function in case of success
// Arguments: soundfont in binary format
// fail: callback function in case of error
// no argument
// errmsg: function called on error (default: alert)
//
// When playing, the following items must/may be set:
// gain: (mandatory) volume, must be set to [0..1]
// speed: (mandatory) must be set to 1
// new_speed: (optional) new speed value
// Audio5 methods
// get_outputs() - get the output devices
// return ['sf2'] or null
//
// play() - start playing
// @start -
// @stop: start and stop music symbols
// @level: repeat variant (optional, default = 0)
//
// stop() - stop playing
//
// set_vol() - set the current sound volume
// @volume: range [0..1] - undefined = return current value
var abcsf2 = [] // SF2 instruments
function Audio5(i_conf) {
var C = abc2svg.C,
conf = i_conf, // configuration
onend = function() {},
onnote = function() {},
errmsg = alert,
ac, // audio context
gain, // global gain
// instruments/notes
instr = [], // [voice] bank + instrument
params = [], // [instr][key] note parameters per instrument
rates = [], // [instr][key] playback rates
w_instr = 0, // number of instruments being loaded
// -- play the memorized events --
s_cur, // current music symbol
s_end, // last music symbol / null
stop, // stop playing
repn, // don't repeat when true
repv, // repeat level (variant number)
stime, // start playing time
timouts = [] // note start events
// default sound font load function
if (!conf.instr_load) {
conf.instr_load = function(instr, done, fail) {
abc2svg.loadjs(conf.sfu + '/' + instr + '.js',
function() {
done(b64dcod(abcsf2[instr]))
},
fail
)
}
}
// base64 stuff
var b64d = []
function init_b64d() {
var b64l = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
l = b64l.length
for (var i = 0; i < l; i++)
b64d[b64l[i]] = i
b64d['='] = 0
}
function b64dcod(s) {
var i, t, dl, a,
l = s.length,
j = 0
dl = l * 3 / 4 // destination length
if (s[l - 1] == '=') {
if (s[l - 2] == '=')
dl--
dl--
l -= 4
}
a = new Uint8Array(dl)
for (i = 0; i < l; i += 4) {
t = (b64d[s[i]] << 18) +
(b64d[s[i + 1]] << 12) +
(b64d[s[i + 2]] << 6) +
b64d[s[i + 3]]
a[j++] = (t >> 16) & 0xff
a[j++] = (t >> 8) & 0xff
a[j++] = t & 0xff
}
if (l != s.length) {
t = (b64d[s[i]] << 18) +
(b64d[s[i + 1]] << 12) +
(b64d[s[i + 2]] << 6) +
b64d[s[i + 3]]
a[j++] = (t >> 16) & 0xff
if (j < dl)
a[j++] = (t >> 8) & 0xff
}
return a
}
// copy a sf2 sample to an audio buffer
// @b = audio buffer (array of [-1..1])
// @s = sf2 sample (PCM 16 bits)
function sample_cp(b, s) {
var i, n,
a = b.getChannelData(0) // destination = array of float32
for (i = 0; i < s.length; i++)
a[i] = s[i] / 196608 // volume divided by 6
}
// create all notes of an instrument
function sf2_create(parser, instr) {
var i, sid, gen, parm, sampleRate, sample,
infos = parser.getInstruments()[0].info
rates[instr] = []
for (i = 0; i < infos.length; i++) {
gen = infos[i].generator
if (!gen.sampleID) // (empty generator!)
continue
sid = gen.sampleID.amount
sampleRate = parser.sampleHeader[sid].sampleRate
sample = parser.sample[sid]
parm = {
attack: Math.pow(2, (gen.attackVolEnv ?
gen.attackVolEnv.amount : -12000) / 1200),
hold: Math.pow(2, (gen.holdVolEnv ?
gen.holdVolEnv.amount : -12000) / 1200),
decay: Math.pow(2, (gen.decayVolEnv ?
gen.decayVolEnv.amount : -12000) / 1200) / 3,
sustain: gen.sustainVolEnv ?
(gen.sustainVolEnv.amount / 1000) : 0,
// release: Math.pow(2, (gen.releaseVolEnv ?
// gen.releaseVolEnv.amount : -12000) / 1200),
buffer: ac.createBuffer(1,
sample.length,
sampleRate)
}
parm.hold += parm.attack
parm.decay += parm.hold
// sustain > 40dB is not audible
if (parm.sustain >= .4)
parm.sustain = 0.01 // must not be null
else
parm.sustain = 1 - parm.sustain / .4
sample_cp(parm.buffer, sample)
if (gen.sampleModes && (gen.sampleModes.amount & 1)) {
parm.loopStart = parser.sampleHeader[sid].startLoop /
sampleRate
parm.loopEnd = parser.sampleHeader[sid].endLoop /
sampleRate
}
// define the notes
var scale = (gen.scaleTuning ?
gen.scaleTuning.amount : 100) / 100,
tune = (gen.coarseTune ? gen.coarseTune.amount : 0) +
(gen.fineTune ? gen.fineTune.amount : 0) / 100 +
parser.sampleHeader[sid].pitchCorrection / 100 -
(gen.overridingRootKey ?
gen.overridingRootKey.amount :
parser.sampleHeader[sid].originalPitch)
for (j = gen.keyRange.lo; j <= gen.keyRange.hi; j++) {
rates[instr][j] = Math.pow(Math.pow(2, 1 / 12),
(j + tune) * scale)
params[instr][j] = parm
}
}
} // sf2_create()
// load an instrument (.js file)
function load_instr(instr) {
w_instr++
conf.instr_load(instr,
function(sf2_bin) {
var parser = new sf2.Parser(sf2_bin)
parser.parse()
sf2_create(parser, instr)
if (--w_instr == 0)
play_start()
},
function() {
errmsg('could not find the instrument ' +
((instr / 128) | 0).toString() + '-' +
(instr % 128).toString())
if (--w_instr == 0)
play_start()
})
} // load_instr()
// start loading the instruments
function load_res() {
var i,
s = s_cur
while (s) {
i = s.instr
if (i != undefined && !params[i]) {
params[i] = []
load_instr(i)
}
s = s.ts_next
}
}
// create a note
// @s = symbol
// @key = MIDI key + detune
// @t = audio start time
// @d = duration adjusted for speed
function note_run(s, key, t, d) {
var g, st,
instr = s.instr,
parm = params[instr][key | 0],
o = ac.createBufferSource()
if (!parm) // if the instrument could not be loaded
return // or if it has not this key
o.buffer = parm.buffer
if (parm.loopStart) {
o.loop = true
o.loopStart = parm.loopStart
o.loopEnd = parm.loopEnd
}
if (o.detune) {
var dt = (key * 100) % 100
if (dt) // if micro-tone
o.detune.value = dt
}
// o.playbackRate.setValueAtTime(parm.rate, ac.currentTime)
o.playbackRate.value = rates[instr][key]
g = ac.createGain()
if (parm.hold < 0.002) {
g.gain.setValueAtTime(1, t)
} else {
if (parm.attack < 0.002) {
g.gain.setValueAtTime(1, t)
} else {
g.gain.setValueAtTime(0, t)
g.gain.linearRampToValueAtTime(1, t + parm.attack)
}
g.gain.setValueAtTime(1, t + parm.hold)
}
g.gain.exponentialRampToValueAtTime(parm.sustain,
t + parm.decay)
o.connect(g)
g.connect(gain)
// start the note
o.start(t)
o.stop(t + d)
} // note_run()
// handle a tie
function do_tie(s, b40, d) {
var i, note,
v = s.v,
end_time = s.time + s.dur
// search the end of the tie
while (1) {
s = s.ts_next
if (!s)
return d
switch (s.type) {
case C.BAR:
if (s.rep_p) {
if (!repn) {
s = s.rep_p
end_time = s.time
}
}
if (s.rep_s) {
if (!s.rep_s[repv + 1])
return d
s = s.rep_s[repv + 1]
end_time = s.time
}
while (s.ts_next && s.ts_next.type == C.BAR)
s = s.ts_next
}
if (s.time > end_time)
return d
if (s.type == C.NOTE && s.v == v)
break
}
i = s.notes.length
while (--i >= 0) {
note = s.notes[i]
if (note.b40 == b40) {
note.ti2 = true // the sound is generated
d += s.pdur / conf.speed
return note.tie_ty ? do_tie(s, b40, d) : d
}
}
return d
} // do_tie()
// generate 2 seconds of music
function play_next() {
var d, i, st, m, note, g, s2, t, maxt,
s = s_cur
if (stop) { // stop
onend(repv)
return
}
while (s.noplay) {
s = s.ts_next
if (!s || s == s_end) {
onend(repv)
return
}
}
t = stime + s.ptim / conf.speed // start time
// if speed change, shift the start time
if (conf.new_speed) {
stime = ac.currentTime -
(ac.currentTime - stime) *
conf.speed / conf.new_speed
conf.speed = conf.new_speed
conf.new_speed = 0
t = stime + s.ptim / conf.speed
}
maxt = t + 2 // max time = now + 2 seconds
timouts = []
while (1) {
switch (s.type) {
case C.BAR:
if (s.bar_type.slice(-1) == ':') // left repeat
repv = 0
if (s.rep_p) { // right repeat
if (!repn) {
stime += (s.ptim - s.rep_p.ptim) /
conf.speed
s = s.rep_p // left repeat
t = stime + s.ptim / conf.speed
repn = true
break
}
repn = false
}
if (s.rep_s) { // first variant
s2 = s.rep_s[++repv] // next variant
if (s2) {
stime += (s.ptim - s2.ptim) /
conf.speed
s = s2
t = stime + s.ptim / conf.speed
repn = false
} else { // end of tune
s = s_end
break
}
}
while (s.ts_next && s.ts_next.type == C.BAR)
s = s.ts_next
break
case C.GRACE:
for (g = s.extra; g; g = g.next) {
d = g.pdur / conf.speed
for (m = 0; m <= g.nhd; m++) {
note = g.notes[m]
note_run(g,
note.midi,
t + g.ptim - s.ptim,
//fixme: there may be a tie...
d)
}
}
break
case C.NOTE:
d = s.pdur / conf.speed
for (m = 0; m <= s.nhd; m++) {
note = s.notes[m]
if (note.ti2)
continue
note_run(s,
note.midi,
t,
note.tie_ty ?
do_tie(s, note.b40, d) : d)
}
// fall thru
case C.REST:
d = s.pdur / conf.speed
// follow the notes/rests while playing
i = s.istart
st = (t - ac.currentTime) * 1000
timouts.push(setTimeout(onnote, st, i, true))
setTimeout(onnote, st + d * 1000, i, false)
break
}
while (1) {
if (s == s_end || !s.ts_next) {
setTimeout(onend,
(t - ac.currentTime + d) * 1000,
repv)
s_cur = s
return
}
s = s.ts_next
if (!s.noplay)
break
}
t = stime + s.ptim / conf.speed // next time
if (t > maxt)
break
}
s_cur = s
// delay before next sound generation
timouts.push(setTimeout(play_next, (t - ac.currentTime)
* 1000 - 300)) // wake before end of playing
} // play_next()
// wait for all resources, then start playing
function play_start() {
if (stop) { // stop playing
onend(repv)
return
}
// all resources are there
gain.connect(ac.destination)
stime = ac.currentTime + .2 // start time + 0.2s
- s_cur.ptim * conf.speed
play_next()
} // play_start()
// Audio5 function
init_b64d() // initialize base64 decoding
if (!conf.sfu)
conf.sfu = "Scc1t2" // set the default soundfont location
// public methods
return {
// get outputs
get_outputs: function() {
return (window.AudioContext || window.webkitAudioContext) ?
['sf2'] : null
}, // get_outputs()
// play the symbols
play: function(i_start, i_end, i_lvl) {
// get the callback functions
if (conf.onend)
onend = conf.onend
if (conf.onnote)
onnote = conf.onnote
if (conf.errmsg)
errmsg = conf.errmsg
// play a null file to unlock the iOS audio
// This is needed for iPhone/iPad/...
function play_unlock() {
var buf = ac.createBuffer(1, 1, 22050),
src = ac.createBufferSource()
src.buffer = buf
src.connect(ac.destination)
src.noteOn(0)
}
// initialize the audio subsystem if not done yet
if (!gain) {
ac = conf.ac
if (!ac) {
conf.ac = ac = new (window.AudioContext ||
window.webkitAudioContext)
if (/iPad|iPhone|iPod/.test(navigator.userAgent))
play_unlock()
}
gain = ac.createGain()
gain.gain.value = conf.gain
}
s_end = i_end
stop = false
while (i_start.noplay)
i_start = i_start.ts_next
s_cur = i_start
repv = i_lvl || 0
w_instr++
load_res()
if (--w_instr == 0) // all resources are there
play_start()
}, // play()
// stop playing
stop: function() {
stop = true
timouts.forEach(function(id) {
clearTimeout(id)
})
play_next()
if (gain) {
gain.disconnect()
gain = null
}
}, // stop()
// set volume
set_vol: function(v) {
if (gain)
gain.gain.value = v
} // set_vol()
} // returned object
} // Audio5()
|
Added util/sndgen.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
// sndgen.js - sound generation
//
// Copyright (C) 2019 Jean-Francois Moine
//
// This file is part of abc2svg-core.
//
// abc2svg-core is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg-core is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// This script generates the play data which are stored in the music symbols:
// - in all symbols
// s.ptim = play time
// - in BAR
// rep_p = on a right repeat bar, pointer to the left repeat symbol
// rep_s = on the first repeat variant, array of pointers to the next symbols,
// indexed by the repeat number
// - in NOTE and REST
// s.pdur = play duration
// s.instr = bank + instrument
// - in the notes[] of NOTE
// s.notes[i].midi
function ToAudio() {
return {
clear: function() { // useless - for compatibility
},
// generate the play data of a tune
add: function(s, // starting symbol
voice_tb) { // voice table
var C = abc2svg.C,
p_time = 0, // last playing time
abc_time = 0, // last ABC time
play_fac = C.BLEN / 4 * 120 / 60, // play time factor - default: Q:1/4=120
i, n, dt, d, v,
rst = s, // left repeat (repeat restart)
rst_fac, // play factor on repeat restart
rsk, // repeat variant (repeat skip)
instr = [] // [voice] bank + instrument
// generate the grace notes
function gen_grace(s) {
var g, i, n, t, d, s2,
next = s.next
// before beat
if (s.sappo) {
d = C.BLEN / 16
} else if ((!next || next.type != C.NOTE)
&& s.prev && s.prev.type == C.NOTE) {
d = s.prev.dur / 2
// on beat
} else {
d = next.dur / 12
if (d & (d - 1) == 0)
d = next.dur / 2 // no dot
else
d = next.dur / 3
next.time += d
next.dur -= d
}
//fixme: assume the grace notes have the same duration
n = 0
for (g = s.extra; g; g = g.next)
n++
d /= n * play_fac
t = p_time
for (g = s.extra; g; g = g.next) {
g.ptim = t
g.pdur = d
g.instr = instr[s.v]
t += d
}
} // gen_grace()
// add() main
// set the MIDI pitches
AbcMIDI().add(s, voice_tb)
// loop on the symbols
rst = s
rst_fac = play_fac
while (s) {
if (s.noplay) { // in display macro sequence
s = s.ts_next
continue
}
if (s.tempo) { // tempo change
d = 0
n = s.tempo_notes.length
for (i = 0; i < n; i++)
d += s.tempo_notes[i]
play_fac = d * s.tempo / 60
}
dt = s.time - abc_time
if (dt > 0) {
p_time += dt / play_fac
abc_time = s.time
}
s.ptim = p_time
v = s.v
if (instr[v] == undefined)
instr[v] = voice_tb[v].instr || 0
switch (s.type) {
case C.BAR:
// right repeat
if (s.bar_type[0] == ':') {
s.rep_p = rst // :| to |:
n = s.text // variants
while (s.ts_next && s.ts_next.type == C.BAR) {
s = s.ts_next
s.ptim = p_time
if (!n && s.text)
n = s.text
}
if (rsk) { // if in a variant
if (!n)
n = "a" // last time
n = n.match(/[1-8]-[2-9]|[1-9,.]|[^\s]+$/g)
while (1) {
d = n.shift()
if (!d)
break
if (d[1] == '-')
for (i = d[0]; i <= d[2]; i++)
rsk.rep_s[i] = s
else if (d >= '1' && d <= '9')
rsk.rep_s[Number(d)] = s
else
rsk.rep_s.push(s)
}
play_fac = rst_fac
break
}
}
// left repeat
if (s.bar_type.slice(-1) == ':') {
rst = s
rst_fac = play_fac
// 1st time repeat
} else if (s.text && s.text[0] == '1') {
rsk = s
s.rep_s = [null, s] // repeat skip
}
break
case C.BLOCK:
switch (s.subtype) {
case "midictl":
switch (s.ctrl) {
case 0: // MSB bank
instr[v] = (instr[v] & 0x3fff) |
(s.val << 14)
break
case 32: // LSB bank
instr[v] = (instr[v] & 0x1fc07f) |
(s.val << 7)
break
// case 121: // reset all controllers
// instr = []
// break
}
break
case "midiprog":
instr[v] = (instr[v] & ~0x7f) | s.instr
break
}
break
case C.GRACE:
if (s.time == 0 // if before beat at start time
&& abc_time == 0) {
dt = 0
if (s.sappo)
dt = C.BLEN / 16
else if (!s.next || s.next.type != C.NOTE)
dt = d / 2
abc_time -= dt
}
gen_grace(s)
break
case C.REST:
case C.NOTE:
d = s.dur
if (s.next && s.next.type == C.GRACE) {
dt = 0
if (s.next.sappo)
dt = C.BLEN / 16
else if (!s.next.next || s.next.next.type != C.NOTE)
dt = d / 2
s.next.time -= dt
d -= dt
}
d /= play_fac
s.pdur = d
s.instr = instr[v]
break
}
s = s.ts_next
} // loop
} // add()
} // return
} // ToAudio()
// nodejs
if (typeof module == 'object' && typeof exports == 'object')
exports.ToAudio = ToAudio
|
Added util/sndmid.js.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
// sndmid.js - audio output using HTML5 MIDI
//
// Copyright (C) 2019 Jean-Francois Moine
//
// This file is part of abc2svg.
//
// abc2svg is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// abc2svg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with abc2svg. If not, see <http://www.gnu.org/licenses/>.
// Midi5 creation
// @conf: configuration object - all items are optional:
// onend: callback function called at end of playing
// Argument:
// repv: last repeat variant number
// onnote: callback function called on note start/stop playing
// Arguments:
// i: start index of the note in the ABC source
// on: true on note start, false on note stop
// When playing, the following items must/may be set:
// speed: (mandatory) must be set to 1
// new_speed: (optional) new speed value
// Midi5 methods
// get_outputs() - get the output ports
//
// set_output() - set the output port
//
// play() - start playing
// @start -
// @stop: start and stop music symbols
// @level: repeat variant (optional, default = 0)
//
// stop() - stop playing
function Midi5(i_conf) {
var C = abc2svg.C,
conf = i_conf, // configuration
onend = function() {},
onnote = function() {},
rf, // get_outputs result function
// MIDI variables
op, // output port
v_i = [], // voice (channel) to instrument
s_cur, // current music symbol
s_end, // last music symbol / null
stop, // stop playing
repn, // don't repeat when true
repv = 0, // repeat variant number
stime, // start playing time in ms
timouts = [] // note start events
// create a note
// @s = symbol
// @k = MIDI key + detune
// @t = audio start time (ms)
// @d = duration adjusted for speed (ms)
function note_run(s, k, t, d) {
var j,
a = (k * 100) % 100, // detune in cents
i = s.instr,
//fixme: problem when more than 16 voices
c = s.v & 0x0f // channel
k |= 0 // remove the detune value
if ((s.instr & ~0x7f) == 16384) // if bank 128 (percussion)
//fixme: may conflict with the voice 9
c = 9 // force the channel 10
if (i != v_i[c]) { // if program change
// at channel start, reset and initialize the controllers
if (v_i[c] == undefined) {
//fixme: does not work with fluidsynth
op.send(new Uint8Array([0xb0 + c, 121, 0]))
if (s.p_v.midictl) {
for (j in s.p_v.midictl)
op.send(new Uint8Array([0xb0 + c,
j,
s.p_v.midictl[j]]))
}
}
v_i[c] = i
op.send(new Uint8Array([0xc0 + c, i & 0x7f])) // program
}
if (a && Midi5.ma.sysexEnabled) { // if microtone
// fixme: should cache the current microtone values
op.send(new Uint8Array([
0xf0, 0x7f, // realtime SysEx
0x7f, // all devices
0x08, // MIDI tuning standard
0x02, // note change
i & 0x7f, // tuning prog number
0x01, // number of notes
k, // key
k, // note
a / .78125, // MSB fract
0, // LSB fract
0xf7 // SysEx end
]), t)
}
op.send(new Uint8Array([0x90 + c, k, 127]), t) // note on
op.send(new Uint8Array([0x80 + c, k, 0]), t + d - 20) // note off
} // note_run()
// handle a tie
function do_tie(s, b40, d) {
var i, note,
v = s.v,
end_time = s.time + s.dur
// search the end of the tie
while (1) {
s = s.ts_next
if (!s)
return d
switch (s.type) {
case C.BAR:
if (s.rep_p) {
if (!repn) {
s = s.rep_p
end_time = s.time
}
}
if (s.rep_s) {
if (!s.rep_s[repv + 1])
return d
s = s.rep_s[repv + 1]
end_time = s.time
}
while (s.ts_next && s.ts_next.type == C.BAR)
s = s.ts_next
}
if (s.time > end_time)
return d
if (s.type == C.NOTE && s.v == v)
break
}
i = s.notes.length
while (--i >= 0) {
note = s.notes[i]
if (note.b40 == b40) {
note.ti2 = true // the sound is generated
d += s.pdur / conf.speed * 1000
return note.tie_ty ? do_tie(s, b40, d) : d
}
}
return d
} // do_tie()
// generate 2 seconds of music
function play_next() {
var d, i, st, m, note, g, s2,
s = s_cur,
t = stime + s.ptim / conf.speed * 1000, // start time
maxt = t + 2000 // max time = now + 2 seconds
if (stop) {
onend(repv)
return
}
// if speed change, shift the start time
if (conf.new_speed) {
stime = window-performance.now() -
(window.performance.now() - stime) *
conf.speed / conf.new_speed
conf.speed = conf.new_speed
conf.new_speed = 0
t = stime + s.ptim / conf.speed * 1000
}
timouts = []
while (1) {
switch (s.type) {
case C.BAR:
if (s.bar_type.slice(-1) == ':') // left repeat
repv = 0
if (s.rep_p) { // right repeat
if (!repn) {
stime += (s.ptim - s.rep_p.ptim) /
conf.speed * 1000
s = s.rep_p // left repeat
t = stime + s.ptim / conf.speed * 1000
repn = true
break
}
repn = false
}
if (s.rep_s) { // first variant
s2 = s.rep_s[++repv] // next variant
if (s2) {
stime += (s.ptim - s2.ptim) /
conf.speed * 1000
s = s2
t = stime + s.ptim / conf.speed * 1000
repn = false
} else { // end of tune
s = s_end
break
}
}
while (s.ts_next && s.ts_next.type == C.BAR)
s = s.ts_next
break
case C.BLOCK:
if (s.subtype == "midictl") {
i = s.v & 0x0f // voice = channel
if ((s.instr & ~0x7f) == 16384) // if percussion
i = 9 // force the channel 10
op.send(new Uint8Array([0xb0 + i,
s.ctrl, s.val]),
t)
}
break
case C.GRACE:
for (g = s.extra; g; g = g.next) {
d = g.pdur / conf.speed * 1000
for (m = 0; m <= g.nhd; m++) {
note = g.notes[m]
note_run(g,
note.midi,
t,
//fixme: there may be a tie...
d)
}
}
break
case C.NOTE:
d = s.pdur / conf.speed * 1000
for (m = 0; m <= s.nhd; m++) {
note = s.notes[m]
if (note.ti2)
continue
note_run(s,
note.midi,
t,
note.tie_ty ?
do_tie(s, note.b40, d) : d)
}
// fall thru
case C.REST:
d = s.pdur / conf.speed * 1000
// follow the notes/rests while playing
i = s.istart
st = t - window.performance.now()
timouts.push(setTimeout(onnote, st, i, true))
setTimeout(onnote, st + d, i, false)
break
}
if (s == s_end || !s.ts_next) {
setTimeout(onend,
t - window.performance.now() + d,
repv)
s_cur = s
return
}
s = s.ts_next
t = stime + s.ptim / conf.speed * 1000 // next time
if (t > maxt)
break
}
s_cur = s
// delay before next sound generation
timouts.push(setTimeout(play_next,
t - window.performance.now()
- 300)) // wake before end of playing
} // play_next()
// MIDI output is possible,
// return the possible ports in return to get_outputs()
function send_outputs(access) {
var o, os,
out = []
Midi5.ma = access // store the MIDI access in the Midi5 function
if (access && access.outputs.size > 0) {
os = access.outputs.values()
while (1) {
o = os.next()
if (!o || o.done)
break
out.push(o.value.name)
}
}
rf(out)
} // send_outputs()
// public methods
return {
// get outputs
get_outputs: function(f) {
if (!navigator.requestMIDIAccess) {
f() // no MIDI
return
}
rf = f
// open MIDI with SysEx
navigator.requestMIDIAccess({sysex: true}).then(
send_outputs,
function(msg) {
// open MIDI without SysEx
navigator.requestMIDIAccess().then(
send_outputs,
function(msg) {
rf()
}
)
}
)
}, // get_outputs()
// set the output port
set_output: function(name) {
var o, os
if (!Midi5.ma)
return
os = Midi5.ma.outputs.values()
while (1) {
o = os.next()
if (!o || o.done)
break
if (o.value.name == name) {
op = o.value
break
}
}
},
// play the symbols
play: function(i_start, i_end, i_lvl) {
// get the callback functions
if (conf.onend)
onend = conf.onend
if (conf.onnote)
onnote = conf.onnote
s_end = i_end
s_cur = i_start
repv = i_lvl || 0
if (0) {
// temperament
op.send(new Uint8Array([
0xf0, 0x7f, // realtime SysEx
0x7f, // all devices
0x08, // MIDI tuning standard
0x02, // note change
0x00, // tuning prog number
0x01, // number of notes
0x69, // key
0x69, // note
0x00, // MSB fract
0, // LSB fract
0xf7 // SysEx end
]), t)
}
v_i = [] // must do a reset of all channels
stime = window.performance.now() + 200 // start time + 0.2s
play_next()
}, // play()
// stop playing
stop: function() {
stop = true
timouts.forEach(function(id) {
clearTimeout(id)
})
onend(repv)
//fixme: op.clear() should exist...
if (op && op.clear)
op.clear()
} // stop()
} // returned object
} // end Midi5
|
Changes to util/toaudio.js.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 |
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// ToAudio creation
function ToAudio() {
var C = abc2svg.C,
| < < | > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
// along with abc2svg-core. If not, see <http://www.gnu.org/licenses/>.
// ToAudio creation
function ToAudio() {
var C = abc2svg.C,
a_e, // event array
p_time, // last playing time
abc_time, // last ABC time
play_factor, // play time factor
abcmidi = AbcMIDI()
// ToAudio
return {
// clear the playing events and
// return the old ones as an array of Float32Array:
// [0]: index of the note in the ABC source
|
| ︙ | ︙ | |||
47 48 49 50 51 52 53 |
var a_pe = a_e;
a_e = null
return a_pe
}, // clear()
// add playing events from the ABC model
add: function(start, // starting symbol
| | < < < < | < < < < | > > > | > > > > > | | < | < > | < < < > | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > | < < < < < < | < | | | | | > < | | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
var a_pe = a_e;
a_e = null
return a_pe
}, // clear()
// add playing events from the ABC model
add: function(start, // starting symbol
voice_tb) { // voice table
var i, n, dt, d, v,
rep_st_s, // start of sequence to be repeated
rep_en_s, // end ("|1")
rep_nx_s, // restart at end of repeat
rep_st_fac, // and play factor
instr = [], // instrument per voice
s = start
// set the accidentals and instruments of the voices
function set_voices() {
var v, p_v, s, mi
// reset the audio engine
a_e.push(new Float32Array([
0,
0, // (time)
-1, // MIDI control
121, // reset all controllers
0,
1,
0]))
for (v = 0; v < voice_tb.length; v++) {
p_v = voice_tb[v];
mi = p_v.instr || 0
if (p_v.midictl) {
for (s = p_v.sym; s; s = s.next)
if (s.dur) // search a note/rest
break
if (!s)
continue // no note in this voice
p_v.midictl.forEach(function(val, i) {
a_e.push(new Float32Array([
s.istart,
0, // (time)
-1, // MIDI control
i,
val,
1,
v]))
})
}
instr[v] = mi; // MIDI instrument
}
} // set_voices()
// handle the ties
function do_tie(s, b40, d) {
var i, note,
v = s.v,
end_time = s.time + s.dur
// search the end of the tie
for (s = s.ts_next; ; s = s.ts_next) {
if (!s)
return d
// skip if end of sequence to be repeated
if (s == rep_en_s) {
s = rep_nx_s
while (s && s.v != v)
s = s.ts_next
if (!s)
return d
end_time = s.time
}
if (s.time != end_time)
return d
if (s.type == C.NOTE && s.v == v)
break
}
i = s.notes.length
while (--i >= 0) {
note = s.notes[i]
if (note.b40 == b40) {
note.ti2 = true // don't generate sound anymore
d += s.dur / play_factor;
return note.tie_ty ? do_tie(s, b40, d) : d
}
}
return d
} // do_tie()
// generate the grace notes
function gen_grace(s) {
|
| ︙ | ︙ | |||
270 271 272 273 274 275 276 |
}
} // gen_grace()
// generate the notes
function gen_notes(s, t, d) {
for (var i = 0; i <= s.nhd; i++) {
var note = s.notes[i]
| > | | | > | | | > > < < < < < < < | > > > > > | < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
}
} // gen_grace()
// generate the notes
function gen_notes(s, t, d) {
for (var i = 0; i <= s.nhd; i++) {
var note = s.notes[i]
if (note.ti2) // tied note
continue
a_e.push(new Float32Array([
s.istart,
t,
instr[s.v],
note.midi,
note.tie_ty ? do_tie(s, note.b40, d) : d,
1,
s.v]))
}
} // gen_note()
// add() main
// set the MIDI pitches
abcmidi.add(start, voice_tb)
if (!a_e) { // if first call
a_e = []
abc_time = p_time = 0;
play_factor = C.BLEN / 4 * 120 / 60 // default: Q:1/4=120
} else if (s.time < abc_time) {
abc_time = s.time
}
set_voices() // initialize the voice parameters
// loop on the symbols
while (s) {
// if (s.type == C.TEMPO
// && s.tempo) {
if (s.tempo) { // tempo change
d = 0;
n = s.tempo_notes.length
for (i = 0; i < n; i++)
d += s.tempo_notes[i];
play_factor = d * s.tempo / 60
}
dt = s.time - abc_time
if (dt > 0) {
p_time += dt / play_factor;
abc_time = s.time
}
switch (s.type) {
case C.BAR:
if (!s.seqst)
break
// end of repeat
if (s == rep_en_s) {
s = rep_nx_s
abc_time = s.time
// right repeat
} else if (s.bar_type[0] == ':') {
rep_nx_s = s // repeat next
if (!rep_en_s) // if no "|1"
rep_en_s = s // repeat end
if (rep_st_s) { // if left repeat
s = rep_st_s
play_factor = rep_st_fac;
} else { // back to the beginning of the tune
s = start;
set_voices();
}
abc_time = s.time
break
}
// left repeat
if (s.bar_type[s.bar_type.length - 1] == ':') {
rep_st_s = s;
rep_en_s = null
rep_st_fac = play_factor
// 1st time repeat
} else if (s.text && s.text[0] == '1') {
rep_en_s = s
}
break
case C.GRACE:
if (s.time == 0 // if before beat at start time
&& abc_time == 0) {
dt = 0
if (s.sappo)
dt = C.BLEN / 16
else if (!s.next || s.next.type != C.NOTE)
dt = d / 2;
abc_time -= dt
}
gen_grace(s)
break
case C.REST:
case C.NOTE:
d = s.dur
if (s.next && s.next.type == C.GRACE) {
dt = 0
if (s.next.sappo)
dt = C.BLEN / 16
|
| ︙ | ︙ | |||
419 420 421 422 423 424 425 | p_time, 0, 0, d, 0, s.v])) break | < < < | | | > > > > > | 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
p_time,
0,
0,
d,
0,
s.v]))
break
case C.BLOCK:
switch (s.subtype) {
case "midictl":
a_e.push(new Float32Array([ // generate a MIDI control
s.istart,
p_time,
-1, // MIDI control
s.ctrl,
s.val,
1,
s.v]))
break
case "midiprog":
instr[s.v] = s.instr // %%MIDI program
break
}
break
}
s = s.ts_next
}
} // add()
} // return
} // ToAudio
// nodejs
if (typeof module == 'object' && typeof exports == 'object')
exports.ToAudio = ToAudio
|
Changes to util/toaudio5.js.
| ︙ | ︙ | |||
51 52 53 54 55 56 57 | // play() - start playing // @start_index - // @stop_index: indexes of the play_event array // @play_event: array of array // [0]: index of the note in the ABC source // [1]: time in seconds // [2]: if >= 0: MIDI instrument (MIDI GM number - 1) | | | | > | | | | 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 |
// play() - start playing
// @start_index -
// @stop_index: indexes of the play_event array
// @play_event: array of array
// [0]: index of the note in the ABC source
// [1]: time in seconds
// [2]: if >= 0: MIDI instrument (MIDI GM number - 1)
// else: MIDI control message
// [3]: MIDI note pitch (with cents) / controller
// [4]: duration / controller value
// [5]: volume (0..1 - optional)
// [6]: voice number
//
// stop() - stop playing
//
// set_vol() - set the current sound volume
// @volume: range [0..1] - undefined = return current value
var abcsf2 = [] // SF2 instruments
function Audio5(i_conf) {
var conf = i_conf, // configuration
onend = function() {},
onnote = function() {},
errmsg = alert,
ac, // audio context
gain, // global gain
// instruments/notes
params = [], // [instr][key] note parameters per instrument
rates = [], // [instr][key] playback rates
w_instr = 0, // number of instruments being loaded
|
| ︙ | ︙ | |||
234 235 236 237 238 239 240 |
if (--w_instr == 0)
play_start(a_e)
})
} // load_instr()
// start loading the instruments
function load_res(a_e) {
| | > | | > > > > > > > > > > > > > > > > > > > > > | | | > | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
if (--w_instr == 0)
play_start(a_e)
})
} // load_instr()
// start loading the instruments
function load_res(a_e) {
var i, e, instr, v,
bk = [] // bank number
for (i = evt_idx; i < iend; i++) {
e = a_e[i]
if (!e)
break
instr = e[2]
v = e[6]
if (bk[v] == undefined)
bk[v] = 0
if (instr < 0) {
switch (e[3]) { // controller
case 0: // MSB bank
bk[v] = (bk[v] & 0x3fff) | (e[4] << 14)
break
case 32: // LSB bank
bk[v] = (bk[v] & 0x1fc07f) | (e[4] << 7)
break
case 121: // reset all controllers
bk = []
break
}
} else {
if (bk[v]) {
instr &= 0x7f
instr |= bk[v]
e[2] = instr // bank + program
}
if (!params[instr]) {
params[instr] = [];
load_instr(instr, a_e)
}
}
}
}
// create a note
// @e[2] = instrument index
// @e[3] = MIDI key + detune
|
| ︙ | ︙ | |||
395 396 397 398 399 400 401 402 |
// play the events
play: function(istart, i_iend, a_e) {
if (!a_e || istart >= a_e.length) {
onend() // nothing to play
return
}
| > > > > > > > | > | > > > > > > > > > | > > > | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 |
// play the events
play: function(istart, i_iend, a_e) {
if (!a_e || istart >= a_e.length) {
onend() // nothing to play
return
}
// get the callback functions
if (conf.onend)
onend = conf.onend
if (conf.onnote)
onnote = conf.onnote
if (conf.errmsg)
errmsg = conf.errmsg
// play a null file to unlock the iOS audio
// This is needed for iPhone/iPad/...
function play_unlock() {
var buf = ac.createBuffer(1, 1, 22050),
src = ac.createBufferSource();
src.buffer = buf;
src.connect(ac.destination);
src.noteOn(0)
}
// initialize the audio subsystem if not done yet
if (!gain) {
ac = conf.ac
if (!ac) {
conf.ac = ac = new (window.AudioContext ||
window.webkitAudioContext);
if (/iPad|iPhone|iPod/.test(navigator.userAgent))
play_unlock()
}
gain = ac.createGain();
gain.gain.value = conf.gain
}
iend = i_iend;
evt_idx = istart;
load_res(a_e);
|
| ︙ | ︙ |
Changes to util/tomidi5.js.
| ︙ | ︙ | |||
50 51 52 53 54 55 56 |
// [5]: volume (0..1 - optional)
// [6]: voice number
//
// stop() - stop playing
function Midi5(i_conf) {
var conf = i_conf, // configuration
| | | > | | | | < < < < | 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 |
// [5]: volume (0..1 - optional)
// [6]: voice number
//
// stop() - stop playing
function Midi5(i_conf) {
var conf = i_conf, // configuration
onend = function() {},
onnote = function() {},
rf, // get_outputs result function
// MIDI variables
op, // output port
v_i = [], // voice (channel) to instrument
bk = [], // bank of the voice
// -- play the memorized events --
evt_idx, // event index while playing
iend, // play array stop index
stime, // start playing time in ms
timouts = [] // note start events
// create a note
// @e[2] = instrument index
// @e[3] = MIDI key + detune
// @e[6] = voice (channel) number
// @t = audio start time (ms)
// @d = duration adjusted for speed (ms)
function note_run(e, t, d) {
var k = e[3] | 0,
i = e[2],
c = e[6] & 0x0f, //fixme
a = (e[3] * 100) % 100 // detune in cents
if (bk[c] == 128) // if bank 128 (percussion)
c = 9 // force the channel 10
if (i != v_i[c]) { // if program change
// at channel start, reset all controllers
//fixme: does not work with fluidsynth
if (v_i[c] == undefined)
op.send(new Uint8Array([0xb0 + c, 121, 0]));
v_i[c] = i
op.send(new Uint8Array([0xc0 + c, i & 0x7f])) // program
}
if (a && Midi5.ma.sysexEnabled) { // if microtone
// fixme: should cache the current microtone values
op.send(new Uint8Array([
0xf0, 0x7f, // realtime SysEx
0x7f, // all devices
0x08, // MIDI tuning standard
|
| ︙ | ︙ | |||
114 115 116 117 118 119 120 |
}
op.send(new Uint8Array([0x90 + c, k, 127]), t); // note on
op.send(new Uint8Array([0x80 + c, k, 0]), t + d - 20) // note off
} // note_run()
// play the next time sequence
function play_next(a_e) {
| | | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
}
op.send(new Uint8Array([0x90 + c, k, 127]), t); // note on
op.send(new Uint8Array([0x80 + c, k, 0]), t + d - 20) // note off
} // note_run()
// play the next time sequence
function play_next(a_e) {
var t, e, e2, maxt, st, d, c
// play the next events
if (a_e) // if not stop
e = a_e[evt_idx]
if (!op || evt_idx >= iend || !e) {
onend()
return
|
| ︙ | ︙ | |||
147 148 149 150 151 152 153 |
note_run(e, t + stime, d)
// follow the notes while playing
st = t + stime - window.performance.now();
timouts.push(setTimeout(onnote, st, e[0], true));
setTimeout(onnote, st + d, e[0], false)
} else { // MIDI control
| > | | > > > > > > > > > > > > > | 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
note_run(e, t + stime, d)
// follow the notes while playing
st = t + stime - window.performance.now();
timouts.push(setTimeout(onnote, st, e[0], true));
setTimeout(onnote, st + d, e[0], false)
} else { // MIDI control
c = e[6] & 0x0f
op.send(new Uint8Array([0xb0 + c, e[3], e[4]]),
t + stime)
if (bk[c] == undefined)
bk[c] = 0
switch (e[3]) {
case 0: // MSB bank
bk[c] = (bk[c] & 0x7f) | (e[4] << 7)
break
case 32: // LSB bank
bk[c] = (bk[c] & 0x3f80) | e[4]
break
case 121: // reset all controllers
bk = []
break
}
}
e = a_e[++evt_idx]
if (!e || evt_idx >= iend) {
setTimeout(onend,
t + stime - window.performance.now() + d)
return
|
| ︙ | ︙ | |||
240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
// play the events
play: function(istart, i_iend, a_e) {
if (!a_e || istart >= a_e.length) {
onend() // nothing to play
return
}
iend = i_iend;
evt_idx = istart;
if (0) {
// temperament
op.send(new Uint8Array([
0xf0, 0x7f, // realtime SysEx
0x7f, // all devices
| > > > > > > > | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
// play the events
play: function(istart, i_iend, a_e) {
if (!a_e || istart >= a_e.length) {
onend() // nothing to play
return
}
// get the callback functions
if (conf.onend)
onend = conf.onend
if (conf.onnote)
onnote = conf.onnote;
iend = i_iend;
evt_idx = istart;
if (0) {
// temperament
op.send(new Uint8Array([
0xf0, 0x7f, // realtime SysEx
0x7f, // all devices
|
| ︙ | ︙ |