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
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export class RenderStylesheetSerializer {
a.push(v);
}
}
o.set("extendbarlines", obj.extendBarLines);
return o;
}
public static setProperty(obj: RenderStylesheet, property: string, v: unknown): boolean {
Expand Down Expand Up @@ -112,6 +113,9 @@ export class RenderStylesheetSerializer {
case "pertrackmultibarrest":
obj.perTrackMultiBarRest = new Set<number>(v as number[]);
return true;
case "extendbarlines":
obj.extendBarLines = v! as boolean;
return true;
}
return false;
}
Expand Down
6 changes: 6 additions & 0 deletions packages/alphatab/src/importer/BinaryStylesheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ export class BinaryStylesheet {
score.stylesheet.otherSystemsTrackNameOrientation = TrackNameOrientation.Vertical;
}
break;
case 'System/ExtendedBarLines':
score.stylesheet.extendBarLines = value as boolean;
break;

case 'Header/Title':
ModelUtils.getOrCreateHeaderFooterStyle(score, ScoreSubElement.Title).template = value as string;
break;
Expand Down Expand Up @@ -517,6 +521,8 @@ export class BinaryStylesheet {
break;
}

binaryStylesheet.addValue('System/ExtendedBarLines', score.stylesheet.extendBarLines, DataType.Boolean);

const scoreStyle = score.style;
if (scoreStyle) {
for (const [k, v] of scoreStyle.headerAndFooter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ export class AlphaTex1LanguageDefinitions {
['firstsystemtracknamemode', [[[[10, 17], 0, ['fullname', 'shortname']]]]],
['othersystemstracknamemode', [[[[10, 17], 0, ['fullname', 'shortname']]]]],
['firstsystemtracknameorientation', [[[[10, 17], 0, ['horizontal', 'vertical']]]]],
['othersystemstracknameorientation', [[[[10, 17], 0, ['horizontal', 'vertical']]]]]
['othersystemstracknameorientation', [[[[10, 17], 0, ['horizontal', 'vertical']]]]],
['extendbarlines', null]
]);
public static readonly staffMetaDataSignatures = AlphaTex1LanguageDefinitions._signatures([
['tuning', [[[[10, 17], 0, ['piano', 'none', 'voice']]], [[[10, 17], 5]]]],
Expand Down Expand Up @@ -525,6 +526,7 @@ export class AlphaTex1LanguageDefinitions {
['othersystemstracknamemode', null],
['firstsystemtracknameorientation', null],
['othersystemstracknameorientation', null],
['extendbarlines', null],
[
'tuning',
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ export class AlphaTex1LanguageHandler implements IAlphaTexLanguageImportHandler
case 'showdynamics':
score.stylesheet.hideDynamics = false;
return ApplyNodeResult.Applied;
case 'extendbarlines':
score.stylesheet.extendBarLines = true;
return ApplyNodeResult.Applied;
case 'bracketextendmode':
const bracketExtendMode = AlphaTex1LanguageHandler._parseEnumValue(
importer,
Expand Down Expand Up @@ -2465,6 +2468,10 @@ export class AlphaTex1LanguageHandler implements IAlphaTexLanguageImportHandler
);
}

if (stylesheet.extendBarLines) {
nodes.push(Atnf.meta('extendBarLines'));
}

// Unsupported:
// 'globaldisplaychorddiagramsontop',
// 'pertrackchorddiagramsontop',
Expand Down
5 changes: 5 additions & 0 deletions packages/alphatab/src/model/RenderStylesheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,9 @@ export class RenderStylesheet {
* If single track: Whether to render multiple subsequent empty (or rest-only) bars together as multi-bar rest.
*/
public perTrackMultiBarRest: Set<number> | null = null;

/**
* Whether barlines should be drawn across staves within the same system.
*/
public extendBarLines: boolean = false;
}
6 changes: 3 additions & 3 deletions packages/alphatab/src/rendering/LineBarRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export abstract class LineBarRenderer extends BarRendererBase {

// during system fitting it can happen that we have fraction widths
// but to have lines until the full end-pixel we round up.
// this way we avoid holes
// this way we avoid holes,
const lineWidth = this.width;

// we want the lines to be exactly virtually aligned with the respective Y-position
Expand Down Expand Up @@ -612,7 +612,7 @@ export abstract class LineBarRenderer extends BarRendererBase {

protected override createPreBeatGlyphs(): void {
super.createPreBeatGlyphs();
this.addPreBeatGlyph(new BarLineGlyph(false));
this.addPreBeatGlyph(new BarLineGlyph(false, this.bar.staff.track.score.stylesheet.extendBarLines));
this.createLinePreBeatGlyphs();
this.addPreBeatGlyph(new BarNumberGlyph(0, this.getLineHeight(-0.5), this.bar.index + 1));
}
Expand All @@ -623,7 +623,7 @@ export abstract class LineBarRenderer extends BarRendererBase {
super.createPostBeatGlyphs();
const lastBar = this.lastBar;

this.addPostBeatGlyph(new BarLineGlyph(true));
this.addPostBeatGlyph(new BarLineGlyph(true, this.bar.staff.track.score.stylesheet.extendBarLines));

if (lastBar.masterBar.isRepeatEnd && lastBar.masterBar.repeatCount > 2) {
this.addPostBeatGlyph(new RepeatCountGlyph(0, this.getLineHeight(-0.5), this.bar.masterBar.repeatCount));
Expand Down
2 changes: 1 addition & 1 deletion packages/alphatab/src/rendering/NumberedBarRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ export class NumberedBarRenderer extends LineBarRenderer {
protected override createPreBeatGlyphs(): void {
this.wasFirstOfLine = this.isFirstOfLine;
if (this.index === 0 || (this.bar.masterBar.isRepeatStart && this._isOnlyNumbered)) {
this.addPreBeatGlyph(new BarLineGlyph(false));
this.addPreBeatGlyph(new BarLineGlyph(false, this.bar.staff.track.score.stylesheet.extendBarLines));
}
this.createLinePreBeatGlyphs();
this.addPreBeatGlyph(new BarNumberGlyph(0, this.getLineHeight(-0.5), this.bar.index + 1));
Expand Down
92 changes: 74 additions & 18 deletions packages/alphatab/src/rendering/glyphs/BarLineGlyph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ abstract class BarLineGlyphBase extends Glyph {
public override doLayout(): void {
this.width = this.renderer.smuflMetrics.thinBarlineThickness;
}

public override paint(cx: number, cy: number, canvas: ICanvas): void {
this.paintExtended(cx, cy, canvas, this.height);
}

public abstract paintExtended(cx: number, cy: number, canvas: ICanvas, newHeight: number): void;
}

/**
Expand All @@ -31,23 +37,23 @@ class BarLineLightGlyph extends BarLineGlyphBase {
: this.renderer.smuflMetrics.thinBarlineThickness;
}

public override paint(cx: number, cy: number, canvas: ICanvas): void {
canvas.fillRect(cx + this.x, cy + this.y, this.renderer.smuflMetrics.thinBarlineThickness, this.height);
public override paintExtended(cx: number, cy: number, canvas: ICanvas, newHeight: number): void {
canvas.fillRect(cx + this.x, cy + this.y, this.renderer.smuflMetrics.thinBarlineThickness, newHeight);
}
}

/**
* @internal
*/
class BarLineDottedGlyph extends BarLineGlyphBase {
public override paint(cx: number, cy: number, canvas: ICanvas): void {
public override paintExtended(cx: number, cy: number, canvas: ICanvas, newHeight: number): void {
const circleRadius: number = this.renderer.smuflMetrics.thinBarlineThickness / 2;

const lineHeight = (this.renderer as LineBarRenderer).getLineHeight(1);

let circleY = cy + this.y + lineHeight * 0.5 + circleRadius;

const bottom = cy + this.y + this.height;
const bottom = cy + this.y + newHeight;
while (circleY < bottom) {
canvas.fillCircle(cx + this.x, circleY, circleRadius);
circleY += lineHeight;
Expand All @@ -59,11 +65,11 @@ class BarLineDottedGlyph extends BarLineGlyphBase {
* @internal
*/
class BarLineDashedGlyph extends BarLineGlyphBase {
public override paint(cx: number, cy: number, canvas: ICanvas): void {
public override paintExtended(cx: number, cy: number, canvas: ICanvas, newHeight: number): void {
const dashSize: number = this.renderer.smuflMetrics.dashedBarlineDashLength;
const x = cx + this.x - this.width / 2;
const dashes: number = Math.ceil(this.height / 2 / dashSize);
const bottom = cy + this.y + this.height;
const dashes: number = Math.ceil(newHeight / 2 / dashSize);
const bottom = cy + this.y + newHeight;
const dashGapLength = this.renderer.smuflMetrics.dashedBarlineGapLength;

const lw = canvas.lineWidth;
Expand Down Expand Up @@ -94,8 +100,8 @@ class BarLineHeavyGlyph extends BarLineGlyphBase {
this.width = this.renderer.smuflMetrics.thickBarlineThickness;
}

public override paint(cx: number, cy: number, canvas: ICanvas): void {
canvas.fillRect(cx + this.x, cy + this.y, this.width, this.height);
public override paintExtended(cx: number, cy: number, canvas: ICanvas, newHeight: number): void {
canvas.fillRect(cx + this.x, cy + this.y, this.width, newHeight);
}
}

Expand All @@ -107,7 +113,7 @@ class BarLineRepeatDotsGlyph extends BarLineGlyphBase {
this.width = this.renderer.smuflMetrics.glyphWidths.get(MusicFontSymbol.RepeatDot)!;
}

public override paint(cx: number, cy: number, canvas: ICanvas): void {
public override paintExtended(cx: number, cy: number, canvas: ICanvas, _newHeight: number): void {
const renderer = this.renderer as LineBarRenderer;

const lineOffset = renderer.heightLineCount % 2 === 0 ? 1 : 0.5;
Expand All @@ -122,16 +128,28 @@ class BarLineRepeatDotsGlyph extends BarLineGlyphBase {

const dotOffset = dotTop - dotHeight / 2;

CanvasHelper.fillMusicFontSymbolSafe(canvas,cx + this.x, exactCenter + dotOffset - lineHeight, 1, MusicFontSymbol.RepeatDot);
CanvasHelper.fillMusicFontSymbolSafe(canvas,cx + this.x, exactCenter + dotOffset + lineHeight, 1, MusicFontSymbol.RepeatDot);
CanvasHelper.fillMusicFontSymbolSafe(
canvas,
cx + this.x,
exactCenter + dotOffset - lineHeight,
1,
MusicFontSymbol.RepeatDot
);
CanvasHelper.fillMusicFontSymbolSafe(
canvas,
cx + this.x,
exactCenter + dotOffset + lineHeight,
1,
MusicFontSymbol.RepeatDot
);
}
}

/**
* @internal
*/
class BarLineShortGlyph extends BarLineGlyphBase {
public override paint(cx: number, cy: number, canvas: ICanvas): void {
public override paintExtended(cx: number, cy: number, canvas: ICanvas, _newHeight: number): void {
const renderer = this.renderer as LineBarRenderer;
const lines = renderer.drawnLineCount;
const gaps = lines - 1;
Expand All @@ -152,7 +170,7 @@ class BarLineShortGlyph extends BarLineGlyphBase {
* @internal
*/
class BarLineTickGlyph extends BarLineGlyphBase {
public override paint(cx: number, cy: number, canvas: ICanvas): void {
public override paintExtended(cx: number, cy: number, canvas: ICanvas, _newHeight: number): void {
const renderer = this.renderer as LineBarRenderer;

const lineHeight = renderer.getLineHeight(1);
Expand All @@ -167,10 +185,12 @@ class BarLineTickGlyph extends BarLineGlyphBase {
*/
export class BarLineGlyph extends LeftToRightLayoutingGlyphGroup {
private _isRight: boolean;
private _extendToNextStaff: boolean;

public constructor(isRight: boolean) {
public constructor(isRight: boolean, extendToNextStaff: boolean) {
super();
this._isRight = isRight;
this._extendToNextStaff = extendToNextStaff;
}

public override doLayout(): void {
Expand Down Expand Up @@ -281,20 +301,56 @@ export class BarLineGlyph extends LeftToRightLayoutingGlyphGroup {

const lineRenderer = this.renderer as LineBarRenderer;

const lineYOffset = lineRenderer.smuflMetrics.staffLineThickness ;
const lineYOffset = lineRenderer.smuflMetrics.staffLineThickness;
const top: number = this.y - lineYOffset;
const bottom: number = this.y + this.renderer.height;
const h: number = (bottom - top);
const h: number = bottom - top;

// round up to have pixel-aligned bar lines, x-shift will be used during rendering
// to avoid shifting again all glyphs
let xShift = 0;
if (this._extendToNextStaff && this._isRight) {
const fullWidth = Math.ceil(this.width);
xShift = fullWidth - this.width;
this.width = fullWidth;
}

for (const g of this.glyphs!) {
g.y = top;
g.x += xShift;
g.height = h;
}
}

public override paint(cx: number, cy: number, canvas: ICanvas): void {
const lines = this.glyphs;
if (!lines) {
return;
}

const renderer = this.renderer as LineBarRenderer;
using _ = ElementStyleHelper.bar(canvas, renderer.barLineBarSubElement, this.renderer.bar, true);
super.paint(cx, cy, canvas);

// extending across systems needs some more dynamic lookup, we do that during drawing
// as during layout things are still moving
let actualLineHeight = this.height;
const thisStaff = renderer.staff;
const allStaves = renderer.staff.system.allStaves;
let isExtended = false;
if (this._extendToNextStaff && thisStaff.index < allStaves.length - 1) {
const nextStaff = allStaves[thisStaff.index + 1];
const lineTop = thisStaff.y + renderer.y;
const lineBottom = nextStaff.y + nextStaff.topOverflow + renderer.smuflMetrics.staffLineThickness;
actualLineHeight = lineBottom - lineTop;
isExtended = true;
}

for (const line of lines) {
if (isExtended) {
(line as BarLineGlyphBase).paintExtended(cx, cy, canvas, actualLineHeight);
} else {
(line as BarLineGlyphBase).paint(cx, cy, canvas);
}
}
}
}
Loading
Loading