VexFlow - Copyright (c) Mohit Muthanna 2010.
This file implements the TextDynamics
which renders traditional
text dynamics markings, ie: p, f, sfz, rfz, ppp
You can render any dynamics string that contains a combination of the following letters: P, M, F, Z, R, S
import { Vex } from './vex';
import { Note } from './note';
import { Glyph } from './glyph';
To enable logging for this class. Set Vex.Flow.TextDynamics.DEBUG
to true
.
function L(...args) { if (TextDynamics.DEBUG) Vex.L('Vex.Flow.TextDynamics', args); }
export class TextDynamics extends Note {
The glyph data for each dynamics letter
static get GLYPHS() {
return {
'f': {
code: 'vba',
width: 12,
},
'p': {
code: 'vbf',
width: 14,
},
'm': {
code: 'v62',
width: 17,
},
's': {
code: 'v4a',
width: 10,
},
'z': {
code: 'v80',
width: 12,
},
'r': {
code: 'vb1',
width: 12,
},
};
}
A TextDynamics
object inherits from Note
so that it can be formatted
within a Voice
.
Create the dynamics marking. text_struct
is an object
that contains a duration
property and a sequence
of
letters that represents the letters to render
constructor(text_struct) {
super(text_struct);
this.setAttribute('type', 'TextDynamics');
this.sequence = text_struct.text.toLowerCase();
this.line = text_struct.line || 0;
this.glyphs = [];
Vex.Merge(this.render_options, {
glyph_font_size: 40,
});
L('New Dynamics Text: ', this.sequence);
}
Set the Stave line on which the note should be placed
setLine(line) {
this.line = line;
return this;
}
Preformat the dynamics text
preFormat() {
let total_width = 0;
Iterate through each letter
this.sequence.split('').forEach(letter => {
Get the glyph data for the letter
const glyph_data = TextDynamics.GLYPHS[letter];
if (!glyph_data) throw new Vex.RERR('Invalid dynamics character: ' + letter);
const size = this.render_options.glyph_font_size;
const glyph = new Glyph(glyph_data.code, size);
Add the glyph
this.glyphs.push(glyph);
total_width += glyph_data.width;
});
Store the width of the text
this.setWidth(total_width);
this.preFormatted = true;
return this;
}
Draw the dynamics text on the rendering context
draw() {
const x = this.getAbsoluteX();
const y = this.stave.getYForLine(this.line + (-3));
L('Rendering Dynamics: ', this.sequence);
let letter_x = x;
this.glyphs.forEach((glyph, index) => {
const current_letter = this.sequence[index];
glyph.render(this.context, letter_x, y);
letter_x += TextDynamics.GLYPHS[current_letter].width;
});
}
}