123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- import Vex from "vexflow";
- import { VoiceEntry } from "../../VoiceData/VoiceEntry";
- import { GraphicalVoiceEntry } from "../GraphicalVoiceEntry";
- import { GraphicalStaffEntry } from "../GraphicalStaffEntry";
- import { unitInPixels } from "./VexFlowMusicSheetDrawer";
- import { NoteEnum } from "../../../Common/DataObjects/Pitch";
- import { Note } from "../../VoiceData/Note";
- import { ColoringModes } from "./../DrawingParameters";
- import { GraphicalNote } from "../GraphicalNote";
- export class VexFlowVoiceEntry extends GraphicalVoiceEntry {
- private mVexFlowStaveNote: Vex.Flow.StemmableNote;
- constructor(parentVoiceEntry: VoiceEntry, parentStaffEntry: GraphicalStaffEntry) {
- super(parentVoiceEntry, parentStaffEntry);
- }
- public applyBordersFromVexflow(): void {
- const staveNote: any = (this.vfStaveNote as any);
- if (!staveNote.getNoteHeadBeginX) {
- return;
- }
- const boundingBox: any = staveNote.getBoundingBox();
- const modifierWidth: number = staveNote.getNoteHeadBeginX() - boundingBox.x;
- this.PositionAndShape.RelativePosition.y = boundingBox.y / unitInPixels;
- this.PositionAndShape.BorderTop = 0;
- this.PositionAndShape.BorderBottom = boundingBox.h / unitInPixels;
- this.PositionAndShape.BorderLeft = -(modifierWidth + staveNote.width / 2) / unitInPixels; // Left of our X origin is the modifier
- this.PositionAndShape.BorderRight = (boundingBox.w - modifierWidth) / unitInPixels; // Right of x origin is the note
- }
- public set vfStaveNote(value: Vex.Flow.StemmableNote) {
- this.mVexFlowStaveNote = value;
- }
- public get vfStaveNote(): Vex.Flow.StemmableNote {
- return this.mVexFlowStaveNote;
- }
- /** (Re-)color notes and stems by setting their Vexflow styles.
- * Could be made redundant by a Vexflow PR, but Vexflow needs more solid and permanent color methods/variables for that
- * See VexFlowConverter.StaveNote()
- */
- public color(): void {
- const defaultColorNotehead: string = this.rules.DefaultColorNotehead;
- const defaultColorRest: string = this.rules.DefaultColorRest;
- const defaultColorStem: string = this.rules.DefaultColorStem;
- const transparentColor: string = "#00000000"; // transparent color in vexflow
- let noteheadColor: string; // if null: no noteheadcolor to set (stays black)
- let sourceNoteNoteheadColor: string;
- const vfStaveNote: any = (<VexFlowVoiceEntry>(this as any)).vfStaveNote;
- for (let i: number = 0; i < this.notes.length; i++) {
- const note: GraphicalNote = this.notes[i];
- sourceNoteNoteheadColor = note.sourceNote.NoteheadColor;
- noteheadColor = sourceNoteNoteheadColor;
- // Switch between XML colors and automatic coloring
- if (this.rules.ColoringMode === ColoringModes.AutoColoring ||
- this.rules.ColoringMode === ColoringModes.CustomColorSet) {
- if (note.sourceNote.isRest()) {
- noteheadColor = this.rules.ColoringSetCurrent.getValue(-1);
- } else {
- const fundamentalNote: NoteEnum = note.sourceNote.Pitch.FundamentalNote;
- noteheadColor = this.rules.ColoringSetCurrent.getValue(fundamentalNote);
- }
- }
- if (!note.sourceNote.PrintObject) {
- noteheadColor = transparentColor; // transparent
- } else if (!noteheadColor // revert transparency after PrintObject was set to false, then true again
- || noteheadColor === "#000000" // questionable, because you might want to set specific notes to black,
- // but unfortunately some programs export everything explicitly as black
- ) {
- noteheadColor = this.rules.DefaultColorNotehead;
- }
- // DEBUG runtime coloring test
- /*const testColor: string = "#FF0000";
- if (i === 2 && Math.random() < 0.1 && note.sourceNote.NoteheadColor !== testColor) {
- const measureNumber: number = note.parentVoiceEntry.parentStaffEntry.parentMeasure.MeasureNumber;
- noteheadColor = testColor;
- console.log("color changed to " + noteheadColor + " of this note:\n" + note.sourceNote.Pitch.ToString() +
- ", in measure #" + measureNumber);
- }*/
- if (!sourceNoteNoteheadColor && this.rules.ColoringMode === ColoringModes.XML && note.sourceNote.PrintObject) {
- if (!note.sourceNote.isRest() && defaultColorNotehead) {
- noteheadColor = defaultColorNotehead;
- } else if (note.sourceNote.isRest() && defaultColorRest) {
- noteheadColor = defaultColorRest;
- }
- }
- if (noteheadColor && note.sourceNote.PrintObject) {
- note.sourceNote.NoteheadColorCurrentlyRendered = noteheadColor;
- } else if (!noteheadColor) {
- continue;
- }
- // color notebeam if all noteheads have same color and stem coloring enabled
- if (this.rules.ColoringEnabled && note.sourceNote.NoteBeam && this.rules.ColorBeams) {
- const beamNotes: Note[] = note.sourceNote.NoteBeam.Notes;
- let colorBeam: boolean = true;
- for (let j: number = 0; j < beamNotes.length; j++) {
- if (beamNotes[j].NoteheadColorCurrentlyRendered !== noteheadColor) {
- colorBeam = false;
- }
- }
- if (colorBeam) {
- if (vfStaveNote?.beam?.setStyle) {
- vfStaveNote.beam.setStyle({ fillStyle: noteheadColor, strokeStyle: noteheadColor});
- }
- }
- }
- if (vfStaveNote) {
- if (vfStaveNote.note_heads) { // see VexFlowConverter, needs Vexflow PR
- const notehead: any = vfStaveNote.note_heads[i];
- if (notehead) {
- notehead.setStyle({ fillStyle: noteheadColor, strokeStyle: noteheadColor });
- }
- }
- // set ledger line color. TODO coordinate this with VexFlowConverter.StaveNote(), where there's also still code for this, maybe unnecessarily.
- if ((vfStaveNote as any).setLedgerLineStyle) { // setLedgerLineStyle doesn't exist on TabNote or rest, would throw error.
- if (noteheadColor === transparentColor) {
- (vfStaveNote as any).setLedgerLineStyle(
- { fillStyle: noteheadColor, strokeStyle: noteheadColor, lineWidth: this.rules.LedgerLineWidth });
- } else {
- (vfStaveNote as any).setLedgerLineStyle({
- fillStyle: this.rules.LedgerLineColorDefault,
- lineWidth: this.rules.LedgerLineWidth,
- strokeStyle: this.rules.LedgerLineColorDefault
- });
- // we could give the color (style) as noteheadColor, but then we need to figure out which note has the ledger line.
- // otherwise ledger lines get the color of the top note, see Function Test Color.
- }
- }
- }
- }
- // color stems
- let stemColor: string = defaultColorStem; // reset to black/default when coloring was disabled. maybe needed elsewhere too
- if (this.rules.ColoringEnabled) {
- stemColor = this.parentVoiceEntry.StemColor; // TODO: once coloringSetCustom gets stem color, respect it
- if (!stemColor
- || stemColor === "#000000") { // see above, noteheadColor === "#000000"
- stemColor = defaultColorStem;
- }
- if (this.rules.ColorStemsLikeNoteheads && noteheadColor) {
- // condition could be even more fine-grained by only recoloring if there was no custom StemColor set. will be more complex though
- stemColor = noteheadColor;
- }
- }
- let stemTransparent: boolean = true;
- for (const note of this.parentVoiceEntry.Notes) {
- if (note.PrintObject) {
- stemTransparent = false;
- break;
- }
- }
- if (stemTransparent) {
- stemColor = transparentColor;
- }
- const stemStyle: Object = { fillStyle: stemColor, strokeStyle: stemColor };
- if (vfStaveNote && vfStaveNote.setStemStyle) {
- if (!stemTransparent) {
- this.parentVoiceEntry.StemColor = stemColor;
- }
- vfStaveNote.setStemStyle(stemStyle);
- if (vfStaveNote.flag && vfStaveNote.setFlagStyle && this.rules.ColorFlags) {
- vfStaveNote.setFlagStyle(stemStyle);
- }
- }
- }
- }
|