abcjs 6.2.2 → 6.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/RELEASE.md +78 -0
- package/abc2xml_239/abc2xml.html +769 -0
- package/abc2xml_239/abc2xml.py +2248 -0
- package/abc2xml_239/abc2xml_changelog.html +124 -0
- package/abc2xml_239/lazy-river.abc +26 -0
- package/abc2xml_239/lazy-river.xml +3698 -0
- package/abc2xml_239/mean-to-me.abc +22 -0
- package/abc2xml_239/mean-to-me.xml +2954 -0
- package/abc2xml_239/pyparsing.py +3672 -0
- package/abc2xml_239/pyparsing.pyc +0 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +909 -485
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/index.js +2 -0
- package/package.json +1 -1
- package/plugin.js +1 -1
- package/src/api/abc_tablatures.js +51 -13
- package/src/api/abc_tunebook_svg.js +5 -3
- package/src/parse/abc_parse_directive.js +17 -16
- package/src/parse/abc_parse_header.js +22 -19
- package/src/parse/abc_parse_music.js +18 -53
- package/src/parse/abc_parse_settings.js +165 -0
- package/src/parse/abc_tokenizer.js +72 -7
- package/src/parse/tune-builder.js +60 -1
- package/src/synth/create-synth.js +4 -0
- package/src/synth/place-note.js +6 -0
- package/src/synth/play-event.js +7 -5
- package/src/synth/synth-controller.js +6 -2
- package/src/tablatures/instruments/string-patterns.js +11 -0
- package/src/tablatures/instruments/{guitar/guitar-patterns.js → tab-string-patterns.js} +6 -6
- package/src/tablatures/instruments/{violin/tab-violin.js → tab-string.js} +13 -11
- package/src/tablatures/tab-absolute-elements.js +19 -9
- package/src/tablatures/tab-renderer.js +24 -10
- package/src/test/abc_parser_lint.js +1 -0
- package/src/write/creation/abstract-engraver.js +9 -2
- package/src/write/creation/add-chord.js +102 -82
- package/src/write/creation/add-text-if.js +2 -2
- package/src/write/creation/decoration.js +16 -8
- package/src/write/creation/elements/bottom-text.js +62 -47
- package/src/write/creation/elements/rich-text.js +51 -0
- package/src/write/creation/elements/top-text.js +37 -11
- package/src/write/creation/glyphs.js +2 -2
- package/src/write/draw/absolute.js +4 -1
- package/src/write/draw/draw.js +13 -4
- package/src/write/draw/glissando.js +1 -0
- package/src/write/draw/non-music.js +3 -1
- package/src/write/draw/relative.js +1 -1
- package/src/write/draw/set-paper-size.js +1 -1
- package/src/write/draw/tempo.js +1 -1
- package/src/write/draw/text.js +10 -0
- package/src/write/draw/tie.js +9 -1
- package/src/write/engraver-controller.js +58 -11
- package/src/write/helpers/classes.js +1 -1
- package/src/write/helpers/get-font-and-attr.js +8 -1
- package/src/write/helpers/get-text-size.js +8 -1
- package/src/write/interactive/selection.js +6 -0
- package/src/write/layout/layout.js +33 -3
- package/src/write/svg.js +30 -0
- package/temp.txt +50 -0
- package/types/index.d.ts +74 -26
- package/version.js +1 -1
- package/.github/workflows/tests.yml +0 -29
- package/src/tablatures/instruments/guitar/tab-guitar.js +0 -48
- package/src/tablatures/instruments/violin/violin-patterns.js +0 -23
|
@@ -639,13 +639,78 @@ var Tokenizer = function(lines, multilineVars) {
|
|
|
639
639
|
return {value: num/den, index: index};
|
|
640
640
|
};
|
|
641
641
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
642
|
+
//
|
|
643
|
+
// MAE 10 Jan 2023 - For better handling of tunes that have tune numbers in front of them.
|
|
644
|
+
//
|
|
645
|
+
// Previous version would take:
|
|
646
|
+
// 21. Woman of the House, The
|
|
647
|
+
// and return:
|
|
648
|
+
// The 21. Woman of the House
|
|
649
|
+
//
|
|
650
|
+
// This fix results in:
|
|
651
|
+
// 21. The Woman of the House
|
|
652
|
+
//
|
|
653
|
+
// Also added additional checks and handlers for lower case ", the" and ", a" since I found several tune collections with those tune name constructs
|
|
654
|
+
//
|
|
655
|
+
// Find an optional title number at the start of a tune title
|
|
656
|
+
function getTitleNumber(str){
|
|
657
|
+
|
|
658
|
+
const regex = /^(\d+)\./;
|
|
659
|
+
|
|
660
|
+
// Use the exec method to search for the pattern in the string
|
|
661
|
+
const match = regex.exec(str);
|
|
662
|
+
|
|
663
|
+
// Check if a match is found
|
|
664
|
+
if (match) {
|
|
665
|
+
|
|
666
|
+
// The matched number is captured in the first group (index 1)
|
|
667
|
+
const foundNumber = match[1];
|
|
668
|
+
return foundNumber;
|
|
669
|
+
|
|
670
|
+
} else {
|
|
671
|
+
|
|
672
|
+
// Return null if no match is found
|
|
673
|
+
return null;
|
|
674
|
+
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
var thePatterns = [
|
|
680
|
+
{ match: /,\s*[Tt]he$/, replace: "The " },
|
|
681
|
+
{ match: /,\s*[Aa]$/, replace: "A " },
|
|
682
|
+
{ match: /,\s*[Aa]n$/, replace: "An " },
|
|
683
|
+
]
|
|
684
|
+
|
|
685
|
+
this.theReverser = function (str) {
|
|
686
|
+
|
|
687
|
+
for (var i = 0; i < thePatterns.length; i++) {
|
|
688
|
+
var thisPattern = thePatterns[i]
|
|
689
|
+
var match = str.match(thisPattern.match)
|
|
690
|
+
if (match) {
|
|
691
|
+
var theTitleNumber = getTitleNumber(str);
|
|
692
|
+
if (theTitleNumber){
|
|
693
|
+
|
|
694
|
+
//console.log("theReverser The titlenumber:"+theTitleNumber);
|
|
695
|
+
|
|
696
|
+
str = str.replace(theTitleNumber+".","");
|
|
697
|
+
str = str.trim();
|
|
698
|
+
}
|
|
699
|
+
var len = match[0].length
|
|
700
|
+
var result = thisPattern.replace + str.substring(0, str.length - len);
|
|
701
|
+
|
|
702
|
+
if (theTitleNumber){
|
|
703
|
+
result = theTitleNumber+". "+result;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
return result;
|
|
707
|
+
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
return str;
|
|
712
|
+
|
|
713
|
+
};
|
|
649
714
|
|
|
650
715
|
this.stripComment = function(str) {
|
|
651
716
|
var i = str.indexOf('%');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
var parseKeyVoice = require('../parse/abc_parse_key_voice');
|
|
2
2
|
var parseCommon = require('../parse/abc_common');
|
|
3
|
+
var parseDirective = require('./abc_parse_directive');
|
|
3
4
|
|
|
4
5
|
var TuneBuilder = function(tune) {
|
|
5
6
|
var self = this;
|
|
@@ -147,6 +148,9 @@ var TuneBuilder = function(tune) {
|
|
|
147
148
|
this.closeLine(); // Close the last line.
|
|
148
149
|
delete tune.runningFonts;
|
|
149
150
|
|
|
151
|
+
simplifyMetaText(tune)
|
|
152
|
+
//addRichTextToAnnotationsAndLyrics(tune)
|
|
153
|
+
|
|
150
154
|
// If the tempo was created with a string like "Allegro", then the duration of a beat needs to be set at the last moment, when it is most likely known.
|
|
151
155
|
if (tune.metaText.tempo && tune.metaText.tempo.bpm && !tune.metaText.tempo.duration)
|
|
152
156
|
tune.metaText.tempo.duration = [ tune.getBeatLength() ];
|
|
@@ -878,7 +882,15 @@ var TuneBuilder = function(tune) {
|
|
|
878
882
|
tune.metaText[key] = value;
|
|
879
883
|
tune.metaTextInfo[key] = info;
|
|
880
884
|
} else {
|
|
881
|
-
tune.metaText[key]
|
|
885
|
+
if (typeof tune.metaText[key] === 'string' && typeof value === 'string')
|
|
886
|
+
tune.metaText[key] += "\n" + value;
|
|
887
|
+
else {
|
|
888
|
+
if (tune.metaText[key] === 'string')
|
|
889
|
+
tune.metaText[key] = [{text: tune.metaText[key]}]
|
|
890
|
+
if (typeof value === 'string')
|
|
891
|
+
value = [{text: value}]
|
|
892
|
+
tune.metaText[key] =tune.metaText[key].concat(value)
|
|
893
|
+
}
|
|
882
894
|
tune.metaTextInfo[key].endChar = info.endChar;
|
|
883
895
|
}
|
|
884
896
|
};
|
|
@@ -898,4 +910,51 @@ var TuneBuilder = function(tune) {
|
|
|
898
910
|
};
|
|
899
911
|
};
|
|
900
912
|
|
|
913
|
+
function isArrayOfStrings(arr) {
|
|
914
|
+
if (!arr) return false
|
|
915
|
+
if (typeof arr === "string") return false
|
|
916
|
+
var str = ''
|
|
917
|
+
for (var i = 0; i < arr.length; i++) {
|
|
918
|
+
if (typeof arr[i] !== 'string')
|
|
919
|
+
return false
|
|
920
|
+
}
|
|
921
|
+
return true
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
function simplifyMetaText(tune) {
|
|
925
|
+
if (isArrayOfStrings(tune.metaText.notes))
|
|
926
|
+
tune.metaText.notes = tune.metaText.notes.join("\n")
|
|
927
|
+
if (isArrayOfStrings(tune.metaText.history))
|
|
928
|
+
tune.metaText.history = tune.metaText.history.join("\n")
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
function addRichTextToAnnotationsAndLyrics(tune) {
|
|
932
|
+
var lines = tune.lines
|
|
933
|
+
for (var i = 0; i < lines.length; i++) {
|
|
934
|
+
if (lines[i].staff !== undefined) {
|
|
935
|
+
for (var s = 0; s < lines[i].staff.length; s++) {
|
|
936
|
+
for (var v = 0; v < lines[i].staff[s].voices.length; v++) {
|
|
937
|
+
var voice = lines[i].staff[s].voices[v];
|
|
938
|
+
for (var n = 0; n < voice.length; n++) {
|
|
939
|
+
var element = voice[n]
|
|
940
|
+
if (element.chord) {
|
|
941
|
+
for (var c = 0; c < element.chord.length; c++) {
|
|
942
|
+
element.chord[c].name = parseDirective.parseFontChangeLine(element.chord[c].name)
|
|
943
|
+
console.log(element.chord[c].name)
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
if (element.lyric) {
|
|
947
|
+
for (var l = 0; l < element.lyric.length; l++) {
|
|
948
|
+
element.lyric[l].syllable = parseDirective.parseFontChangeLine(element.lyric[l].syllable)
|
|
949
|
+
console.log(element.lyric[l].syllable)
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
}
|
|
959
|
+
|
|
901
960
|
module.exports = TuneBuilder;
|
package/src/synth/place-note.js
CHANGED
|
@@ -17,6 +17,12 @@ function placeNote(outputAudioBuffer, sampleRate, sound, startArray, volumeMulti
|
|
|
17
17
|
len = 0.005; // Have some small audible length no matter how short the note is.
|
|
18
18
|
var offlineCtx = new OfflineAC(2,Math.floor((len+fadeTimeSec)*sampleRate),sampleRate);
|
|
19
19
|
var noteName = pitchToNoteName[sound.pitch];
|
|
20
|
+
if (!soundsCache[sound.instrument]) {
|
|
21
|
+
// It shouldn't happen that the entire instrument cache wasn't created, but this has been seen in practice, so guard against it.
|
|
22
|
+
if (debugCallback)
|
|
23
|
+
debugCallback('placeNote skipped (instrument empty): '+sound.instrument+':'+noteName)
|
|
24
|
+
return Promise.resolve();
|
|
25
|
+
}
|
|
20
26
|
var noteBufferPromise = soundsCache[sound.instrument][noteName];
|
|
21
27
|
|
|
22
28
|
if (!noteBufferPromise) {
|
package/src/synth/play-event.js
CHANGED
|
@@ -2,7 +2,7 @@ var SynthSequence = require('./synth-sequence');
|
|
|
2
2
|
var CreateSynth = require('./create-synth');
|
|
3
3
|
var activeAudioContext = require("./active-audio-context");
|
|
4
4
|
|
|
5
|
-
function playEvent(midiPitches, midiGracePitches, millisecondsPerMeasure) {
|
|
5
|
+
function playEvent(midiPitches, midiGracePitches, millisecondsPerMeasure, soundFontUrl, debugCallback) {
|
|
6
6
|
var sequence = new SynthSequence();
|
|
7
7
|
|
|
8
8
|
for (var i = 0; i < midiPitches.length; i++) {
|
|
@@ -21,18 +21,20 @@ function playEvent(midiPitches, midiGracePitches, millisecondsPerMeasure) {
|
|
|
21
21
|
var ac = activeAudioContext();
|
|
22
22
|
if (ac.state === "suspended") {
|
|
23
23
|
return ac.resume().then(function () {
|
|
24
|
-
return doPlay(sequence, millisecondsPerMeasure);
|
|
24
|
+
return doPlay(sequence, millisecondsPerMeasure, soundFontUrl, debugCallback);
|
|
25
25
|
});
|
|
26
26
|
} else {
|
|
27
|
-
return doPlay(sequence, millisecondsPerMeasure);
|
|
27
|
+
return doPlay(sequence, millisecondsPerMeasure, soundFontUrl, debugCallback);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function doPlay(sequence, millisecondsPerMeasure) {
|
|
31
|
+
function doPlay(sequence, millisecondsPerMeasure, soundFontUrl, debugCallback) {
|
|
32
32
|
var buffer = new CreateSynth();
|
|
33
33
|
return buffer.init({
|
|
34
34
|
sequence: sequence,
|
|
35
|
-
millisecondsPerMeasure: millisecondsPerMeasure
|
|
35
|
+
millisecondsPerMeasure: millisecondsPerMeasure,
|
|
36
|
+
options: { soundFontUrl: soundFontUrl },
|
|
37
|
+
debugCallback: debugCallback,
|
|
36
38
|
}).then(function () {
|
|
37
39
|
return buffer.prime();
|
|
38
40
|
}).then(function () {
|
|
@@ -21,6 +21,10 @@ function SynthController() {
|
|
|
21
21
|
self.load = function (selector, cursorControl, visualOptions) {
|
|
22
22
|
if (!visualOptions)
|
|
23
23
|
visualOptions = {};
|
|
24
|
+
if (visualOptions.displayPlay === undefined)
|
|
25
|
+
visualOptions.displayPlay = true
|
|
26
|
+
if (visualOptions.displayProgress === undefined)
|
|
27
|
+
visualOptions.displayProgress = true
|
|
24
28
|
self.control = new CreateSynthControl(selector, {
|
|
25
29
|
loopHandler: visualOptions.displayLoop ? self.toggleLoop : undefined,
|
|
26
30
|
restartHandler: visualOptions.displayRestart ? self.restart : undefined,
|
|
@@ -41,7 +45,7 @@ function SynthController() {
|
|
|
41
45
|
self.setTune = function(visualObj, userAction, audioParams) {
|
|
42
46
|
self.visualObj = visualObj;
|
|
43
47
|
self.disable(false);
|
|
44
|
-
self.options = audioParams;
|
|
48
|
+
self.options = audioParams ? audioParams : {};
|
|
45
49
|
|
|
46
50
|
if (self.control) {
|
|
47
51
|
self.pause();
|
|
@@ -195,7 +199,7 @@ function SynthController() {
|
|
|
195
199
|
|
|
196
200
|
self._randomAccess = function (ev) {
|
|
197
201
|
var background = (ev.target.classList.contains('abcjs-midi-progress-indicator')) ? ev.target.parentNode : ev.target;
|
|
198
|
-
var percent = (ev.x - background.
|
|
202
|
+
var percent = (ev.x - background.getBoundingClientRect().left) / background.offsetWidth;
|
|
199
203
|
if (percent < 0)
|
|
200
204
|
percent = 0;
|
|
201
205
|
if (percent > 1)
|
|
@@ -265,6 +265,17 @@ StringPatterns.prototype.tabInfos = function (plugin) {
|
|
|
265
265
|
return '';
|
|
266
266
|
};
|
|
267
267
|
|
|
268
|
+
// MAE 27 Nov 2023
|
|
269
|
+
StringPatterns.prototype.suppress = function (plugin) {
|
|
270
|
+
var _super = plugin._super;
|
|
271
|
+
var suppress = _super.params.suppress;
|
|
272
|
+
if (suppress){
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
return false;
|
|
276
|
+
};
|
|
277
|
+
// MAE 27 Nov 2023 End
|
|
278
|
+
|
|
268
279
|
/**
|
|
269
280
|
* Common patterns for all string instruments
|
|
270
281
|
* @param {} plugin
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
var StringPatterns = require('
|
|
1
|
+
var StringPatterns = require('./string-patterns');
|
|
2
2
|
|
|
3
|
-
function
|
|
3
|
+
function TabStringPatterns(plugin, defaultTuning) {
|
|
4
4
|
this.tuning = plugin._super.params.tuning;
|
|
5
5
|
if (!this.tuning) {
|
|
6
|
-
this.tuning =
|
|
6
|
+
this.tuning = defaultTuning;
|
|
7
7
|
}
|
|
8
8
|
plugin.tuning = this.tuning;
|
|
9
9
|
this.strings = new StringPatterns(plugin);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
TabStringPatterns.prototype.notesToNumber = function (notes, graces) {
|
|
13
13
|
var converter = this.strings;
|
|
14
14
|
return converter.notesToNumber(notes, graces);
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
TabStringPatterns.prototype.stringToPitch = function (stringNumber) {
|
|
18
18
|
var converter = this.strings;
|
|
19
19
|
return converter.stringToPitch(stringNumber);
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
module.exports =
|
|
23
|
+
module.exports = TabStringPatterns;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
var StringTablature = require('
|
|
3
|
-
var TabCommon = require('
|
|
4
|
-
var TabRenderer = require('
|
|
5
|
-
var
|
|
2
|
+
var StringTablature = require('./string-tablature');
|
|
3
|
+
var TabCommon = require('../tab-common');
|
|
4
|
+
var TabRenderer = require('../tab-renderer');
|
|
5
|
+
var TabStringPatterns = require('./tab-string-patterns');
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -11,18 +11,20 @@ var ViolinPatterns = require('./violin-patterns');
|
|
|
11
11
|
* @param {*} tuneNumber the parsed tune AST tree
|
|
12
12
|
* @param {*} params complementary args provided to Tablature Plugin
|
|
13
13
|
*/
|
|
14
|
-
Plugin.prototype.init = function (abcTune, tuneNumber, params) {
|
|
14
|
+
Plugin.prototype.init = function (abcTune, tuneNumber, params, staffNumber, tabSettings) {
|
|
15
15
|
var _super = new TabCommon(abcTune, tuneNumber, params);
|
|
16
16
|
this.abcTune = abcTune;
|
|
17
17
|
this._super = _super;
|
|
18
18
|
this.linePitch = 3;
|
|
19
|
-
this.nbLines =
|
|
20
|
-
this.isTabBig =
|
|
19
|
+
this.nbLines = tabSettings.defaultTuning.length;
|
|
20
|
+
this.isTabBig = tabSettings.isTabBig;
|
|
21
|
+
this.tabSymbolOffset = tabSettings.tabSymbolOffset;
|
|
21
22
|
this.capo = params.capo;
|
|
22
23
|
this.transpose = params.visualTranspose;
|
|
24
|
+
this.hideTabSymbol = params.hideTabSymbol;
|
|
23
25
|
this.tablature = new StringTablature(this.nbLines,
|
|
24
26
|
this.linePitch);
|
|
25
|
-
var semantics = new
|
|
27
|
+
var semantics = new TabStringPatterns(this, tabSettings.defaultTuning);
|
|
26
28
|
this.semantics = semantics;
|
|
27
29
|
};
|
|
28
30
|
|
|
@@ -38,8 +40,8 @@ function Plugin() {}
|
|
|
38
40
|
//
|
|
39
41
|
// Tablature plugin definition
|
|
40
42
|
//
|
|
41
|
-
var
|
|
42
|
-
return { name: '
|
|
43
|
+
var AbcStringTab = function () {
|
|
44
|
+
return { name: 'StringTab', tablature: Plugin };
|
|
43
45
|
};
|
|
44
46
|
|
|
45
|
-
module.exports =
|
|
47
|
+
module.exports = AbcStringTab;
|
|
@@ -60,13 +60,22 @@ function buildTabAbsolute(plugin, absX, relX) {
|
|
|
60
60
|
icon: tabIcon,
|
|
61
61
|
Ypos: tabYPos
|
|
62
62
|
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
63
|
+
|
|
64
|
+
// Offset the TAB symbol position if specified in the tab description
|
|
65
|
+
tabYPos += plugin.tabSymbolOffset;
|
|
66
|
+
|
|
67
|
+
// For tablature like whistle tab where you want the TAB symbol hidden
|
|
68
|
+
if (!plugin.hideTabSymbol){
|
|
69
|
+
|
|
70
|
+
var tabAbsolute = new AbsoluteElement(element, 0, 0, "symbol", 0);
|
|
71
|
+
tabAbsolute.x = absX;
|
|
72
|
+
var tabRelative = new RelativeElement(tabIcon, 0, 0, 7.5, "tab");
|
|
73
|
+
tabRelative.x = relX;
|
|
74
|
+
tabAbsolute.children.push(tabRelative);
|
|
75
|
+
if (tabAbsolute.abcelem.el_type == 'tab') {
|
|
76
|
+
tabRelative.pitch = tabYPos;
|
|
77
|
+
}
|
|
78
|
+
|
|
70
79
|
}
|
|
71
80
|
return tabAbsolute;
|
|
72
81
|
}
|
|
@@ -177,10 +186,11 @@ TabAbsoluteElements.prototype.build = function (plugin,
|
|
|
177
186
|
tabVoice,
|
|
178
187
|
voiceIndex,
|
|
179
188
|
staffIndex,
|
|
180
|
-
keySig
|
|
189
|
+
keySig,
|
|
190
|
+
tabVoiceIndex ) {
|
|
181
191
|
var staffSize = getInitialStaffSize(staffAbsolute);
|
|
182
192
|
var source = staffAbsolute[staffIndex+voiceIndex];
|
|
183
|
-
var dest = staffAbsolute[
|
|
193
|
+
var dest = staffAbsolute[tabVoiceIndex];
|
|
184
194
|
var tabPos = null;
|
|
185
195
|
var defNote = null;
|
|
186
196
|
if (source.children[0].abcelem.el_type != 'clef') {
|
|
@@ -37,12 +37,24 @@ function buildTabName(self, dest) {
|
|
|
37
37
|
var controller = self.renderer.controller;
|
|
38
38
|
var textSize = controller.getTextSize;
|
|
39
39
|
var tabName = stringSemantics.tabInfos(self.plugin);
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
var suppress = stringSemantics.suppress(self.plugin);
|
|
41
|
+
var doDraw = true;
|
|
42
|
+
|
|
43
|
+
if (suppress){
|
|
44
|
+
doDraw = false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if (doDraw){
|
|
49
|
+
var size = textSize.calc(tabName, 'tablabelfont', 'text instrumentname');
|
|
50
|
+
dest.tabNameInfos = {
|
|
51
|
+
textSize: {height:size.height,width:size.width},
|
|
52
|
+
name: tabName
|
|
53
|
+
};
|
|
54
|
+
return size.height;
|
|
55
|
+
}
|
|
56
|
+
return 0
|
|
57
|
+
|
|
46
58
|
}
|
|
47
59
|
|
|
48
60
|
/**
|
|
@@ -230,16 +242,18 @@ TabRenderer.prototype.doLayout = function () {
|
|
|
230
242
|
if (ii > 0) tabVoice.duplicate = true;
|
|
231
243
|
var nameHeight = buildTabName(this, tabVoice) / spacing.STEP;
|
|
232
244
|
nameHeight = Math.max(nameHeight, 1) // If there is no label for the tab line, then there needs to be a little padding
|
|
233
|
-
|
|
234
|
-
staffGroup.
|
|
245
|
+
// This was pushing down the top staff by the tab label height
|
|
246
|
+
//staffGroup.staffs[this.staffIndex].top += nameHeight;
|
|
247
|
+
staffGroup.staffs[this.staffIndex].top += 1;
|
|
248
|
+
staffGroup.height += nameHeight;
|
|
235
249
|
tabVoice.staff = staffGroupInfos;
|
|
250
|
+
var tabVoiceIndex = voices.length
|
|
236
251
|
voices.splice(voices.length, 0, tabVoice);
|
|
237
252
|
var keySig = checkVoiceKeySig(voices, ii + this.staffIndex);
|
|
238
253
|
this.tabStaff.voices[ii] = [];
|
|
239
|
-
this.absolutes.build(this.plugin, voices, this.tabStaff.voices[ii], ii , this.staffIndex ,keySig);
|
|
254
|
+
this.absolutes.build(this.plugin, voices, this.tabStaff.voices[ii], ii , this.staffIndex ,keySig, tabVoiceIndex);
|
|
240
255
|
}
|
|
241
256
|
linkStaffAndTabs(staffGroup.staffs); // crossreference tabs and staff
|
|
242
257
|
};
|
|
243
258
|
|
|
244
|
-
|
|
245
259
|
module.exports = TabRenderer;
|
|
@@ -427,6 +427,7 @@ var ParserLint = function() {
|
|
|
427
427
|
var formattingProperties = {
|
|
428
428
|
type:"object",
|
|
429
429
|
properties: {
|
|
430
|
+
accentAbove: { type: "boolean", optional: true },
|
|
430
431
|
alignbars: { type: "number", optional: true },
|
|
431
432
|
aligncomposer: { type: "string", Enum: [ 'left', 'center','right' ], optional: true },
|
|
432
433
|
annotationfont: fontType,
|
|
@@ -53,6 +53,7 @@ var AbstractEngraver = function (getTextSize, tuneNumber, options) {
|
|
|
53
53
|
this.percmap = options.percmap;
|
|
54
54
|
this.initialClef = options.initialClef
|
|
55
55
|
this.jazzchords = !!options.jazzchords
|
|
56
|
+
this.accentAbove = !!options.accentAbove
|
|
56
57
|
this.germanAlphabet = !!options.germanAlphabet
|
|
57
58
|
this.reset();
|
|
58
59
|
};
|
|
@@ -747,6 +748,12 @@ AbstractEngraver.prototype.addNoteToAbcElement = function (abselem, elem, dot, s
|
|
|
747
748
|
else
|
|
748
749
|
p1 += 1;
|
|
749
750
|
}
|
|
751
|
+
if (noteHead && noteHead.c === 'noteheads.triangle.quarter') {
|
|
752
|
+
if (dir === 'down')
|
|
753
|
+
p2 -= 0.7;
|
|
754
|
+
else
|
|
755
|
+
p1 -= 1.2;
|
|
756
|
+
}
|
|
750
757
|
abselem.addRight(new RelativeElement(null, dx, 0, p1, { "type": "stem", "pitch2": p2, linewidth: width, bottom: p1 - 1 }));
|
|
751
758
|
//var RelativeElement = function RelativeElement(c, dx, w, pitch, opt) {
|
|
752
759
|
min = Math.min(p1, p2);
|
|
@@ -824,7 +831,7 @@ AbstractEngraver.prototype.createNote = function (elem, nostem, isSingleLineStaf
|
|
|
824
831
|
}
|
|
825
832
|
|
|
826
833
|
if (elem.decoration) {
|
|
827
|
-
this.decoration.createDecoration(voice, elem.decoration, abselem.top, (notehead) ? notehead.w : 0, abselem, roomtaken, dir, abselem.bottom, elem.positioning, this.hasVocals);
|
|
834
|
+
this.decoration.createDecoration(voice, elem.decoration, abselem.top, (notehead) ? notehead.w : 0, abselem, roomtaken, dir, abselem.bottom, elem.positioning, this.hasVocals, this.accentAbove);
|
|
828
835
|
}
|
|
829
836
|
|
|
830
837
|
if (elem.barNumber) {
|
|
@@ -983,7 +990,7 @@ AbstractEngraver.prototype.createBarLine = function (voice, elem, isFirstStaff)
|
|
|
983
990
|
}
|
|
984
991
|
|
|
985
992
|
if (elem.decoration) {
|
|
986
|
-
this.decoration.createDecoration(voice, elem.decoration, 12, (thick) ? 3 : 1, abselem, 0, "down", 2, elem.positioning, this.hasVocals);
|
|
993
|
+
this.decoration.createDecoration(voice, elem.decoration, 12, (thick) ? 3 : 1, abselem, 0, "down", 2, elem.positioning, this.hasVocals, this.accentAbove);
|
|
987
994
|
}
|
|
988
995
|
|
|
989
996
|
if (thick) {
|