staverepetition.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // [VexFlow](http://vexflow.com) - Copyright (c) Mohit Muthanna 2010.
  2. // Author Larry Kuhns 2011
  3. import { StaveModifier } from './stavemodifier';
  4. import { Glyph } from './glyph';
  5. export class Repetition extends StaveModifier {
  6. static get CATEGORY() { return 'repetitions'; }
  7. static get type() {
  8. return {
  9. NONE: 1, // no coda or segno
  10. CODA_LEFT: 2, // coda at beginning of stave
  11. CODA_RIGHT: 3, // coda at end of stave
  12. SEGNO_LEFT: 4, // segno at beginning of stave
  13. SEGNO_RIGHT: 5, // segno at end of stave
  14. DC: 6, // D.C. at end of stave
  15. DC_AL_CODA: 7, // D.C. al coda at end of stave
  16. DC_AL_FINE: 8, // D.C. al Fine end of stave
  17. DS: 9, // D.S. at end of stave
  18. DS_AL_CODA: 10, // D.S. al coda at end of stave
  19. DS_AL_FINE: 11, // D.S. al Fine at end of stave
  20. FINE: 12, // Fine at end of stave
  21. TO_CODA: 13, // To Coda at end of stave
  22. };
  23. }
  24. constructor(type, x, y_shift) {
  25. super();
  26. this.setAttribute('type', 'Repetition');
  27. this.symbol_type = type;
  28. this.x = x;
  29. this.x_shift = 0;
  30. this.y_shift = y_shift;
  31. this.font = {
  32. family: 'times',
  33. size: 12,
  34. weight: 'bold italic',
  35. };
  36. }
  37. getCategory() { return Repetition.CATEGORY; }
  38. setShiftX(x) { this.x_shift = x; return this; }
  39. setShiftY(y) { this.y_shift = y; return this; }
  40. setX(x) {
  41. this.x = x; return this;
  42. }
  43. draw(stave, x) {
  44. this.setRendered();
  45. switch (this.symbol_type) {
  46. case Repetition.type.CODA_RIGHT:
  47. this.drawCodaFixed(stave, x + stave.width);
  48. break;
  49. case Repetition.type.CODA_LEFT:
  50. this.drawSymbolText(stave, x, 'Coda', true);
  51. break;
  52. case Repetition.type.SEGNO_LEFT:
  53. this.drawSignoFixed(stave, x);
  54. break;
  55. case Repetition.type.SEGNO_RIGHT:
  56. this.drawSignoFixed(stave, x + stave.width);
  57. break;
  58. case Repetition.type.DC:
  59. this.drawSymbolText(stave, x, 'D.C.', false);
  60. break;
  61. case Repetition.type.DC_AL_CODA:
  62. this.drawSymbolText(stave, x, 'D.C. al', true);
  63. break;
  64. case Repetition.type.DC_AL_FINE:
  65. this.drawSymbolText(stave, x, 'D.C. al Fine', false);
  66. break;
  67. case Repetition.type.DS:
  68. this.drawSymbolText(stave, x, 'D.S.', false);
  69. break;
  70. case Repetition.type.DS_AL_CODA:
  71. this.drawSymbolText(stave, x, 'D.S. al', true);
  72. break;
  73. case Repetition.type.DS_AL_FINE:
  74. this.drawSymbolText(stave, x, 'D.S. al Fine', false);
  75. break;
  76. case Repetition.type.FINE:
  77. this.drawSymbolText(stave, x, 'Fine', false);
  78. break;
  79. // VexFlowPatch: added TO_CODA type, handling
  80. case Repetition.type.TO_CODA:
  81. this.drawSymbolText(stave, x, 'To', true);
  82. break;
  83. default:
  84. break;
  85. }
  86. return this;
  87. }
  88. drawCodaFixed(stave, x) {
  89. const y = stave.getYForTopText(stave.options.num_lines) + this.y_shift;
  90. Glyph.renderGlyph(stave.context, this.x + x + this.x_shift, y + 25, 40, 'v4d', true);
  91. return this;
  92. }
  93. drawSignoFixed(stave, x) {
  94. const y = stave.getYForTopText(stave.options.num_lines) + this.y_shift;
  95. Glyph.renderGlyph(stave.context, this.x + x + this.x_shift, y + 25, 30, 'v8c', true);
  96. return this;
  97. }
  98. drawSymbolText(stave, x, text, draw_coda) {
  99. const ctx = stave.checkContext();
  100. ctx.save();
  101. ctx.setFont(this.font.family, this.font.size, this.font.weight);
  102. // Default to right symbol
  103. let text_x = 0 + this.x_shift;
  104. let symbol_x = x + this.x_shift;
  105. if (this.symbol_type === Repetition.type.CODA_LEFT) {
  106. // Offset Coda text to right of stave beginning
  107. text_x = this.x + stave.options.vertical_bar_width;
  108. symbol_x = text_x + ctx.measureText(text).width + 12;
  109. } else {
  110. // VexFlowPatch: fix placement, like for DS_AL_CODA
  111. this.x_shift = -(text_x + ctx.measureText(text).width + 12 + stave.options.vertical_bar_width + 12);
  112. // TO_CODA and DS_AL_CODA draw in the next measure without this x_shift, not sure why not for other symbols.
  113. text_x = this.x + this.x_shift + stave.options.vertical_bar_width;
  114. symbol_x = text_x + ctx.measureText(text).width + 12;
  115. }
  116. // earlier, we applied this to most elements individually, not necessary:
  117. // } else if (this.symbol_type === Repetition.type.TO_CODA) {
  118. // // text_x = x + this.x + this.x_shift + stave.options.vertical_bar_width;
  119. // // symbol_x = text_x + ctx.measureText(text).width + 12;
  120. // // VexFlowPatch: fix placement, like for DS_AL_CODA
  121. // this.x_shift = -(text_x + ctx.measureText(text).width + 12 + stave.options.vertical_bar_width + 12);
  122. // // TO_CODA and DS_AL_CODA draw in the next measure without this x_shift, not sure why not for other symbols.
  123. // text_x = this.x + this.x_shift + stave.options.vertical_bar_width;
  124. // symbol_x = text_x + ctx.measureText(text).width + 12;
  125. // } else if (this.symbol_type === Repetition.type.DS_AL_CODA) {
  126. // this.x_shift = -(text_x + ctx.measureText(text).width + 12 + stave.options.vertical_bar_width + 12);
  127. // // TO_CODA and DS_AL_CODA draw in the next measure without this x_shift, not sure why not for other symbols.
  128. // text_x = this.x + this.x_shift + stave.options.vertical_bar_width;
  129. // symbol_x = text_x + ctx.measureText(text).width + 12;
  130. // } else {
  131. // // Offset Signo text to left stave end
  132. // symbol_x = this.x + x + stave.width - 5 + this.x_shift;
  133. // text_x = symbol_x - + ctx.measureText(text).width - 12;
  134. // }
  135. const y = stave.getYForTopText(stave.options.num_lines) + this.y_shift + 25;
  136. if (draw_coda) {
  137. Glyph.renderGlyph(ctx, symbol_x, y, 40, 'v4d', true);
  138. }
  139. ctx.fillText(text, text_x, y + 5);
  140. ctx.restore();
  141. return this;
  142. }
  143. }