Skip to content

Commit

Permalink
Merge pull request #223 from stringsync/fixes
Browse files Browse the repository at this point in the history
Gladiolus Rag fixes
  • Loading branch information
jaredjj3 authored May 31, 2024
2 parents 3e0e3c1 + ed13dc3 commit b859966
Show file tree
Hide file tree
Showing 18 changed files with 341 additions and 128 deletions.
173 changes: 173 additions & 0 deletions src/rendering/barline.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import * as musicxml from '@/musicxml';
import * as vexflow from 'vexflow';
import { Config } from './config';

/** The result of rendering a barline. */
export type BarlineRendering = {
type: 'barline';
vexflow: {
barlineType: vexflow.BarlineType;
staveConnectorType: vexflow.StaveConnectorType;
};
};

export type BarlineType = 'single' | 'double-same' | 'double-different' | 'repeat' | 'none';

export type BarlineLocation = 'left' | 'middle' | 'right';

export class Barline {
private config: Config;
private type: BarlineType;
private location: BarlineLocation;

constructor(opts: { config: Config; type: BarlineType; location: BarlineLocation }) {
this.config = opts.config;
this.type = opts.type;
this.location = opts.location;
}

static fromMusicXML(opts: { config: Config; musicXML: { barline: musicxml.Barline } }) {
let barlineType: BarlineType = 'none';

const barline = opts.musicXML.barline;
if (barline.isRepeat()) {
barlineType = 'repeat';
} else {
switch (barline.getBarStyle()) {
case 'regular':
case 'short':
case 'dashed':
case 'dotted':
case 'heavy':
barlineType = 'single';
break;
case 'heavy-heavy':
case 'light-light':
barlineType = 'double-same';
break;
case 'heavy-light':
case 'light-heavy':
barlineType = 'double-different';
break;
}
}

let location: BarlineLocation;
switch (barline.getLocation()) {
case 'left':
location = 'left';
break;
case 'middle':
location = 'middle';
break;
case 'right':
location = 'right';
break;
}

return new Barline({
config: opts.config,
type: barlineType,
location: location,
});
}

/** Returns the type of the barline. */
getType(): BarlineType {
return this.type;
}

/** Returns the width of the barline. */
getWidth(): number {
return this.type === 'none' ? 0 : 1;
}

/** Renders the barline. */
render(): BarlineRendering {
return {
type: 'barline',
vexflow: {
barlineType: this.getVfBarlineType(),
staveConnectorType: this.getVfStaveConnectorType(),
},
};
}

private getVfBarlineType(): vexflow.BarlineType {
switch (this.type) {
case 'single':
return vexflow.Barline.type.SINGLE;
case 'double-same':
return vexflow.Barline.type.DOUBLE;
case 'double-different':
switch (this.location) {
case 'left':
case 'middle':
return vexflow.Barline.type.DOUBLE;
case 'right':
return vexflow.Barline.type.END;
}
break;
case 'repeat':
switch (this.location) {
case 'left':
return vexflow.Barline.type.REPEAT_BEGIN;
case 'middle':
return vexflow.Barline.type.REPEAT_BOTH;
case 'right':
return vexflow.Barline.type.REPEAT_END;
}
break;
case 'none':
return vexflow.Barline.type.NONE;
}
}

private getVfStaveConnectorType(): vexflow.StaveConnectorType {
switch (this.type) {
case 'single':
switch (this.location) {
case 'left':
return 'singleLeft';
case 'middle':
return 'single';
case 'right':
return 'singleRight';
}
break;
case 'double-same':
switch (this.location) {
case 'left':
return 'thinDouble';
case 'middle':
return 'double';
case 'right':
// vexflow doesn't have a thin double right barline, so we show nothing instead.
return 'none';
}
break;
case 'double-different':
switch (this.location) {
case 'left':
return 'boldDoubleLeft';
case 'middle':
return 'double';
case 'right':
return 'boldDoubleRight';
}
break;
case 'repeat':
switch (this.location) {
case 'left':
return 'boldDoubleLeft';
case 'middle':
return 'double';
case 'right':
return 'boldDoubleRight';
}
break;
default:
return 'none';
}
}
}
4 changes: 2 additions & 2 deletions src/rendering/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ export type Config = {

export const DEFAULT_CONFIG: Config = {
DEFAULT_SYSTEM_DISTANCE: 80,
DEFAULT_STAVE_DISTANCE: 80,
DEFAULT_STAVE_DISTANCE: 140,
TITLE_TOP_PADDING: 40,
TITLE_FONT_FAMILY: 'Arial',
TITLE_FONT_SIZE: '36px',
REHEARSAL_FONT_FAMILY: 'Times New Roman',
REHEARSAL_FONT_SIZE: '16px',
PART_NAME_FONT_FAMILY: 'Arial',
PART_NAME_FONT_SIZE: '13px',
PART_DISTANCE: 60,
PART_DISTANCE: 80,
VOICE_PADDING: 80,
MEASURE_NUMBER_FONT_SIZE: '10px',
MULTI_MEASURE_REST_WIDTH: 200,
Expand Down
28 changes: 0 additions & 28 deletions src/rendering/conversions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,34 +171,6 @@ export const fromBarStyleToBarlineType = (barStyle: musicxml.BarStyle): vexflow.
}
};

/** Converts a `BarlineType` to a _beginning_ `StaveConnectorType`. Defaults to `vexflow.BarlineType.SINGLE`. */
export const fromBarlineTypeToBeginningStaveConnectorType = (
barlineType: vexflow.BarlineType
): vexflow.StaveConnectorType => {
switch (barlineType) {
case vexflow.BarlineType.SINGLE:
return 'singleLeft';
case vexflow.BarlineType.DOUBLE:
return 'boldDoubleLeft';
default:
return vexflow.BarlineType.SINGLE;
}
};

/** Converts a `BarlineType` to an _ending_ `StaveConnectorType`. Defaults to `vexflow.BarlineType.SINGLE`. */
export const fromBarlineTypeToEndingStaveConnectorType = (
barlineType: vexflow.BarlineType
): vexflow.StaveConnectorType => {
switch (barlineType) {
case vexflow.BarlineType.SINGLE:
return 'singleRight';
case vexflow.BarlineType.END:
return 'boldDoubleRight';
default:
return vexflow.BarlineType.SINGLE;
}
};

/** Converts `Notehead` to a `NoteheadSuffix`. Defaults to ''. */
export const fromNoteheadToNoteheadSuffix = (notehead: musicxml.Notehead | null): NoteheadSuffix | null => {
switch (notehead) {
Expand Down
27 changes: 16 additions & 11 deletions src/rendering/measure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Division } from './division';
import { Spanners } from './spanners';
import { PartName } from './partname';
import { MeasureEntryIterator } from './measureentryiterator';
import { Barline } from './barline';

const MEASURE_LABEL_OFFSET_X = 0;
const MEASURE_LABEL_OFFSET_Y = 24;
Expand Down Expand Up @@ -139,7 +140,7 @@ export class Measure {

/** Returns the width of the end barline. */
getEndBarlineWidth(): number {
return this.getEndBarStyle() === 'none' ? 0 : 1;
return this.getEndBarline().getWidth();
}

/** Renders the measure. */
Expand Down Expand Up @@ -216,8 +217,8 @@ export class Measure {
private getFragments(): MeasureFragment[] {
const result = new Array<MeasureFragment>();

const beginningBarStyle = this.getBeginningBarStyle();
const endBarStyle = this.getEndBarStyle();
const startBarline = this.getStartBarline();
const endBarline = this.getEndBarline();
const boundaries = this.getFragmentBoundaries();

const iterators: Record<string, MeasureEntryIterator> = {};
Expand All @@ -231,6 +232,8 @@ export class Measure {
const isFirstBoundary = index === 0;
const isLastBoundary = index === boundaries.length - 1;

const startBarlines = new Array<PartScoped<Barline>>();
const endBarlines = new Array<PartScoped<Barline>>();
const beginningBarStyles = new Array<PartScoped<musicxml.BarStyle>>();
const endBarStyles = new Array<PartScoped<musicxml.BarStyle>>();
const measureEntries = new Array<PartScoped<MeasureEntry>>();
Expand All @@ -253,10 +256,10 @@ export class Measure {
if (measureEntries.length > 0) {
for (const partId of this.partIds) {
if (isFirstBoundary) {
beginningBarStyles.push({ partId, value: beginningBarStyle });
startBarlines.push({ partId, value: startBarline });
}
if (isLastBoundary) {
endBarStyles.push({ partId, value: endBarStyle });
endBarlines.push({ partId, value: endBarline });
}
}
}
Expand All @@ -272,6 +275,8 @@ export class Measure {
index: result.length,
partIds: this.partIds,
partNames: this.partNames,
startBarlines,
endBarlines,
musicXML: {
staveLayouts: this.musicXML.staveLayouts,
beginningBarStyles,
Expand Down Expand Up @@ -340,25 +345,25 @@ export class Measure {
return util.sortBy(unique, (boundary) => boundary.toBeats());
}

private getBeginningBarStyle(): musicxml.BarStyle {
private getStartBarline(): Barline {
return (
util.first(
this.musicXML.measures
.flatMap((measure) => measure.value.getBarlines())
.filter((barline) => barline.getLocation() === 'left')
.map((barline) => barline.getBarStyle())
) ?? 'regular'
.map((barline) => Barline.fromMusicXML({ config: this.config, musicXML: { barline } }))
) ?? new Barline({ config: this.config, type: 'single', location: 'left' })
);
}

private getEndBarStyle(): musicxml.BarStyle {
private getEndBarline(): Barline {
return (
util.first(
this.musicXML.measures
.flatMap((measure) => measure.value.getBarlines())
.filter((barline) => barline.getLocation() === 'right')
.map((barline) => barline.getBarStyle())
) ?? 'regular'
.map((barline) => Barline.fromMusicXML({ config: this.config, musicXML: { barline } }))
) ?? new Barline({ config: this.config, type: 'single', location: 'right' })
);
}

Expand Down
Loading

0 comments on commit b859966

Please sign in to comment.