abcjs 6.0.0-beta.9 → 6.0.2

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.
Files changed (197) hide show
  1. package/.github/workflows/tests.yml +29 -0
  2. package/CODE_OF_CONDUCT.md +76 -0
  3. package/CONTRIBUTING.md +1 -0
  4. package/LICENSE.md +1 -1
  5. package/README.md +88 -7
  6. package/RELEASE.md +961 -1
  7. package/abcjs-audio.css +14 -5
  8. package/dist/.gitignore +1 -2
  9. package/dist/abcjs-basic-min.js +3 -0
  10. package/dist/abcjs-basic-min.js.LICENSE +23 -0
  11. package/dist/abcjs-basic.js +28232 -0
  12. package/dist/abcjs-basic.js.map +1 -0
  13. package/dist/abcjs-plugin-min.js +3 -0
  14. package/dist/abcjs-plugin-min.js.LICENSE +23 -0
  15. package/index.js +27 -2
  16. package/{static-wrappers/license.js → license.js} +1 -1
  17. package/package.json +26 -29
  18. package/{src/plugin/abc_plugin.js → plugin.js} +31 -19
  19. package/src/api/abc_animation.js +1 -17
  20. package/src/api/abc_tablatures.js +144 -0
  21. package/src/api/abc_timing_callbacks.js +216 -117
  22. package/src/api/abc_tunebook.js +18 -67
  23. package/src/api/abc_tunebook_svg.js +40 -48
  24. package/src/data/abc_tune.js +232 -972
  25. package/src/data/deline-tune.js +199 -0
  26. package/src/edit/abc_editarea.js +112 -0
  27. package/src/edit/abc_editor.js +95 -221
  28. package/src/midi/abc_midi_create.js +48 -50
  29. package/src/parse/abc_common.js +0 -14
  30. package/src/parse/abc_parse.js +167 -1321
  31. package/src/parse/abc_parse_book.js +62 -0
  32. package/src/parse/abc_parse_directive.js +164 -41
  33. package/src/parse/abc_parse_header.js +116 -145
  34. package/src/parse/abc_parse_key_voice.js +26 -20
  35. package/src/parse/abc_parse_music.js +1337 -0
  36. package/src/parse/abc_tokenizer.js +21 -15
  37. package/src/parse/abc_transpose.js +3 -15
  38. package/src/parse/tune-builder.js +896 -0
  39. package/src/parse/wrap_lines.js +205 -453
  40. package/src/synth/abc_midi_flattener.js +1292 -0
  41. package/src/{midi → synth}/abc_midi_renderer.js +44 -17
  42. package/src/synth/abc_midi_sequencer.js +648 -0
  43. package/src/synth/active-audio-context.js +3 -14
  44. package/src/synth/cents-to-factor.js +10 -0
  45. package/src/synth/create-note-map.js +21 -32
  46. package/src/synth/create-synth-control.js +20 -103
  47. package/src/synth/create-synth.js +185 -77
  48. package/src/synth/download-buffer.js +7 -21
  49. package/src/synth/get-midi-file.js +13 -20
  50. package/src/synth/images/{loading.svg → loading.svg.js} +4 -0
  51. package/src/synth/images/loop.svg.js +65 -0
  52. package/src/synth/images/pause.svg.js +10 -0
  53. package/src/synth/images/play.svg.js +9 -0
  54. package/src/synth/images/{reset.svg → reset.svg.js} +5 -1
  55. package/src/synth/instrument-index-to-name.js +1 -16
  56. package/src/synth/load-note.js +37 -76
  57. package/src/synth/pitch-to-note-name.js +0 -15
  58. package/src/synth/pitches-to-perc.js +64 -0
  59. package/src/synth/place-note.js +78 -68
  60. package/src/synth/play-event.js +17 -18
  61. package/src/synth/register-audio-context.js +11 -23
  62. package/src/synth/sounds-cache.js +0 -15
  63. package/src/synth/supports-audio.js +9 -23
  64. package/src/synth/synth-controller.js +80 -49
  65. package/src/synth/synth-sequence.js +20 -34
  66. package/src/tablatures/instruments/guitar/guitar-fonts.js +19 -0
  67. package/src/tablatures/instruments/guitar/guitar-patterns.js +23 -0
  68. package/src/tablatures/instruments/guitar/tab-guitar.js +50 -0
  69. package/src/tablatures/instruments/string-patterns.js +277 -0
  70. package/src/tablatures/instruments/string-tablature.js +56 -0
  71. package/src/tablatures/instruments/tab-note.js +282 -0
  72. package/src/tablatures/instruments/tab-notes.js +41 -0
  73. package/src/tablatures/instruments/violin/tab-violin.js +47 -0
  74. package/src/tablatures/instruments/violin/violin-fonts.js +19 -0
  75. package/src/tablatures/instruments/violin/violin-patterns.js +23 -0
  76. package/src/tablatures/tab-absolute-elements.js +310 -0
  77. package/src/tablatures/tab-common.js +29 -0
  78. package/src/tablatures/tab-renderer.js +243 -0
  79. package/src/tablatures/transposer.js +110 -0
  80. package/src/test/abc_midi_lint.js +5 -22
  81. package/src/test/abc_midi_sequencer_lint.js +11 -14
  82. package/src/test/abc_parser_lint.js +136 -32
  83. package/src/test/abc_vertical_lint.js +94 -32
  84. package/src/test/rendering-lint.js +38 -5
  85. package/src/write/abc_absolute_element.js +112 -120
  86. package/src/write/abc_abstract_engraver.js +102 -253
  87. package/src/write/abc_beam_element.js +30 -290
  88. package/src/write/abc_brace_element.js +12 -121
  89. package/src/write/abc_create_clef.js +21 -32
  90. package/src/write/abc_create_key_signature.js +8 -26
  91. package/src/write/abc_create_note_head.js +107 -0
  92. package/src/write/abc_create_time_signature.js +2 -21
  93. package/src/write/abc_crescendo_element.js +3 -50
  94. package/src/write/abc_decoration.js +7 -30
  95. package/src/write/abc_dynamic_decoration.js +3 -37
  96. package/src/write/abc_ending_element.js +1 -57
  97. package/src/write/abc_engraver_controller.js +111 -234
  98. package/src/write/abc_glyphs.js +8 -18
  99. package/src/write/abc_relative_element.js +57 -97
  100. package/src/write/abc_renderer.js +10 -832
  101. package/src/write/abc_spacing.js +0 -15
  102. package/src/write/abc_staff_group_element.js +14 -349
  103. package/src/write/abc_tempo_element.js +9 -117
  104. package/src/write/abc_tie_element.js +5 -68
  105. package/src/write/abc_triplet_element.js +6 -124
  106. package/src/write/abc_voice_element.js +7 -222
  107. package/src/write/add-chord.js +103 -0
  108. package/src/write/add-text-if.js +33 -0
  109. package/src/write/bottom-text.js +79 -0
  110. package/src/write/calcHeight.js +17 -0
  111. package/src/write/classes.js +100 -0
  112. package/src/write/draw/absolute.js +68 -0
  113. package/src/write/draw/beam.js +56 -0
  114. package/src/write/draw/brace.js +106 -0
  115. package/src/write/draw/crescendo.js +38 -0
  116. package/src/write/draw/debug-box.js +8 -0
  117. package/src/write/draw/draw.js +56 -0
  118. package/src/write/draw/dynamics.js +20 -0
  119. package/src/write/draw/ending.js +46 -0
  120. package/src/write/draw/group-elements.js +66 -0
  121. package/src/write/draw/horizontal-line.js +25 -0
  122. package/src/write/draw/non-music.js +50 -0
  123. package/src/write/draw/print-line.js +24 -0
  124. package/src/write/draw/print-path.js +7 -0
  125. package/src/write/draw/print-stem.js +30 -0
  126. package/src/write/draw/print-symbol.js +59 -0
  127. package/src/write/draw/print-vertical-line.js +18 -0
  128. package/src/write/draw/relative.js +77 -0
  129. package/src/write/draw/round-number.js +5 -0
  130. package/src/write/draw/selectables.js +59 -0
  131. package/src/write/draw/separator.js +16 -0
  132. package/src/write/draw/set-paper-size.js +45 -0
  133. package/src/write/{sprintf.js → draw/sprintf.js} +0 -0
  134. package/src/write/draw/staff-group.js +226 -0
  135. package/src/write/draw/staff-line.js +9 -0
  136. package/src/write/draw/staff.js +33 -0
  137. package/src/write/draw/tab-line.js +40 -0
  138. package/src/write/draw/tempo.js +45 -0
  139. package/src/write/draw/text.js +71 -0
  140. package/src/write/draw/tie.js +97 -0
  141. package/src/write/draw/triplet.js +46 -0
  142. package/src/write/draw/voice.js +102 -0
  143. package/src/write/format-jazz-chord.js +15 -0
  144. package/src/write/free-text.js +41 -0
  145. package/src/write/get-font-and-attr.js +37 -0
  146. package/src/write/get-text-size.js +56 -0
  147. package/src/write/highlight.js +11 -0
  148. package/src/write/layout/VoiceElements.js +121 -0
  149. package/src/write/layout/beam.js +213 -0
  150. package/src/write/layout/get-left-edge-of-staff.js +56 -0
  151. package/src/write/layout/getBarYAt.js +6 -0
  152. package/src/write/layout/layout.js +94 -0
  153. package/src/write/layout/setUpperAndLowerElements.js +232 -0
  154. package/src/write/layout/staffGroup.js +146 -0
  155. package/src/write/layout/triplet.js +75 -0
  156. package/src/write/layout/voice.js +137 -0
  157. package/src/write/selection.js +188 -70
  158. package/src/write/separator.js +10 -0
  159. package/src/write/set-class.js +21 -0
  160. package/src/write/subtitle.js +12 -0
  161. package/src/write/svg.js +95 -43
  162. package/src/write/top-text.js +54 -0
  163. package/src/write/unhighlight.js +11 -0
  164. package/test.js +27 -64
  165. package/types/index.d.ts +1095 -0
  166. package/version.js +1 -1
  167. package/.babelrc +0 -5
  168. package/.eslintrc +0 -3
  169. package/.gitmodules +0 -3
  170. package/Dockerfile +0 -8
  171. package/abcjs-midi.css +0 -166
  172. package/build-utils/loadPresets.js +0 -14
  173. package/build-utils/presets/webpack.analyze.js +0 -6
  174. package/build-utils/presets/webpack.optimize.js +0 -30
  175. package/build-utils/webpack.development.js +0 -14
  176. package/build-utils/webpack.production.js +0 -35
  177. package/deploy-docs.sh +0 -25
  178. package/docker-compose.yml +0 -13
  179. package/docs/README.md +0 -33
  180. package/fix-versions.sh +0 -23
  181. package/midi.js +0 -62
  182. package/src/api/abc_tunebook_midi.js +0 -116
  183. package/src/midi/abc_midi_controls.js +0 -701
  184. package/src/midi/abc_midi_flattener.js +0 -1119
  185. package/src/midi/abc_midi_js_preparer.js +0 -243
  186. package/src/midi/abc_midi_sequencer.js +0 -401
  187. package/src/midi/abc_midi_ui_generator.js +0 -86
  188. package/src/plugin/abc_plugin_midi.js +0 -220
  189. package/src/synth/images/loop.svg +0 -61
  190. package/src/synth/images/pause.svg +0 -6
  191. package/src/synth/images/play.svg +0 -5
  192. package/src/transform/abc2abc_write.js +0 -395
  193. package/static-wrappers/basic.js +0 -2
  194. package/static-wrappers/midi.js +0 -2
  195. package/static-wrappers/plugin-midi.js +0 -6
  196. package/static-wrappers/plugin.js +0 -6
  197. package/webpack.config.js +0 -29
@@ -1,43 +1,20 @@
1
1
  // abc_renderer.js: API to render to SVG/Raphael/whatever rendering engine
2
- // Copyright (C) 2010-2020 Gregory Dyke (gregdyke at gmail dot com)
3
- //
4
- // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5
- // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
6
- // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
7
- // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
- //
9
- // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
- //
11
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
12
- // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
13
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
14
- // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16
2
 
3
+ /*global Math */
17
4
 
18
- /*global Math, console */
19
-
20
- var glyphs = require('./abc_glyphs');
21
5
  var spacing = require('./abc_spacing');
22
- var sprintf = require('./sprintf');
23
6
  var Svg = require('./svg');
24
- var AbsoluteElement = require('./abc_absolute_element');
25
7
 
26
8
  /**
27
9
  * Implements the API for rendering ABCJS Abstract Rendering Structure to a canvas/paper (e.g. SVG, Raphael, etc)
28
10
  * @param {Object} paper
29
- * @param {bool} doRegression
30
11
  */
31
- var Renderer = function(paper, doRegression, shouldAddClasses) {
12
+ var Renderer = function(paper) {
32
13
  this.paper = new Svg(paper);
33
- this.controller = null; //TODO-GD only used when drawing the ABCJS ARS to connect the controller with the elements for highlighting
14
+ this.controller = null;
34
15
 
35
16
  this.space = 3*spacing.SPACE;
36
17
  this.padding = {}; // renderer's padding is managed by the controller
37
- this.doRegression = doRegression;
38
- this.shouldAddClasses = shouldAddClasses;
39
- if (this.doRegression)
40
- this.regressionLines = [];
41
18
  this.reset();
42
19
  };
43
20
 
@@ -46,144 +23,25 @@ Renderer.prototype.reset = function() {
46
23
  this.paper.clear();
47
24
  this.y = 0;
48
25
  this.abctune = null;
49
- this.lastM = null;
50
- this.ingroup = false;
51
26
  this.path = null;
52
27
  this.isPrint = false;
53
28
  this.initVerticalSpace();
54
- if (this.doRegression)
55
- this.regressionLines = [];
56
- // HACK-PER: There was a problem in Raphael where every path string that was sent to it was cached.
57
- // That was causing the browser's memory to steadily grow until the browser went slower and slower until
58
- // it crashed. The fix to that was a patch to Raphael, so it is only patched on the versions of this library that
59
- // bundle Raphael with it. Also, if Raphael gets an update, then that patch will be lost. On version 2.1.2 of Raphael,
60
- // the patch is on line 1542 and 1545 and it is:
61
- // p[ps].sleep = 1;
62
29
  };
63
30
 
64
31
  Renderer.prototype.newTune = function(abcTune) {
65
32
  this.abctune = abcTune; // TODO-PER: this is just to get the font info.
66
33
  this.setVerticalSpace(abcTune.formatting);
67
- this.measureNumber = null;
68
- this.noteNumber = null;
69
- this.setPrintMode(abcTune.media === 'print');
34
+ //this.measureNumber = null;
35
+ //this.noteNumber = null;
36
+ this.isPrint = abcTune.media === 'print';
70
37
  this.setPadding(abcTune);
71
38
  };
72
39
 
73
- Renderer.prototype.createElemSet = function(options) {
74
- return this.paper.openGroup(options);
75
- };
76
-
77
- Renderer.prototype.closeElemSet = function() {
78
- return this.paper.closeGroup();
79
- };
80
-
81
- /**
82
- * Set whether we are formatting this for the screen, or as a preview for creating a PDF version.
83
- * @param {bool} isPrint
84
- */
85
- Renderer.prototype.setPrintMode = function (isPrint) {
86
- this.isPrint = isPrint;
87
- };
88
-
89
- /**
90
- * Set the size of the canvas.
91
- * @param {object} maxwidth
92
- * @param {object} scale
93
- */
94
- Renderer.prototype.setPaperSize = function (maxwidth, scale, responsive) {
95
- var w = (maxwidth+this.padding.right)*scale;
96
- var h = (this.y+this.padding.bottom)*scale;
97
- if (this.isPrint)
98
- h = Math.max(h, 1056); // 11in x 72pt/in x 1.33px/pt
99
- // TODO-PER: We are letting the page get as long as it needs now, but eventually that should go to a second page.
100
- if (this.doRegression)
101
- this.regressionLines.push("PAPER SIZE: ("+w+","+h+")");
102
-
103
- // for accessibility
104
- var text = "Sheet Music";
105
- if (this.abctune && this.abctune.metaText && this.abctune.metaText.title)
106
- text += " for \"" + this.abctune.metaText.title + '"';
107
- this.paper.setTitle(text);
108
-
109
- // for dragging - don't select during drag
110
- var styles = [
111
- "-webkit-touch-callout: none;",
112
- "-webkit-user-select: none;",
113
- "-khtml-user-select: none;",
114
- "-moz-user-select: none;",
115
- "-ms-user-select: none;",
116
- "user-select: none;"
117
- ];
118
- this.paper.insertStyles(".abcjs-dragging-in-progress text, .abcjs-dragging-in-progress tspan {" + styles.join(" ") + ")}");
119
-
120
- var parentStyles = { overflow: "hidden" };
121
- if (responsive === 'resize') {
122
- this.paper.setResponsiveWidth(w, h);
123
- } else {
124
- parentStyles.width = "";
125
- parentStyles.height = h + "px";
126
- if (scale < 1) {
127
- parentStyles.width = w + "px";
128
- this.paper.setSize(w / scale, h / scale);
129
- } else
130
- this.paper.setSize(w, h);
131
- }
132
- this.paper.setScale(scale);
133
- this.paper.setParentStyles(parentStyles);
134
- };
135
-
136
- function getClassSet(el) {
137
- var oldClass = el.getAttribute('class');
138
- if (!oldClass)
139
- oldClass = "";
140
- var klasses = oldClass.split(" ");
141
- var obj = {};
142
- for (var i = 0; i < klasses.length; i++)
143
- obj[klasses[i]] = true;
144
- return obj;
145
- }
146
-
147
- function setClassSet(el, klassSet) {
148
- var klasses = [];
149
- for (var key in klassSet) {
150
- if (klassSet.hasOwnProperty(key))
151
- klasses.push(key);
152
- }
153
- el.setAttribute('class', klasses.join(' '));
154
- }
155
-
156
- Renderer.prototype.addGlobalClass = function (klass) {
157
- // Can't use classList on IE
158
- if (this.paper) {
159
- var obj = getClassSet(this.paper.svg);
160
- obj[klass] = true;
161
- setClassSet(this.paper.svg, obj);
162
- }
163
- };
164
-
165
- Renderer.prototype.removeGlobalClass = function (klass) {
166
- // Can't use classList on IE
167
- if (this.paper) {
168
- var obj = getClassSet(this.paper.svg);
169
- delete obj[klass];
170
- setClassSet(this.paper.svg, obj);
171
- }
172
- };
173
-
174
- /**
175
- * Set the padding
176
- * @param {object} params
177
- */
178
40
  Renderer.prototype.setPaddingOverride = function(params) {
179
41
  this.paddingOverride = { top: params.paddingtop, bottom: params.paddingbottom,
180
42
  right: params.paddingright, left: params.paddingleft };
181
43
  };
182
44
 
183
- /**
184
- * Set the padding
185
- * @param {object} params
186
- */
187
45
  Renderer.prototype.setPadding = function(abctune) {
188
46
  // If the padding is set in the tune, then use that.
189
47
  // Otherwise, if the padding is set in the override, use that.
@@ -243,7 +101,7 @@ Renderer.prototype.initVerticalSpace = function() {
243
101
  text: 18.9, // Set the vertical space above the history.
244
102
  title: 7.56, // Set the vertical space above the title.
245
103
  top: 30.24, //Set the vertical space above the tunes and on the top of the continuation pages.
246
- vocal: 30.67, // Set the vertical space above the lyrics under the staves.
104
+ vocal: 0, // Set the vertical space above the lyrics under the staves.
247
105
  words: 0 // Set the vertical space above the lyrics at the end of the tune.
248
106
  };
249
107
  /*
@@ -301,460 +159,11 @@ Renderer.prototype.setVerticalSpace = function(formatting) {
301
159
  this.spacing.words = formatting.wordsspace *4/3;
302
160
  };
303
161
 
304
- /**
305
- * Leave space at the top of the paper
306
- * @param {object} abctune
307
- */
308
- Renderer.prototype.topMargin = function(abctune) {
309
- this.moveY(this.padding.top);
310
- };
311
-
312
- /**
313
- * Leave space before printing the music
314
- */
315
- Renderer.prototype.addMusicPadding = function() {
316
- this.moveY(this.spacing.music);
317
- };
318
162
 
319
163
  /**
320
164
  * Leave space before printing a staff system
321
165
  */
322
- Renderer.prototype.addStaffPadding = function(lastStaffGroup, thisStaffGroup) {
323
- var lastStaff = lastStaffGroup.staffs[lastStaffGroup.staffs.length-1];
324
- var lastBottomLine = -(lastStaff.bottom - 2); // The 2 is because the scale goes to 2 below the last line.
325
- var nextTopLine = thisStaffGroup.staffs[0].top - 10; // Because 10 represents the top line.
326
- var naturalSeparation = nextTopLine + lastBottomLine; // This is how far apart they'd be without extra spacing
327
- var separationInPixels = naturalSeparation * spacing.STEP;
328
- if (separationInPixels < this.spacing.staffSeparation)
329
- this.moveY(this.spacing.staffSeparation-separationInPixels);
330
- };
331
-
332
- /**
333
- * Text that goes above the score
334
- * @param {number} width
335
- * @param {object} abctune
336
- */
337
- Renderer.prototype.engraveTopText = function(width, abctune) {
338
- var el;
339
- if (abctune.metaText.header && this.isPrint) {
340
- // Note: whether there is a header or not doesn't change any other positioning, so this doesn't change the Y-coordinate.
341
- // This text goes above the margin, so we'll temporarily move up.
342
- var headerTextHeight = this.getTextSize("XXXX", "headerfont", 'abcjs-header abcjs-meta-top').height;
343
- this.y -=headerTextHeight;
344
- this.outputTextIf(this.padding.left, abctune.metaText.header.left, 'headerfont', 'header meta-top', 0, null, 'start');
345
- this.outputTextIf(this.padding.left + width / 2, abctune.metaText.header.center, 'headerfont', 'header meta-top', 0, null, 'middle');
346
- this.outputTextIf(this.padding.left + width, abctune.metaText.header.right, 'headerfont', 'header meta-top', 0, null, 'end');
347
- this.y += headerTextHeight;
348
- }
349
- if (this.isPrint)
350
- this.moveY(this.spacing.top);
351
- if (abctune.metaText.title) {
352
- this.wrapInAbsElem({el_type: "title", startChar: -1, endChar: -1, text: abctune.metaText.title}, 'title meta-top', function() {
353
- return this.outputTextIf(this.padding.left + width / 2, abctune.metaText.title, 'titlefont', 'title meta-top', this.spacing.title, 0, 'middle')[2];
354
- });
355
- }
356
- if (abctune.lines[0] && abctune.lines[0].subtitle) {
357
- this.wrapInAbsElem({el_type: "subtitle", startChar: -1, endChar: -1, text: abctune.lines[0].subtitle}, 'text meta-top subtitle', function() {
358
- return this.outputTextIf(this.padding.left + width / 2, abctune.lines[0].subtitle, 'subtitlefont', 'text meta-top subtitle', this.spacing.subtitle, 0, 'middle')[2];
359
- });
360
- }
361
-
362
- if (abctune.metaText.rhythm || abctune.metaText.origin || abctune.metaText.composer) {
363
- this.moveY(this.spacing.composer);
364
- var rSpace;
365
- if (abctune.metaText.rhythm && abctune.metaText.rhythm.length > 0) {
366
- this.wrapInAbsElem({el_type: "rhythm", startChar: -1, endChar: -1, text: abctune.metaText.rhythm}, 'meta-top rhythm', function() {
367
- rSpace = this.outputTextIf(this.padding.left, abctune.metaText.rhythm, 'infofont', 'meta-top rhythm', 0, null, "start");
368
- return rSpace[2];
369
- });
370
- }
371
- var composerLine = "";
372
- if (abctune.metaText.composer) composerLine += abctune.metaText.composer;
373
- if (abctune.metaText.origin) composerLine += ' (' + abctune.metaText.origin + ')';
374
- if (composerLine.length > 0) {
375
- var space;
376
- this.wrapInAbsElem({el_type: "composer", startChar: -1, endChar: -1, text: composerLine}, 'meta-top rhythm', function() {
377
- space = this.outputTextIf(this.padding.left + width, composerLine, 'composerfont', 'meta-top composer', 0, null, "end");
378
- return space[2];
379
- });
380
- this.moveY(space[1]);
381
- } else {
382
- this.moveY(rSpace[1]);
383
- }
384
- // TODO-PER: The following is a hack to make the elements line up with abcm2ps. Don't know where the extra space is coming from.
385
- this.moveY(-6);
386
- //} else if (this.isPrint) {
387
- // // abcm2ps adds this space whether there is anything to write or not.
388
- // this.moveY(this.spacing.composer);
389
- // var space2 = this.getTextSize("M", 'composerfont', 'meta-top');
390
- // this.moveY(space2.height);
391
- }
392
-
393
- if (abctune.metaText.author && abctune.metaText.author.length > 0) {
394
- var space3;
395
- this.wrapInAbsElem({el_type: "author", startChar: -1, endChar: -1, text: abctune.metaText.author}, 'meta-top author', function() {
396
- space3 = this.outputTextIf(this.padding.left + width, abctune.metaText.author, 'composerfont', 'meta-top author', 0, 0, "end");
397
- return space3[2];
398
- });
399
- }
400
-
401
- if (abctune.metaText.partOrder && abctune.metaText.partOrder.length > 0) {
402
- var space4;
403
- this.wrapInAbsElem({el_type: "partOrder", startChar: -1, endChar: -1, text: abctune.metaText.partOrder}, 'meta-top part-order', function() {
404
- space4 = this.outputTextIf(this.padding.left, abctune.metaText.partOrder, 'partsfont', 'meta-top part-order', 0, 0, "start");
405
- return space4[2];
406
- });
407
- }
408
- };
409
-
410
- Renderer.prototype.wrapInAbsElem = function(abcelem, klass, creator) {
411
- this.controller.currentAbsEl = new AbsoluteElement(abcelem, 0, 0, klass, this.controller.engraver.tuneNumber, {});
412
- var el = creator.bind(this)();
413
- this.controller.currentAbsEl.elemset = [el];
414
- };
415
-
416
- /**
417
- * Text that goes below the score
418
- * @param {number} width
419
- * @param {object} abctune
420
- */
421
- Renderer.prototype.engraveExtraText = function(width, abctune) {
422
- this.lineNumber = null;
423
- this.measureNumber = null;
424
- this.noteNumber = null;
425
- this.voiceNumber = null;
426
-
427
- if (abctune.metaText.unalignedWords && abctune.metaText.unalignedWords.length > 0) {
428
- this.wrapInAbsElem({el_type: "unalignedWords", startChar: -1, endChar: -1}, 'meta-bottom extra-text', function () {
429
- var hash = this.getFontAndAttr("wordsfont", 'meta-bottom unaligned-words');
430
- var space = this.getTextSize("i", 'wordsfont', 'meta-bottom unaligned-words');
431
-
432
- this.moveY(this.spacing.words, 1);
433
- var historyLen = this.controller.history.length;
434
- this.createElemSet({klass: "abcjs-meta-bottom abcjs-unaligned-words"});
435
- for (var j = 0; j < abctune.metaText.unalignedWords.length; j++) {
436
- if (abctune.metaText.unalignedWords[j] === '')
437
- this.moveY(hash.font.size, 1);
438
- else if (typeof abctune.metaText.unalignedWords[j] === 'string') {
439
- this.outputTextIf(this.padding.left + spacing.INDENT, abctune.metaText.unalignedWords[j], 'wordsfont', 'meta-bottom unaligned-words', 0, 0, "start", true);
440
- } else {
441
- var largestY = 0;
442
- var offsetX = 0;
443
- for (var k = 0; k < abctune.metaText.unalignedWords[j].length; k++) {
444
- var thisWord = abctune.metaText.unalignedWords[j][k];
445
- var type = (thisWord.font) ? thisWord.font : "wordsfont";
446
- this.renderText({x: this.padding.left + spacing.INDENT + offsetX, y: this.y, text: thisWord.text, type: type, klass: 'meta-bottom unaligned-words', anchor: 'start', noClass: true});
447
- var size = this.getTextSize(thisWord.text, type, 'meta-bottom unaligned-words');
448
- largestY = Math.max(largestY, size.height);
449
- offsetX += size.width;
450
- // If the phrase ends in a space, then that is not counted in the width, so we need to add that in ourselves.
451
- if (thisWord.text[thisWord.text.length - 1] === ' ') {
452
- offsetX += space.width;
453
- }
454
- }
455
- this.moveY(largestY, 1);
456
- }
457
- }
458
- this.moveY(hash.font.size, 2);
459
- var g = this.closeElemSet();
460
- this.controller.combineHistory(this.controller.history.length-historyLen, g);
461
- return g;
462
- });
463
- }
464
-
465
- var extraText = "";
466
- if (abctune.metaText.book) extraText += "Book: " + abctune.metaText.book + "\n";
467
- if (abctune.metaText.source) extraText += "Source: " + abctune.metaText.source + "\n";
468
- if (abctune.metaText.discography) extraText += "Discography: " + abctune.metaText.discography + "\n";
469
- if (abctune.metaText.notes) extraText += "Notes: " + abctune.metaText.notes + "\n";
470
- if (abctune.metaText.transcription) extraText += "Transcription: " + abctune.metaText.transcription + "\n";
471
- if (abctune.metaText.history) extraText += "History: " + abctune.metaText.history + "\n";
472
- if (abctune.metaText['abc-copyright']) extraText += "Copyright: " + abctune.metaText['abc-copyright'] + "\n";
473
- if (abctune.metaText['abc-creator']) extraText += "Creator: " + abctune.metaText['abc-creator'] + "\n";
474
- if (abctune.metaText['abc-edited-by']) extraText += "Edited By: " + abctune.metaText['abc-edited-by'] + "\n";
475
- if (extraText.length > 0) {
476
- this.wrapInAbsElem({el_type: "extraText", startChar: -1, endChar: -1}, 'meta-bottom extra-text', function() {
477
- var el = this.outputTextIf(this.padding.left, extraText, 'historyfont', 'meta-bottom extra-text', this.spacing.info, 0, "start");
478
- return el[2];
479
- });
480
- }
481
-
482
- if (abctune.metaText.footer && this.isPrint) {
483
- this.controller.currentAbsEl = { tuneNumber: this.controller.engraver.tuneNumber, elemset: [], abcelem: { el_type: "footer", startChar: -1, endChar: -1, text: "" }};
484
- // Note: whether there is a footer or not doesn't change any other positioning, so this doesn't change the Y-coordinate.
485
- el = this.outputTextIf(this.padding.left, abctune.metaText.footer.left, 'footerfont', 'header meta-bottom', 0, null, 'start');
486
- if (el[2])
487
- this.controller.currentAbsEl.elemset.push(el[2]);
488
- el = this.outputTextIf(this.padding.left + width / 2, abctune.metaText.footer.center, 'footerfont', 'header meta-bottom', 0, null, 'middle');
489
- if (el[2])
490
- this.controller.currentAbsEl.elemset.push(el[2]);
491
- el = this.outputTextIf(this.padding.left + width, abctune.metaText.footer.right, 'footerfont', 'header meta-bottom', 0, null, 'end');
492
- if (el[2])
493
- this.controller.currentAbsEl.elemset.push(el[2]);
494
- }
495
- };
496
-
497
- Renderer.prototype.outputFreeText = function (text, vskip) {
498
- this.controller.currentAbsEl = { tuneNumber: this.controller.engraver.tuneNumber, elemset: [], abcelem: { el_type: "free-text", startChar: -1, endChar: -1, text: text }};
499
- if (vskip)
500
- this.moveY(vskip);
501
- var hash = this.getFontAndAttr('textfont', 'defined-text');
502
- if (text === "") { // we do want to print out blank lines if they have been specified.
503
- this.moveY(hash.attr['font-size'] * 2); // move the distance of the line, plus the distance of the margin, which is also one line.
504
- } else if (typeof text === 'string') {
505
- this.moveY(hash.attr['font-size']/2); // TODO-PER: move down some - the y location should be the top of the text, but we output text specifying the center line.
506
- this.outputTextIf(this.padding.left, text, 'textfont', 'defined-text', 0, 0, "start");
507
- } else {
508
- var str = "";
509
- var isCentered = false; // The structure is wrong here: it requires an array to do centering, but it shouldn't have.
510
- for (var i = 0; i < text.length; i++) {
511
- if (text[i].font)
512
- str += "FONT(" + text[i].font + ")";
513
- str += text[i].text;
514
- if (text[i].center)
515
- isCentered = true;
516
- }
517
- var alignment = isCentered ? 'middle' : 'start';
518
- var x = isCentered ? this.controller.width / 2 : this.padding.left;
519
- this.outputTextIf(x, str, 'textfont', 'defined-text', 0, 1, alignment);
520
- }
521
- };
522
-
523
- Renderer.prototype.outputSeparator = function (separator) {
524
- if (!separator.lineLength)
525
- return;
526
- this.moveY(separator.spaceAbove);
527
- this.printSeparator(separator.lineLength);
528
- this.moveY(separator.spaceBelow);
529
- };
530
-
531
- /**
532
- * Output an extra subtitle that is defined later in the tune.
533
- */
534
- Renderer.prototype.outputSubtitle = function (width, subtitle) {
535
- this.outputTextIf(this.padding.left + width / 2, subtitle, 'subtitlefont', 'text subtitle', this.spacing.subtitle, 0, 'middle');
536
- };
537
-
538
- /**
539
- * Begin a group of glyphs that will always be moved, scaled and highlighted together
540
- */
541
- Renderer.prototype.beginGroup = function () {
542
- this.path = [];
543
- this.lastM = [0,0];
544
- this.ingroup = true;
545
- };
546
166
 
547
- /**
548
- * Add a path to the current group
549
- * @param {Array} path
550
- * @private
551
- */
552
- Renderer.prototype.addPath = function (path) {
553
- path = path || [];
554
- if (path.length===0) return;
555
- path[0][0]="m";
556
- path[0][1]-=this.lastM[0];
557
- path[0][2]-=this.lastM[1];
558
- this.lastM[0]+=path[0][1];
559
- this.lastM[1]+=path[0][2];
560
- this.path.push(path[0]);
561
- for (var i=1,ii=path.length;i<ii;i++) {
562
- if (path[i][0]==="m") {
563
- this.lastM[0]+=path[i][1];
564
- this.lastM[1]+=path[i][2];
565
- }
566
- this.path.push(path[i]);
567
- }
568
- };
569
-
570
- /**
571
- * End a group of glyphs that will always be moved, scaled and highlighted together
572
- */
573
- Renderer.prototype.endGroup = function (klass) {
574
- this.ingroup = false;
575
- if (this.path.length===0) return null;
576
- var path = "";
577
- for (var i = 0; i < this.path.length; i++)
578
- path += this.path[i].join(" ");
579
- var ret = this.paper.path({path: path, stroke:"none", fill:"#000000", 'class': this.addClasses(klass)});
580
- this.controller.recordHistory(ret);
581
- this.path = [];
582
- if (this.doRegression) this.addToRegression(ret);
583
-
584
- return ret;
585
- };
586
-
587
- /**
588
- * gets scaled
589
- * @param {number} x1 start x
590
- * @param {number} x2 end x
591
- * @param {number} pitch pitch the stave line is drawn at
592
- */
593
- Renderer.prototype.printStaveLine = function (x1,x2, pitch, klass) {
594
- var isIE=/*@cc_on!@*/false;//IE detector
595
- var dy = 0.35;
596
- var fill = "#000000";
597
- if (isIE) {
598
- dy = 1;
599
- fill = "#666666";
600
- }
601
- var y = this.calcY(pitch);
602
- var pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x1, y-dy, x2, y-dy,
603
- x2, y+dy, x1, y+dy);
604
- var options = {path:pathString, stroke:"none", fill:fill};
605
- if (klass)
606
- options['class'] = klass;
607
- var ret = this.paper.pathToBack(options);
608
- if (this.doRegression) this.addToRegression(ret);
609
-
610
- return ret;
611
- };
612
-
613
- /**
614
- * gets scaled if not in a group
615
- * @param {number} x x coordinate of the stem
616
- * @param {number} dx stem width
617
- * @param {number} y1 y coordinate of the stem bottom
618
- * @param {number} y2 y coordinate of the stem top
619
- */
620
- Renderer.prototype.printStem = function (x, dx, y1, y2) {
621
- if (dx<0) { // correct path "handedness" for intersection with other elements
622
- var tmp = y2;
623
- y2 = y1;
624
- y1 = tmp;
625
- }
626
- var isIE=/*@cc_on!@*/false;//IE detector
627
- var fill = "#000000";
628
- if (isIE && dx<1) {
629
- dx = 1;
630
- fill = "#666666";
631
- }
632
- if (~~x === x) x+=0.05; // raphael does weird rounding (for VML)
633
- var pathArray = [["M",x,y1],["L", x, y2],["L", x+dx, y2],["L",x+dx,y1],["z"]];
634
- if (!isIE && this.ingroup) {
635
- this.addPath(pathArray);
636
- } else {
637
- var path = "";
638
- for (var i = 0; i < pathArray.length; i++)
639
- path += pathArray[i].join(" ");
640
- var ret = this.paper.pathToBack({path:path, stroke:"none", fill:fill, 'class': this.addClasses('stem')});
641
- if (this.doRegression) this.addToRegression(ret);
642
-
643
- return ret;
644
- }
645
- };
646
-
647
- function kernSymbols(lastSymbol, thisSymbol, lastSymbolWidth) {
648
- // This is just some adjustments to make it look better.
649
- var width = lastSymbolWidth;
650
- if (lastSymbol === 'f' && thisSymbol === 'f')
651
- width = width*2/3;
652
- if (lastSymbol === 'p' && thisSymbol === 'p')
653
- width = width*5/6;
654
- if (lastSymbol === 'f' && thisSymbol === 'z')
655
- width = width*5/8;
656
- return width;
657
- }
658
-
659
- /**
660
- * assumes this.y is set appropriately
661
- * if symbol is a multichar string without a . (as in scripts.staccato) 1 symbol per char is assumed
662
- * not scaled if not in printgroup
663
- */
664
- Renderer.prototype.printSymbol = function (x, offset, symbol, scalex, scaley, klass) {
665
- var el;
666
- var ycorr;
667
- if (!symbol) return null;
668
- if (symbol.length > 1 && symbol.indexOf(".") < 0) {
669
- this.paper.openGroup({klass: klass});
670
- var dx = 0;
671
- for (var i = 0; i < symbol.length; i++) {
672
- var s = symbol.charAt(i);
673
- ycorr = glyphs.getYCorr(s);
674
- el = glyphs.printSymbol(x + dx, this.calcY(offset + ycorr), s, this.paper, '');
675
- if (el) {
676
- if (this.doRegression) this.addToRegression(el);
677
- if (i < symbol.length - 1)
678
- dx += kernSymbols(s, symbol.charAt(i + 1), glyphs.getSymbolWidth(s));
679
- } else {
680
- this.renderText({ x: x, y: this.y, text: "no symbol:" + symbol, type: "debugfont", klass: 'debug-msg', anchor: 'start'});
681
- }
682
- }
683
- var g = this.paper.closeGroup();
684
- this.controller.recordHistory(g);
685
- return g;
686
- } else {
687
- ycorr = glyphs.getYCorr(symbol);
688
- if (this.ingroup) {
689
- this.addPath(glyphs.getPathForSymbol(x, this.calcY(offset + ycorr), symbol, scalex, scaley));
690
- } else {
691
- el = glyphs.printSymbol(x, this.calcY(offset + ycorr), symbol, this.paper, klass);
692
- this.controller.recordHistory(el);
693
- if (el) {
694
- if (this.doRegression) this.addToRegression(el);
695
- return el;
696
- } else
697
- this.renderText({ x: x, y: this.y, text: "no symbol:" + symbol, type: "debugfont", klass: 'debug-msg', anchor: 'start'});
698
- }
699
- return null;
700
- }
701
- };
702
-
703
- Renderer.prototype.scaleExistingElem = function (elem, scaleX, scaleY, x, y) {
704
- this.paper.setAttributeOnElement(elem, { style: "transform:scale("+scaleX+","+scaleY + ");transform-origin:" + x + "px " + y + "px;"});
705
- };
706
-
707
- Renderer.prototype.printPath = function (attrs, params) {
708
- var ret = this.paper.path(attrs);
709
- if (!params || !params.history)
710
- this.controller.recordHistory(ret);
711
- else if (params.history === 'not-selectable')
712
- this.controller.recordHistory(ret, true);
713
-
714
- if (this.doRegression) this.addToRegression(ret);
715
- return ret;
716
- };
717
-
718
- Renderer.prototype.drawArc = function(x1, x2, pitch1, pitch2, above, klass, isTie) {
719
- // If it is a tie vs. a slur, draw it shallower.
720
- var spacing = isTie ? 1.2 : 1.5;
721
-
722
- x1 = x1 + 6;
723
- x2 = x2 + 4;
724
- pitch1 = pitch1 + ((above)?spacing:-spacing);
725
- pitch2 = pitch2 + ((above)?spacing:-spacing);
726
- var y1 = this.calcY(pitch1);
727
- var y2 = this.calcY(pitch2);
728
-
729
- //unit direction vector
730
- var dx = x2-x1;
731
- var dy = y2-y1;
732
- var norm= Math.sqrt(dx*dx+dy*dy);
733
- var ux = dx/norm;
734
- var uy = dy/norm;
735
-
736
- var flatten = norm/3.5;
737
- var maxFlatten = isTie ? 10 : 25; // If it is a tie vs. a slur, draw it shallower.
738
- var curve = ((above)?-1:1)*Math.min(maxFlatten, Math.max(4, flatten));
739
-
740
- var controlx1 = x1+flatten*ux-curve*uy;
741
- var controly1 = y1+flatten*uy+curve*ux;
742
- var controlx2 = x2-flatten*ux-curve*uy;
743
- var controly2 = y2-flatten*uy+curve*ux;
744
- var thickness = 2;
745
- var pathString = sprintf("M %f %f C %f %f %f %f %f %f C %f %f %f %f %f %f z", x1, y1,
746
- controlx1, controly1, controlx2, controly2, x2, y2,
747
- controlx2-thickness*uy, controly2+thickness*ux, controlx1-thickness*uy, controly1+thickness*ux, x1, y1);
748
- if (klass)
749
- klass += ' slur';
750
- else
751
- klass = 'slur';
752
- var ret = this.paper.path({path:pathString, stroke:"none", fill:"#000000", 'class': this.addClasses(klass)});
753
- this.controller.recordHistory(ret);
754
- if (this.doRegression) this.addToRegression(ret);
755
-
756
- return ret;
757
- };
758
167
  /**
759
168
  * Calculates the y for a given pitch value (relative to the stave the renderer is currently printing)
760
169
  * @param {number} ofs pitch value (bottom C on a G clef = 0, D=1, etc.)
@@ -763,244 +172,13 @@ Renderer.prototype.calcY = function(ofs) {
763
172
  return this.y - ofs*spacing.STEP;
764
173
  };
765
174
 
766
- /**
767
- * Print @param {number} numLines. If there is 1 line it is the B line. Otherwise the bottom line is the E line.
768
- */
769
- Renderer.prototype.printStave = function (startx, endx, numLines) {
770
- var klass = "abcjs-top-line";
771
- this.paper.openGroup({ prepend: true, klass: "abcjs-staff abcjs-l" + this.lineNumber });
772
- // If there is one line, it is the B line. Otherwise, the bottom line is the E line.
773
- if (numLines === 1) {
774
- this.printStaveLine(startx,endx,6, klass);
775
- } else {
776
- for (var i = numLines - 1; i >= 0; i--) {
777
- this.printStaveLine(startx, endx, (i + 1) * 2, klass);
778
- klass = undefined;
779
- }
780
- }
781
- var ret = this.paper.closeGroup();
782
- this.controller.currentAbsEl = { tuneNumber: this.controller.engraver.tuneNumber, elemset: [ret], abcelem: { el_type: "staff", startChar: -1, endChar: -1 }};
783
- this.controller.recordHistory(ret, true);
784
- };
785
-
786
- /**
787
- *
788
- * @private
789
- */
790
- Renderer.prototype.addClasses = function (c) {
791
- if (!this.shouldAddClasses)
792
- return "";
793
- var ret = [];
794
- if (c && c.length > 0) ret.push(c);
795
- if (this.lineNumber !== null && this.lineNumber !== undefined) ret.push("l"+this.lineNumber);
796
- if (this.measureNumber !== null && this.measureNumber !== undefined) ret.push("m"+this.measureNumber);
797
- if (this.voiceNumber !== null && this.voiceNumber !== undefined) ret.push("v"+this.voiceNumber);
798
- if (c && (c.indexOf('note') >= 0 || c.indexOf('rest') >= 0 || c.indexOf('lyric') >= 0 ) && this.noteNumber !== null && this.noteNumber !== undefined) ret.push("n"+this.noteNumber);
799
- // add a prefix to all classes that abcjs adds.
800
- if (ret.length > 0) {
801
- ret = ret.join(' '); // Some strings are compound classes - that is, specify more than one class in a string.
802
- ret = ret.split(' ');
803
- for (var i = 0; i < ret.length; i++) {
804
- if (ret[i].indexOf('abcjs-') !== 0 && ret[i].length > 0) // if the prefix doesn't already exist and the class is not blank.
805
- ret[i] = 'abcjs-' + ret[i];
806
- }
807
- }
808
- return ret.join(' ');
809
- };
810
-
811
- Renderer.prototype.getFontAndAttr = function(type, klass) {
812
- var font;
813
- if (typeof type === 'string') {
814
- font = this.abctune.formatting[type];
815
- // Raphael deliberately changes the font units to pixels for some reason, so we need to change points to pixels here.
816
- if (font)
817
- font = {face: font.face, size: Math.round(font.size * 4 / 3), decoration: font.decoration, style: font.style, weight: font.weight, box: font.box};
818
- else
819
- font = {face: "Arial", size: Math.round(12 * 4 / 3), decoration: "underline", style: "normal", weight: "normal"};
820
- } else
821
- font = {face: type.face, size: Math.round(type.size * 4 / 3), decoration: type.decoration, style: type.style, weight: type.weight, box: type.box};
822
-
823
- var attr = {"font-size": font.size, 'font-style': font.style,
824
- "font-family": font.face, 'font-weight': font.weight, 'text-decoration': font.decoration,
825
- 'class': this.addClasses(klass) };
826
- //attr.font = ""; // There is a spurious font definition that is put on all text elements. This overwrites it.
827
- return { font: font, attr: attr };
828
- };
829
-
830
- Renderer.prototype.getTextSize = function(text, type, klass, el) {
831
- var hash = this.getFontAndAttr(type, klass);
832
- var size = this.paper.getTextSize(text, hash.attr, el);
833
- if (hash.font.box) {
834
- return { height: size.height + 8, width: size.width + 8 };
835
- }
836
- return size;
837
- };
838
-
839
- Renderer.prototype.renderText = function(params) {
840
- var hash = this.getFontAndAttr(params.type, params.klass);
841
- if (params.anchor)
842
- hash.attr["text-anchor"] = params.anchor;
843
- hash.attr.x = params.x;
844
- hash.attr.y = params.y + 7; // TODO-PER: Not sure why the text appears to be 7 pixels off.
845
- if (!params.centerVertically)
846
- hash.attr.dy = "0.5em";
847
- if (params.type === 'debugfont') {
848
- console.log("Debug msg: " + params.text);
849
- hash.attr.stroke = "#ff0000";
850
- }
851
-
852
- var text = params.text.replace(/\n\n/g, "\n \n");
853
- text = text.replace(/^\n/, "\xA0\n");
854
-
855
- var klass2 = hash.attr['class'];
856
- if (hash.font.box) {
857
- hash.attr.x += 2;
858
- hash.attr.y += 4;
859
- delete hash.attr['class'];
860
- this.createElemSet({klass: klass2, fill: "#000000"});
861
- }
862
- if (params.noClass)
863
- delete hash.attr['class'];
864
- var el = this.paper.text(text, hash.attr);
865
- var elem = el;
866
-
867
- if (hash.font.box) {
868
- var size = this.getTextSize(text, params.type, params.klass); // This size already has the box factored in, so the needs to be taken into consideration.
869
- var padding = 2;
870
- this.paper.rect({ x: params.x - padding, y: params.y, width: size.width - padding, height: size.height - 8});
871
- elem = this.closeElemSet();
872
- }
873
- if (!params.history)
874
- this.controller.recordHistory(elem);
875
- else if (params.history === 'not-selectable')
876
- this.controller.recordHistory(elem, true);
877
- if (this.doRegression) this.addToRegression(el);
878
- return elem;
879
- };
880
-
881
175
  Renderer.prototype.moveY = function (em, numLines) {
882
176
  if (numLines === undefined) numLines = 1;
883
- this.y += em*numLines;
884
- };
885
-
886
- Renderer.prototype.skipSpaceY = function () {
887
- this.y += this.space;
177
+ this.y += em * numLines;
888
178
  };
889
179
 
890
- // Call with 'kind' being the font type to use,
891
- // if marginBottom === null then don't increment the Y after printing, otherwise that is the extra number of em's to leave below the line.
892
- // and alignment being "start", "middle", or "end".
893
- Renderer.prototype.outputTextIf = function(x, str, kind, klass, marginTop, marginBottom, alignment, noClass) {
894
- if (str) {
895
- if (marginTop)
896
- this.moveY(marginTop);
897
- var el = this.renderText({x: x, y: this.y, text: str, type: kind, klass: klass, anchor: alignment, noClass: noClass});
898
- var bb = this.getTextSize(str, kind, klass, el);
899
- var width = isNaN(bb.width) ? 0 : bb.width;
900
- var height = isNaN(bb.height) ? 0 : bb.height;
901
- var hash = this.getFontAndAttr(kind, klass);
902
- if (hash.font.box) {
903
- width += 8;
904
- height += 8;
905
- }
906
- if (marginBottom !== null) {
907
- var numLines = str.split("\n").length;
908
- if (!isNaN(bb.height))
909
- this.moveY(height/numLines, (numLines + marginBottom));
910
- }
911
- return [width, height, el];
912
- }
913
- return [0,0];
914
- };
915
-
916
- Renderer.prototype.addInvisibleMarker = function (className) {
917
- var y = Math.round(this.y);
918
- this.paper.pathToBack({path:"M 0 " + y + " L 0 0", stroke:"none", fill:"none", "stroke-opacity": 0, "fill-opacity": 0, 'class': this.addClasses(className), 'data-vertical': y });
919
- };
920
-
921
- Renderer.prototype.printSeparator = function(width) {
922
- var fill = "rgba(0,0,0,255)";
923
- var stroke = "rgba(0,0,0,0)";
924
- var y = Math.round(this.y);
925
- var staffWidth = this.controller.width;
926
- var x1 = (staffWidth - width)/2;
927
- var x2 = x1 + width;
928
- var pathString = 'M ' + x1 + ' ' + y +
929
- ' L ' + x2 + ' ' + y +
930
- ' L ' + x2 + ' ' + (y+1) +
931
- ' L ' + x1 + ' ' + (y+1) +
932
- ' L ' + x1 + ' ' + y + ' z';
933
- this.paper.pathToBack({path:pathString, stroke:stroke, fill:fill, 'class': this.addClasses('defined-text')});
934
- };
935
-
936
- // For debugging, it is sometimes useful to know where you are vertically.
937
- Renderer.prototype.printHorizontalLine = function (width, vertical, comment) {
938
- var dy = 0.35;
939
- var fill = "rgba(0,0,255,.4)";
940
- var y = this.y;
941
- if (vertical) y = vertical;
942
- y = Math.round(y);
943
- this.paper.text(""+Math.round(y), {x: 10, y: y, "text-anchor": "start", "font-size":"18px", fill: fill, stroke: fill });
944
- var x1 = 50;
945
- var x2 = width;
946
- var pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x1, y-dy, x1+x2, y-dy,
947
- x2, y+dy, x1, y+dy);
948
- this.paper.pathToBack({path:pathString, stroke:"none", fill:fill, 'class': this.addClasses('staff')});
949
- for (var i = 1; i < width/100; i++) {
950
- pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", i*100-dy, y-5, i*100-dy, y+5,
951
- i*100+dy, y-5, i*100+dy, y+5);
952
- this.paper.pathToBack({path:pathString, stroke:"none", fill:fill, 'class': this.addClasses('staff')});
953
- }
954
- if (comment)
955
- this.paper.text(comment, {x: width+70, y: y, "text-anchor": "start", "font-size":"18px", fill: fill, stroke: fill });
956
- };
957
-
958
- Renderer.prototype.printShadedBox = function (x, y, width, height, color, opacity, comment) {
959
- var box = this.paper.rect({ x: x, y: y, width: width, height: height, fill: color, stroke: color, "fill-opacity": opacity, "stroke-opacity": opacity });
960
- if (comment)
961
- this.paper.text(comment, {x: 0, y: y+7, "text-anchor": "start", "font-size":"14px", fill: "rgba(0,0,255,.4)", stroke: "rgba(0,0,255,.4)" });
962
- return box;
963
- };
964
-
965
- Renderer.prototype.printVerticalLine = function (x, y1, y2) {
966
- var dy = 0.35;
967
- var fill = "#00aaaa";
968
- var pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x - dy, y1, x - dy, y2,
969
- x + dy, y1, x + dy, y2);
970
- this.paper.pathToBack({path: pathString, stroke: "none", fill: fill, 'class': this.addClasses('staff')});
971
- pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x - 20, y1, x - 20, y1+3,
972
- x, y1, x, y1+3);
973
- this.paper.pathToBack({path: pathString, stroke: "none", fill: fill, 'class': this.addClasses('staff')});
974
- pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x + 20, y2, x + 20, y2+3,
975
- x, y2, x, y2+3);
976
- this.paper.pathToBack({path: pathString, stroke: "none", fill: fill, 'class': this.addClasses('staff')});
977
-
978
- };
979
-
980
- /**
981
- * @private
982
- */
983
- Renderer.prototype.addToRegression = function (el) {
984
- var box;
985
- try {
986
- box = el.getBBox();
987
- } catch(e) {
988
- box = { width: 0, height: 0 };
989
- }
990
- //var str = "("+box.x+","+box.y+")["+box.width+","+box.height+"] "
991
- var str = el.type + ' ' + box.toString() + ' ';
992
- var attrs = [];
993
- for (var key in el.attrs) {
994
- if (el.attrs.hasOwnProperty(key)) {
995
- if (key === 'class')
996
- str = el.attrs[key] + " " + str;
997
- else
998
- attrs.push(key+": "+el.attrs[key]);
999
- }
1000
- }
1001
- attrs.sort();
1002
- str += "{ " +attrs.join(" ") + " }";
1003
- this.regressionLines.push(str);
180
+ Renderer.prototype.absolutemoveY = function (y) {
181
+ this.y = y;
1004
182
  };
1005
183
 
1006
184
  module.exports = Renderer;