Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/alphatab/src/EngravingSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ export class EngravingSettings {

this.leftHandTabTieWidth = 2.2 * this.oneStaffSpace;
this.numberedDashGlyphWidth = 1.5 * this.oneStaffSpace;
this.numberedChordNoteGap = 0.5 * this.oneStaffSpace;
this.deadSlappedLineWidth = 0.25 * this.oneStaffSpace;

this.simpleSlideWidth = 1.3 * this.oneStaffSpace;
Expand Down Expand Up @@ -827,6 +828,13 @@ export class EngravingSettings {
*/
public stemFlagHeight: Map<Duration, number> = new Map<Duration, number>();

/**
* The vertical gap between the stacked numbers of a chord in numbered notation,
* measured between the octave dots of the lower and the higher number.
* @since 1.10.0
*/
public numberedChordNoteGap = 0;

// Idea: maybe we can encode and pack this large metadata into a more compact format (e.g. BSON or a custom binary blob?)
// This metadata below is updated automatically from the bravura_metadata.json via npm script

Expand Down
1 change: 1 addition & 0 deletions packages/alphatab/src/generated/EngravingSettingsCloner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export class EngravingSettingsCloner {
clone.beatContentPadding = original.beatContentPadding;
clone.barlineContentPadding = original.barlineContentPadding;
clone.stemFlagHeight = new Map(original.stemFlagHeight);
clone.numberedChordNoteGap = original.numberedChordNoteGap;
return clone;
}
}
6 changes: 6 additions & 0 deletions packages/alphatab/src/generated/EngravingSettingsJson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -430,4 +430,10 @@ export interface EngravingSettingsJson {
* The space needed by flags on the stem-side from top to bottom to place.
*/
stemFlagHeight?: Map<Duration | keyof typeof Duration | Lowercase<keyof typeof Duration>, number>;
/**
* The vertical gap between the stacked numbers of a chord in numbered notation,
* measured between the octave dots of the lower and the higher number.
* @since 1.10.0
*/
numberedChordNoteGap?: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { IObjectWriter } from "@coderline/alphatab/io/IObjectWriter";
* @internal
*/
export class EngravingSettingsSerializer {
private static readonly _fields: RecordFields = new RecordFields(["musicfontsize", "onestaffspace", "tablinespacing", "arrowshaftthickness", "barlineseparation", "beamspacing", "beamthickness", "bracketthickness", "dashedbarlinedashlength", "dashedbarlinegaplength", "dashedbarlinethickness", "hairpinthickness", "legerlinethickness", "legerlineextension", "octavelinethickness", "pedallinethickness", "repeatbarlinedotseparation", "repeatendinglinethickness", "slurmidpointthickness", "stafflinethickness", "stemthickness", "thickbarlinethickness", "thinbarlinethickness", "thinthickbarlineseparation", "tiemidpointthickness", "tupletbracketthickness", "stemup", "stemdown", "repeatoffsetx", "standardstemlength", "stemflagoffsets", "glyphtop", "glyphbottom", "glyphwidths", "glyphheights", "numberedbarrendererbarsize", "numberedbarrendererbarspacing", "numbereddashglyphpadding", "numbereddashglyphwidth", "linerangedglyphdashgap", "linerangedglyphdashsize", "prenoteeffectpadding", "postnoteeffectpadding", "onnoteeffectpadding", "stringnumbercirclepadding", "rowcontainerpadding", "rowcontainergap", "alternateendingspadding", "sustainpedallinepadding", "tieheight", "beattimerpadding", "bendnoteheadelementpadding", "ghostparenthesiswidth", "ghostparenthesispadding", "brokenbeamwidth", "tabwhammytextpadding", "tabwhammyperhalfheight", "tabwhammydashsize", "songbookwhammydipheight", "deadslappedlinewidth", "lefthandtabtiewidth", "tabbenddashsize", "tabbendstaffpadding", "tabbendpervalueheight", "tabbendlabelpadding", "simpleslidewidth", "simpleslideheight", "chorddiagrampaddingx", "chorddiagrampaddingy", "chorddiagramstringspacing", "chorddiagramfretspacing", "chorddiagramnutheight", "chorddiagramfretheight", "chorddiagramlinewidth", "tripletfeelbracketpadding", "accidentalpadding", "prebeatglyphspacing", "temponotescale", "tuningglyphcirclenumberscale", "tuningglyphstringcolumnscale", "tuningglyphstringrowpadding", "directionsscale", "multivoicedisplacednoteheadspacing", "staffcontentpadding", "beatcontentpadding", "barlinecontentpadding", "stemflagheight"]);
private static readonly _fields: RecordFields = new RecordFields(["musicfontsize", "onestaffspace", "tablinespacing", "arrowshaftthickness", "barlineseparation", "beamspacing", "beamthickness", "bracketthickness", "dashedbarlinedashlength", "dashedbarlinegaplength", "dashedbarlinethickness", "hairpinthickness", "legerlinethickness", "legerlineextension", "octavelinethickness", "pedallinethickness", "repeatbarlinedotseparation", "repeatendinglinethickness", "slurmidpointthickness", "stafflinethickness", "stemthickness", "thickbarlinethickness", "thinbarlinethickness", "thinthickbarlineseparation", "tiemidpointthickness", "tupletbracketthickness", "stemup", "stemdown", "repeatoffsetx", "standardstemlength", "stemflagoffsets", "glyphtop", "glyphbottom", "glyphwidths", "glyphheights", "numberedbarrendererbarsize", "numberedbarrendererbarspacing", "numbereddashglyphpadding", "numbereddashglyphwidth", "linerangedglyphdashgap", "linerangedglyphdashsize", "prenoteeffectpadding", "postnoteeffectpadding", "onnoteeffectpadding", "stringnumbercirclepadding", "rowcontainerpadding", "rowcontainergap", "alternateendingspadding", "sustainpedallinepadding", "tieheight", "beattimerpadding", "bendnoteheadelementpadding", "ghostparenthesiswidth", "ghostparenthesispadding", "brokenbeamwidth", "tabwhammytextpadding", "tabwhammyperhalfheight", "tabwhammydashsize", "songbookwhammydipheight", "deadslappedlinewidth", "lefthandtabtiewidth", "tabbenddashsize", "tabbendstaffpadding", "tabbendpervalueheight", "tabbendlabelpadding", "simpleslidewidth", "simpleslideheight", "chorddiagrampaddingx", "chorddiagrampaddingy", "chorddiagramstringspacing", "chorddiagramfretspacing", "chorddiagramnutheight", "chorddiagramfretheight", "chorddiagramlinewidth", "tripletfeelbracketpadding", "accidentalpadding", "prebeatglyphspacing", "temponotescale", "tuningglyphcirclenumberscale", "tuningglyphstringcolumnscale", "tuningglyphstringrowpadding", "directionsscale", "multivoicedisplacednoteheadspacing", "staffcontentpadding", "beatcontentpadding", "barlinecontentpadding", "stemflagheight", "numberedchordnotegap"]);
public static read(obj: EngravingSettings, reader: IObjectReader): void {
reader.readRecord(EngravingSettingsSerializer._fields, (id, k, rr) => EngravingSettingsSerializer._readField(obj, id, rr, false));
}
Expand Down Expand Up @@ -287,6 +287,9 @@ export class EngravingSettingsSerializer {
case 86:
EngravingSettingsSerializer._readStemFlagHeight(obj, r, flexible);
return true;
case 87:
obj.numberedChordNoteGap = r.readNumber();
return true;
}
return false;
}
Expand Down Expand Up @@ -514,6 +517,7 @@ export class EngravingSettingsSerializer {
w.writeNumber(v);
}
w.endMap();
w.numberField(87, obj.numberedChordNoteGap);
w.endObject();
}
}
2 changes: 1 addition & 1 deletion packages/alphatab/src/generated/SerializerSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ export class SerializerSchema {
/**
* A hash of the field ids, keys and types of all serialized classes (50 classes).
*/
public static readonly fingerprint: number = 0xa8bdf264;
public static readonly fingerprint: number = 0xb9644837;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import { RecordFields } from "@coderline/alphatab/io/RecordFields";
import { ElementDisplaySerializer } from "@coderline/alphatab/generated/model/ElementDisplaySerializer";
import { BarNumberDisplay } from "@coderline/alphatab/model/RenderStylesheet";
import { JsonHelper } from "@coderline/alphatab/io/JsonHelper";
import { NumberedNoteMode } from "@coderline/alphatab/model/StaffConfigs";
import type { IObjectWriter } from "@coderline/alphatab/io/IObjectWriter";
/**
* @internal
*/
export class NumberedStaffConfigSerializer {
private static readonly _fields: RecordFields = new RecordFields(["timesignature", "barnumber"]);
private static readonly _fields: RecordFields = new RecordFields(["timesignature", "barnumber", "notes"]);
public static read(obj: NumberedStaffConfig, reader: IObjectReader): void {
reader.readRecord(NumberedStaffConfigSerializer._fields, (id, k, rr) => NumberedStaffConfigSerializer._readField(obj, id, rr, false));
}
Expand All @@ -36,6 +37,9 @@ export class NumberedStaffConfigSerializer {
case 1:
obj.barNumber = JsonHelper.parseEnum<BarNumberDisplay>(r.readValue(), BarNumberDisplay);
return true;
case 2:
obj.notes = JsonHelper.parseEnum<NumberedNoteMode>(r.readValue(), NumberedNoteMode);
return true;
}
return false;
}
Expand Down Expand Up @@ -69,6 +73,7 @@ export class NumberedStaffConfigSerializer {
ElementDisplaySerializer.write(obj.timeSignature, w);
}
w.valueField(1, obj.barNumber as number | undefined);
w.valueField(2, obj.notes as number | undefined);
w.endObject();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { TabRhythmMode } from '@coderline/alphatab/NotationSettings';
import type { NumberedNoteMode } from '@coderline/alphatab/model/StaffConfigs';
import type {
AlphaTexAccidentalMode,
AlphaTexStaffType,
Expand Down Expand Up @@ -456,6 +457,13 @@ export class AlphaTex1EnumMappings {
['automatic', 3]
]);
public static readonly tabRhythmModeReversed = AlphaTex1EnumMappings._reverse(AlphaTex1EnumMappings.tabRhythmMode);
public static readonly numberedNoteMode = new Map<string, NumberedNoteMode>([
['allnotes', 0],
['singlenote', 1]
]);
public static readonly numberedNoteModeReversed = AlphaTex1EnumMappings._reverse(
AlphaTex1EnumMappings.numberedNoteMode
);
public static readonly keySignaturesMinorReversed = new Map<KeySignature, string>([
[-7, 'abminor'],
[-6, 'ebminor'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,8 @@ export class AlphaTex1LanguageDefinitions {
['restsplacement', [[[[100, 107], 0, ['allstaves', 'primary']]]]],
['restssystems', [[[[100, 107], 0, ['allsystems', 'firstsystemonly']]]]],
['barnumber', [[[[100, 107], 0, ['allbars', 'firstofsystem', 'hide']]]]],
['rhythm', [[[[100, 107], 0, ['hidden', 'showwithbeams', 'showwithbars', 'automatic']]]]]
['rhythm', [[[[100, 107], 0, ['hidden', 'showwithbeams', 'showwithbars', 'automatic']]]]],
['notes', [[[[100, 107], 0, ['allnotes', 'singlenote']]]]]
]
],
[
Expand Down Expand Up @@ -645,7 +646,8 @@ export class AlphaTex1LanguageDefinitions {
['restsplacement', [[[[100, 107], 0, ['allstaves', 'primary']]]]],
['restssystems', [[[[100, 107], 0, ['allsystems', 'firstsystemonly']]]]],
['barnumber', [[[[100, 107], 0, ['allbars', 'firstofsystem', 'hide']]]]],
['rhythm', [[[[100, 107], 0, ['hidden', 'showwithbeams', 'showwithbars', 'automatic']]]]]
['rhythm', [[[[100, 107], 0, ['hidden', 'showwithbeams', 'showwithbars', 'automatic']]]]],
['notes', [[[[100, 107], 0, ['allnotes', 'singlenote']]]]]
]
],
['ts', null],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,12 @@ import { SimileMark } from '@coderline/alphatab/model/SimileMark';
import { SlideInType } from '@coderline/alphatab/model/SlideInType';
import { SlideOutType } from '@coderline/alphatab/model/SlideOutType';
import { Staff } from '@coderline/alphatab/model/Staff';
import type {
NumberedStaffConfig,
ScoreStaffConfig,
SlashStaffConfig,
TabStaffConfig
import {
NumberedNoteMode,
type NumberedStaffConfig,
type ScoreStaffConfig,
type SlashStaffConfig,
type TabStaffConfig
} from '@coderline/alphatab/model/StaffConfigs';
import { Track } from '@coderline/alphatab/model/Track';
import { TremoloPickingEffect, TremoloPickingStyle } from '@coderline/alphatab/model/TremoloPickingEffect';
Expand Down Expand Up @@ -1456,6 +1457,10 @@ export class AlphaTex1LanguageHandler implements IAlphaTexLanguageImportHandler
const c: NumberedStaffConfig = staff?.numberedConfig ?? stylesheet?.numberedConfig ?? {};
c.timeSignature = element('ts', c.timeSignature);
c.barNumber = barNumber(c.barNumber);
if (name === 'notes') {
c.notes = AlphaTex1EnumMappings.numberedNoteMode.get(value())!;
applied = true;
}
if (staff && applied) {
staff.numberedConfig = c;
}
Expand Down Expand Up @@ -3168,6 +3173,9 @@ export class AlphaTex1LanguageHandler implements IAlphaTexLanguageImportHandler
element(slash, 'ks', slc?.keySignature, defaults?.slashConfig?.keySignature);
element(slash, 'ts', slc?.timeSignature, defaults?.slashConfig?.timeSignature);
element(numbered, 'ts', nc?.timeSignature, defaults?.numberedConfig?.timeSignature);
if (nc?.notes !== undefined && nc!.notes !== defaults?.numberedConfig?.notes) {
Atnf.prop(numbered.properties, 'notes', Atnf.identValue(NumberedNoteMode[nc!.notes!]));
}
barNumbers.push(sc?.barNumber);
barNumbers.push(tc?.barNumber);
barNumbers.push(slc?.barNumber);
Expand Down
14 changes: 8 additions & 6 deletions packages/alphatab/src/model/RenderStylesheet.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { TabRhythmMode } from '@coderline/alphatab/NotationSettings';
import { StaffPlacement, SystemDisplay } from '@coderline/alphatab/model/ElementDisplay';
import type {
NumberedStaffConfig,
ScoreStaffConfig,
SlashStaffConfig,
TabStaffConfig
import {
NumberedNoteMode,
type NumberedStaffConfig,
type ScoreStaffConfig,
type SlashStaffConfig,
type TabStaffConfig
} from '@coderline/alphatab/model/StaffConfigs';
import type { Track } from '@coderline/alphatab/model/Track';

Expand Down Expand Up @@ -291,6 +292,7 @@ export class RenderStylesheet {
*/
public numberedConfig: NumberedStaffConfig = {
timeSignature: { isVisible: true, staffPlacement: StaffPlacement.Primary, systemDisplay: SystemDisplay.AllSystems },
barNumber: BarNumberDisplay.FirstOfSystem
barNumber: BarNumberDisplay.FirstOfSystem,
notes: NumberedNoteMode.AllNotes
};
}
22 changes: 22 additions & 0 deletions packages/alphatab/src/model/StaffConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,23 @@ export interface SlashStaffConfig {
barNumber?: BarNumberDisplay;
}

/**
* Lists the modes how the notes of a beat are written on the numbered (jianpu) staff.
* @since 1.10.0
* @public
*/
export enum NumberedNoteMode {
/**
* Every voice is written on its own row and chords are written as stacked numbers,
* the lowest note at the bottom.
*/
AllNotes = 0,
/**
* Only the first voice is written, with a single number per beat showing the highest note of a chord.
*/
SingleNote = 1
}

/**
* Per-staff-type display configuration for the numbered (jianpu) staff.
* The "1=X" key designation is rendered as an above-staff effect-band
Expand All @@ -56,4 +73,9 @@ export interface SlashStaffConfig {
export interface NumberedStaffConfig {
timeSignature?: ElementDisplay;
barNumber?: BarNumberDisplay;
/**
* How the notes of the voices and chords are written.
* @since 1.10.0
*/
notes?: NumberedNoteMode;
}
11 changes: 6 additions & 5 deletions packages/alphatab/src/model/_barrel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,12 @@ export {
SystemDisplay,
type ElementDisplay
} from '@coderline/alphatab/model/ElementDisplay';
export type {
ScoreStaffConfig,
TabStaffConfig,
SlashStaffConfig,
NumberedStaffConfig
export {
NumberedNoteMode,
type ScoreStaffConfig,
type TabStaffConfig,
type SlashStaffConfig,
type NumberedStaffConfig
} from '@coderline/alphatab/model/StaffConfigs';
export type {
ScoreBarOverride,
Expand Down
26 changes: 26 additions & 0 deletions packages/alphatab/src/rendering/BarRendererBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,24 @@ export class BarRendererBase {
this.isFinalized = true;
}

/**
* Measures the height and the overflows of the bar again after its glyphs moved vertically. Only valid
* right before {@link scaleToWidth}, which emits the skylines and registers the overflows on the staff.
*/
protected remeasureVertically(): void {
this.updateSizes();
for (const v of this.helpers.beamHelpers) {
for (const h of v) {
h.invalidateDrawingInfos();
}
}
this._contentTopOverflow = 0;
this._contentBottomOverflow = 0;
this._hasPositionedOverflow = false;
this.calculateOverflows(0, this.height);
this._emitPreBeatOverflows(this.height);
}

protected emitHelperSkyline(_h: BeamingHelper): void {}

public emitBeatSkyline(_beatContainer: BeatContainerGlyphBase): void {}
Expand All @@ -519,6 +537,13 @@ export class BarRendererBase {

protected wasFirstOfStaff: boolean = false;

/**
* The geometry of the header glyphs of the bar; null before the first layout.
*/
protected get headerProfile(): HeaderProfile | null {
return this._headerProfile;
}

public get isFirstOfStaff(): boolean {
return this.index === 0;
}
Expand Down Expand Up @@ -789,6 +814,7 @@ export class BarRendererBase {
private _registerStaffOverflow() {
this.staff!.registerOverflowTop(this.topOverflow);
this.staff!.registerOverflowBottom(this.bottomOverflow);
this.staff!.registerStaffBottom(this.height);
}

/** Public wrapper for `_registerStaffOverflow`. */
Expand Down
25 changes: 24 additions & 1 deletion packages/alphatab/src/rendering/LineBarRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,29 @@ export abstract class LineBarRenderer extends BarRendererBase {
public abstract get heightLineCount(): number;
public abstract get drawnLineCount(): number;

/**
* The lines one staff row spans. Staff-sized glyphs (header bar lines, repeat dots, dead-slapped crosses) are
* laid out in the first row, so they do not depend on the height of renderers with several rows.
*/
public get staffRowLineCount(): number {
return this.heightLineCount;
}

/**
* The number of staff rows stacked in the bar. Bar-level glyphs of a row (time signatures, repeat dots) are
* written in front of every row.
*/
public get staffRowCount(): number {
return 1;
}

/**
* The vertical offset of the staff row with the given index from the first row.
*/
public getStaffRowOffset(_index: number): number {
return 0;
}

protected get topGlyphOverflow() {
return 0;
}
Expand All @@ -86,7 +109,7 @@ export abstract class LineBarRenderer extends BarRendererBase {
}

protected updateFirstLineY() {
const fullLineHeight = this.lineOffset * (this.heightLineCount - 1);
const fullLineHeight = this.lineOffset * (this.staffRowLineCount - 1);
const actualLineHeight = this.drawnLineCount === 0 ? 0 : (this.drawnLineCount - 1) * this.lineOffset;
const lineYOffset = this.smuflMetrics.staffLineThickness / 2;

Expand Down
Loading
Loading