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
5 changes: 3 additions & 2 deletions src.csharp/AlphaTab/Platform/CSharp/GdiCanvas.cs
Original file line number Diff line number Diff line change
Expand Up @@ -421,11 +421,12 @@ public void FillText(string text, double x, double y)
_graphics.DrawString(text, _font, _brush, new PointF((float) x, (float) y), _stringFormat);
}

public double MeasureText(string text)
public TextMetrics MeasureText(string text)
{
lock (MeasurementGraphics)
{
return MeasurementGraphics.MeasureString(text, _font, new PointF(0,0), _stringFormat).Width;
var measured = MeasurementGraphics.MeasureString(text, _font, new PointF(0,0), _stringFormat);
return new TextMetrics(measured.Width, measured.Height);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src.csharp/AlphaTab/Platform/Svg/FontSizes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static void GenerateFontLookup(string family)
}

// TODO: maybe allow fallback to GDI/Skia based on availability?
FontSizeLookupTables.Set(family, new Uint8Array(new[] {8}));
FontSizeLookupTables.Set(family, new FontSizeDefinition(new Uint8Array(new[] {8}), 1.2));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import alphaTab.model.MusicFontSymbol
import alphaTab.platform.ICanvas
import alphaTab.platform.TextAlign
import alphaTab.platform.TextBaseline
import alphaTab.platform.TextMetrics
import android.content.Context
import android.graphics.*
import kotlin.contracts.ExperimentalContracts
Expand Down Expand Up @@ -283,18 +284,20 @@ internal class AndroidCanvas : ICanvas {
}


override fun measureText(text: String): Double {
override fun measureText(text: String): TextMetrics {
if (text.isEmpty()) {
return 0.0
return TextMetrics(0.0, 0.0)
}
var size = 0.0
var width = 0.0
var height = 0.0

textRun(typeFace, font.size, fun(paint) {
val bounds = Rect()
paint.getTextBounds(text, 0, text.length, bounds)
size = bounds.width().toDouble()
width = bounds.width().toDouble()
height = bounds.height().toDouble()
})
return size
return TextMetrics(width, height)
}

override fun fillMusicFontSymbol(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal class FontSizesPartials {
}

// TODO: maybe allow fallback to System Rendering / Skia based on availability?
FontSizes.FontSizeLookupTables.set(family, Uint8Array(ubyteArrayOf((8).toUByte())))
FontSizes.FontSizeLookupTables.set(family, FontSizeDefinition(Uint8Array(ubyteArrayOf((8).toUByte())), 1.2))
}
}
}
24 changes: 12 additions & 12 deletions src/AlphaTabApiBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { BeatBounds } from '@src/rendering/utils/BeatBounds';
import { Bounds } from '@src/rendering/utils/Bounds';
import { BoundsLookup } from '@src/rendering/utils/BoundsLookup';
import { MasterBarBounds } from '@src/rendering/utils/MasterBarBounds';
import { StaveGroupBounds } from '@src/rendering/utils/StaveGroupBounds';
import { StaffSystemBounds } from '@src/rendering/utils/StaffSystemBounds';
import { ResizeEventArgs } from '@src/ResizeEventArgs';
import { Settings } from '@src/Settings';

Expand Down Expand Up @@ -1026,15 +1026,15 @@ export class AlphaTabApiBase<TSettings> {

if (this.settings.player.enableAnimatedBeatCursor) {
let nextBeatX: number = barBoundings.visualBounds.x + barBoundings.visualBounds.w;
// get position of next beat on same stavegroup
// get position of next beat on same system
if (nextBeat) {
// if we are moving within the same bar or to the next bar
// transition to the next beat, otherwise transition to the end of the bar.
let nextBeatBoundings: BeatBounds | null = cache.findBeat(nextBeat);
if (
nextBeatBoundings &&
nextBeatBoundings.barBounds.masterBarBounds.staveGroupBounds ===
barBoundings.staveGroupBounds
nextBeatBoundings.barBounds.masterBarBounds.staffSystemBounds ===
barBoundings.staffSystemBounds
) {
nextBeatX = nextBeatBoundings.visualBounds.x;
}
Expand Down Expand Up @@ -1343,16 +1343,16 @@ export class AlphaTabApiBase<TSettings> {
}
// if the selection goes across multiple staves, we need a special selection highlighting
if (
startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds !==
endBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds
startBeat.bounds!.barBounds.masterBarBounds.staffSystemBounds !==
endBeat.bounds!.barBounds.masterBarBounds.staffSystemBounds
) {
// from the startbeat to the end of the staff,
// then fill all staffs until the end-beat staff
// then from staff-start to the end beat (or to end of bar if it's the last beat)
let staffStartX: number = startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds!.visualBounds.x;
let staffStartX: number = startBeat.bounds!.barBounds.masterBarBounds.staffSystemBounds!.visualBounds.x;
let staffEndX: number =
startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds!.visualBounds.x +
startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds!.visualBounds.w;
startBeat.bounds!.barBounds.masterBarBounds.staffSystemBounds!.visualBounds.x +
startBeat.bounds!.barBounds.masterBarBounds.staffSystemBounds!.visualBounds.w;
let startSelection: IContainer = this.uiFacade.createSelectionElement()!;
startSelection.setBounds(
startX,
Expand All @@ -1361,10 +1361,10 @@ export class AlphaTabApiBase<TSettings> {
startBeat.bounds!.barBounds.masterBarBounds.visualBounds.h
);
selectionWrapper.appendChild(startSelection);
let staffStartIndex: number = startBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds!.index + 1;
let staffEndIndex: number = endBeat.bounds!.barBounds.masterBarBounds.staveGroupBounds!.index;
let staffStartIndex: number = startBeat.bounds!.barBounds.masterBarBounds.staffSystemBounds!.index + 1;
let staffEndIndex: number = endBeat.bounds!.barBounds.masterBarBounds.staffSystemBounds!.index;
for (let staffIndex: number = staffStartIndex; staffIndex < staffEndIndex; staffIndex++) {
let staffBounds: StaveGroupBounds = cache.staveGroups[staffIndex];
let staffBounds: StaffSystemBounds = cache.staffSystems[staffIndex];
let middleSelection: IContainer = this.uiFacade.createSelectionElement()!;
middleSelection.setBounds(
staffStartX,
Expand Down
59 changes: 57 additions & 2 deletions src/DisplaySettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class DisplaySettings {
public barCountPerPartial: number = 10;

/**
* Whether the last system (row) should be also justified to the whole width of the music sheet.
* Whether the last system (row) should be also justified to the whole width of the music sheet.
* (applies only for page layout).
*/
public justifyLastSystem: boolean = false;
Expand All @@ -77,7 +77,62 @@ export class DisplaySettings {
/**
* Gets or sets the padding between the music notation and the border.
*/
public padding: number[] | null = null;
public padding: number[] = [35, 35];

/**
* Gets or sets the top padding applied to first system.
*/
public firstSystemPaddingTop: number = 5;

/**
* Gets or sets the top padding applied to systems.
*/
public systemPaddingTop: number = 10;

/**
* Gets or sets the bottom padding applied to systems.
*/
public systemPaddingBottom: number = 20;

/**
* Gets or sets the bottom padding applied to last system.
*/
public lastSystemPaddingBottom: number = 0;

/**
* Gets or sets the padding left to the track name label of the system.
*/
public systemLabelPaddingLeft: number = 0;

/**
* Gets or sets the padding right to the track name label of the system.
*/
public systemLabelPaddingRight: number = 5;

/**
* Gets or sets the padding between the accolade bar and the start of the bar itself.
*/
public accoladeBarPaddingRight: number = 3;

/**
* Gets or sets the top padding applied to main notation staffs.
*/
public notationStaffPaddingTop: number = 5;

/**
* Gets or sets the bottom padding applied to main notation staffs.
*/
public notationStaffPaddingBottom: number = 5;

/**
* Gets or sets the top padding applied to effect annotation staffs.
*/
public effectStaffPaddingTop: number = 0;

/**
* Gets or sets the bottom padding applied to effect annotation staffs.
*/
public effectStaffPaddingBottom: number = 0;

/**
* Gets how the systems should be layed out.
Expand Down
46 changes: 45 additions & 1 deletion src/generated/DisplaySettingsSerializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ export class DisplaySettingsSerializer {
o.set("justifylastsystem", obj.justifyLastSystem);
o.set("resources", RenderingResourcesSerializer.toJson(obj.resources));
o.set("padding", obj.padding);
o.set("firstsystempaddingtop", obj.firstSystemPaddingTop);
o.set("systempaddingtop", obj.systemPaddingTop);
o.set("systempaddingbottom", obj.systemPaddingBottom);
o.set("lastsystempaddingbottom", obj.lastSystemPaddingBottom);
o.set("systemlabelpaddingleft", obj.systemLabelPaddingLeft);
o.set("systemlabelpaddingright", obj.systemLabelPaddingRight);
o.set("accoladebarpaddingright", obj.accoladeBarPaddingRight);
o.set("notationstaffpaddingtop", obj.notationStaffPaddingTop);
o.set("notationstaffpaddingbottom", obj.notationStaffPaddingBottom);
o.set("effectstaffpaddingtop", obj.effectStaffPaddingTop);
o.set("effectstaffpaddingbottom", obj.effectStaffPaddingBottom);
o.set("systemslayoutmode", obj.systemsLayoutMode as number);
return o;
}
Expand Down Expand Up @@ -65,7 +76,40 @@ export class DisplaySettingsSerializer {
obj.justifyLastSystem = v! as boolean;
return true;
case "padding":
obj.padding = v as number[] | null;
obj.padding = v! as number[];
return true;
case "firstsystempaddingtop":
obj.firstSystemPaddingTop = v! as number;
return true;
case "systempaddingtop":
obj.systemPaddingTop = v! as number;
return true;
case "systempaddingbottom":
obj.systemPaddingBottom = v! as number;
return true;
case "lastsystempaddingbottom":
obj.lastSystemPaddingBottom = v! as number;
return true;
case "systemlabelpaddingleft":
obj.systemLabelPaddingLeft = v! as number;
return true;
case "systemlabelpaddingright":
obj.systemLabelPaddingRight = v! as number;
return true;
case "accoladebarpaddingright":
obj.accoladeBarPaddingRight = v! as number;
return true;
case "notationstaffpaddingtop":
obj.notationStaffPaddingTop = v! as number;
return true;
case "notationstaffpaddingbottom":
obj.notationStaffPaddingBottom = v! as number;
return true;
case "effectstaffpaddingtop":
obj.effectStaffPaddingTop = v! as number;
return true;
case "effectstaffpaddingbottom":
obj.effectStaffPaddingBottom = v! as number;
return true;
case "systemslayoutmode":
obj.systemsLayoutMode = JsonHelper.parseEnum<SystemsLayoutMode>(v, SystemsLayoutMode)!;
Expand Down
2 changes: 1 addition & 1 deletion src/model/Bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class Bar {

/**
* A relative scale for the size of the bar when displayed. The scale is relative
* within a single line (system/stave group). The sum of all scales in one line make the total width,
* within a single line (system). The sum of all scales in one line make the total width,
* and then this individual scale gives the relative size.
*/
public displayScale:number = 1;
Expand Down
22 changes: 21 additions & 1 deletion src/platform/ICanvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,26 @@ export enum TextBaseline {
Bottom
}

/**
* The TextMetrics class represents the dimensions of a piece of text in the canvas;
*/
export class TextMetrics {
/**
* Returns the width of a segment of inline text in CSS pixels.
*/
public width: number;

/**
* Returns the height of a segment of inline text in CSS pixels.
*/
public height: number;

public constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
}

/**
* This is the base public interface for canvas implementations on different plattforms.
*/
Expand Down Expand Up @@ -66,7 +86,7 @@ export interface ICanvas {

fillText(text: string, x: number, y: number): void;

measureText(text: string): number;
measureText(text: string): TextMetrics;

fillMusicFontSymbol(x: number, y: number, scale: number, symbol: MusicFontSymbol, centerAtPosition?: boolean): void;

Expand Down
21 changes: 15 additions & 6 deletions src/platform/javascript/AlphaTabWebWorker.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { JsonConverter } from '@src/model/JsonConverter';
import { Score } from '@src/model/Score';
import { IWorkerScope } from '@src/platform/javascript/IWorkerScope';
import { FontSizes } from '@src/platform/svg/FontSizes';
import { FontSizeDefinition, FontSizes } from '@src/platform/svg/FontSizes';
import { ScoreRenderer } from '@src/rendering/ScoreRenderer';
import { Settings } from '@src/Settings';
import { Logger } from '@src/Logger';
Expand Down Expand Up @@ -80,7 +80,8 @@ export class AlphaTabWebWorker {
break;
case 'alphaTab.renderScore':
this.updateFontSizes(data.fontSizes);
let score: any = data.score == null ? null : JsonConverter.jsObjectToScore(data.score, this._renderer.settings);
let score: any =
data.score == null ? null : JsonConverter.jsObjectToScore(data.score, this._renderer.settings);
this.renderMultiple(score, data.trackIndexes);
break;
case 'alphaTab.updateSettings':
Expand All @@ -89,13 +90,21 @@ export class AlphaTabWebWorker {
}
}

private updateFontSizes(fontSizes: any): void {
private updateFontSizes(fontSizes: { [key: string]: FontSizeDefinition } | Map<string, FontSizeDefinition>): void {
if (!(fontSizes instanceof Map)) {
const obj = fontSizes;
fontSizes = new Map<string, FontSizeDefinition>();
for (const font in obj) {
fontSizes.set(font, obj[font]);
}
}

if (fontSizes) {
if (!FontSizes.FontSizeLookupTables) {
FontSizes.FontSizeLookupTables = new Map<string, Uint8Array>();
FontSizes.FontSizeLookupTables = new Map<string, FontSizeDefinition>();
}
for (let font in fontSizes) {
FontSizes.FontSizeLookupTables.set(font, fontSizes[font]);
for (let [k, v] of fontSizes) {
FontSizes.FontSizeLookupTables.set(k, v);
}
}
}
Expand Down
Loading