Skip to content

Commit

Permalink
testing and code review changes for annotation text metrics
Browse files Browse the repository at this point in the history
1. Change spelling of font family in metrics to match the css name
2. hash strings based on width/font data so they don't have to be recalculated
3. Add different font sizes to test cases
4. Add lines if the font height exceeds a single line
  • Loading branch information
AaronDavidNewman committed Mar 14, 2021
1 parent e9209f6 commit 237d05c
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 263 deletions.
44 changes: 25 additions & 19 deletions src/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ export class Annotation extends Modifier {
return 'annotations';
}

// Is there a better source for this?
static get distanceBetweenLines() {
return 10;
}

// Text annotations can be positioned and justified relative to the note.
static get Justify() {
return {
Expand Down Expand Up @@ -69,21 +74,24 @@ export class Annotation extends Modifier {
for (let i = 0; i < annotations.length; ++i) {
let testWidth = 0;
const annotation = annotations[i];
const textFont = TextFont.getTextFontFromVexFontData({ family: annotation.font.family,
size: annotation.font.size, weight: 'normal' });
for (let j = 0; j < annotation.text.length; ++j) {
testWidth += textFont.getWidthForCharacter(annotation.text[j]);
}
const textFont = TextFont.getTextFontFromVexFontData({
family: annotation.font.family,
size: annotation.font.size,
weight: 'normal',
});
// Calculate if the vertical extent will exceed a single line and adjust accordingly.
const numLines = Math.floor(textFont.maxHeight / Annotation.distanceBetweenLines) + 1;
// Get the string width from the font metrics
testWidth = textFont.getWidthForString(annotation.text);
width = Math.max(width, testWidth);
if (annotation.getPosition() === Modifier.Position.ABOVE) {
annotation.setTextLine(state.top_text_line);
state.top_text_line++;
state.top_text_line += numLines;
} else {
annotation.setTextLine(state.text_line);
state.text_line++;
state.text_line += numLines;
}
}

state.left_shift += width / 2;
state.right_shift += width / 2;
return true;
Expand Down Expand Up @@ -113,7 +121,9 @@ export class Annotation extends Modifier {
this.setWidth(Flow.textWidth(text));
}

getCategory() { return Annotation.CATEGORY; }
getCategory() {
return Annotation.CATEGORY;
}

// Set font family, size, and weight. E.g., `Arial`, `10pt`, `Bold`.
setFont(family, size, weight) {
Expand All @@ -124,19 +134,17 @@ export class Annotation extends Modifier {
// Set vertical position of text (above or below stave). `just` must be
// a value in `Annotation.VerticalJustify`.
setVerticalJustification(just) {
this.vert_justification = typeof (just) === 'string'
? Annotation.VerticalJustifyString[just]
: just;
this.vert_justification = typeof just === 'string' ? Annotation.VerticalJustifyString[just] : just;
return this;
}

// Get and set horizontal justification. `justification` is a value in
// `Annotation.Justify`.
getJustification() { return this.justification; }
getJustification() {
return this.justification;
}
setJustification(just) {
this.justification = typeof (just) === 'string'
? Annotation.JustifyString[just]
: just;
this.justification = typeof just === 'string' ? Annotation.JustifyString[just] : just;
return this;
}

Expand All @@ -145,9 +153,7 @@ export class Annotation extends Modifier {
this.checkContext();

if (!this.note) {
throw new Vex.RERR(
'NoNoteForAnnotation', "Can't draw text annotation without an attached note."
);
throw new Vex.RERR('NoNoteForAnnotation', "Can't draw text annotation without an attached note.");
}

this.setRendered();
Expand Down
2 changes: 1 addition & 1 deletion src/fonts/petalumascript_textmetrics.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const PetalumaScriptTextMetrics = {
name: 'PetalumaScript',
name: 'petalumaScript',
smufl: false,
spacing:50,
"glyphs": {
Expand Down
2 changes: 1 addition & 1 deletion src/fonts/robotoslab_textmetrics.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const RobotoSlabTextMetrics = {
name: 'RobotoSlab',
name: 'Roboto Slab',
smufl: false,
spacing:50,
"glyphs": {
Expand Down
33 changes: 30 additions & 3 deletions src/textfont.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class TextFont {
if (!TextFont.registryInstance) {
TextFont.registryInstance = [];
TextFont.registryInstance.push({
name: 'RobotoSlab',
name: 'Roboto Slab',
resolution: RobotoSlabTextMetrics.resolution,
glyphs: RobotoSlabTextMetrics.glyphs,
family: RobotoSlabTextMetrics.fontFamily,
Expand All @@ -49,7 +49,7 @@ export class TextFont {
description: 'Default serif text font to pair with Bravura/Gonville engraving font',
});
TextFont.registryInstance.push({
name: 'PetalumaScript',
name: 'petalumaScript',
resolution: PetalumaScriptTextMetrics.resolution,
glyphs: PetalumaScriptTextMetrics.glyphs,
family: PetalumaScriptTextMetrics.fontFamily,
Expand Down Expand Up @@ -118,6 +118,13 @@ export class TextFont {
return fs && typeof fs === 'string' && fs.toLowerCase() === 'italic';
}

static get fontTextHash() {
if (typeof TextFont.fontTextHashInstance === 'undefined') {
TextFont.fontTextHashInstance = {};
}
return TextFont.fontTextHashInstance;
}

// ### getTextFontFromVexFontData
// Find the font that most closely matches the parameters from the given font data.
// Primarily we look for font family, also bold and italic attributes. This
Expand Down Expand Up @@ -154,7 +161,7 @@ export class TextFont {
}
}
}
if (typeof(fd.size) === 'number' && fd.size > 0) {
if (typeof fd.size === 'number' && fd.size > 0) {
rv.setFontSize(fd.size);
}
return rv;
Expand Down Expand Up @@ -210,6 +217,13 @@ export class TextFont {
if (!this.maxSizeGlyph) {
this.maxSizeGlyph = 'H';
}
this.weight = typeof this.weight === 'undefined' ? '' : this.weight;
this.style = typeof this.style === 'undefined' ? '' : this.style;
this.setHashBase();
}

setHashBase() {
this.textHashBase = this.family + '-' + this.size + '-' + this.weight + '-' + this.style;
}

getMetricForCharacter(c) {
Expand All @@ -232,6 +246,18 @@ export class TextFont {
return (metric.advanceWidth / this.resolution) * this.pointsToPixels;
}

getWidthForString(s) {
const key = this.textHashBase + '-' + s;
let width = 0;
if (!TextFont.fontTextHash[key]) {
for (let j = 0; j < s.length; ++j) {
width += this.getWidthForCharacter(s[j]);
}
TextFont.fontTextHash[key] = width;
}
return TextFont.fontTextHash[key];
}

// ### pointsToPixels
// The font size is specified in points, convert to 'pixels' in the svg space
get pointsToPixels() {
Expand All @@ -240,6 +266,7 @@ export class TextFont {

setFontSize(size) {
this.size = size;
this.setHashBase();
return this;
}
}
Loading

0 comments on commit 237d05c

Please sign in to comment.