vexflow
Version:
A JavaScript library for rendering music notation and guitar tablature.
138 lines (137 loc) • 4.29 kB
JavaScript
import { Glyph } from './glyph.js';
import { StaveModifier, StaveModifierPosition } from './stavemodifier.js';
import { Tables } from './tables.js';
import { defined, log } from './util.js';
function L(...args) {
if (Clef.DEBUG)
log('Vex.Flow.Clef', args);
}
class Clef extends StaveModifier {
static get CATEGORY() {
return "Clef";
}
static get types() {
return {
treble: {
code: 'gClef',
line: 3,
},
bass: {
code: 'fClef',
line: 1,
},
alto: {
code: 'cClef',
line: 2,
},
tenor: {
code: 'cClef',
line: 1,
},
percussion: {
code: 'unpitchedPercussionClef1',
line: 2,
},
soprano: {
code: 'cClef',
line: 4,
},
'mezzo-soprano': {
code: 'cClef',
line: 3,
},
'baritone-c': {
code: 'cClef',
line: 0,
},
'baritone-f': {
code: 'fClef',
line: 2,
},
subbass: {
code: 'fClef',
line: 0,
},
french: {
code: 'gClef',
line: 4,
},
tab: {
code: '6stringTabClef',
line: 2.5,
},
};
}
static get annotationSmufl() {
return {
'8va': 'timeSig8',
'8vb': 'timeSig8',
};
}
constructor(type, size, annotation) {
super();
this.clef = Clef.types['treble'];
this.setPosition(StaveModifierPosition.BEGIN);
this.setType(type, size, annotation);
this.setWidth(Glyph.getWidth(this.clef.code, Clef.getPoint(this.size), `clef_${this.size}`));
L('Creating clef:', type);
}
setType(type, size, annotation) {
this.type = type;
this.clef = Clef.types[type];
if (size === undefined) {
this.size = 'default';
}
else {
this.size = size;
}
const musicFont = Tables.currentMusicFont();
if (annotation !== undefined) {
const code = Clef.annotationSmufl[annotation];
const point = (Clef.getPoint(this.size) / 5) * 3;
const line = musicFont.lookupMetric(`clef_${this.size}.annotations.${annotation}.${this.type}.line`);
const x_shift = musicFont.lookupMetric(`clef_${this.size}.annotations.${annotation}.${this.type}.shiftX`);
this.annotation = { code, point, line, x_shift };
this.attachment = new Glyph(this.annotation.code, this.annotation.point);
this.attachment.metrics.x_max = 0;
this.attachment.setXShift(this.annotation.x_shift);
}
else {
this.annotation = undefined;
}
return this;
}
getWidth() {
if (this.type === 'tab') {
defined(this.stave, 'ClefError', "Can't get width without stave.");
}
return this.width;
}
static getPoint(size) {
return size == 'default' ? Tables.NOTATION_FONT_SCALE : (Tables.NOTATION_FONT_SCALE / 3) * 2;
}
setStave(stave) {
this.stave = stave;
return this;
}
draw() {
const stave = this.checkStave();
const ctx = stave.checkContext();
this.setRendered();
this.applyStyle(ctx);
ctx.openGroup('clef', this.getAttribute('id'));
Glyph.renderGlyph(ctx, this.x, stave.getYForLine(this.clef.line), Clef.getPoint(this.size), this.clef.code, {
category: `clef_${this.size}`,
});
if (this.annotation !== undefined && this.attachment !== undefined) {
this.placeGlyphOnLine(this.attachment, stave, this.annotation.line);
this.attachment.setStave(stave);
this.attachment.setContext(ctx);
this.attachment.renderToStave(this.x);
}
ctx.closeGroup();
this.restoreStyle(ctx);
}
}
Clef.DEBUG = false;
export { Clef };