Skip to content

Commit

Permalink
fix issues regarding annotations on tab notes
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronDavidNewman committed Dec 27, 2021
1 parent 63052e4 commit b8c0ebf
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 23 deletions.
46 changes: 32 additions & 14 deletions src/annotation.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
// [VexFlow](https://vexflow.com) - Copyright (c) Mohit Muthanna 2010.
// MIT License
import { Element } from './element';
import { FontInfo } from './font';
import { FontInfo, log, ModifierContextState, StemmableNote, TextFormatter } from './index';
import { Modifier, ModifierPosition } from './modifier';
import { Stave } from './stave';
import { Stem } from './stem';
import { ModifierContextState } from './modifiercontext';
import { StemmableNote } from './stemmablenote';
import { Tables } from './tables';
import { TextFormatter } from './textformatter';
import { log } from './util';
import { TabNote, TabNotePosition } from './tabnote';

// eslint-disable-next-line
function L(...args: any[]) {
Expand Down Expand Up @@ -71,6 +68,12 @@ export class Annotation extends Modifier {
/** Arrange annotations within a `ModifierContext` */
static format(annotations: Annotation[], state: ModifierContextState): boolean {
if (!annotations || annotations.length === 0) return false;
const topString = (ar : TabNotePosition[]): number => {
return ar.map((x) => x.str).reduce((a, b) => a > b ? a : b);
}
const bottomString = (ar : TabNotePosition[]): number => {
return ar.map((x) => x.str).reduce((a, b) => a < b ? a : b);
}

let width = 0;
for (let i = 0; i < annotations.length; ++i) {
Expand All @@ -85,9 +88,18 @@ export class Annotation extends Modifier {
const stemDirection = note.hasStem() ? note.getStemDirection() : Stem.UP;
let stemHeight = 0;
let lines = 5;
if (note instanceof StemmableNote) {
if (note instanceof TabNote) {
if (note.render_options.draw_stem) {
const stem = (note as StemmableNote).getStem();
if (stem) {
stemHeight = Math.abs(stem.getHeight()) / Tables.STAVE_LINE_DISTANCE;
}
} else {
stemHeight = 0;
}
} else if (note instanceof StemmableNote) {
const stem = (note as StemmableNote).getStem();
if (stem) {
if (stem && note.getNoteType() === 'n') {
stemHeight = Math.abs(stem.getHeight()) / Tables.STAVE_LINE_DISTANCE;
}
}
Expand All @@ -100,6 +112,9 @@ export class Annotation extends Modifier {

if (annotation.verticalJustification === this.VerticalJustify.TOP) {
let noteLine = note.getLineNumber(true);
if (note instanceof TabNote) {
noteLine = lines - (bottomString((note as TabNote).getPositions()) - 0.5);
}
if (stemDirection === Stem.UP) {
noteLine += stemHeight;
}
Expand All @@ -114,6 +129,9 @@ export class Annotation extends Modifier {
}
} else if (annotation.verticalJustification === this.VerticalJustify.BOTTOM) {
let noteLine = lines - note.getLineNumber();
if (note instanceof TabNote) {
noteLine = topString((note as TabNote).getPositions()) - 1;
}
if (stemDirection === Stem.DOWN) {
noteLine += stemHeight;
}
Expand Down Expand Up @@ -157,10 +175,6 @@ export class Annotation extends Modifier {
// The default width is calculated from the text.
this.setWidth(Tables.textWidth(text));
}
setPosition(position: string | number): this {
return super.setPosition(position);
}

/**
* Set vertical position of text (above or below stave).
* @param just value in `AnnotationVerticalJustify`.
Expand Down Expand Up @@ -230,9 +244,10 @@ export class Annotation extends Modifier {
}

if (this.verticalJustification === AnnotationVerticalJustify.BOTTOM) {
// HACK: We need to compensate for the text's height since its origin
// is bottom-right.
y = note.getYs()[0] + (this.text_line + 1) * Tables.STAVE_LINE_DISTANCE + text_height;
// Use the largest (lowest) Y value
const ys: number[] = note.getYs();
y = ys.reduce((a, b) => a > b ? a : b);
y += (this.text_line + 1) * Tables.STAVE_LINE_DISTANCE + text_height;
if (has_stem && stemDirection === Stem.DOWN) {
y = Math.max(y, stem_ext.topY + text_height + spacing * this.text_line);
}
Expand All @@ -243,6 +258,9 @@ export class Annotation extends Modifier {
} else if (this.verticalJustification === AnnotationVerticalJustify.TOP) {
y = note.getYs()[0] - (this.text_line + 1) * Tables.STAVE_LINE_DISTANCE;
if (has_stem && stemDirection === Stem.UP) {
// If the stem is above the stave already, go with default line width vs. actual
// since the lines between don't really matter.
spacing = stem_ext.topY < stave.getTopLineTopY() ? Tables.STAVE_LINE_DISTANCE : spacing;
y = Math.min(y, stem_ext.topY - spacing * (this.text_line + 1));
}
} /* CENTER_STEM */ else {
Expand Down
13 changes: 6 additions & 7 deletions tests/annotation_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function simple(options: TestOptions, contextBuilder: ContextBuilder): void {
positions: [{ str: 2, fret: 10 }],
duration: 'h',
})
.addModifier(new Annotation('T'), 0)
.addModifier(new Annotation('T').setVerticalJustification(AnnotationVerticalJustify.TOP), 0)
.addModifier(new Bend('Full'), 0),
];

Expand Down Expand Up @@ -177,7 +177,6 @@ function harmonic(options: TestOptions, contextBuilder: ContextBuilder): void {

function picking(options: TestOptions, contextBuilder: ContextBuilder): void {
const ctx = contextBuilder(options.elementId, 500, 240);
ctx.scale(1.5, 1.5);
ctx.setFillStyle('#221');
ctx.setStrokeStyle('#221');
ctx.setFont(Font.SANS_SERIF, FONT_SIZE);
Expand All @@ -200,19 +199,19 @@ function picking(options: TestOptions, contextBuilder: ContextBuilder): void {
tabNote({
positions: [{ str: 6, fret: 9 }],
duration: '8',
}).addModifier(annotation('p'), 0),
}).addModifier(annotation('p').setVerticalJustification(AnnotationVerticalJustify.TOP), 0),
tabNote({
positions: [{ str: 3, fret: 9 }],
duration: '8',
}).addModifier(annotation('i'), 0),
}).addModifier(annotation('i').setVerticalJustification(AnnotationVerticalJustify.TOP), 0),
tabNote({
positions: [{ str: 2, fret: 9 }],
duration: '8',
}).addModifier(annotation('m'), 0),
}).addModifier(annotation('m').setVerticalJustification(AnnotationVerticalJustify.TOP), 0),
tabNote({
positions: [{ str: 1, fret: 9 }],
duration: '8',
}).addModifier(annotation('a'), 0),
}).addModifier(annotation('a').setVerticalJustification(AnnotationVerticalJustify.TOP), 0),
];

Formatter.FormatAndDraw(ctx, stave, notes);
Expand Down Expand Up @@ -466,7 +465,7 @@ function tabNotes(options: TestOptions, contextBuilder: ContextBuilder): void {
// Alternatively, you could add all the notes in one big array with spread syntax.
// voice.addTickables([...notes1, ...notes2, ...notes3]);

new Formatter().joinVoices([voice]).formatToStave([voice], stave);
new Formatter().joinVoices([voice]).formatToStave([voice], stave, { stave });

voice.draw(ctx, stave);

Expand Down
4 changes: 2 additions & 2 deletions tests/stavenote_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { TestOptions, VexFlowTests } from './vexflow_test_helpers';

import { Accidental } from '../src/accidental';
import { Annotation } from '../src/annotation';
import { Annotation, AnnotationVerticalJustify } from '../src/annotation';
import { Articulation } from '../src/articulation';
import { Beam } from '../src/beam';
import { Flow } from '../src/flow';
Expand Down Expand Up @@ -1031,7 +1031,7 @@ function centerAlignedRestAnnotation(options: TestOptions): void {

const note = f
.StaveNote({ keys: ['b/4'], duration: '1r', align_center: true })
.addAnnotation(0, new Annotation('Whole measure rest').setPosition(3));
.addAnnotation(0, new Annotation('Whole measure rest').setVerticalJustification(AnnotationVerticalJustify.TOP));

const voice = f.Voice().setStrict(false).addTickables([note]);

Expand Down

0 comments on commit b8c0ebf

Please sign in to comment.