Browse Source

Added more files and fixed imports as far as possible

Matthias 9 năm trước cách đây
mục cha
commit
7b9f111a99

+ 3 - 1
src/Common/DataObjects/RectangleF_2D.ts

@@ -1,4 +1,6 @@
-export class RectangleF_2D {
+import {SizeF_2D} from "./SizeF_2D";
+import {PointF_2D} from "./PointF_2D";
+export class RectangleF_2D {
     public X: number;
     public Y: number;
     public Width: number;

+ 1 - 1
src/Common/DataObjects/SizeF_2D.ts

@@ -1,7 +1,7 @@
 export class SizeF_2D {
     public Width: number;
     public Height: number;
-    constructor(width: number, height: number) {
+    constructor(width: number = 0, height: number = 0) {
         this.Width = width;
         this.Height = height;
     }

+ 14 - 0
src/MusicalScore/Graphical/AbstractGraphicalInstruction.ts

@@ -0,0 +1,14 @@
+import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
+import {GraphicalObject} from "./GraphicalObject";
+export class AbstractGraphicalInstruction extends GraphicalObject {
+    protected parent: GraphicalStaffEntry;
+    constructor(parent: GraphicalStaffEntry) {
+        this.parent = parent;
+    }
+    public get Parent(): GraphicalStaffEntry {
+        return this.parent;
+    }
+    public set Parent(value: GraphicalStaffEntry) {
+        this.parent = value;
+    }
+}

+ 2 - 2
src/MusicalScore/Graphical/BoundingBox.ts

@@ -363,7 +363,7 @@ export class BoundingBox {
         public computeNonOverlappingPosition(placementPsi: BoundingBox, direction: ColDirEnum, position: PointF_2D): void {
             this.RelativePosition = new PointF_2D(position.X, position.Y);
             this.setAbsolutePositionFromParent();
-            var currentPosition: number = 0.0f;
+            var currentPosition: number = 0.0;
             var hasBeenMoved: boolean = false;
             do {
                 switch (direction) {
@@ -398,7 +398,7 @@ export class BoundingBox {
             return null;
         }
         public getObjectsInRegion<T>(region: BoundingBox): IEnumerable<T> {
-            return getObjectsInRegion<T>(region, true);
+            return this.getObjectsInRegion<T>(region, true);
         }
         public getObjectsInRegion<T>(region: BoundingBox, liesInside: boolean): IEnumerable<T> {
             if (this.dataObject instanceof T) {

+ 5 - 3
src/MusicalScore/Graphical/EngravingRules.ts

@@ -1,4 +1,6 @@
-import PagePlacementEnum = PhonicScore.MusicalScore.Graphical.SheetData.PagePlacementEnum;
+import {PagePlacementEnum} from "./GraphicalMusicPage";
+import {MusicSymbol} from "./MusicSymbol";
+import {FontInfo} from "./FontInfo";
 export class EngravingRules {
     private static rules: EngravingRules;
     private static unit: number = 1.0;
@@ -132,8 +134,8 @@ export class EngravingRules {
     private subMeasureXSpacingThreshold: number;
     private measureDynamicsMaxScalingFactor: number;
     private maxInstructionsConstValue: number;
-    private noteDistances: number[] = 1.0,1.0,1.3,1.6,2.0,2.5,3.0,4.0;
-    private noteDistancesScalingFactors: number[] = 1.0,2.0,4.0,8.0,16.0,32.0,64.0,128.0;
+    private noteDistances: number[] = [1.0,1.0,1.3,1.6,2.0,2.5,3.0,4.0];
+    private noteDistancesScalingFactors: number[] = [1.0,2.0,4.0,8.0,16.0,32.0,64.0,128.0];
     private durationDistanceDict: Dictionary<number, number> = new Dictionary<number, number>();
     private durationScalingDistanceDict: Dictionary<number, number> = new Dictionary<number, number>();
     constructor() {

+ 347 - 0
src/MusicalScore/Graphical/FontInfo.ts

@@ -0,0 +1,347 @@
+import {MusicSymbol} from "./MusicSymbol";
+import {SizeF_2D} from "../../Common/DataObjects/SizeF_2D";
+import {PointF_2D} from "../../Common/DataObjects/PointF_2D";
+import {BoundingBox} from "./BoundingBox";
+export class FontInfo {
+    protected static info: FontInfo = new FontInfo();
+    protected symbolMapping: Dictionary<MusicSymbol, SymbolInfo> = new Dictionary<MusicSymbol, SymbolInfo>();
+    constructor() {
+        this.createSymbols();
+    }
+    public static get Info(): FontInfo {
+        return FontInfo.info;
+    }
+    public updateSymbol(symbol: MusicSymbol, newSymbolInfo: SymbolInfo): void {
+        this.symbolMapping[symbol] = newSymbolInfo;
+    }
+    public getSymbolInfo(symbol: MusicSymbol): SymbolInfo {
+        try {
+            return this.symbolMapping[symbol];
+        }
+        catch (ex) {
+            Logger.DefaultLogger.LogError(LogLevel.DEBUG, "FontInfo.getSymbolInfo", ex);
+            return new SymbolInfo();
+        }
+
+    }
+    public getBoundingBox(symbol: MusicSymbol): SizeF_2D {
+        try {
+            return this.symbolMapping[symbol].boundingBox;
+        }
+        catch (ex) {
+            Logger.DefaultLogger.LogError(LogLevel.DEBUG, "FontInfo.getBoundingBox", ex);
+            return new SizeF_2D();
+        }
+
+    }
+    public addBoundingBox(symbol: MusicSymbol, boundingBox: SizeF_2D): void {
+        var si: SymbolInfo = this.symbolMapping[symbol];
+        si.boundingBox = boundingBox;
+        this.symbolMapping.Remove(symbol);
+        this.symbolMapping.Add(symbol, si);
+    }
+    public getCenterDistance(symbol: SymbolInfo): SizeF_2D {
+        var symbolBox: SizeF_2D = symbol.boundingBox;
+        var symbolCenter: PointF_2D = symbol.center;
+        var centerDistance: SizeF_2D = new SizeF_2D(symbolBox.Width * symbolCenter.X, symbolBox.Height * symbolCenter.Y);
+        return centerDistance;
+    }
+    public fillPSI(psi: BoundingBox, symbol: MusicSymbol): void {
+        this.fillPSI(psi, symbol, 1.0f);
+    }
+    public fillPSI(psi: BoundingBox, symbol: MusicSymbol, scaleFactor: number): void {
+        var symbolInfo: SymbolInfo = this.symbolMapping[symbol];
+        var symbolBox: SizeF_2D = symbolInfo.boundingBox;
+        var symbolCenter: PointF_2D = symbolInfo.center;
+        var centerDistance: SizeF_2D = new SizeF_2D(symbolBox.Width * symbolCenter.X, symbolBox.Height * symbolCenter.Y);
+        var symbolMargins: SymbolMargins = symbolInfo.margins;
+        psi.BorderLeft = -centerDistance.Width * scaleFactor;
+        psi.BorderRight = (symbolBox.Width - centerDistance.Width) * scaleFactor;
+        psi.BorderTop = -centerDistance.Height * scaleFactor;
+        psi.BorderBottom = (symbolBox.Height - centerDistance.Height) * scaleFactor;
+        psi.BorderMarginLeft = (-centerDistance.Width - symbolBox.Width * symbolMargins.left) * scaleFactor;
+        psi.BorderMarginRight = (symbolBox.Width - centerDistance.Width + symbolBox.Width * symbolMargins.right) * scaleFactor;
+        psi.BorderMarginTop = (-centerDistance.Height - symbolBox.Height * symbolMargins.top) * scaleFactor;
+        psi.BorderMarginBottom = (symbolBox.Height - centerDistance.Height + symbolBox.Height * symbolMargins.bottom) * scaleFactor;
+    }
+    protected getString(symbol: MusicSymbol): string {
+        try {
+            return this.symbolMapping[symbol].symbol;
+        }
+        catch (ex) {
+            Logger.DefaultLogger.LogError(LogLevel.DEBUG, "FontInfo.getString", ex);
+            return null;
+        }
+
+    }
+    protected getScaleFactor(symbol: MusicSymbol): number {
+        try {
+            return this.symbolMapping[symbol].scaleFactor;
+        }
+        catch (ex) {
+            Logger.DefaultLogger.LogError(LogLevel.DEBUG, "FontInfo.getScaleFactor", ex);
+            return -1F;
+        }
+
+    }
+    private createSymbols(): void {
+        var scaleVector: number[] = 1,1, 3, 3, 3,
+            3, 3, 3, 3,
+            3, 1, 1, 7f,
+                3.5f, 4, 1, 1,
+                    2.0f, 3.4f,
+                        0.6f, 0.6f, 3, 2,
+                            3, 4, 5,
+                            2.2f, 2.55f, 2.5f, 2.2f, 1,
+                                2, 2, 2, 2,
+                                2, 2, 2, 2,
+                                2, 2, 0.4f,
+                                    1, 1,
+                                    1, 0.2f, 1, 1.5f, 1.5f,
+                                        0.75f * 2,
+                                            0.75f * 3,
+                                                0.75f * (1 + 1865.0f / 2680.0f),
+        0.75f * (1 + 1865.0f / 2680.0f),
+        0.75f * (1 + 1865.0f / 2680.0f),
+        0.75f * (1 + 1865.0f / 2680.0f),
+        2.7f, 3.0f,
+            2, 7.987f, 7.987f, 7.987f, 7.987f,
+                4.228f, 4.228f, 4.228f, 4.228f,
+                    1.25f, 0.75f, 1.05f, 0.85f, 1.05f,
+                        1.1f, 2, 1.9f,
+                            1.2f, 1.2f, 1.35f, 1.2f, 1.2f,
+                                1, 1.7f, 1.8f,
+                                    1.09f, 0.77f,
+                                        3.0f;
+        var centerVector: PointF_2D[] = new PointF_2D(0.5f, 0.5f),
+        new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.0f, 1.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 1.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 1.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 1.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(500.0f / 940.0f, 1660.0f / 2675.0f),
+            new PointF_2D(500.0f / 1830.0f, 760.0f / 2680.0f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(400.0f / 925.0f, 1210.0f / 2680.0f),
+            new PointF_2D(400.0f / 1500.0f, 360.0f / 2680.0f),
+            new PointF_2D(480.0f / 1190.0f, 260.0f / 2680.0f),
+            new PointF_2D(510.0f / 1040.0f, 190.0f / 2680.0f),
+            new PointF_2D(535.0f / 960.0f, 160.0f / 2680.0f),
+            new PointF_2D(400.0f / 990.0f, 1960.0f / 2680.0f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(785.0f / 1570.0f, 1960.0f / 2680.0f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.0f, 0.0f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(2880.0f / 5760.0f, 2250.0f / 2680.0f),
+            new PointF_2D(2850.0f / 5700.0f, 1810.0f / 2680.0f),
+            new PointF_2D(450.0f / 900.0f, 1560.0f / 2680.0f),
+            new PointF_2D(5250.0f / 10500.0f, 1340.0f / 2680.0f),
+            new PointF_2D(1787.0f / 3574.0f, 1340.0f / 2680.0f),
+            new PointF_2D(872.0f / 1744.0f, 1340.0f / 2680.0f),
+            new PointF_2D(872.0f / 1744.0f, 1340.0f / 2680.0f),
+            new PointF_2D(1500.0f / 3000.0f, 1865.0f / 2680.0f),
+            new PointF_2D(1100.0f / 2200.0f, 1865.0f / 2680.0f),
+            new PointF_2D(1000.0f / 2000.0f, 2680.0f / 2680.0f),
+            new PointF_2D(1250.0f / 2500.0f, 2680.0f / 2680.0f),
+            new PointF_2D(2330.0f / 4660.0f, 2680.0f / 2680.0f),
+            new PointF_2D(1430.0f / 2860.0f, 2680.0f / 2680.0f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.63f, 0.5448f),
+            new PointF_2D(0.63f, 0.667f),
+            new PointF_2D(0.63f, 0.5448f),
+            new PointF_2D(0.63f, 0.667f),
+            new PointF_2D(0.2f, 0.224f),
+            new PointF_2D(0.2f, 0.4067f),
+            new PointF_2D(0.2f, 0.224f),
+            new PointF_2D(0.2f, 0.4067f),
+            new PointF_2D(0.5f, 0.653f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.52f, 0.925f),
+            new PointF_2D(0.5f, 1f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.634f),
+            new PointF_2D(0.5f, 0.5f),
+            new PointF_2D(0.5f, 0.5f);
+        var marginVector: SymbolMargins[] = new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+        new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.05f, 0.05f, 0.05f, 0.05f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.05f, 0.05f),
+            new SymbolMargins(0.1f, 0.1f, 0.05f, 0.05f),
+            new SymbolMargins(0.1f, 0.1f, 0.05f, 0.05f),
+            new SymbolMargins(0.05f, 0.05f, 0.05f, 0.05f),
+            new SymbolMargins(0.1f, 0.1f),
+            new SymbolMargins(0.2f, 0.2f),
+            new SymbolMargins(0.2f, 0.2f),
+            new SymbolMargins(0.2f, 0.2f),
+            new SymbolMargins(0.2f, 0.2f),
+            new SymbolMargins(0.2f, 0.2f),
+            new SymbolMargins(0.2f, 0.2f),
+            new SymbolMargins(0.2f, 0.2f),
+            new SymbolMargins(0.2f, 0.2f),
+            new SymbolMargins(0.2f, 0.2f),
+            new SymbolMargins(0.2f, 0.2f),
+            new SymbolMargins(0.7f, 0.7f, 0.7f, 0.7f),
+            new SymbolMargins(0.2f, 0.2f, 0.3f, 0.3f),
+            new SymbolMargins(0.2f, 0.2f, 0.3f, 0.3f),
+            new SymbolMargins(0.1f, 0.1f, 0.2f, 0.2f),
+            new SymbolMargins(0.1f, 0.1f, 1.0f, 1.0f),
+            new SymbolMargins(0.1f, 0.1f, 0.2f, 0.2f),
+            new SymbolMargins(0.3f, 0.3f, 0.2f, 0.2f),
+            new SymbolMargins(0.3f, 0.3f, 0.2f, 0.2f),
+            new SymbolMargins(0.0f, 0.0f, 0.2f, 0.2f),
+            new SymbolMargins(0.0f, 0.0f, 0.2f, 0.2f),
+            new SymbolMargins(0.0f, 0.0f, 0.2f, 0.2f),
+            new SymbolMargins(0.0f, 0.0f, 0.2f, 0.2f),
+            new SymbolMargins(0.0f, 0.0f, 0.2f, 0.2f),
+            new SymbolMargins(0.0f, 0.0f, 0.2f, 0.2f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.05f, 0.05f, 0.05f, 0.05f),
+            new SymbolMargins(0.05f, 0.05f, 0.05f, 0.05f),
+            new SymbolMargins(0.05f, 0.05f, 0.05f, 0.05f),
+            new SymbolMargins(0.05f, 0.05f, 0.05f, 0.05f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f),
+            new SymbolMargins(0.1f, 0.1f, 0.1f, 0.1f);
+        var values: Array = Enum.GetValues(/*typeof*/MusicSymbol);
+        var i: number = 0;
+        for (var c: string = <string>0x21; c <<string>0x21 + values.Length; c++) {
+            var si: SymbolInfo = new SymbolInfo(c.ToString(), i, scaleVector[i], centerVector[i], marginVector[i]);
+            this.symbolMapping.Add(<MusicSymbol>values.GetValue(i), si);
+            i++;
+        }
+    }
+}
+export class SymbolInfo {
+    public symbol: string;
+    public id: number;
+    public scaleFactor: number;
+    public boundingBox: SizeF_2D;
+    public center: PointF_2D;
+    public margins: SymbolMargins;
+    constructor(symbol: string, id: number, scaleFactor: number, center: PointF_2D, margins: SymbolMargins) {
+        this();
+        this.symbol = symbol;
+        this.id = id;
+        this.scaleFactor = scaleFactor;
+        this.center = center;
+        this.margins = margins;
+    }
+    public get ScaleFactor(): number {
+        return this.scaleFactor;
+    }
+    public set ScaleFactor(value: number) {
+        this.scaleFactor = value;
+    }
+    public get BoundingBox(): SizeF_2D {
+        return this.boundingBox;
+    }
+    public set BoundingBox(value: SizeF_2D) {
+        this.boundingBox = value;
+    }
+    public get Center(): PointF_2D {
+        return this.center;
+    }
+    public set Center(value: PointF_2D) {
+        this.center = value;
+    }
+    public get Margins(): SymbolMargins {
+        return this.margins;
+    }
+    public set Margins(value: SymbolMargins) {
+        this.margins = value;
+    }
+}
+
+export class SymbolMargins {
+    public left: number;
+    public right: number;
+    public top: number;
+    public bottom: number;
+    constructor(left: number, right: number, top: number = 0, bottom: number = 0) {
+        this.left = left;
+        this.right = right;
+        this.top = top;
+        this.bottom = bottom;
+    }
+}

+ 28 - 0
src/MusicalScore/Graphical/GraphicalChordSymbolContainer.ts

@@ -0,0 +1,28 @@
+import {TextAlignment} from "../../Common/Enums/TextAlignment";
+import {Label} from "../Label";
+import {GraphicalLabel} from "./GraphicalLabel";
+import {ChordSymbolContainer} from "../VoiceData/ChordSymbolContainer";
+import {BoundingBox} from "./BoundingBox";
+import {GraphicalObject} from "./GraphicalObject";
+import {PointF_2D} from "../../Common/DataObjects/PointF_2D";
+export class GraphicalChordSymbolContainer extends GraphicalObject {
+    private chordSymbolContainer: ChordSymbolContainer;
+    private graphicalLabel: GraphicalLabel;
+    constructor(chordSymbolContainer: ChordSymbolContainer, parent: BoundingBox, textHeight: number, transposeHalftones: number) {
+        this.chordSymbolContainer = chordSymbolContainer;
+        this.boundingBox = new BoundingBox(parent, this);
+        this.calculateLabel(textHeight, transposeHalftones);
+    }
+    public get GetChordSymbolContainer(): ChordSymbolContainer {
+        return this.chordSymbolContainer;
+    }
+    public get GetGraphicalLabel(): GraphicalLabel {
+        return this.graphicalLabel;
+    }
+    private calculateLabel(textHeight: number, transposeHalftones: number): void {
+        var text: string = ChordSymbolContainer.calculateChordText(this.chordSymbolContainer, transposeHalftones);
+        this.graphicalLabel = new GraphicalLabel(new Label(text), textHeight, TextAlignment.CenterBottom, this.boundingBox);
+        this.graphicalLabel.PositionAndShape.RelativePosition = new PointF_2D(0.0, 0.0);
+        this.boundingBox.ChildElements.Add(this.graphicalLabel.PositionAndShape);
+    }
+}

+ 1 - 0
src/MusicalScore/Graphical/GraphicalLabel.ts

@@ -3,6 +3,7 @@ import {TextAlignment} from "../../Common/Enums/TextAlignment";
 import {Clickable} from "./Clickable";
 import {BoundingBox} from "./BoundingBox";
 import {EngravingRules} from "./EngravingRules";
+import {MusicSheetCalculator} from "./MusicSheetCalculator";
 export class GraphicalLabel extends Clickable {
     private label: Label;
     constructor(label: Label, textHeight: number, alignment: TextAlignment) {

+ 42 - 0
src/MusicalScore/Graphical/GraphicalLyricEntry.ts

@@ -0,0 +1,42 @@
+import {LyricsEntry} from "../VoiceData/Lyrics/LyricsEntry";
+import {GraphicalLyricWord} from "./GraphicalLyricWord";
+import {GraphicalLabel} from "./GraphicalLabel";
+import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
+import {Label} from "../Label";
+import {TextAlignment} from "../../Common/Enums/TextAlignment";
+import {PointF_2D} from "../../Common/DataObjects/PointF_2D";
+export class GraphicalLyricEntry {
+    private lyricsEntry: LyricsEntry;
+    private graphicalLyricWord: GraphicalLyricWord;
+    private graphicalLabel: GraphicalLabel;
+    private graphicalStaffEntry: GraphicalStaffEntry;
+    constructor(lyricsEntry: LyricsEntry, graphicalStaffEntry: GraphicalStaffEntry, lyricsHeight: number, staffHeight: number) {
+        this.lyricsEntry = lyricsEntry;
+        this.graphicalStaffEntry = graphicalStaffEntry;
+        this.graphicalLabel = new GraphicalLabel(new Label(lyricsEntry.Text), lyricsHeight,
+            TextAlignment.CenterBottom,
+            graphicalStaffEntry.PositionAndShape);
+        this.graphicalLabel.PositionAndShape.RelativePosition = new PointF_2D(0.0, staffHeight);
+    }
+    public get GetLyricsEntry(): LyricsEntry {
+        return this.lyricsEntry;
+    }
+    public get ParentLyricWord(): GraphicalLyricWord {
+        return this.graphicalLyricWord;
+    }
+    public set ParentLyricWord(value: GraphicalLyricWord) {
+        this.graphicalLyricWord = value;
+    }
+    public get GraphicalLabel(): GraphicalLabel {
+        return this.graphicalLabel;
+    }
+    public set GraphicalLabel(value: GraphicalLabel) {
+        this.graphicalLabel = value;
+    }
+    public get StaffEntryParent(): GraphicalStaffEntry {
+        return this.graphicalStaffEntry;
+    }
+    public set StaffEntryParent(value: GraphicalStaffEntry) {
+        this.graphicalStaffEntry = value;
+    }
+}

+ 29 - 0
src/MusicalScore/Graphical/GraphicalLyricWord.ts

@@ -0,0 +1,29 @@
+import {LyricWord} from "../VoiceData/Lyrics/LyricsWord";
+import {GraphicalLyricEntry} from "./GraphicalLyricEntry";
+export class GraphicalLyricWord {
+    private lyricWord: LyricWord;
+    private graphicalLyricsEntries: List<GraphicalLyricEntry> = new List<GraphicalLyricEntry>();
+    constructor(lyricWord: LyricWord) {
+        this.lyricWord = lyricWord;
+        this.initialize();
+    }
+    public get GetLyricWord(): LyricWord {
+        return this.lyricWord;
+    }
+    public get GraphicalLyricsEntries(): List<GraphicalLyricEntry> {
+        return this.graphicalLyricsEntries;
+    }
+    public set GraphicalLyricsEntries(value: List<GraphicalLyricEntry>) {
+        this.graphicalLyricsEntries = value;
+    }
+    public isFilled(): boolean {
+        for (var i: number = 0; i < this.graphicalLyricsEntries.Count; i++)
+            if (this.graphicalLyricsEntries[i] == null)
+                return false;
+        return true;
+    }
+    private initialize(): void {
+        for (var i: number = 0; i < this.lyricWord.Syllabels.Count; i++)
+            this.graphicalLyricsEntries.Add(null);
+    }
+}

+ 1 - 0
src/MusicalScore/Graphical/GraphicalMusicPage.ts

@@ -4,6 +4,7 @@ import {GraphicalLabel} from "./GraphicalLabel";
 import {MusicSystem} from "./MusicSystem";
 import {EngravingRules} from "./EngravingRules";
 import {PointF_2D} from "../../Common/DataObjects/PointF_2D";
+import {GraphicalMusicSheet} from "./GraphicalMusicSheet";
 export class GraphicalMusicPage extends GraphicalObject {
     private musicSystems: List<MusicSystem> = new List<MusicSystem>();
     private labels: List<GraphicalLabel> = new List<GraphicalLabel>();

+ 728 - 0
src/MusicalScore/Graphical/GraphicalMusicSheet.ts

@@ -0,0 +1,728 @@
+import {MusicSheet} from "../MusicSheet";
+import {SourceMeasure} from "../VoiceData/SourceMeasure";
+import {StaffMeasure} from "./StaffMeasure";
+import {FontInfo} from "./FontInfo";
+import {GraphicalMusicPage} from "./GraphicalMusicPage";
+import {VerticalGraphicalStaffEntryContainer} from "./VerticalGraphicalStaffEntryContainer";
+import {GraphicalLabel} from "./GraphicalLabel";
+import {GraphicalLine} from "./GraphicalLine";
+import {MusicSystem} from "./MusicSystem";
+import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
+import {SourceStaffEntry} from "../VoiceData/SourceStaffEntry";
+import {PointF_2D} from "../../Common/DataObjects/PointF_2D";
+import {ClefInstruction} from "../VoiceData/Instructions/ClefInstruction";
+import {AbstractNotationInstruction} from "../VoiceData/Instructions/AbstractNotationInstruction";
+import {KeyInstruction} from "../VoiceData/Instructions/KeyInstruction";
+import {Fraction} from "../../Common/DataObjects/fraction";
+import {GraphicalNote} from "./GraphicalNote";
+import {Instrument} from "../Instrument";
+import {BoundingBox} from "./BoundingBox";
+import {VoiceEntry} from "../VoiceData/VoiceEntry";
+import {Note} from "../VoiceData/Note";
+import {MusicSheetCalculator} from "./MusicSheetCalculator";
+export class GraphicalMusicSheet {
+    constructor(musicSheet: MusicSheet, calculator: MusicSheetCalculator) {
+        this.musicSheet = musicSheet;
+        this.numberOfStaves = this.musicSheet.Staves.Count;
+        this.calculator = calculator;
+        this.SourceToGraphicalMeasureLinks = new Dictionary<SourceMeasure, List<StaffMeasure>>();
+        this.calculator.initialize(this);
+    }
+    private musicSheet: MusicSheet;
+    private fontInfo: FontInfo = this.FontInfo.Info;
+    private calculator: MusicSheetCalculator;
+    private musicPages: List<GraphicalMusicPage> = new List<GraphicalMusicPage>();
+    private measureList: List<List<StaffMeasure>> = new List<List<StaffMeasure>>();
+    private verticalGraphicalStaffEntryContainers: List<VerticalGraphicalStaffEntryContainer> = new List<VerticalGraphicalStaffEntryContainer>();
+    private title: GraphicalLabel;
+    private subtitle: GraphicalLabel;
+    private composer: GraphicalLabel;
+    private lyricist: GraphicalLabel;
+    private scoreFollowingLines: List<GraphicalLine> = new List<GraphicalLine>();
+    private maxAllowedSystemWidth: number;
+    private systemImages: Dictionary<MusicSystem, SystemImageProperties> = new Dictionary<MusicSystem, SystemImageProperties>();
+    private numberOfStaves: number;
+    private leadSheet: boolean = false;
+    public get ParentMusicSheet(): MusicSheet {
+        return this.musicSheet;
+    }
+    public get GetCalculator(): MusicSheetCalculator {
+        return this.calculator;
+    }
+    public get MusicPages(): List<GraphicalMusicPage> {
+        return this.musicPages;
+    }
+    public set MusicPages(value: List<GraphicalMusicPage>) {
+        this.musicPages = value;
+    }
+    public get FontInfo(): FontInfo {
+        return this.fontInfo;
+    }
+    public get MeasureList(): List<List<StaffMeasure>> {
+        return this.measureList;
+    }
+    public set MeasureList(value: List<List<StaffMeasure>>) {
+        this.measureList = value;
+    }
+    public get VerticalGraphicalStaffEntryContainers(): List<VerticalGraphicalStaffEntryContainer> {
+        return this.verticalGraphicalStaffEntryContainers;
+    }
+    public set VerticalGraphicalStaffEntryContainers(value: List<VerticalGraphicalStaffEntryContainer>) {
+        this.verticalGraphicalStaffEntryContainers = value;
+    }
+    public get Title(): GraphicalLabel {
+        return this.title;
+    }
+    public set Title(value: GraphicalLabel) {
+        this.title = value;
+    }
+    public get Subtitle(): GraphicalLabel {
+        return this.subtitle;
+    }
+    public set Subtitle(value: GraphicalLabel) {
+        this.subtitle = value;
+    }
+    public get Composer(): GraphicalLabel {
+        return this.composer;
+    }
+    public set Composer(value: GraphicalLabel) {
+        this.composer = value;
+    }
+    public get Lyricist(): GraphicalLabel {
+        return this.lyricist;
+    }
+    public set Lyricist(value: GraphicalLabel) {
+        this.lyricist = value;
+    }
+    public get ScoreFollowingLines(): List<GraphicalLine> {
+        return this.scoreFollowingLines;
+    }
+    public get MaxAllowedSystemWidth(): number {
+        return this.maxAllowedSystemWidth;
+    }
+    public set MaxAllowedSystemWidth(value: number) {
+        this.maxAllowedSystemWidth = value;
+    }
+    public get SystemImages(): Dictionary<MusicSystem, SystemImageProperties> {
+        return this.systemImages;
+    }
+    public SourceToGraphicalMeasureLinks: Dictionary<SourceMeasure, List<StaffMeasure>>;
+    public get NumberOfStaves(): number {
+        return this.numberOfStaves;
+    }
+    public get LeadSheet(): boolean {
+        return this.leadSheet;
+    }
+    public set LeadSheet(value: boolean) {
+        this.leadSheet = value;
+    }
+    public static transformRelativeToAbsolutePosition(graphicalMusicSheet: GraphicalMusicSheet): void {
+        for (var i: number = 0; i < graphicalMusicSheet.MusicPages.Count; i++) {
+            var pageAbsolute: PointF_2D = graphicalMusicSheet.MusicPages[i].setMusicPageAbsolutePosition(i, graphicalMusicSheet.ParentMusicSheet.Rules);
+            var page: GraphicalMusicPage = graphicalMusicSheet.MusicPages[i];
+            page.PositionAndShape.calculateAbsolutePositionsRecursive(pageAbsolute.X, pageAbsolute.Y);
+        }
+    }
+    public Initialize(): void {
+        this.verticalGraphicalStaffEntryContainers.Clear();
+        this.musicPages.Clear();
+        this.measureList.Clear();
+    }
+    public reCalculate(): void {
+        this.calculator.calculate();
+    }
+    public prepare(): void {
+        this.calculator.prepareGraphicalMusicSheet();
+    }
+    public EnforceRedrawOfMusicSystems(): void {
+        for (var idx: number = 0, len = this.musicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.musicPages[idx];
+            for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                musicSystem.NeedsToBeRedrawn = true;
+            }
+        }
+    }
+    public getClickedObject<T>(positionOnMusicSheet: PointF_2D): T {
+        for (var idx: number = 0, len = this.MusicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.MusicPages[idx];
+            return graphicalMusicPage.PositionAndShape.getClickedObjectOfType<T>(positionOnMusicSheet);
+        }
+        return null;
+    }
+    public findGraphicalStaffEntryFromMeasureList(staffIndex: number, measureIndex: number,
+        sourceStaffEntry: SourceStaffEntry): GraphicalStaffEntry {
+        for (var i: number = measureIndex; i < this.measureList.Count; i++) {
+            var graphicalMeasure: StaffMeasure = this.measureList[i][staffIndex];
+            for (var idx: number = 0, len = graphicalMeasure.StaffEntries.Count; idx < len; ++idx) {
+                var graphicalStaffEntry: GraphicalStaffEntry = graphicalMeasure.StaffEntries[idx];
+                if (graphicalStaffEntry.SourceStaffEntry == sourceStaffEntry)
+                    return graphicalStaffEntry;
+            }
+        }
+        return null;
+    }
+    public findNextGraphicalStaffEntry(staffIndex: number, measureIndex: number,
+        graphicalStaffEntry: GraphicalStaffEntry): GraphicalStaffEntry {
+        var graphicalMeasure: StaffMeasure = graphicalStaffEntry.ParentMeasure;
+        var graphicalStaffEntryIndex: number = graphicalMeasure.StaffEntries.IndexOf(graphicalStaffEntry);
+        if (graphicalStaffEntryIndex < graphicalMeasure.StaffEntries.Count - 1) {
+            return graphicalMeasure.StaffEntries[graphicalStaffEntryIndex + 1];
+        }
+        else if (measureIndex < this.measureList.Count - 1) {
+            var nextMeasure: StaffMeasure = this.measureList[measureIndex + 1][staffIndex];
+            if (nextMeasure.StaffEntries.Count > 0)
+                return nextMeasure.StaffEntries[0];
+        }
+        return null;
+    }
+    public getFirstVisibleMeasuresListFromIndeces(start: number, end: number): List<StaffMeasure> {
+        var graphicalMeasures: List<StaffMeasure> = new List<StaffMeasure>();
+        var numberOfStaves: number = this.measureList[0].Count;
+        for (var i: number = start; i <= end; i++)
+            for (var j: number = 0; j < numberOfStaves; j++)
+                if (this.measureList[i][j].isVisible()) {
+                    graphicalMeasures.Add(this.measureList[i][j]);
+                    break;
+                }
+        return graphicalMeasures;
+    }
+    public orderMeasuresByStaffLine(measures: List<StaffMeasure>): List<List<StaffMeasure>> {
+        var orderedMeasures: List<List<StaffMeasure>> = new List<List<StaffMeasure>>();
+        var mList: List<StaffMeasure> = new List<StaffMeasure>();
+        orderedMeasures.Add(mList);
+        for (var i: number = 0; i < measures.Count; i++) {
+            if (i == 0)
+                mList.Add(measures[0]);
+            else {
+                if (measures[i].ParentStaffLine == measures[i - 1].ParentStaffLine)
+                    mList.Add(measures[i]);
+                else {
+                    if (!orderedMeasures.Contains(mList))
+                        orderedMeasures.Add(mList);
+                    mList = new List<StaffMeasure>();
+                    orderedMeasures.Add(mList);
+                    mList.Add(measures[i]);
+                }
+            }
+        }
+        return orderedMeasures;
+    }
+    public initializeActiveClefs(): List<ClefInstruction> {
+        var activeClefs: List<ClefInstruction> = new List<ClefInstruction>();
+        var firstSourceMeasure: SourceMeasure = this.musicSheet.getFirstSourceMeasure();
+        if (firstSourceMeasure != null) {
+            for (var i: number = 0; i < firstSourceMeasure.CompleteNumberOfStaves; i++) {
+                for (var idx: number = 0, len = firstSourceMeasure.FirstInstructionsStaffEntries[i].Instructions.Count; idx < len; ++idx) {
+                    var abstractNotationInstruction: AbstractNotationInstruction = firstSourceMeasure.FirstInstructionsStaffEntries[i].Instructions[idx];
+                    if (abstractNotationInstruction instanceof ClefInstruction) {
+                        activeClefs.Add(<ClefInstruction>abstractNotationInstruction);
+                    }
+                }
+            }
+        }
+        return activeClefs;
+    }
+    public GetMainKey(): KeyInstruction {
+        var firstSourceMeasure: SourceMeasure = this.musicSheet.getFirstSourceMeasure();
+        if (firstSourceMeasure != null) {
+            for (var i: number = 0; i < firstSourceMeasure.CompleteNumberOfStaves; i++) {
+                for (var idx: number = 0, len = firstSourceMeasure.FirstInstructionsStaffEntries[i].Instructions.Count; idx < len; ++idx) {
+                    var abstractNotationInstruction: AbstractNotationInstruction = firstSourceMeasure.FirstInstructionsStaffEntries[i].Instructions[idx];
+                    if (abstractNotationInstruction instanceof KeyInstruction) {
+                        return <KeyInstruction>abstractNotationInstruction;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+    public getOrCreateVerticalContainer(timestamp: Fraction): VerticalGraphicalStaffEntryContainer {
+        if (this.verticalGraphicalStaffEntryContainers.Count == 0 || timestamp > this.verticalGraphicalStaffEntryContainers.Last().AbsoluteTimestamp) {
+            var verticalGraphicalStaffEntryContainer: VerticalGraphicalStaffEntryContainer = new VerticalGraphicalStaffEntryContainer(this.numberOfStaves, timestamp);
+            this.verticalGraphicalStaffEntryContainers.Add(verticalGraphicalStaffEntryContainer);
+            return verticalGraphicalStaffEntryContainer;
+        }
+        var i: number;
+        for (; i >= 0; i--) {
+            if (this.verticalGraphicalStaffEntryContainers[i].AbsoluteTimestamp < timestamp) {
+                var verticalGraphicalStaffEntryContainer: VerticalGraphicalStaffEntryContainer = new VerticalGraphicalStaffEntryContainer(this.numberOfStaves, timestamp);
+                this.verticalGraphicalStaffEntryContainers.Insert(i + 1, verticalGraphicalStaffEntryContainer);
+                return verticalGraphicalStaffEntryContainer;
+            }
+            if (this.verticalGraphicalStaffEntryContainers[i].AbsoluteTimestamp == timestamp)
+                return this.verticalGraphicalStaffEntryContainers[i];
+        }
+        return null;
+    }
+    public GetVerticalContainerFromTimestamp(timestamp: Fraction, startIndex: number): VerticalGraphicalStaffEntryContainer {
+        var index: number = this.verticalGraphicalStaffEntryContainers.BinarySearch(startIndex,
+            this.verticalGraphicalStaffEntryContainers.Count - startIndex,
+            new VerticalGraphicalStaffEntryContainer(0,
+                timestamp),
+            new VerticalGraphicalStaffEntryContainer.VgseContainerTimestampComparer());
+        if (index >= 0)
+            return this.verticalGraphicalStaffEntryContainers[index];
+        return null;
+    }
+    public GetVerticalContainerFromTimestamp(timestamp: Fraction): VerticalGraphicalStaffEntryContainer {
+        var index: number = this.verticalGraphicalStaffEntryContainers.BinarySearch(new VerticalGraphicalStaffEntryContainer(0, timestamp),
+            new VerticalGraphicalStaffEntryContainer.VgseContainerTimestampComparer());
+        if (index >= 0)
+            return this.verticalGraphicalStaffEntryContainers[index];
+        return null;
+    }
+    public GetInterpolatedIndexInVerticalContainers(musicTimestamp: Fraction): number {
+        var containers: List<VerticalGraphicalStaffEntryContainer> = this.verticalGraphicalStaffEntryContainers;
+        var leftIndex: number = 0;
+        var rightIndex: number = containers.Count - 1;
+        var foundIndex: number;
+        var leftTS: Fraction = null;
+        var rightTS: Fraction = null;
+        if (musicTimestamp <= containers.Last().AbsoluteTimestamp) {
+            while (rightIndex - leftIndex > 1) {
+                var middleIndex: number = (rightIndex + leftIndex) / 2;
+                if (containers[leftIndex].AbsoluteTimestamp == musicTimestamp) {
+                    rightIndex = leftIndex;
+                    break;
+                }
+                else if (containers[rightIndex].AbsoluteTimestamp == musicTimestamp) {
+                    leftIndex = rightIndex;
+                    break;
+                }
+                else if (containers[middleIndex].AbsoluteTimestamp == musicTimestamp) {
+                    return this.verticalGraphicalStaffEntryContainers.IndexOf(containers[middleIndex]);
+                }
+                else if (containers[middleIndex].AbsoluteTimestamp > musicTimestamp) {
+                    rightIndex = middleIndex;
+                }
+                else {
+                    leftIndex = middleIndex;
+                }
+            }
+            if (leftIndex == rightIndex)
+                return this.verticalGraphicalStaffEntryContainers.IndexOf(containers[leftIndex]);
+            leftTS = containers[leftIndex].AbsoluteTimestamp;
+            rightTS = containers[rightIndex].AbsoluteTimestamp;
+        }
+        else {
+            leftTS = containers.Last().AbsoluteTimestamp;
+            rightTS = new Fraction(getLongestStaffEntryDuration(containers.Count - 1) + leftTS);
+            rightIndex = containers.Count;
+        }
+        var diff: number = rightTS.RealValue - leftTS.RealValue;
+        var diffTS: number = rightTS.RealValue - musicTimestamp.RealValue;
+        foundIndex = rightIndex - (diffTS / diff);
+        return Math.Min(foundIndex, this.verticalGraphicalStaffEntryContainers.Count);
+    }
+    private getLongestStaffEntryDuration(index: number): Fraction {
+        var maxLength: Fraction = new Fraction(0, 1);
+        for (var idx: number = 0, len = this.verticalGraphicalStaffEntryContainers[index].StaffEntries.Count; idx < len; ++idx) {
+            var graphicalStaffEntry: GraphicalStaffEntry = this.verticalGraphicalStaffEntryContainers[index].StaffEntries[idx];
+            if (graphicalStaffEntry == null)
+                continue;
+            for (var idx2: number = 0, len2 = graphicalStaffEntry.Notes.Count; idx2 < len2; ++idx2) {
+                var graphicalNotes: List<GraphicalNote> = graphicalStaffEntry.Notes[idx2];
+                for (var idx3: number = 0, len3 = graphicalNotes.Count; idx3 < len3; ++idx3) {
+                    var note: GraphicalNote = graphicalNotes[idx3];
+                    if (note.GraphicalNoteLength > maxLength)
+                        maxLength = note.GraphicalNoteLength;
+                }
+            }
+        }
+        return maxLength;
+    }
+    public getVisibleStavesIndecesFromSourceMeasure(visibleMeasures: List<StaffMeasure>): List<number> {
+        var visibleInstruments: List<Instrument> = new List<Instrument>();
+        var visibleStavesIndeces: List<number> = new List<number>();
+        for (var idx: number = 0, len = visibleMeasures.Count; idx < len; ++idx) {
+            var graphicalMeasure: StaffMeasure = visibleMeasures[idx];
+            var instrument: Instrument = graphicalMeasure.ParentStaff.ParentInstrument;
+            if (!visibleInstruments.Contains(instrument))
+                visibleInstruments.Add(instrument);
+        }
+        for (var idx: number = 0, len = visibleInstruments.Count; idx < len; ++idx) {
+            var instrument: Instrument = visibleInstruments[idx];
+            var index: number = this.musicSheet.GetGlobalStaffIndexOfFirstStaff(instrument);
+            for (var j: number = 0; j < instrument.Staves.Count; j++)
+                visibleStavesIndeces.Add(index + j);
+        }
+        return visibleStavesIndeces;
+    }
+    public getGraphicalMeasureFromSourceMeasureAndIndex(sourceMeasure: SourceMeasure, index: number): StaffMeasure {
+        for (var i: number = 0; i < this.measureList.Count; i++) {
+            if (this.measureList[i][0].ParentSourceMeasure == sourceMeasure)
+                return this.measureList[i][index];
+        }
+        return null;
+    }
+    public getMeasureIndex(graphicalMeasure: StaffMeasure, measureIndex: number, inListIndex: number): boolean {
+        measureIndex = 0;
+        inListIndex = 0;
+        for (; measureIndex < this.measureList.Count; measureIndex++) {
+            for (var idx: number = 0, len = this.measureList[measureIndex].Count; idx < len; ++idx) {
+                var measure: StaffMeasure = this.measureList[measureIndex][idx];
+                if (measure == graphicalMeasure)
+                    return true;
+            }
+        }
+        return false;
+    }
+    public getMeasureIndex(entry: GraphicalStaffEntry, measureIndex: number, inListIndex: number): boolean {
+        return this.getMeasureIndex(entry.ParentMeasure, measureIndex, inListIndex);
+    }
+    public GetNearesNote(clickPosition: PointF_2D, maxClickDist: PointF_2D): GraphicalNote {
+        var initialSearchArea: number = 10;
+        var foundNotes: List<GraphicalNote> = new List<GraphicalNote>();
+        var region: BoundingBox = new BoundingBox(null);
+        region.BorderLeft = clickPosition.X - initialSearchArea;
+        region.BorderTop = clickPosition.Y - initialSearchArea;
+        region.BorderRight = clickPosition.X + initialSearchArea;
+        region.BorderBottom = clickPosition.Y + initialSearchArea;
+        region.AbsolutePosition = new PointF_2D(0, 0);
+        for (var idx: number = 0, len = this.MusicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.MusicPages[idx];
+            var entries: IEnumerable<GraphicalNote> = graphicalMusicPage.PositionAndShape.getObjectsInRegion<GraphicalNote>(region);
+            var entriesArr: GraphicalNote[] = __as__<GraphicalNote[]>(entries, GraphicalNote[]) ?? entries.ToArray();
+            if (entries == null) {
+                continue;
+            }
+            else {
+                for (var idx2: number = 0, len2 = entriesArr.length; idx2 < len2; ++idx2) {
+                    var note: GraphicalNote = entriesArr[idx2];
+                    if (Math.Abs(note.PositionAndShape.AbsolutePosition.X - clickPosition.X) < maxClickDist.X && Math.Abs(note.PositionAndShape.AbsolutePosition.Y - clickPosition.Y) < maxClickDist.Y)
+                        foundNotes.Add(note);
+                }
+            }
+        }
+        var closest: GraphicalNote = null;
+        for (var idx: number = 0, len = foundNotes.Count; idx < len; ++idx) {
+            var note: GraphicalNote = foundNotes[idx];
+            if (closest == null)
+                closest = note;
+            else {
+                if (note.ParentStaffEntry.RelInMeasureTimestamp == null)
+                    continue;
+                var deltaNew: number = this.CalculateDistance(note.PositionAndShape.AbsolutePosition, clickPosition);
+                var deltaOld: number = this.CalculateDistance(closest.PositionAndShape.AbsolutePosition, clickPosition);
+                if (deltaNew < deltaOld)
+                    closest = note;
+            }
+        }
+        if (closest != null)
+            return closest;
+        return null;
+    }
+    public GetClickableLabel(clickPosition: PointF_2D): GraphicalLabel {
+        var initialSearchAreaX: number = 4;
+        var initialSearchAreaY: number = 4;
+        var region: BoundingBox = new BoundingBox(null);
+        region.BorderLeft = clickPosition.X - initialSearchAreaX;
+        region.BorderTop = clickPosition.Y - initialSearchAreaY;
+        region.BorderRight = clickPosition.X + initialSearchAreaX;
+        region.BorderBottom = clickPosition.Y + initialSearchAreaY;
+        region.AbsolutePosition = new PointF_2D(0, 0);
+        for (var idx: number = 0, len = this.MusicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.MusicPages[idx];
+            var entries: GraphicalLabel[] = graphicalMusicPage.PositionAndShape.getObjectsInRegion<GraphicalLabel>(region).ToArray();
+            if (entries.length != 1) {
+                continue;
+            }
+            else {
+                for (var idx2: number = 0, len2 = entries.length; idx2 < len2; ++idx2) {
+                    var clickedLabel: GraphicalLabel = entries[idx2];
+                    return clickedLabel;
+                }
+            }
+        }
+        return null;
+    }
+    public GetNearestStaffEntry(clickPosition: PointF_2D): GraphicalStaffEntry {
+        var initialSearchArea: number = 10;
+        var foundEntries: List<GraphicalStaffEntry> = new List<GraphicalStaffEntry>();
+        var region: BoundingBox = new BoundingBox(null);
+        region.BorderLeft = clickPosition.X - initialSearchArea;
+        region.BorderTop = clickPosition.Y - initialSearchArea;
+        region.BorderRight = clickPosition.X + initialSearchArea;
+        region.BorderBottom = clickPosition.Y + initialSearchArea;
+        region.AbsolutePosition = new PointF_2D(0, 0);
+        for (var idx: number = 0, len = this.MusicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.MusicPages[idx];
+            var entries: GraphicalStaffEntry[] = graphicalMusicPage.PositionAndShape.getObjectsInRegion<GraphicalStaffEntry>(region, false).ToArray();
+            if (entries == null || entries.Count() == 0) {
+                continue;
+            }
+            else {
+                for (var idx2: number = 0, len2 = entries.Count(); idx2 < len2; ++idx2) {
+                    var gse: GraphicalStaffEntry = entries[idx2];
+                    foundEntries.Add(gse);
+                }
+            }
+        }
+        var closest: GraphicalStaffEntry = null;
+        for (var idx: number = 0, len = foundEntries.Count; idx < len; ++idx) {
+            var gse: GraphicalStaffEntry = foundEntries[idx];
+            if (closest == null)
+                closest = gse;
+            else {
+                if (gse.RelInMeasureTimestamp == null)
+                    continue;
+                var deltaNew: number = this.CalculateDistance(gse.PositionAndShape.AbsolutePosition, clickPosition);
+                var deltaOld: number = this.CalculateDistance(closest.PositionAndShape.AbsolutePosition, clickPosition);
+                if (deltaNew < deltaOld)
+                    closest = gse;
+            }
+        }
+        if (closest != null)
+            return closest;
+        return null;
+    }
+    public GetPossibleCommentAnchor(clickPosition: PointF_2D): SourceStaffEntry {
+        var entry: GraphicalStaffEntry = this.GetNearestStaffEntry(clickPosition);
+        if (entry == null)
+            return null;
+        return entry.SourceStaffEntry;
+    }
+    public getClickedObjectOfType<T>(positionOnMusicSheet: PointF_2D): T {
+        for (var idx: number = 0, len = this.musicPages.Count; idx < len; ++idx) {
+            var page: GraphicalMusicPage = this.musicPages[idx];
+            var o: Object = page.PositionAndShape.getClickedObjectOfType<T>(positionOnMusicSheet);
+            if (o != null)
+                return __as__<T>(o, T);
+        }
+        return null;
+    }
+    public tryGetTimestampFromPosition(positionOnMusicSheet: PointF_2D): Fraction {
+        var entry: GraphicalStaffEntry = this.getClickedObjectOfType<GraphicalStaffEntry>(positionOnMusicSheet);
+        if (entry == null)
+            return null;
+        return entry.getAbsoluteTimestamp();
+    }
+    public tryGetClickableLabel(positionOnMusicSheet: PointF_2D): GraphicalLabel {
+        try {
+            return this.GetClickableLabel(positionOnMusicSheet);
+        }
+        catch (ex) {
+            Logger.DefaultLogger.LogError(LogLevel.NORMAL, "GraphicalMusicSheet.tryGetClickableObject",
+                "positionOnMusicSheet: " + positionOnMusicSheet, ex);
+        }
+
+        return null;
+    }
+    public tryGetTimeStampFromPosition(positionOnMusicSheet: PointF_2D): Fraction {
+        try {
+            var entry: GraphicalStaffEntry = this.GetNearestStaffEntry(positionOnMusicSheet);
+            if (entry == null)
+                return null;
+            return entry.getAbsoluteTimestamp();
+        }
+        catch (ex) {
+            Logger.DefaultLogger.LogError(LogLevel.NORMAL, "GraphicalMusicSheet.tryGetTimeStampFromPosition",
+                "positionOnMusicSheet: " + positionOnMusicSheet, ex);
+        }
+
+        return null;
+    }
+    private CalculateDistance(pt1: PointF_2D, pt2: PointF_2D): number {
+        var deltaX: number = pt1.X - pt2.X;
+        var deltaY: number = pt1.Y - pt2.Y;
+        return (deltaX * deltaX) + (deltaY * deltaY);
+    }
+    public getStaffEntry(index: number): GraphicalStaffEntry {
+        return this.getStaffEntry(this.VerticalGraphicalStaffEntryContainers[index]);
+    }
+    public getStaffEntry(container: VerticalGraphicalStaffEntryContainer): GraphicalStaffEntry {
+        var staffEntry: GraphicalStaffEntry = null;
+        try {
+            for (var idx: number = 0, len = container.StaffEntries.Count; idx < len; ++idx) {
+                var entry: GraphicalStaffEntry = container.StaffEntries[idx];
+                if (entry == null || !entry.SourceStaffEntry.ParentStaff.ParentInstrument.Visible)
+                    continue;
+                if (staffEntry == null) {
+                    staffEntry = entry;
+                }
+                else if (entry.PositionAndShape != null && staffEntry.PositionAndShape != null) {
+                    if (staffEntry.PositionAndShape.RelativePosition.X > entry.PositionAndShape.RelativePosition.X)
+                        staffEntry = entry;
+                }
+            }
+        }
+        catch (ex) {
+            Logger.DefaultLogger.LogError(LogLevel.NORMAL, "GraphicalMusicSheet.getStaffEntry", ex);
+        }
+
+        return staffEntry;
+    }
+    public GetPreviousVisibleContainerIndex(index: number): number {
+        for (var i: number = index - 1; i >= 0; i--) {
+            var entries: List<GraphicalStaffEntry> = this.verticalGraphicalStaffEntryContainers[i].StaffEntries;
+            for (var idx: number = 0, len = entries.Count; idx < len; ++idx) {
+                var entry: GraphicalStaffEntry = entries[idx];
+                if (entry != null && entry.SourceStaffEntry.ParentStaff.ParentInstrument.Visible)
+                    return i;
+            }
+        }
+        return -1;
+    }
+    public GetNextVisibleContainerIndex(index: number): number {
+        for (var i: number = index + 1; i < this.verticalGraphicalStaffEntryContainers.Count; ++i) {
+            var entries: List<GraphicalStaffEntry> = this.verticalGraphicalStaffEntryContainers[i].StaffEntries;
+            for (var idx: number = 0, len = entries.Count; idx < len; ++idx) {
+                var entry: GraphicalStaffEntry = entries[idx];
+                if (entry != null && entry.SourceStaffEntry.ParentStaff.ParentInstrument.Visible)
+                    return i;
+            }
+        }
+        return -1;
+    }
+    public findClosestLeftStaffEntry(fractionalIndex: number, searchOnlyVisibleEntries: boolean): GraphicalStaffEntry {
+        var foundEntry: GraphicalStaffEntry = null;
+        var leftIndex: number = <number>Math.Floor(fractionalIndex);
+        leftIndex = Math.Min(this.VerticalGraphicalStaffEntryContainers.Count - 1, leftIndex);
+        for (var i: number = leftIndex; i >= 0; i--) {
+            foundEntry = this.getStaffEntry(i);
+            if (foundEntry != null) {
+                if (searchOnlyVisibleEntries) {
+                    if (foundEntry.SourceStaffEntry.ParentStaff.ParentInstrument.Visible)
+                        return foundEntry;
+                }
+                else return foundEntry;
+            }
+        }
+        return null;
+    }
+    public findClosestRightStaffEntry(fractionalIndex: number, returnOnlyVisibleEntries: boolean): GraphicalStaffEntry {
+        var foundEntry: GraphicalStaffEntry = null;
+        var rightIndex: number = <number>Math.Max(0, Math.Ceiling(fractionalIndex));
+        for (var i: number = rightIndex; i < this.VerticalGraphicalStaffEntryContainers.Count; i++) {
+            foundEntry = this.getStaffEntry(i);
+            if (foundEntry != null) {
+                if (returnOnlyVisibleEntries) {
+                    if (foundEntry.SourceStaffEntry.ParentStaff.ParentInstrument.Visible)
+                        return foundEntry;
+                }
+                else return foundEntry;
+            }
+        }
+        return null;
+    }
+    public calculateXPositionFromTimestamp(timeStamp: Fraction, currentMusicSystem: MusicSystem): number {
+        var fractionalIndex: number = this.GetInterpolatedIndexInVerticalContainers(timeStamp);
+        var previousStaffEntry: GraphicalStaffEntry = this.findClosestLeftStaffEntry(fractionalIndex, true);
+        var nextStaffEntry: GraphicalStaffEntry = this.findClosestRightStaffEntry(fractionalIndex, true);
+        var currentTimeStamp: number = timeStamp.RealValue;
+        if (previousStaffEntry == null && nextStaffEntry == null) {
+            currentMusicSystem = null;
+            return 0;
+        }
+        var previousStaffEntryMusicSystem: MusicSystem = null;
+        if (previousStaffEntry != null) {
+            previousStaffEntryMusicSystem = previousStaffEntry.ParentMeasure.ParentStaffLine.ParentMusicSystem;
+        }
+        else {
+            previousStaffEntryMusicSystem = nextStaffEntry.ParentMeasure.ParentStaffLine.ParentMusicSystem;
+        }
+        var nextStaffEntryMusicSystem: MusicSystem = null;
+        if (nextStaffEntry != null) {
+            nextStaffEntryMusicSystem = nextStaffEntry.ParentMeasure.ParentStaffLine.ParentMusicSystem;
+        }
+        else {
+            nextStaffEntryMusicSystem = previousStaffEntry.ParentMeasure.ParentStaffLine.ParentMusicSystem;
+        }
+        if (previousStaffEntryMusicSystem == nextStaffEntryMusicSystem) {
+            currentMusicSystem = previousStaffEntryMusicSystem;
+            var fraction: number;
+            var previousStaffEntryPositionX: number;
+            var nextStaffEntryPositionX: number;
+            if (previousStaffEntry == null) {
+                previousStaffEntryPositionX = nextStaffEntryPositionX = nextStaffEntry.PositionAndShape.AbsolutePosition.X;
+                fraction = 0;
+            }
+            else if (nextStaffEntry == null) {
+                previousStaffEntryPositionX = previousStaffEntry.PositionAndShape.AbsolutePosition.X;
+                nextStaffEntryPositionX = currentMusicSystem.GetRightBorderAbsoluteXPosition();
+                fraction = (currentTimeStamp - previousStaffEntry.getAbsoluteTimestamp().RealValue) / ((previousStaffEntry.ParentMeasure.ParentSourceMeasure.AbsoluteTimestamp + previousStaffEntry.ParentMeasure.ParentSourceMeasure.Duration).RealValue - previousStaffEntry.getAbsoluteTimestamp().RealValue);
+            }
+            else {
+                previousStaffEntryPositionX = previousStaffEntry.PositionAndShape.AbsolutePosition.X;
+                nextStaffEntryPositionX = nextStaffEntry.PositionAndShape.AbsolutePosition.X;
+                if (previousStaffEntry == nextStaffEntry)
+                    fraction = 0;
+                else fraction = (currentTimeStamp - previousStaffEntry.getAbsoluteTimestamp().RealValue) / (nextStaffEntry.getAbsoluteTimestamp().RealValue - previousStaffEntry.getAbsoluteTimestamp().RealValue);
+            }
+            fraction = Math.Min(1, Math.Max(0, fraction));
+            var interpolatedXPosition: number = previousStaffEntryPositionX + fraction * (nextStaffEntryPositionX - previousStaffEntryPositionX);
+            return interpolatedXPosition;
+        }
+        else {
+            var nextSystemLeftBorderTimeStamp: number = nextStaffEntry.ParentMeasure.ParentSourceMeasure.AbsoluteTimestamp.RealValue;
+            var fraction: number;
+            var interpolatedXPosition: number;
+            if (currentTimeStamp < nextSystemLeftBorderTimeStamp) {
+                currentMusicSystem = previousStaffEntryMusicSystem;
+                var previousStaffEntryPositionX: number = previousStaffEntry.PositionAndShape.AbsolutePosition.X;
+                var previousSystemRightBorderX: number = currentMusicSystem.GetRightBorderAbsoluteXPosition();
+                fraction = (currentTimeStamp - previousStaffEntry.getAbsoluteTimestamp().RealValue) / (nextSystemLeftBorderTimeStamp - previousStaffEntry.getAbsoluteTimestamp().RealValue);
+                fraction = Math.Min(1, Math.Max(0, fraction));
+                interpolatedXPosition = previousStaffEntryPositionX + fraction * (previousSystemRightBorderX - previousStaffEntryPositionX);
+            }
+            else {
+                currentMusicSystem = nextStaffEntryMusicSystem;
+                var nextStaffEntryPositionX: number = nextStaffEntry.PositionAndShape.AbsolutePosition.X;
+                var nextSystemLeftBorderX: number = currentMusicSystem.GetLeftBorderAbsoluteXPosition();
+                fraction = (currentTimeStamp - nextSystemLeftBorderTimeStamp) / (nextStaffEntry.getAbsoluteTimestamp().RealValue - nextSystemLeftBorderTimeStamp);
+                fraction = Math.Min(1, Math.Max(0, fraction));
+                interpolatedXPosition = nextSystemLeftBorderX + fraction * (nextStaffEntryPositionX - nextSystemLeftBorderX);
+            }
+            return interpolatedXPosition;
+        }
+    }
+    public GetNumberOfVisibleInstruments(): number {
+        var visibleInstrumentCount: number = 0;
+        for (var idx: number = 0, len = this.musicSheet.Instruments.Count; idx < len; ++idx) {
+            var instrument: Instrument = this.musicSheet.Instruments[idx];
+            if (instrument.Visible == true)
+                visibleInstrumentCount++;
+        }
+        return visibleInstrumentCount;
+    }
+    public GetNumberOfFollowedInstruments(): number {
+        var followedInstrumentCount: number = 0;
+        for (var idx: number = 0, len = this.musicSheet.Instruments.Count; idx < len; ++idx) {
+            var instrument: Instrument = this.musicSheet.Instruments[idx];
+            if (instrument.Following == true)
+                followedInstrumentCount++;
+        }
+        return followedInstrumentCount;
+    }
+    public GetGraphicalFromSourceMeasure(sourceMeasure: SourceMeasure): List<StaffMeasure> {
+        return this.SourceToGraphicalMeasureLinks[sourceMeasure];
+    }
+    public GetGraphicalFromSourceStaffEntry(sourceStaffEntry: SourceStaffEntry): GraphicalStaffEntry {
+        var graphicalMeasure: StaffMeasure = this.SourceToGraphicalMeasureLinks[sourceStaffEntry.VerticalContainerParent.ParentMeasure][sourceStaffEntry.ParentStaff.IdInMusicSheet];
+        return graphicalMeasure.findGraphicalStaffEntryFromTimestamp(sourceStaffEntry.Timestamp);
+    }
+    public GetGraphicalFromSourceStaffEntry(voiceEntries: List<VoiceEntry>): GraphicalStaffEntry {
+        if (voiceEntries.Count == 0)
+            return null;
+        var sse: SourceStaffEntry = voiceEntries[0].ParentSourceStaffEntry;
+        var graphicalMeasure: StaffMeasure = this.SourceToGraphicalMeasureLinks[sse.VerticalContainerParent.ParentMeasure][sse.ParentStaff.IdInMusicSheet];
+        return graphicalMeasure.findGraphicalStaffEntryFromTimestamp(sse.Timestamp);
+    }
+    public GetGraphicalNoteFromSourceNote(note: Note, containingGse: GraphicalStaffEntry): GraphicalNote {
+        for (var idx: number = 0, len = containingGse.Notes.Count; idx < len; ++idx) {
+            var graphicalNotes: List<GraphicalNote> = containingGse.Notes[idx];
+            for (var idx2: number = 0, len2 = graphicalNotes.Count; idx2 < len2; ++idx2) {
+                var graphicalNote: GraphicalNote = graphicalNotes[idx2];
+                if (graphicalNote.SourceNote == note)
+                    return graphicalNote;
+            }
+        }
+        return null;
+    }
+}
+export class SystemImageProperties {
+    public PositionInPixels: PointF_2D;
+    public SystemImageId: number;
+    public System: MusicSystem;
+}

+ 1 - 0
src/MusicalScore/Graphical/GraphicalNote.ts

@@ -6,6 +6,7 @@ import {OctaveEnum} from "../VoiceData/Expressions/ContinuousExpressions/octaveS
 import {Pitch} from "../../Common/DataObjects/pitch";
 import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
 import {GraphicalObject} from "./GraphicalObject";
+import {MusicSheetCalculator} from "./MusicSheetCalculator";
 export class GraphicalNote extends GraphicalObject {
     constructor(note: Note, parent: GraphicalStaffEntry) {
         this.SourceNote = note;

+ 4 - 0
src/MusicalScore/Graphical/GraphicalStaffEntry.ts

@@ -11,6 +11,10 @@ import {GraphicalTie} from "./GraphicalTie";
 import {GraphicalObject} from "./GraphicalObject";
 import {StaffMeasure} from "./StaffMeasure";
 import {GraphicalNote} from "./GraphicalNote";
+import {GraphicalChordSymbolContainer} from "./GraphicalChordSymbolContainer";
+import {GraphicalLyricEntry} from "./GraphicalLyricEntry";
+import {AbstractGraphicalInstruction} from "./AbstractGraphicalInstruction";
+import {GraphicalStaffEntryLink} from "./GraphicalStaffEntryLink";
 export class GraphicalStaffEntry extends GraphicalObject {
     private graphicalInstructions: List<AbstractGraphicalInstruction> = new List<AbstractGraphicalInstruction>();
     private graphicalTies: List<GraphicalTie> = new List<GraphicalTie>();

+ 50 - 0
src/MusicalScore/Graphical/GraphicalStaffEntryLink.ts

@@ -0,0 +1,50 @@
+import {StaffEntryLink} from "../VoiceData/StaffEntryLink";
+import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
+import {GraphicalNote} from "./GraphicalNote";
+export class GraphicalStaffEntryLink {
+    private staffEntryLink: StaffEntryLink;
+    private graphicalLinkedStaffEntries: List<GraphicalStaffEntry> = new List<GraphicalStaffEntry>();
+    constructor(staffEntryLink: StaffEntryLink) {
+        this.staffEntryLink = staffEntryLink;
+        this.initialize();
+    }
+    public get GetStaffEntryLink(): StaffEntryLink {
+        return this.staffEntryLink;
+    }
+    public get GraphicalLinkedStaffEntries(): List<GraphicalStaffEntry> {
+        return this.graphicalLinkedStaffEntries;
+    }
+    public set GraphicalLinkedStaffEntries(value: List<GraphicalStaffEntry>) {
+        this.graphicalLinkedStaffEntries = value;
+    }
+    public isFilled(): boolean {
+        for (var i: number = 0; i < this.graphicalLinkedStaffEntries.Count; i++) {
+            if (this.graphicalLinkedStaffEntries[i] == null)
+                return false;
+        }
+        return true;
+    }
+    public getLinkedStaffEntriesGraphicalNotes(graphicalStaffEntry: GraphicalStaffEntry): List<GraphicalNote> {
+        if (this.graphicalLinkedStaffEntries.Contains(graphicalStaffEntry)) {
+            var notes: List<GraphicalNote> = new List<GraphicalNote>();
+            for (var idx: number = 0, len = this.graphicalLinkedStaffEntries.Count; idx < len; ++idx) {
+                var graphicalLinkedStaffEntry: GraphicalStaffEntry = this.graphicalLinkedStaffEntries[idx];
+                for (var idx2: number = 0, len2 = graphicalLinkedStaffEntry.Notes.Count; idx2 < len2; ++idx2) {
+                    var graphicalNotes: List<GraphicalNote> = graphicalLinkedStaffEntry.Notes[idx2];
+                    for (var idx3: number = 0, len3 = graphicalNotes.Count; idx3 < len3; ++idx3) {
+                        var graphicalNote: GraphicalNote = graphicalNotes[idx3];
+                        if (graphicalNote.SourceNote.ParentStaffEntry.Link != null && graphicalNote.SourceNote.ParentVoiceEntry == this.staffEntryLink.GetVoiceEntry)
+                            notes.Add(graphicalNote);
+                    }
+                }
+            }
+            return notes;
+        }
+        return null;
+    }
+    private initialize(): void {
+        for (var idx: number = 0, len = this.staffEntryLink.LinkStaffEntries.Count; idx < len; ++idx) {
+            this.graphicalLinkedStaffEntries.Add(null);
+        }
+    }
+}

+ 1 - 4
src/MusicalScore/Graphical/GraphicalTie.ts

@@ -4,10 +4,7 @@ export class GraphicalTie {
     private tie: Tie;
     private startNote: GraphicalNote;
     private endNote: GraphicalNote;
-    constructor(tie: Tie) {
-        this.tie = tie;
-    }
-    constructor(tie: Tie, start: GraphicalNote, end: GraphicalNote) {
+    constructor(tie: Tie, start: GraphicalNote = null, end: GraphicalNote = null) {
         this.tie = tie;
         this.startNote = start;
         this.endNote = end;

+ 1229 - 0
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -0,0 +1,1229 @@
+import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
+import {StaffLine} from "./StaffLine";
+import {GraphicalMusicSheet} from "./GraphicalMusicSheet";
+import {EngravingRules} from "./EngravingRules";
+import {Tie} from "../VoiceData/Tie";
+import {Fraction} from "../../Common/DataObjects/fraction";
+import {Note} from "../VoiceData/Note";
+import {MusicSheet} from "../MusicSheet";
+import {StaffMeasure} from "./StaffMeasure";
+import {ClefInstruction} from "../VoiceData/Instructions/ClefInstruction";
+import {LyricWord} from "../VoiceData/Lyrics/LyricsWord";
+import {SourceMeasure} from "../VoiceData/SourceMeasure";
+import {GraphicalMusicPage} from "./GraphicalMusicPage";
+import {GraphicalNote} from "./GraphicalNote";
+import {Beam} from "../VoiceData/Beam";
+import {OctaveEnum} from "../VoiceData/Expressions/ContinuousExpressions/octaveShift";
+import {LyricsEntry} from "../VoiceData/Lyrics/LyricsEntry";
+import {VoiceEntry} from "../VoiceData/VoiceEntry";
+import {OrnamentContainer} from "../VoiceData/OrnamentContainer";
+import {ArticulationEnum} from "../VoiceData/VoiceEntry";
+import {Tuplet} from "../VoiceData/Tuplet";
+import {MusicSystem} from "./MusicSystem";
+import {GraphicalTie} from "./GraphicalTie";
+import {RepetitionInstruction} from "../VoiceData/Instructions/RepetitionInstruction";
+import {MultiExpression} from "../VoiceData/Expressions/multiExpression";
+import {StaffEntryLink} from "../VoiceData/StaffEntryLink";
+import {MusicSystemBuilder} from "./MusicSystemBuilder";
+import {MultiTempoExpression} from "../VoiceData/Expressions/multiTempoExpression";
+import {Repetition} from "../MusicSource/Repetition";
+import {PointF_2D} from "../../Common/DataObjects/PointF_2D";
+import {SourceStaffEntry} from "../VoiceData/SourceStaffEntry";
+import {BoundingBox} from "./BoundingBox";
+import {Instrument} from "../Instrument";
+import {GraphicalLabel} from "./GraphicalLabel";
+import {TextAlignment} from "../../Common/Enums/TextAlignment";
+import {VerticalGraphicalStaffEntryContainer} from "./VerticalGraphicalStaffEntryContainer";
+import {KeyInstruction} from "../VoiceData/Instructions/KeyInstruction";
+import {AbstractNotationInstruction} from "../VoiceData/Instructions/AbstractNotationInstruction";
+import {ClefEnum} from "../VoiceData/Instructions/ClefInstruction";
+import {TechnicalInstruction} from "../VoiceData/Instructions/TechnicalInstruction";
+import {Pitch} from "../../Common/DataObjects/pitch";
+import {LinkedVoice} from "../VoiceData/LinkedVoice";
+import {ColDirEnum} from "./BoundingBox";
+export class MusicSheetCalculator {
+    public static TransposeCalculator: ITransposeCalculator;
+    protected static textMeasurer: ITextMeasurer;
+    protected staffEntriesWithGraphicalTies: List<GraphicalStaffEntry> = new List<GraphicalStaffEntry>();
+    protected staffEntriesWithOrnaments: List<GraphicalStaffEntry> = new List<GraphicalStaffEntry>();
+    protected staffEntriesWithChordSymbols: List<GraphicalStaffEntry> = new List<GraphicalStaffEntry>();
+    protected staffLinesWithLyricWords: List<StaffLine> = new List<StaffLine>();
+    protected staffLinesWithGraphicalExpressions: List<StaffLine> = new List<StaffLine>();
+    protected graphicalMusicSheet: GraphicalMusicSheet;
+    protected rules: EngravingRules;
+    protected symbolFactory: IGraphicalSymbolFactory;
+    constructor(symbolFactory: IGraphicalSymbolFactory) {
+        this.symbolFactory = symbolFactory;
+    }
+    public static get TextMeasurer(): ITextMeasurer {
+        return MusicSheetCalculator.textMeasurer;
+    }
+    public static set TextMeasurer(value: ITextMeasurer) {
+        MusicSheetCalculator.textMeasurer = value;
+    }
+    protected get leadSheet(): boolean {
+        return this.graphicalMusicSheet.LeadSheet;
+    }
+    private static addTieToTieTimestampsDict(tieTimestampListDict: Dictionary<Tie, List<Fraction>>, note: Note): void {
+        note.NoteTie.initializeBoolList();
+        var tieTimestampList: List<Fraction> = new List<Fraction>();
+        for (var m: number = 0; m < note.NoteTie.Fractions.Count; m++) {
+            var musicTimestamp: Fraction;
+            if (m == 0)
+                musicTimestamp = new Fraction(note.calculateNoteLengthWithoutTie() + note.getAbsoluteTimestamp());
+            else musicTimestamp = new Fraction(tieTimestampList[m - 1] + note.NoteTie.Fractions[m - 1]);
+            tieTimestampList.Add(musicTimestamp);
+        }
+        tieTimestampListDict.Add(note.NoteTie, tieTimestampList);
+    }
+    public initialize(graphicalMusicSheet: GraphicalMusicSheet): void {
+        this.graphicalMusicSheet = graphicalMusicSheet;
+        this.rules = graphicalMusicSheet.ParentMusicSheet.Rules;
+        this.prepareGraphicalMusicSheet();
+        this.calculate();
+    }
+    public prepareGraphicalMusicSheet(): void {
+        this.graphicalMusicSheet.SystemImages.Clear();
+        var musicSheet: MusicSheet = this.graphicalMusicSheet.ParentMusicSheet;
+        this.staffEntriesWithGraphicalTies.Clear();
+        this.staffEntriesWithOrnaments.Clear();
+        this.staffEntriesWithChordSymbols.Clear();
+        this.staffLinesWithLyricWords.Clear();
+        this.staffLinesWithGraphicalExpressions.Clear();
+        this.graphicalMusicSheet.Initialize();
+        var measureList: List<List<StaffMeasure>> = this.graphicalMusicSheet.MeasureList;
+        var accidentalCalculators: List<AccidentalCalculator> = this.createAccidentalCalculators();
+        var activeClefs: List<ClefInstruction> = this.graphicalMusicSheet.initializeActiveClefs();
+        var lyricWords: List<LyricWord> = new List<LyricWord>();
+        var completeNumberOfStaves: number = musicSheet.getCompleteNumberOfStaves();
+        var openOctaveShifts: List<OctaveShiftParams> = new List<OctaveShiftParams>();
+        var tieTimestampListDictList: List<Dictionary<Tie, List<Fraction>>> = new List<Dictionary<Tie, List<Fraction>>>();
+        for (var i: number = 0; i < completeNumberOfStaves; i++) {
+            var tieTimestampListDict: Dictionary<Tie, List<Fraction>> = new Dictionary<Tie, List<Fraction>>();
+            tieTimestampListDictList.Add(tieTimestampListDict);
+            openOctaveShifts.Add(null);
+        }
+        for (var idx: number = 0, len = musicSheet.SourceMeasures.Count; idx < len; ++idx) {
+            var sourceMeasure: SourceMeasure = musicSheet.SourceMeasures[idx];
+            var graphicalMeasures: List<StaffMeasure> = this.createGraphicalMeasuresForSourceMeasure(sourceMeasure,
+                accidentalCalculators,
+                lyricWords,
+                tieTimestampListDictList,
+                openOctaveShifts,
+                activeClefs);
+            measureList.Add(graphicalMeasures);
+        }
+        this.handleStaffEntries();
+        this.calculateVerticalContainersList();
+        this.setIndecesToVerticalGraphicalContainers();
+    }
+    public calculate(): void {
+        this.clearSystemsAndMeasures();
+        this.clearRecreatedObjects();
+        this.createGraphicalTies();
+        this.calculateSheetLabelBoundingBoxes();
+        this.calculateXLayout(this.graphicalMusicSheet, this.maxInstrNameLabelLength());
+        this.graphicalMusicSheet.MusicPages = new List<GraphicalMusicPage>();
+        this.calculateMusicSystems();
+        this.graphicalMusicSheet.MusicPages[0].PositionAndShape.BorderMarginBottom += 9;
+        GraphicalMusicSheet.transformRelativeToAbsolutePosition(this.graphicalMusicSheet);
+    }
+    public calculateXLayout(graphicalMusicSheet: GraphicalMusicSheet, maxInstrNameLabelLength: number): void {
+        var maxLength: number = 0;
+        var maxInstructionsLength: number = this.rules.MaxInstructionsConstValue;
+        if (this.graphicalMusicSheet.MeasureList.Count > 0) {
+            maxLength = calculateMeasureXLayout(this.graphicalMusicSheet.MeasureList[0]) * 1.2f + maxInstrNameLabelLength + maxInstructionsLength;
+            for (var i: number = 1; i < this.graphicalMusicSheet.MeasureList.Count; i++) {
+                var measures: List<StaffMeasure> = this.graphicalMusicSheet.MeasureList[i];
+                maxLength = Math.Max(maxLength, this.calculateMeasureXLayout(measures) * 1.2f + maxInstructionsLength);
+            }
+        }
+        this.graphicalMusicSheet.MaxAllowedSystemWidth = maxLength;
+    }
+    protected calculateMeasureXLayout(measures: List<StaffMeasure>): number { throw new Error('not implemented'); }
+    protected calculateSystemYLayout(): void { throw new Error('not implemented'); }
+    protected initStaffMeasuresCreation(): void { throw new Error('not implemented'); }
+    protected handleBeam(graphicalNote: GraphicalNote, beam: Beam, openBeams: List<Beam>): void { throw new Error('not implemented'); }
+    protected createGraphicalTieNote(beams: List<Beam>, activeClef: ClefInstruction,
+        octaveShiftValue: OctaveEnum,
+        graphicalStaffEntry: GraphicalStaffEntry, duration: Fraction, numberOfDots: number,
+        openTie: Tie, isLastTieNote: boolean): void { throw new Error('not implemented'); }
+    protected handleVoiceEntryLyrics(lyricsEntries: Dictionary<number, LyricsEntry>, voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry,
+        openLyricWords: List<LyricWord>): void { throw new Error('not implemented'); }
+    protected handleVoiceEntryOrnaments(ornamentContainer: OrnamentContainer, voiceEntry: VoiceEntry,
+        graphicalStaffEntry: GraphicalStaffEntry): void { throw new Error('not implemented'); }
+    protected handleVoiceEntryArticulations(articulations: List<ArticulationEnum>,
+        voiceEntry: VoiceEntry,
+        graphicalStaffEntry: GraphicalStaffEntry): void { throw new Error('not implemented'); }
+    protected handleTuplet(graphicalNote: GraphicalNote, tuplet: Tuplet, openTuplets: List<Tuplet>): void { throw new Error('not implemented'); }
+    protected layoutVoiceEntry(voiceEntry: VoiceEntry, graphicalNotes: List<GraphicalNote>, graphicalStaffEntry: GraphicalStaffEntry, hasPitchedNote: boolean, isGraceStaffEntry: boolean): void { throw new Error('not implemented'); }
+    protected layoutStaffEntry(graphicalStaffEntry: GraphicalStaffEntry): void { throw new Error('not implemented'); }
+    protected handleTie(tie: Tie, startGraphicalStaffEntry: GraphicalStaffEntry, staffIndex: number,
+        measureIndex: number): void { throw new Error('not implemented'); }
+    protected updateStaffLineBorders(staffLine: StaffLine): void { throw new Error('not implemented'); }
+    protected calculateMeasureNumberPlacement(musicSystem: MusicSystem): void { throw new Error('not implemented'); }
+    protected layoutGraphicalTie(tie: GraphicalTie, tieIsAtSystemBreak: boolean): void { throw new Error('not implemented'); }
+    protected calculateSingleStaffLineLyricsPosition(staffLine: StaffLine, lyricVersesNumber: List<number>): void { throw new Error('not implemented'); }
+    protected calculateSingleOctaveShift(sourceMeasure: SourceMeasure, multiExpression: MultiExpression,
+        measureIndex: number, staffIndex: number): void { throw new Error('not implemented'); }
+    protected calculateWordRepetitionInstruction(repetitionInstruction: RepetitionInstruction,
+        measureIndex: number): void { throw new Error('not implemented'); }
+    protected calculateMoodAndUnknownExpression(multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void { throw new Error('not implemented'); }
+    protected clearRecreatedObjects(): void {
+
+    }
+    protected handleStaffEntryLink(graphicalStaffEntry: GraphicalStaffEntry,
+        staffEntryLinks: List<StaffEntryLink>): void {
+
+    }
+    protected calculateMusicSystems(): void {
+        if (this.graphicalMusicSheet.MeasureList != null) {
+            var measureList: List<List<StaffMeasure>> = this.graphicalMusicSheet.MeasureList.Select(ml => ml.Where(m => m.isVisible()).ToList()).ToList();
+            var numberOfStaffLines: number = 0;
+            for (var idx: number = 0, len = measureList.Count; idx < len; ++idx) {
+                var gmlist: List<StaffMeasure> = measureList[idx];
+                numberOfStaffLines = Math.Max(gmlist.Count, numberOfStaffLines);
+                break;
+            }
+            if (numberOfStaffLines == 0)
+                return
+            var musicSystemBuilder: MusicSystemBuilder = new MusicSystemBuilder();
+            musicSystemBuilder.initialize(this.graphicalMusicSheet, measureList, numberOfStaffLines, this.symbolFactory);
+            musicSystemBuilder.buildMusicSystems();
+            this.checkMeasuresForWholeRestNotes();
+            if (!this.leadSheet) {
+                this.calculateBeams();
+                this.optimizeRestPlacement();
+                this.calculateStaffEntryArticulationMarks();
+                this.calculateTieCurves();
+            }
+            this.calculateSkyBottomLines();
+            this.calculateTupletNumbers();
+            for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+                var graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+                for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                    var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                    this.calculateMeasureNumberPlacement(musicSystem);
+                }
+            }
+            if (!this.leadSheet)
+                this.calculateSlurs();
+            if (!this.leadSheet)
+                this.calculateOrnaments();
+            this.updateSkyBottomLines();
+            this.calculateChordSymbols();
+            if (!this.leadSheet) {
+                this.calculateDynamicExpressions();
+                this.optimizeStaffLineDynamicExpressionsPositions();
+                this.calculateMoodAndUnknownExpressions();
+                this.calculateOctaveShifts();
+                this.calculateWordRepetitionInstructions();
+            }
+            this.calculateRepetitionEndings();
+            if (!this.leadSheet)
+                this.calculateTempoExpressions();
+            this.calculateLyricsPosition();
+            for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+                var graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+                for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                    var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                    for (var idx3: number = 0, len3 = musicSystem.StaffLines.Count; idx3 < len3; ++idx3) {
+                        var staffLine: StaffLine = musicSystem.StaffLines[idx3];
+                        this.updateStaffLineBorders(staffLine);
+                    }
+                }
+            }
+            this.calculateComments();
+            this.calculateSystemYLayout();
+            this.calculateMarkedAreas();
+            for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+                var graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+                for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                    var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                    musicSystem.setMusicSystemLabelsYPosition();
+                    if (!this.leadSheet) {
+                        musicSystem.setYPositionsToVerticalLineObjectsAndCreateLines(this.rules);
+                        musicSystem.createSystemLeftVerticalLineObject(this.rules.SystemThinLineWidth, this.rules.SystemLabelsRightMargin);
+                        musicSystem.createInstrumentBrackets(this.graphicalMusicSheet.ParentMusicSheet.Instruments, this.rules.StaffHeight);
+                        musicSystem.createGroupBrackets(this.graphicalMusicSheet.ParentMusicSheet.InstrumentalGroups, this.rules.StaffHeight, 0);
+                        musicSystem.alignBeginInstructions();
+                    }
+                    else if (musicSystem == musicSystem.Parent.MusicSystems[0]) {
+                        musicSystem.createSystemLeftVerticalLineObject(this.rules.SystemThinLineWidth, this.rules.SystemLabelsRightMargin);
+                    }
+                    musicSystem.calculateBorders(this.rules);
+                }
+                var distance: number = graphicalMusicPage.MusicSystems[0].PositionAndShape.BorderTop;
+                for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                    var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                    var newPosition: PointF_2D = new PointF_2D(musicSystem.PositionAndShape.RelativePosition.X, musicSystem.PositionAndShape.RelativePosition.Y - distance);
+                    musicSystem.PositionAndShape.RelativePosition = newPosition;
+                }
+                if (graphicalMusicPage == this.graphicalMusicSheet.MusicPages[0])
+                    this.calculatePageLabels(graphicalMusicPage);
+                graphicalMusicPage.PositionAndShape.calculateTopBottomBorders();
+            }
+        }
+    }
+    protected updateSkyBottomLine(staffLine: StaffLine): void {
+
+    }
+    protected calculateSkyBottomLine(staffLine: StaffLine): void {
+
+    }
+    protected calculateMarkedAreas(): void {
+
+    }
+    protected calculateComments(): void {
+
+    }
+    protected optimizeStaffLineDynamicExpressionsPositions(): void {
+
+    }
+    protected calculateChordSymbols(): void {
+
+    }
+    protected layoutMeasureWithWholeRest(rest: GraphicalNote, gse: GraphicalStaffEntry,
+        measure: StaffMeasure): void {
+
+    }
+    protected layoutBeams(staffEntry: GraphicalStaffEntry): void {
+
+    }
+    protected layoutArticulationMarks(articulations: List<ArticulationEnum>, voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry): void {
+
+    }
+    protected layoutOrnament(ornaments: OrnamentContainer, voiceEntry: VoiceEntry,
+        graphicalStaffEntry: GraphicalStaffEntry): void {
+
+    }
+    protected calculateRestNotePlacementWithinGraphicalBeam(graphicalStaffEntry: GraphicalStaffEntry,
+        restNote: GraphicalNote,
+        previousNote: GraphicalNote,
+        nextStaffEntry: GraphicalStaffEntry,
+        nextNote: GraphicalNote): void {
+
+    }
+    protected calculateTupletNumbers(): void {
+
+    }
+    protected calculateSlurs(): void {
+
+    }
+    protected layoutFingering(staffLine: StaffLine, skyBottomLineCalculator: SkyBottomLineCalculator,
+        staffEntry: GraphicalStaffEntry, measureRelativePosition: PointF_2D): void {
+
+    }
+    protected calculateDynamicExpressionsForSingleMultiExpression(multiExpression: MultiExpression, measureIndex: number, staffIndex: number): void {
+
+    }
+    protected calcGraphicalRepetitionEndingsRecursively(repetition: Repetition): void {
+
+    }
+    protected layoutSingleRepetitionEnding(start: StaffMeasure, end: StaffMeasure, numberText: string, offset: number, leftOpen: boolean, rightOpen: boolean): void {
+
+    }
+    protected calculateTempoExpressionsForSingleMultiTempoExpression(sourceMeasure: SourceMeasure, multiTempoExpression: MultiTempoExpression, measureIndex: number): void {
+
+    }
+    protected clearSystemsAndMeasures(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = musicSystem.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var staffLine: StaffLine = musicSystem.StaffLines[idx3];
+                    for (var idx4: number = 0, len4 = staffLine.Measures.Count; idx4 < len4; ++idx4) {
+                        var graphicalMeasure: StaffMeasure = staffLine.Measures[idx4];
+                        if (graphicalMeasure.FirstInstructionStaffEntry != null) {
+                            graphicalMeasure.PositionAndShape.ChildElements.Remove(graphicalMeasure.FirstInstructionStaffEntry.PositionAndShape);
+                            graphicalMeasure.FirstInstructionStaffEntry = null;
+                            graphicalMeasure.BeginInstructionsWidth = 0.0f;
+                        }
+                        if (graphicalMeasure.LastInstructionStaffEntry != null) {
+                            graphicalMeasure.PositionAndShape.ChildElements.Remove(graphicalMeasure.LastInstructionStaffEntry.PositionAndShape);
+                            graphicalMeasure.LastInstructionStaffEntry = null;
+                            graphicalMeasure.EndInstructionsWidth = 0.0f;
+                        }
+                    }
+                    staffLine.Measures.Clear();
+                    staffLine.PositionAndShape.ChildElements.Clear();
+                }
+                musicSystem.StaffLines.Clear();
+                musicSystem.PositionAndShape.ChildElements.Clear();
+            }
+            graphicalMusicPage.MusicSystems.Clear();
+            graphicalMusicPage.PositionAndShape.ChildElements.Clear();
+        }
+        this.graphicalMusicSheet.MusicPages.Clear();
+    }
+    protected handleVoiceEntry(voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry,
+        accidentalCalculator: AccidentalCalculator, openLyricWords: List<LyricWord>,
+        tieTimestampListDict: Dictionary<Tie, List<Fraction>>, activeClef: ClefInstruction,
+        openTuplets: List<Tuplet>, openBeams: List<Beam>,
+        octaveShiftValue: OctaveEnum, grace: boolean = false, linkedNotes: List<Note> = null, sourceStaffEntry: SourceStaffEntry = null): OctaveEnum {
+        var graphicalNotes: List<GraphicalNote> = graphicalStaffEntry.findOrCreateGraphicalNotesListFromVoiceEntry(voiceEntry);
+        for (var idx: number = 0, len = voiceEntry.Notes.Count; idx < len; ++idx) {
+            var note: Note = voiceEntry.Notes[idx];
+            if (sourceStaffEntry != null && sourceStaffEntry.Link != null && linkedNotes != null && !linkedNotes.Contains(note))
+                continue;
+            var graphicalNote: GraphicalNote;
+            var numberOfDots: number = note.calculateNumberOfNeededDots();
+            if (grace)
+                graphicalNote = this.symbolFactory.createGraceNote(note, numberOfDots, graphicalStaffEntry, activeClef, octaveShiftValue);
+            else {
+                graphicalNote = this.symbolFactory.createNote(note, numberOfDots, graphicalStaffEntry, activeClef, octaveShiftValue);
+            }
+            if (note.NoteTie != null) {
+                MusicSheetCalculator.addTieToTieTimestampsDict(tieTimestampListDict, note);
+            }
+            if (note.Pitch != null) {
+                this.checkNoteForAccidental(graphicalNote, accidentalCalculator, activeClef, octaveShiftValue, grace);
+            }
+            this.resetYPositionForLeadSheet(graphicalNote.PositionAndShape);
+            graphicalStaffEntry.addGraphicalNoteToListAtCorrectYPosition(graphicalNotes, graphicalNote);
+            graphicalStaffEntry.PositionAndShape.ChildElements.Add(graphicalNote.PositionAndShape);
+            graphicalNote.PositionAndShape.calculateBoundingBox();
+            if (!this.leadSheet) {
+                if (note.NoteBeam != null)
+                    handleBeam(graphicalNote, note.NoteBeam, openBeams);
+                if (note.NoteTuplet != null)
+                    handleTuplet(graphicalNote, note.NoteTuplet, openTuplets);
+            }
+        }
+        if (voiceEntry.Articulations.Count > 0)
+            this.handleVoiceEntryArticulations(voiceEntry.Articulations, voiceEntry, graphicalStaffEntry);
+        if (voiceEntry.TechnicalInstructions.Count > 0)
+            this.checkVoiceEntriesForTechnicalInstructions(voiceEntry, graphicalStaffEntry);
+        if (voiceEntry.LyricsEntries.Count > 0)
+            this.handleVoiceEntryLyrics(voiceEntry.LyricsEntries, voiceEntry, graphicalStaffEntry, openLyricWords);
+        if (voiceEntry.OrnamentContainer != null)
+            this.handleVoiceEntryOrnaments(voiceEntry.OrnamentContainer, voiceEntry, graphicalStaffEntry);
+        return octaveShiftValue;
+    }
+    protected handleVoiceEntryGraceNotes(graceEntries: List<VoiceEntry>, graphicalGraceEntries: List<GraphicalStaffEntry>, graphicalStaffEntry: GraphicalStaffEntry,
+        accidentalCalculator: AccidentalCalculator, activeClef: ClefInstruction,
+        octaveShiftValue: OctaveEnum, lyricWords: List<LyricWord>,
+        tieTimestampListDict: Dictionary<Tie, List<Fraction>>,
+        tuplets: List<Tuplet>, beams: List<Beam>): void {
+        if (graceEntries != null) {
+            for (var idx: number = 0, len = graceEntries.Count; idx < len; ++idx) {
+                var graceVoiceEntry: VoiceEntry = graceEntries[idx];
+                var graceStaffEntry: GraphicalStaffEntry = this.symbolFactory.createGraceStaffEntry(graphicalStaffEntry,
+                    graphicalStaffEntry.ParentMeasure);
+                graphicalGraceEntries.Add(graceStaffEntry);
+                graphicalStaffEntry.PositionAndShape.ChildElements.Add(graceStaffEntry.PositionAndShape);
+                this.handleVoiceEntry(graceVoiceEntry, graceStaffEntry, accidentalCalculator, lyricWords,
+                    tieTimestampListDict, activeClef, tuplets,
+                    beams, octaveShiftValue, true);
+            }
+        }
+    }
+    protected handleOpenTies(measure: StaffMeasure, beams: List<Beam>, tieTimestampListDict: Dictionary<Tie, List<Fraction>>,
+        activeClef: ClefInstruction, octaveShiftParams: OctaveShiftParams): void {
+        for (var m: number = tieTimestampListDict.Count - 1; m >= 0; m--) {
+            var keyValuePair: KeyValuePair<Tie, List<Fraction>> = tieTimestampListDict.ElementAt(m);
+            var openTie: Tie = keyValuePair.Key;
+            var tieTimestamps: List<Fraction> = keyValuePair.Value;
+            var absoluteTimestamp: Fraction = null;
+            var k: number;
+            for (; k < tieTimestamps.Count; k++) {
+                if (!openTie.NoteHasBeenCreated[k]) {
+                    absoluteTimestamp = tieTimestamps[k];
+                    if (absoluteTimestamp >= (measure.ParentSourceMeasure.AbsoluteTimestamp + measure.ParentSourceMeasure.Duration))
+                        continue;
+                    var graphicalStaffEntry: GraphicalStaffEntry = null;
+                    if (absoluteTimestamp != null) {
+                        for (var idx: number = 0, len = measure.StaffEntries.Count; idx < len; ++idx) {
+                            var gse: GraphicalStaffEntry = measure.StaffEntries[idx];
+                            if (gse.getAbsoluteTimestamp() == absoluteTimestamp) {
+                                graphicalStaffEntry = gse;
+                                break;
+                            }
+                        }
+                        if (graphicalStaffEntry == null) {
+                            graphicalStaffEntry = this.createStaffEntryForTieNote(measure, absoluteTimestamp, openTie);
+                        }
+                    }
+                    if (graphicalStaffEntry != null) {
+                        var octaveShiftValue: OctaveEnum = OctaveEnum.NONE;
+                        if (octaveShiftParams != null) {
+                            if (graphicalStaffEntry.getAbsoluteTimestamp() >= octaveShiftParams.GetAbsoluteStartTimestamp && graphicalStaffEntry.getAbsoluteTimestamp() <= octaveShiftParams.GetAbsoluteEndTimestamp) {
+                                octaveShiftValue = octaveShiftParams.GetOpenOctaveShift.Type;
+                            }
+                        }
+                        var isLastTieNote: boolean = k == tieTimestamps.Count - 1;
+                        var tieFraction: Fraction = openTie.Fractions[k];
+                        var numberOfDots: number = openTie.Start.calculateNumberOfNeededDots();
+                        this.createGraphicalTieNote(beams, activeClef, octaveShiftValue, graphicalStaffEntry, tieFraction, numberOfDots, openTie, isLastTieNote);
+                        var tieStartNote: Note = openTie.Start;
+                        if (isLastTieNote && tieStartNote.ParentVoiceEntry.Articulations.Count == 1 && tieStartNote.ParentVoiceEntry.Articulations[0] == ArticulationEnum.fermata) {
+                            this.symbolFactory.addFermataAtTiedEndNote(tieStartNote, graphicalStaffEntry);
+                        }
+                        openTie.NoteHasBeenCreated[k] = true;
+                        if (openTie.allGraphicalNotesHaveBeenCreated())
+                            tieTimestampListDict.Remove(openTie);
+                    }
+                }
+            }
+        }
+    }
+    protected resetYPositionForLeadSheet(psi: BoundingBox): void {
+        if (this.leadSheet) {
+            psi.RelativePosition = new PointF_2D(psi.RelativePosition.X, 0.0f);
+        }
+    }
+    protected layoutVoiceEntries(graphicalStaffEntry: GraphicalStaffEntry): void {
+        graphicalStaffEntry.PositionAndShape.RelativePosition = new PointF_2D(0.0f, 0.0f);
+        var isGraceStaffEntry: boolean = graphicalStaffEntry.StaffEntryParent != null;
+        if (!this.leadSheet) {
+            var graphicalStaffEntryNotes: List<GraphicalNote>[] = graphicalStaffEntry.Notes.Where(n => n.Count > 0).ToArray();
+            for (var idx4: number = 0, len4 = graphicalStaffEntryNotes.length; idx4 < len4; ++idx4) {
+                var graphicalNotes: List<GraphicalNote> = graphicalStaffEntryNotes[idx4];
+                var voiceEntry: VoiceEntry = graphicalNotes[0].SourceNote.ParentVoiceEntry;
+                var hasPitchedNote: boolean = graphicalNotes[0].SourceNote.Pitch != null;
+                this.layoutVoiceEntry(voiceEntry, graphicalNotes, graphicalStaffEntry, hasPitchedNote, isGraceStaffEntry);
+            }
+        }
+    }
+    protected maxInstrNameLabelLength(): number {
+        var maxLabelLength: number = 0.0f;
+        var instrumentsArr: Instrument[] = this.graphicalMusicSheet.ParentMusicSheet.Instruments.Where(i => i.Voices.Count > 0 && i.Voices[0].Visible).ToArray();
+        for (var idx: number = 0, len = instrumentsArr.length; idx < len; ++idx) {
+            var instrument: Instrument = instrumentsArr[idx];
+            var graphicalLabel: GraphicalLabel = new GraphicalLabel(instrument.NameLabel, this.rules.InstrumentLabelTextHeight, TextAlignment.LeftCenter);
+            graphicalLabel.setLabelPositionAndShapeBorders();
+            maxLabelLength = Math.Max(maxLabelLength, graphicalLabel.PositionAndShape.MarginSize.Width);
+        }
+        return maxLabelLength;
+    }
+    protected calculateSheetLabelBoundingBoxes(): void {
+        var musicSheet: MusicSheet = this.graphicalMusicSheet.ParentMusicSheet;
+        if (musicSheet.Title != null) {
+            var title: GraphicalLabel = new GraphicalLabel(musicSheet.Title, this.rules.SheetTitleHeight, TextAlignment.CenterBottom);
+            this.graphicalMusicSheet.Title = title;
+            title.setLabelPositionAndShapeBorders();
+        }
+        if (musicSheet.Subtitle != null) {
+            var subtitle: GraphicalLabel = new GraphicalLabel(musicSheet.Subtitle, this.rules.SheetSubtitleHeight, TextAlignment.CenterCenter);
+            this.graphicalMusicSheet.Subtitle = subtitle;
+            subtitle.setLabelPositionAndShapeBorders();
+        }
+        if (musicSheet.Composer != null) {
+            var composer: GraphicalLabel = new GraphicalLabel(musicSheet.Composer, this.rules.SheetComposerHeight, TextAlignment.RightCenter);
+            this.graphicalMusicSheet.Composer = composer;
+            composer.setLabelPositionAndShapeBorders();
+        }
+        if (musicSheet.Lyricist != null) {
+            var lyricist: GraphicalLabel = new GraphicalLabel(musicSheet.Lyricist, this.rules.SheetAuthorHeight, TextAlignment.LeftCenter);
+            this.graphicalMusicSheet.Lyricist = lyricist;
+            lyricist.setLabelPositionAndShapeBorders();
+        }
+    }
+    protected checkMeasuresForWholeRestNotes(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var musicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = musicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var musicSystem: MusicSystem = musicPage.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = musicSystem.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var staffLine: StaffLine = musicSystem.StaffLines[idx3];
+                    for (var idx4: number = 0, len4 = staffLine.Measures.Count; idx4 < len4; ++idx4) {
+                        var measure: StaffMeasure = staffLine.Measures[idx4];
+                        if (measure.StaffEntries.Count == 1) {
+                            var gse: GraphicalStaffEntry = measure.StaffEntries[0];
+                            if (gse.Notes.Count > 0 && gse.Notes[0].Count > 0) {
+                                var graphicalNote: GraphicalNote = gse.Notes[0][0];
+                                if (graphicalNote.SourceNote.Pitch == null && graphicalNote.SourceNote.Length >= new Fraction(1, 2)) {
+                                    this.layoutMeasureWithWholeRest(graphicalNote, gse, measure);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    protected optimizeRestNotePlacement(graphicalStaffEntry: GraphicalStaffEntry, measure: StaffMeasure): void {
+        if (graphicalStaffEntry.Notes.Count == 0)
+            return
+        var voice1Notes: List<GraphicalNote> = graphicalStaffEntry.Notes[0];
+        if (voice1Notes.Count == 0)
+            return
+        var voice1Note1: GraphicalNote = voice1Notes[0];
+        var voice1Note1IsRest: boolean = voice1Note1.SourceNote.Pitch == null;
+        if (graphicalStaffEntry.Notes.Count == 2) {
+            var voice2Note1IsRest: boolean = false;
+            var voice2Notes: List<GraphicalNote> = graphicalStaffEntry.Notes[1];
+            if (voice2Notes.Count > 0) {
+                var voice2Note1: GraphicalNote = voice1Notes[0];
+                voice2Note1IsRest = voice2Note1.SourceNote.Pitch == null;
+            }
+            if (voice1Note1IsRest && voice2Note1IsRest) {
+                this.calculateTwoRestNotesPlacementWithCollisionDetection(graphicalStaffEntry);
+            }
+            else if (voice1Note1IsRest || voice2Note1IsRest) {
+                this.calculateRestNotePlacementWithCollisionDetectionFromGraphicalNote(graphicalStaffEntry);
+            }
+        }
+        else if (voice1Note1IsRest && graphicalStaffEntry != measure.StaffEntries[0] && graphicalStaffEntry != measure.StaffEntries[measure.StaffEntries.Count - 1]) {
+            var staffEntryIndex: number = measure.StaffEntries.IndexOf(graphicalStaffEntry);
+            var previousStaffEntry: GraphicalStaffEntry = measure.StaffEntries[staffEntryIndex - 1];
+            var nextStaffEntry: GraphicalStaffEntry = measure.StaffEntries[staffEntryIndex + 1];
+            if (previousStaffEntry.Notes.Count == 1) {
+                var previousNote: GraphicalNote = previousStaffEntry.Notes[0][0];
+                if (previousNote.SourceNote.NoteBeam != null && nextStaffEntry.Notes.Count == 1) {
+                    var nextNote: GraphicalNote = nextStaffEntry.Notes[0][0];
+                    if (nextNote.SourceNote.NoteBeam != null && previousNote.SourceNote.NoteBeam == nextNote.SourceNote.NoteBeam) {
+                        this.calculateRestNotePlacementWithinGraphicalBeam(graphicalStaffEntry, voice1Note1,
+                            previousNote,
+                            nextStaffEntry,
+                            nextNote);
+                        graphicalStaffEntry.PositionAndShape.calculateBoundingBox();
+                    }
+                }
+            }
+        }
+    }
+    protected getRelativePositionInStaffLineFromTimestamp(timestamp: Fraction, verticalIndex: number, staffLine: StaffLine,
+        multiStaffInstrument: boolean, firstVisibleMeasureRelativeX: number = 0.0): PointF_2D {
+        var relative: PointF_2D = new PointF_2D();
+        var leftStaffEntry: GraphicalStaffEntry = null;
+        var rightStaffEntry: GraphicalStaffEntry = null;
+        var numEntries: number = this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers.Count;
+        var index: number = this.graphicalMusicSheet.GetInterpolatedIndexInVerticalContainers(timestamp);
+        var leftIndex: number = <number>Math.Min(Math.Floor(index), numEntries - 1);
+        var rightIndex: number = <number>Math.Min(Math.Ceiling(index), numEntries - 1);
+        if (leftIndex < 0 || verticalIndex < 0)
+            return relative;
+        leftStaffEntry = this.getFirstLeftNotNullStaffEntryFromContainer(leftIndex, verticalIndex, multiStaffInstrument);
+        rightStaffEntry = this.getFirstRightNotNullStaffEntryFromContainer(rightIndex, verticalIndex, multiStaffInstrument);
+        if (leftStaffEntry != null && rightStaffEntry != null) {
+            var measureRelativeX: number = leftStaffEntry.ParentMeasure.PositionAndShape.RelativePosition.X;
+            if (firstVisibleMeasureRelativeX > 0)
+                measureRelativeX = firstVisibleMeasureRelativeX;
+            var leftX: number = leftStaffEntry.PositionAndShape.RelativePosition.X + measureRelativeX;
+            var rightX: number = rightStaffEntry.PositionAndShape.RelativePosition.X + rightStaffEntry.ParentMeasure.PositionAndShape.RelativePosition.X;
+            if (firstVisibleMeasureRelativeX > 0)
+                rightX = rightStaffEntry.PositionAndShape.RelativePosition.X + measureRelativeX;
+            var timestampQuotient: number = 0.0f;
+            if (leftStaffEntry != rightStaffEntry) {
+                var leftTimestamp: Fraction = leftStaffEntry.getAbsoluteTimestamp();
+                var rightTimestamp: Fraction = rightStaffEntry.getAbsoluteTimestamp();
+                var leftDifference: Fraction = new Fraction(timestamp - leftTimestamp);
+                timestampQuotient = leftDifference.RealValue / (rightTimestamp - leftTimestamp).RealValue;
+            }
+            if (leftStaffEntry.ParentMeasure.ParentStaffLine != rightStaffEntry.ParentMeasure.ParentStaffLine) {
+                if (leftStaffEntry.ParentMeasure.ParentStaffLine == staffLine)
+                    rightX = staffLine.PositionAndShape.Size.Width;
+                else leftX = staffLine.PositionAndShape.RelativePosition.X;
+            }
+            relative = new PointF_2D(leftX + (rightX - leftX) * timestampQuotient, 0.0f);
+        }
+        return relative;
+    }
+    protected getRelativeXPositionFromTimestamp(timestamp: Fraction): number {
+        var numEntries: number = this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers.Count;
+        var index: number = this.graphicalMusicSheet.GetInterpolatedIndexInVerticalContainers(timestamp);
+        var discreteIndex: number = <number>Math.Max(0, Math.Min(Math.Round(index), numEntries - 1));
+        var gse: GraphicalStaffEntry = this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[discreteIndex].getFirstNonNullStaffEntry();
+        var posX: number = gse.PositionAndShape.RelativePosition.X + gse.ParentMeasure.PositionAndShape.RelativePosition.X;
+        return posX;
+    }
+    private createAccidentalCalculators(): List<AccidentalCalculator> {
+        var accidentalCalculators: List<AccidentalCalculator> = new List<AccidentalCalculator>();
+        var firstSourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.getFirstSourceMeasure();
+        if (firstSourceMeasure != null) {
+            for (var i: number = 0; i < firstSourceMeasure.CompleteNumberOfStaves; i++) {
+                for (var idx: number = 0, len = firstSourceMeasure.FirstInstructionsStaffEntries[i].Instructions.Count; idx < len; ++idx) {
+                    var abstractNotationInstruction: AbstractNotationInstruction = firstSourceMeasure.FirstInstructionsStaffEntries[i].Instructions[idx];
+                    if (abstractNotationInstruction instanceof KeyInstruction) {
+                        var keyInstruction: KeyInstruction = <KeyInstruction>abstractNotationInstruction;
+                        var accidentalCalculator: AccidentalCalculator = new AccidentalCalculator(this.symbolFactory);
+                        accidentalCalculator.ActiveKeyInstruction = keyInstruction;
+                        accidentalCalculators.Add(accidentalCalculator);
+                    }
+                }
+            }
+        }
+        return accidentalCalculators;
+    }
+    private calculateVerticalContainersList(): void {
+        var numberOfEntries: number = this.graphicalMusicSheet.MeasureList[0].Count;
+        for (var i: number = 0; i < this.graphicalMusicSheet.MeasureList.Count; i++) {
+            for (var j: number = 0; j < numberOfEntries; j++) {
+                var measure: StaffMeasure = this.graphicalMusicSheet.MeasureList[i][j];
+                for (var idx: number = 0, len = measure.StaffEntries.Count; idx < len; ++idx) {
+                    var graphicalStaffEntry: GraphicalStaffEntry = measure.StaffEntries[idx];
+                    var verticalContainer: VerticalGraphicalStaffEntryContainer = this.graphicalMusicSheet.getOrCreateVerticalContainer(graphicalStaffEntry.getAbsoluteTimestamp());
+                    if (verticalContainer != null) {
+                        verticalContainer.StaffEntries[j] = graphicalStaffEntry;
+                        graphicalStaffEntry.ParentVerticalContainer = verticalContainer;
+                    }
+                    else {
+
+                    }
+                }
+            }
+        }
+    }
+    private setIndecesToVerticalGraphicalContainers(): void {
+        for (var i: number = 0; i < this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers.Count; i++)
+            this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[i].Index = i;
+    }
+    private createGraphicalMeasuresForSourceMeasure(sourceMeasure: SourceMeasure, accidentalCalculators: List<AccidentalCalculator>,
+        openLyricWords: List<LyricWord>,
+        tieTimestampListDictList: List<Dictionary<Tie, List<Fraction>>>,
+        openOctaveShifts: List<OctaveShiftParams>, activeClefs: List<ClefInstruction>): List<StaffMeasure> {
+        this.initStaffMeasuresCreation();
+        var verticalMeasureList: List<StaffMeasure> = new List<StaffMeasure>();
+        var openBeams: List<Beam> = new List<Beam>();
+        var openTuplets: List<Tuplet> = new List<Tuplet>();
+        var staffEntryLinks: List<StaffEntryLink> = new List<StaffEntryLink>();
+        for (var staffIndex: number = 0; staffIndex < sourceMeasure.CompleteNumberOfStaves; staffIndex++) {
+            var measure: StaffMeasure = createGraphicalMeasure(sourceMeasure, tieTimestampListDictList[staffIndex], openTuplets, openBeams, accidentalCalculators[staffIndex], activeClefs, openOctaveShifts, openLyricWords, staffIndex, staffEntryLinks);
+            verticalMeasureList.Add(measure);
+        }
+        this.graphicalMusicSheet.SourceToGraphicalMeasureLinks[sourceMeasure] = verticalMeasureList;
+        return verticalMeasureList;
+    }
+    private createGraphicalMeasure(sourceMeasure: SourceMeasure, tieTimestampListDict: Dictionary<Tie, List<Fraction>>, openTuplets: List<Tuplet>, openBeams: List<Beam>,
+        accidentalCalculator: AccidentalCalculator, activeClefs: List<ClefInstruction>, openOctaveShifts: List<OctaveShiftParams>, openLyricWords: List<LyricWord>, staffIndex: number,
+        staffEntryLinks: List<StaffEntryLink>): StaffMeasure {
+        var staff: Staff = this.graphicalMusicSheet.ParentMusicSheet.getStaffFromIndex(staffIndex);
+        var measure: StaffMeasure = this.symbolFactory.createStaffMeasure(sourceMeasure, staff);
+        measure.hasError = sourceMeasure.getErrorInMeasure(staffIndex);
+        if (sourceMeasure.FirstInstructionsStaffEntries[staffIndex] != null) {
+            for (var idx: number = 0, len = sourceMeasure.FirstInstructionsStaffEntries[staffIndex].Instructions.Count; idx < len; ++idx) {
+                var instruction: AbstractNotationInstruction = sourceMeasure.FirstInstructionsStaffEntries[staffIndex].Instructions[idx];
+                if (instruction instanceof KeyInstruction) {
+                    var key: KeyInstruction = new KeyInstruction(<KeyInstruction>instruction);
+                    if (this.graphicalMusicSheet.ParentMusicSheet.Transpose != 0 && measure.ParentStaff.ParentInstrument.MidiInstrumentId != Common.Enums.MidiInstrument.Percussion && MusicSheetCalculator.TransposeCalculator != null)
+                        MusicSheetCalculator.TransposeCalculator.TransposeKey(key,
+                            this.graphicalMusicSheet.ParentMusicSheet.Transpose);
+                    accidentalCalculator.ActiveKeyInstruction = key;
+                }
+            }
+        }
+        for (var idx: number = 0, len = sourceMeasure.StaffLinkedExpressions[staffIndex].Count; idx < len; ++idx) {
+            var multiExpression: MultiExpression = sourceMeasure.StaffLinkedExpressions[staffIndex][idx];
+            if (multiExpression.OctaveShiftStart != null) {
+                var openOctaveShift: OctaveShift = multiExpression.OctaveShiftStart;
+                openOctaveShifts[staffIndex] = new OctaveShiftParams(openOctaveShift, multiExpression.AbsoluteTimestamp,
+                    openOctaveShift.ParentEndMultiExpression.AbsoluteTimestamp);
+            }
+        }
+        for (var entryIndex: number = 0; entryIndex < sourceMeasure.VerticalSourceStaffEntryContainers.Count; entryIndex++) {
+            if (sourceMeasure.VerticalSourceStaffEntryContainers[entryIndex][staffIndex] != null) {
+                var sourceStaffEntry: SourceStaffEntry = sourceMeasure.VerticalSourceStaffEntryContainers[entryIndex][staffIndex];
+                for (var idx: number = 0, len = sourceStaffEntry.Instructions.Count; idx < len; ++idx) {
+                    var abstractNotationInstruction: AbstractNotationInstruction = sourceStaffEntry.Instructions[idx];
+                    if (abstractNotationInstruction instanceof ClefInstruction)
+                        activeClefs[staffIndex] = <ClefInstruction>abstractNotationInstruction;
+                }
+                var graphicalStaffEntry: GraphicalStaffEntry = this.symbolFactory.createStaffEntry(sourceStaffEntry, measure);
+                if (measure.StaffEntries.Count > entryIndex) {
+                    measure.addGraphicalStaffEntryAtTimestamp(graphicalStaffEntry);
+                }
+                else measure.addGraphicalStaffEntry(graphicalStaffEntry);
+                var linkedNotes: List<Note> = new List<Note>();
+                if (sourceStaffEntry.Link != null) {
+                    sourceStaffEntry.findLinkedNotes(linkedNotes);
+                    this.handleStaffEntryLink(graphicalStaffEntry, staffEntryLinks);
+                }
+                var octaveShiftValue: OctaveEnum = OctaveEnum.NONE;
+                if (openOctaveShifts[staffIndex] != null) {
+                    var octaveShiftParams: OctaveShiftParams = openOctaveShifts[staffIndex];
+                    if (sourceStaffEntry.AbsoluteTimestamp >= octaveShiftParams.GetAbsoluteStartTimestamp && sourceStaffEntry.AbsoluteTimestamp <= octaveShiftParams.GetAbsoluteEndTimestamp) {
+                        octaveShiftValue = octaveShiftParams.GetOpenOctaveShift.Type;
+                    }
+                }
+                for (var idx: number = 0, len = sourceStaffEntry.VoiceEntries.Count; idx < len; ++idx) {
+                    var voiceEntry: VoiceEntry = sourceStaffEntry.VoiceEntries[idx];
+                    handleVoiceEntryGraceNotes(voiceEntry.GraceVoiceEntriesBefore, graphicalStaffEntry.GraceStaffEntriesBefore, graphicalStaffEntry, accidentalCalculator, activeClefs[staffIndex], octaveShiftValue, openLyricWords,
+                        tieTimestampListDict,
+                        openTuplets,
+                        openBeams);
+                    octaveShiftValue = handleVoiceEntry(voiceEntry, graphicalStaffEntry,
+                        accidentalCalculator, openLyricWords,
+                        tieTimestampListDict,
+                        activeClefs[staffIndex], openTuplets,
+                        openBeams, octaveShiftValue, false, linkedNotes,
+                        sourceStaffEntry);
+                    handleVoiceEntryGraceNotes(voiceEntry.GraceVoiceEntriesAfter, graphicalStaffEntry.GraceStaffEntriesAfter, graphicalStaffEntry, accidentalCalculator, activeClefs[staffIndex], octaveShiftValue, openLyricWords,
+                        tieTimestampListDict,
+                        openTuplets,
+                        openBeams);
+                }
+                if (sourceStaffEntry.Instructions.Count > 0) {
+                    var clefInstruction: ClefInstruction = <ClefInstruction>sourceStaffEntry.Instructions[0];
+                    this.symbolFactory.createInStaffClef(graphicalStaffEntry, clefInstruction);
+                }
+                if (sourceStaffEntry.ChordContainer != null) {
+                    sourceStaffEntry.ParentStaff.ParentInstrument.HasChordSymbols = true;
+                    this.symbolFactory.createChordSymbol(sourceStaffEntry, graphicalStaffEntry, this.graphicalMusicSheet.ParentMusicSheet.Transpose);
+                }
+            }
+        }
+        if (tieTimestampListDict.Count > 0) {
+            handleOpenTies(measure, openBeams,
+                tieTimestampListDict, activeClefs[staffIndex], openOctaveShifts[staffIndex]);
+        }
+        accidentalCalculator.DoCalculationsAtEndOfMeasure();
+        if (sourceMeasure.LastInstructionsStaffEntries[staffIndex] != null) {
+            var lastStaffEntry: SourceStaffEntry = sourceMeasure.LastInstructionsStaffEntries[staffIndex];
+            for (var idx: number = 0, len = lastStaffEntry.Instructions.Count; idx < len; ++idx) {
+                var abstractNotationInstruction: AbstractNotationInstruction = lastStaffEntry.Instructions[idx];
+                if (abstractNotationInstruction instanceof ClefInstruction)
+                    activeClefs[staffIndex] = <ClefInstruction>abstractNotationInstruction;
+            }
+        }
+        for (var idx: number = 0, len = sourceMeasure.StaffLinkedExpressions[staffIndex].Count; idx < len; ++idx) {
+            var multiExpression: MultiExpression = sourceMeasure.StaffLinkedExpressions[staffIndex][idx];
+            if (multiExpression.OctaveShiftEnd != null && openOctaveShifts[staffIndex] != null && multiExpression.OctaveShiftEnd == openOctaveShifts[staffIndex].GetOpenOctaveShift) {
+                openOctaveShifts[staffIndex] = null;
+            }
+        }
+        if (measure.StaffEntries.Count == 0) {
+            var sourceStaffEntry: SourceStaffEntry = new SourceStaffEntry(null, staff);
+            var note: Note = new Note(null, sourceStaffEntry, new Fraction(sourceMeasure.Duration), null);
+            var graphicalStaffEntry: GraphicalStaffEntry = this.symbolFactory.createStaffEntry(sourceStaffEntry, measure);
+            measure.addGraphicalStaffEntry(graphicalStaffEntry);
+            graphicalStaffEntry.RelInMeasureTimestamp = new Fraction(0, 1);
+            var graphicalNotes: List<GraphicalNote> = new List<GraphicalNote>();
+            graphicalStaffEntry.Notes.Add(graphicalNotes);
+            var numberOfDots: number = note.calculateNumberOfNeededDots();
+            var graphicalNote: GraphicalNote = this.symbolFactory.createNote(note, numberOfDots, graphicalStaffEntry, new ClefInstruction(ClefEnum.G, 0, 2));
+            graphicalNotes.Add(graphicalNote);
+            graphicalStaffEntry.PositionAndShape.ChildElements.Add(graphicalNote.PositionAndShape);
+        }
+        return measure;
+    }
+    private calculatePageLabels(page: GraphicalMusicPage): void {
+        var relative: PointF_2D = new PointF_2D();
+        var firstSystemAbsoluteTopMargin: number = 10;
+        if (page.MusicSystems.Count > 0) {
+            var firstMusicSystem: MusicSystem = page.MusicSystems.First();
+            firstSystemAbsoluteTopMargin = firstMusicSystem.PositionAndShape.RelativePosition.Y + firstMusicSystem.PositionAndShape.BorderTop;
+        }
+        if (this.graphicalMusicSheet.Title != null) {
+            var title: GraphicalLabel = this.graphicalMusicSheet.Title;
+            title.PositionAndShape.Parent = page.PositionAndShape;
+            page.PositionAndShape.ChildElements.Add(title.PositionAndShape);
+            relative.X = this.graphicalMusicSheet.ParentMusicSheet.PageWidth / 2;
+            relative.Y = this.rules.TitleTopDistance + this.rules.SheetTitleHeight;
+            title.PositionAndShape.RelativePosition = relative;
+            page.Labels.Add(title);
+        }
+        if (this.graphicalMusicSheet.Subtitle != null) {
+            var subtitle: GraphicalLabel = this.graphicalMusicSheet.Subtitle;
+            subtitle.PositionAndShape.Parent = page.PositionAndShape;
+            page.PositionAndShape.ChildElements.Add(subtitle.PositionAndShape);
+            relative.X = this.graphicalMusicSheet.ParentMusicSheet.PageWidth / 2;
+            relative.Y = this.rules.TitleTopDistance + this.rules.SheetTitleHeight + this.rules.SheetMinimumDistanceBetweenTitleAndSubtitle;
+            subtitle.PositionAndShape.RelativePosition = relative;
+            page.Labels.Add(subtitle);
+        }
+        if (this.graphicalMusicSheet.Composer != null) {
+            var composer: GraphicalLabel = this.graphicalMusicSheet.Composer;
+            composer.PositionAndShape.Parent = page.PositionAndShape;
+            page.PositionAndShape.ChildElements.Add(composer.PositionAndShape);
+            composer.setLabelPositionAndShapeBorders();
+            relative.X = this.graphicalMusicSheet.ParentMusicSheet.PageWidth - this.rules.PageRightMargin;
+            relative.Y = firstSystemAbsoluteTopMargin - this.rules.SystemComposerDistance;
+            composer.PositionAndShape.RelativePosition = relative;
+            page.Labels.Add(composer);
+        }
+        if (this.graphicalMusicSheet.Lyricist != null) {
+            var lyricist: GraphicalLabel = this.graphicalMusicSheet.Lyricist;
+            lyricist.PositionAndShape.Parent = page.PositionAndShape;
+            page.PositionAndShape.ChildElements.Add(lyricist.PositionAndShape);
+            lyricist.setLabelPositionAndShapeBorders();
+            relative.X = this.rules.PageLeftMargin;
+            relative.Y = firstSystemAbsoluteTopMargin - this.rules.SystemComposerDistance;
+            lyricist.PositionAndShape.RelativePosition = relative;
+            page.Labels.Add(lyricist);
+        }
+    }
+    private checkVoiceEntriesForTechnicalInstructions(voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry): void {
+        for (var idx: number = 0, len = voiceEntry.TechnicalInstructions.Count; idx < len; ++idx) {
+            var technicalInstruction: TechnicalInstruction = voiceEntry.TechnicalInstructions[idx];
+            this.symbolFactory.createGraphicalTechnicalInstruction(technicalInstruction, graphicalStaffEntry);
+        }
+    }
+    private checkNoteForAccidental(graphicalNote: GraphicalNote, accidentalCalculator: AccidentalCalculator, activeClef: ClefInstruction,
+        octaveEnum: OctaveEnum, grace: boolean = false): void {
+        var pitch: Pitch = graphicalNote.SourceNote.Pitch;
+        var transpose: number = this.graphicalMusicSheet.ParentMusicSheet.Transpose;
+        if (transpose != 0 && graphicalNote.SourceNote.ParentStaffEntry.ParentStaff.ParentInstrument.MidiInstrumentId != Common.Enums.MidiInstrument.Percussion) {
+            pitch = graphicalNote.Transpose(accidentalCalculator.ActiveKeyInstruction, activeClef,
+                transpose, octaveEnum);
+            if (graphicalNote.SourceNote.NoteTie != null)
+                graphicalNote.SourceNote.NoteTie.BaseNoteYPosition = graphicalNote.PositionAndShape.RelativePosition.Y;
+        }
+        graphicalNote.SourceNote.HalfTone = pitch.getHalfTone();
+        var scalingFactor: number = 1.0f;
+        if (grace)
+            scalingFactor = this.rules.GraceNoteScalingFactor;
+        accidentalCalculator.CheckAccidental(graphicalNote, pitch, grace, scalingFactor);
+    }
+    private createStaffEntryForTieNote(measure: StaffMeasure, absoluteTimestamp: Fraction, openTie: Tie): GraphicalStaffEntry {
+        var graphicalStaffEntry: GraphicalStaffEntry;
+        graphicalStaffEntry = this.symbolFactory.createStaffEntry(openTie.Start.ParentStaffEntry, measure);
+        graphicalStaffEntry.RelInMeasureTimestamp = new Fraction(absoluteTimestamp - measure.ParentSourceMeasure.AbsoluteTimestamp);
+        resetYPositionForLeadSheet(graphicalStaffEntry.PositionAndShape);
+        measure.addGraphicalStaffEntry(graphicalStaffEntry);
+        return graphicalStaffEntry;
+    }
+    private updateSkyBottomLines(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = musicSystem.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var staffLine: StaffLine = musicSystem.StaffLines[idx3];
+                    this.updateSkyBottomLine(staffLine);
+                }
+            }
+        }
+    }
+    private handleStaffEntries(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MeasureList.Count; idx < len; ++idx) {
+            var measures: List<StaffMeasure> = this.graphicalMusicSheet.MeasureList[idx];
+            for (var idx2: number = 0, len2 = measures.Count; idx2 < len2; ++idx2) {
+                var measure: StaffMeasure = measures[idx2];
+                for (var idx3: number = 0, len3 = measure.StaffEntries.Count; idx3 < len3; ++idx3) {
+                    var graphicalStaffEntry: GraphicalStaffEntry = measure.StaffEntries[idx3];
+                    if (graphicalStaffEntry.ParentMeasure != null && graphicalStaffEntry.Notes.Count > 0 && graphicalStaffEntry.Notes[0].Count > 0) {
+                        this.layoutVoiceEntries(graphicalStaffEntry);
+                        this.layoutStaffEntry(graphicalStaffEntry);
+                    }
+                }
+            }
+        }
+    }
+    private createGraphicalTies(): void {
+        for (var measureIndex: number = 0; measureIndex < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.Count; measureIndex++) {
+            var sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[measureIndex];
+            for (var staffIndex: number = 0; staffIndex < sourceMeasure.CompleteNumberOfStaves; staffIndex++) {
+                for (var j: number = 0; j < sourceMeasure.VerticalSourceStaffEntryContainers.Count; j++) {
+                    if (sourceMeasure.VerticalSourceStaffEntryContainers[j][staffIndex] != null) {
+                        var sourceStaffEntry: SourceStaffEntry = sourceMeasure.VerticalSourceStaffEntryContainers[j][staffIndex];
+                        var startStaffEntry: GraphicalStaffEntry = this.graphicalMusicSheet.findGraphicalStaffEntryFromMeasureList(staffIndex, measureIndex, sourceStaffEntry);
+                        for (var idx: number = 0, len = sourceStaffEntry.VoiceEntries.Count; idx < len; ++idx) {
+                            var voiceEntry: VoiceEntry = sourceStaffEntry.VoiceEntries[idx];
+                            for (var idx2: number = 0, len2 = voiceEntry.Notes.Count; idx2 < len2; ++idx2) {
+                                var note: Note = voiceEntry.Notes[idx2];
+                                if (note.NoteTie != null) {
+                                    var tie: Tie = note.NoteTie;
+                                    this.handleTie(tie, startStaffEntry, staffIndex, measureIndex);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    private calculateSkyBottomLines(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = musicSystem.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var staffLine: StaffLine = musicSystem.StaffLines[idx3];
+                    this.calculateSkyBottomLine(staffLine);
+                }
+            }
+        }
+    }
+    private calculateBeams(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var musicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = musicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var musicSystem: MusicSystem = musicPage.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = musicSystem.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var staffLine: StaffLine = musicSystem.StaffLines[idx3];
+                    for (var idx4: number = 0, len4 = staffLine.Measures.Count; idx4 < len4; ++idx4) {
+                        var measure: StaffMeasure = staffLine.Measures[idx4];
+                        for (var idx5: number = 0, len5 = measure.StaffEntries.Count; idx5 < len5; ++idx5) {
+                            var staffEntry: GraphicalStaffEntry = measure.StaffEntries[idx5];
+                            this.layoutBeams(staffEntry);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    private calculateStaffEntryArticulationMarks(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var page: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = page.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var system: MusicSystem = page.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = system.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var line: StaffLine = system.StaffLines[idx3];
+                    for (var idx4: number = 0, len4 = line.Measures.Count; idx4 < len4; ++idx4) {
+                        var measure: StaffMeasure = line.Measures[idx4];
+                        for (var idx5: number = 0, len5 = measure.StaffEntries.Count; idx5 < len5; ++idx5) {
+                            var graphicalStaffEntry: GraphicalStaffEntry = measure.StaffEntries[idx5];
+                            for (var idx6: number = 0, len6 = graphicalStaffEntry.SourceStaffEntry.VoiceEntries.Count; idx6 < len6; ++idx6) {
+                                var voiceEntry: VoiceEntry = graphicalStaffEntry.SourceStaffEntry.VoiceEntries[idx6];
+                                if (voiceEntry.Articulations.Count > 0)
+                                    this.layoutArticulationMarks(voiceEntry.Articulations, voiceEntry, graphicalStaffEntry);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    private calculateOrnaments(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var page: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = page.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var system: MusicSystem = page.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = system.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var line: StaffLine = system.StaffLines[idx3];
+                    for (var idx4: number = 0, len4 = line.Measures.Count; idx4 < len4; ++idx4) {
+                        var measure: StaffMeasure = line.Measures[idx4];
+                        for (var idx5: number = 0, len5 = measure.StaffEntries.Count; idx5 < len5; ++idx5) {
+                            var graphicalStaffEntry: GraphicalStaffEntry = measure.StaffEntries[idx5];
+                            for (var idx6: number = 0, len6 = graphicalStaffEntry.SourceStaffEntry.VoiceEntries.Count; idx6 < len6; ++idx6) {
+                                var voiceEntry: VoiceEntry = graphicalStaffEntry.SourceStaffEntry.VoiceEntries[idx6];
+                                if (voiceEntry.OrnamentContainer != null) {
+                                    if (voiceEntry.hasTie() && graphicalStaffEntry.RelInMeasureTimestamp != voiceEntry.Timestamp)
+                                        continue;
+                                    this.layoutOrnament(voiceEntry.OrnamentContainer, voiceEntry, graphicalStaffEntry);
+                                    if (!this.staffEntriesWithOrnaments.Contains(graphicalStaffEntry))
+                                        this.staffEntriesWithOrnaments.Add(graphicalStaffEntry);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    private optimizeRestPlacement(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var page: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = page.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var system: MusicSystem = page.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = system.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var line: StaffLine = system.StaffLines[idx3];
+                    for (var idx4: number = 0, len4 = line.Measures.Count; idx4 < len4; ++idx4) {
+                        var measure: StaffMeasure = line.Measures[idx4];
+                        for (var idx5: number = 0, len5 = measure.StaffEntries.Count; idx5 < len5; ++idx5) {
+                            var graphicalStaffEntry: GraphicalStaffEntry = measure.StaffEntries[idx5];
+                            this.optimizeRestNotePlacement(graphicalStaffEntry, measure);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    private calculateTwoRestNotesPlacementWithCollisionDetection(graphicalStaffEntry: GraphicalStaffEntry): void {
+        var firstRestNote: GraphicalNote = graphicalStaffEntry.Notes[0][0];
+        var secondRestNote: GraphicalNote = graphicalStaffEntry.Notes[1][0];
+        secondRestNote.PositionAndShape.RelativePosition = new PointF_2D(0.0f, 2.5f);
+        graphicalStaffEntry.PositionAndShape.calculateAbsolutePositionsRecursiveWithoutTopelement();
+        firstRestNote.PositionAndShape.computeNonOverlappingPositionWithMargin(graphicalStaffEntry.PositionAndShape, ColDirEnum.Up,
+            new PointF_2D(0.0f, secondRestNote.PositionAndShape.RelativePosition.Y));
+        var relative: PointF_2D = firstRestNote.PositionAndShape.RelativePosition;
+        relative.Y -= 1.0f;
+        firstRestNote.PositionAndShape.RelativePosition = relative;
+        graphicalStaffEntry.PositionAndShape.calculateBoundingBox();
+    }
+    private calculateRestNotePlacementWithCollisionDetectionFromGraphicalNote(graphicalStaffEntry: GraphicalStaffEntry): void {
+        var restNote: GraphicalNote;
+        var graphicalNotes: List<GraphicalNote>;
+        if (graphicalStaffEntry.Notes[0][0].SourceNote.Pitch == null) {
+            restNote = graphicalStaffEntry.Notes[0][0];
+            graphicalNotes = graphicalStaffEntry.Notes[1];
+        }
+        else {
+            graphicalNotes = graphicalStaffEntry.Notes[0];
+            restNote = graphicalStaffEntry.Notes[1][0];
+        }
+        var collision: boolean = false;
+        graphicalStaffEntry.PositionAndShape.calculateAbsolutePositionsRecursiveWithoutTopelement();
+        for (var idx: number = 0, len = graphicalNotes.Count; idx < len; ++idx) {
+            var graphicalNote: GraphicalNote = graphicalNotes[idx];
+            if (restNote.PositionAndShape.marginCollisionDetection(graphicalNote.PositionAndShape)) {
+                collision = true;
+                break;
+            }
+        }
+        if (collision) {
+            if (restNote.SourceNote.ParentVoiceEntry.ParentVoice instanceof LinkedVoice) {
+                var bottomBorder: number = graphicalNotes[0].PositionAndShape.BorderMarginBottom + graphicalNotes[0].PositionAndShape.RelativePosition.Y;
+                restNote.PositionAndShape.RelativePosition = new PointF_2D(0.0f, bottomBorder - restNote.PositionAndShape.BorderMarginTop + 0.5f);
+            }
+            else {
+                if (graphicalNotes[0].SourceNote.ParentVoiceEntry.ParentVoice instanceof LinkedVoice) {
+                    var topBorder: number = graphicalNotes.Last().PositionAndShape.BorderMarginTop + graphicalNotes.Last().PositionAndShape.RelativePosition.Y;
+                    restNote.PositionAndShape.RelativePosition = new PointF_2D(0.0f, topBorder - restNote.PositionAndShape.BorderMarginBottom - 0.5f);
+                }
+                else {
+                    var topBorder: number = graphicalNotes.Last().PositionAndShape.BorderMarginTop + graphicalNotes.Last().PositionAndShape.RelativePosition.Y;
+                    var bottomBorder: number = graphicalNotes[0].PositionAndShape.BorderMarginBottom + graphicalNotes[0].PositionAndShape.RelativePosition.Y;
+                    if (bottomBorder < 2.0f)
+                    restNote.PositionAndShape.RelativePosition = new PointF_2D(0.0f, bottomBorder - restNote.PositionAndShape.BorderMarginTop + 0.5f);
+ else restNote.PositionAndShape.RelativePosition = new PointF_2D(0.0f, topBorder - restNote.PositionAndShape.BorderMarginBottom - 0.0f);
+                }
+            }
+        }
+        graphicalStaffEntry.PositionAndShape.calculateBoundingBox();
+    }
+    private calculateTieCurves(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = musicSystem.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var staffLine: StaffLine = musicSystem.StaffLines[idx3];
+                    for (var idx4: number = 0, len5 = staffLine.Measures.Count; idx4 < len5; ++idx4) {
+                        var measure: StaffMeasure = staffLine.Measures[idx4];
+                        for (var idx6: number = 0, len6 = measure.StaffEntries.Count; idx6 < len6; ++idx6) {
+                            var staffEntry: GraphicalStaffEntry = measure.StaffEntries[idx6];
+                            var graphicalTies: List<GraphicalTie> = staffEntry.GraphicalTies;
+                            for (var idx7: number = 0, len7 = graphicalTies.Count; idx7 < len7; ++idx7) {
+                                var graphicalTie: GraphicalTie = graphicalTies[idx7];
+                                if (graphicalTie.StartNote != null && graphicalTie.StartNote.ParentStaffEntry == staffEntry) {
+                                    var tieIsAtSystemBreak: boolean = (graphicalTie.StartNote.ParentStaffEntry.ParentMeasure.ParentStaffLine != graphicalTie.EndNote.ParentStaffEntry.ParentMeasure.ParentStaffLine);
+                                    this.layoutGraphicalTie(graphicalTie, tieIsAtSystemBreak);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    private calculateFingering(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = musicSystem.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var staffLine: StaffLine = musicSystem.StaffLines[idx3];
+                    var skyBottomLineCalculator: SkyBottomLineCalculator = new SkyBottomLineCalculator(this.rules);
+                    for (var idx4: number = 0, len4 = staffLine.Measures.Count; idx4 < len4; ++idx4) {
+                        var measure: StaffMeasure = staffLine.Measures[idx4];
+                        var measureRelativePosition: PointF_2D = measure.PositionAndShape.RelativePosition;
+                        for (var idx5: number = 0, len5 = measure.StaffEntries.Count; idx5 < len5; ++idx5) {
+                            var staffEntry: GraphicalStaffEntry = measure.StaffEntries[idx5];
+                            var hasTechnicalInstruction: boolean = false;
+                            for (var idx6: number = 0, len6 = staffEntry.SourceStaffEntry.VoiceEntries.Count; idx6 < len6; ++idx6) {
+                                var ve: VoiceEntry = staffEntry.SourceStaffEntry.VoiceEntries[idx6];
+                                if (ve.TechnicalInstructions.Count > 0) {
+                                    hasTechnicalInstruction = true;
+                                    break;
+                                }
+                            }
+                            if (hasTechnicalInstruction) {
+                                this.layoutFingering(staffLine, skyBottomLineCalculator, staffEntry, measureRelativePosition);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    private calculateLyricsPosition(): void {
+        for (var idx: number = 0, len = this.graphicalMusicSheet.ParentMusicSheet.Instruments.Count; idx < len; ++idx) {
+            var instrument: Instrument = this.graphicalMusicSheet.ParentMusicSheet.Instruments[idx];
+            if (instrument.HasLyrics && instrument.LyricVersesNumbers.Count > 0)
+                instrument.LyricVersesNumbers.Sort();
+        }
+        for (var idx: number = 0, len = this.graphicalMusicSheet.MusicPages.Count; idx < len; ++idx) {
+            var graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];
+            for (var idx2: number = 0, len2 = graphicalMusicPage.MusicSystems.Count; idx2 < len2; ++idx2) {
+                var musicSystem: MusicSystem = graphicalMusicPage.MusicSystems[idx2];
+                for (var idx3: number = 0, len3 = musicSystem.StaffLines.Count; idx3 < len3; ++idx3) {
+                    var staffLine: StaffLine = musicSystem.StaffLines[idx3];
+                    this.calculateSingleStaffLineLyricsPosition(staffLine, staffLine.ParentStaff.ParentInstrument.LyricVersesNumbers);
+                }
+            }
+        }
+    }
+    private calculateDynamicExpressions(): void {
+        for (var i: number = 0; i < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.Count; i++) {
+            var sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[i];
+            for (var j: number = 0; j < sourceMeasure.StaffLinkedExpressions.Count; j++) {
+                if (this.graphicalMusicSheet.MeasureList[i][j].ParentStaff.ParentInstrument.Visible)
+                    for (var k: number = 0; k < sourceMeasure.StaffLinkedExpressions[j].Count; k++)
+                        if (sourceMeasure.StaffLinkedExpressions[j][k].InstantaniousDynamic != null || (sourceMeasure.StaffLinkedExpressions[j][k].StartingContinuousDynamic != null && sourceMeasure.StaffLinkedExpressions[j][k].StartingContinuousDynamic.StartMultiExpression == sourceMeasure.StaffLinkedExpressions[j][k] && sourceMeasure.StaffLinkedExpressions[j][k].UnknownList.Count == 0)) {
+                            this.calculateDynamicExpressionsForSingleMultiExpression(sourceMeasure.StaffLinkedExpressions[j][k], i, j);
+                        }
+            }
+        }
+    }
+    private calculateOctaveShifts(): void {
+        for (var i: number = 0; i < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.Count; i++) {
+            var sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[i];
+            for (var j: number = 0; j < sourceMeasure.StaffLinkedExpressions.Count; j++) {
+                if (this.graphicalMusicSheet.MeasureList[i][j].ParentStaff.ParentInstrument.Visible)
+                    for (var k: number = 0; k < sourceMeasure.StaffLinkedExpressions[j].Count; k++)
+                        if ((sourceMeasure.StaffLinkedExpressions[j][k].OctaveShiftStart != null)) {
+                            this.calculateSingleOctaveShift(sourceMeasure, sourceMeasure.StaffLinkedExpressions[j][k], i, j);
+                        }
+            }
+        }
+    }
+    private getFirstLeftNotNullStaffEntryFromContainer(horizontalIndex: number, verticalIndex: number, multiStaffInstrument: boolean): GraphicalStaffEntry {
+        if (this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[horizontalIndex].StaffEntries[verticalIndex] != null)
+            return this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[horizontalIndex].StaffEntries[verticalIndex];
+        for (var i: number = horizontalIndex - 1; i >= 0; i--)
+            if (this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[i].StaffEntries[verticalIndex] != null)
+                return this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[i].StaffEntries[verticalIndex];
+        return null;
+    }
+    private getFirstRightNotNullStaffEntryFromContainer(horizontalIndex: number, verticalIndex: number, multiStaffInstrument: boolean): GraphicalStaffEntry {
+        if (this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[horizontalIndex].StaffEntries[verticalIndex] != null)
+            return this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[horizontalIndex].StaffEntries[verticalIndex];
+        for (var i: number = horizontalIndex + 1; i < this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers.Count; i++)
+            if (this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[i].StaffEntries[verticalIndex] != null)
+                return this.graphicalMusicSheet.VerticalGraphicalStaffEntryContainers[i].StaffEntries[verticalIndex];
+        return null;
+    }
+    private calculateWordRepetitionInstructions(): void {
+        for (var i: number = 0; i < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.Count; i++) {
+            var sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[i];
+            for (var idx: number = 0, len = sourceMeasure.FirstRepetitionInstructions.Count; idx < len; ++idx) {
+                var instruction: RepetitionInstruction = sourceMeasure.FirstRepetitionInstructions[idx];
+                this.calculateWordRepetitionInstruction(instruction, i);
+            }
+            for (var idx: number = 0, len = sourceMeasure.LastRepetitionInstructions.Count; idx < len; ++idx) {
+                var instruction: RepetitionInstruction = sourceMeasure.LastRepetitionInstructions[idx];
+                this.calculateWordRepetitionInstruction(instruction, i);
+            }
+        }
+    }
+    private calculateRepetitionEndings(): void {
+        var musicsheet: MusicSheet = this.graphicalMusicSheet.ParentMusicSheet;
+        for (var idx: number = 0, len = musicsheet.Repetitions.Count; idx < len; ++idx) {
+            var partListEntry: Repetition = musicsheet.Repetitions[idx];
+            this.calcGraphicalRepetitionEndingsRecursively(partListEntry);
+        }
+    }
+    private calculateTempoExpressions(): void {
+        for (var i: number = 0; i < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.Count; i++) {
+            var sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[i];
+            for (var j: number = 0; j < sourceMeasure.TempoExpressions.Count; j++) {
+                this.calculateTempoExpressionsForSingleMultiTempoExpression(sourceMeasure, sourceMeasure.TempoExpressions[j], i);
+            }
+        }
+    }
+    private calculateMoodAndUnknownExpressions(): void {
+        for (var i: number = 0; i < this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.Count; i++) {
+            var sourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures[i];
+            for (var j: number = 0; j < sourceMeasure.StaffLinkedExpressions.Count; j++) {
+                if (this.graphicalMusicSheet.MeasureList[i][j].ParentStaff.ParentInstrument.Visible)
+                    for (var k: number = 0; k < sourceMeasure.StaffLinkedExpressions[j].Count; k++)
+                        if ((sourceMeasure.StaffLinkedExpressions[j][k].MoodList.Count > 0) || (sourceMeasure.StaffLinkedExpressions[j][k].UnknownList.Count > 0)) {
+                            this.calculateMoodAndUnknownExpression(sourceMeasure.StaffLinkedExpressions[j][k], i, j);
+                        }
+            }
+        }
+    }
+}

+ 171 - 0
src/MusicalScore/Graphical/MusicSymbol.ts

@@ -0,0 +1,171 @@
+export enum MusicSymbol {
+    Unused_first_Symbol,
+
+    BLACK_HEAD,
+
+    UPWARDS_TAIL,
+
+    DOWNWARDS_TAIL,
+
+    UPWARDS_DOUBLE_TAIL,
+
+    DOWNWARDS_DOUBLE_TAIL,
+
+    UPWARDS_TRIPLE_TAIL,
+
+    DOWNWARDS_TRIPLE_TAIL,
+
+    UPWARDS_QUAD_TAIL,
+
+    DOWNWARDS_QUAD_TAIL,
+
+    ROUND_HEAD,
+
+    WHITE_HEAD,
+
+    G_CLEF,
+
+    F_CLEF,
+
+    C_CLEF,
+
+    BREVE,
+
+    BREVE_REST,
+
+    COMMON_TIME,
+
+    CUT_TIME,
+
+    WHOLE_REST,
+
+    HALF_REST,
+
+    QUARTER_REST,
+
+    EIGHTH_REST,
+
+    SIXTEENTH_REST,
+
+    THIRTYSECOND_REST,
+
+    SIXTYFOURTH_REST,
+
+    FLAT,
+
+    SHARP,
+
+    NATURAL,
+
+    DOUBLE_FLAT,
+
+    DOUBLE_SHARP,
+
+    ZERO,
+
+    ONE,
+
+    TWO,
+
+    THREE,
+
+    FOUR,
+
+    FIVE,
+
+    SIX,
+
+    SEVEN,
+
+    EIGHT,
+
+    NINE,
+
+    DOT,
+
+    FERMATA,
+
+    INVERTED_FERMATA,
+
+    SPICCATO,
+
+    TENUTO,
+
+    MARCATO,
+
+    MARCATISSIMO,
+
+    INVERTED_MARCATISSIMO,
+
+    P,
+
+    F,
+
+    S,
+
+    Z,
+
+    M,
+
+    R,
+
+    SEGNO,
+
+    CODA,
+
+    DRUM_CLEF,
+
+    G_CLEF_SUB8,
+
+    G_CLEF_SUPER8,
+
+    G_CLEF_SUB15,
+
+    G_CLEF_SUPER15,
+
+    F_CLEF_SUB8,
+
+    F_CLEF_SUPER8,
+
+    F_CLEF_SUB15,
+
+    F_CLEF_SUPER15,
+
+    DOWN_BOW,
+
+    MORDENT,
+
+    INVERTED_MORDENT,
+
+    TURN,
+
+    INVERTED_TURN,
+
+    LEFTHAND_PIZZICATO,
+
+    RELEASE_PED,
+
+    ENGAGE_PED,
+
+    VA8,
+
+    VB8,
+
+    TRILL,
+
+    MA15,
+
+    MB15,
+
+    HIGH,
+
+    PLAY,
+
+    MIC,
+
+    SNAP_PIZZICATO,
+
+    NATURAL_HARMONIC,
+
+    EditPen
+}

+ 2 - 1
src/MusicalScore/Graphical/MusicSystem.ts

@@ -11,6 +11,7 @@ import {StaffMeasure} from "./StaffMeasure";
 import {GraphicalObject} from "./GraphicalObject";
 import {EngravingRules} from "./EngravingRules";
 import {PointF_2D} from "../../Common/DataObjects/PointF_2D";
+import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
 export class MusicSystem extends GraphicalObject {
     public NeedsToBeRedrawn: boolean = true;
     protected parent: GraphicalMusicPage;
@@ -129,7 +130,7 @@ export class MusicSystem extends GraphicalObject {
             }
             if (instrumentGroup.InstrumentalGroups.Count < 1)
                 continue;
-            createGroupBrackets(instrumentGroup.InstrumentalGroups, staffHeight, recursionDepth + 1);
+            this.createGroupBrackets(instrumentGroup.InstrumentalGroups, staffHeight, recursionDepth + 1);
         }
     }
     public createMusicSystemLabel(instrumentLabelTextHeight: number, systemLabelsRightMargin: number, labelMarginBorderFactor: number): void {

+ 690 - 0
src/MusicalScore/Graphical/MusicSystemBuilder.ts

@@ -0,0 +1,690 @@
+import {StaffMeasure} from "./StaffMeasure";
+import {GraphicalMusicPage} from "./GraphicalMusicPage";
+import {EngravingRules} from "./EngravingRules";
+import {RhythmInstruction} from "../VoiceData/Instructions/RhythmInstruction";
+import {KeyInstruction} from "../VoiceData/Instructions/KeyInstruction";
+import {ClefInstruction} from "../VoiceData/Instructions/ClefInstruction";
+import {SourceMeasure} from "../VoiceData/SourceMeasure";
+import {MusicSystem} from "./MusicSystem";
+import {BoundingBox} from "./BoundingBox";
+import {Staff} from "../VoiceData/Staff";
+import {MusicSheet} from "../MusicSheet";
+import {Instrument} from "../Instrument";
+import {PointF_2D} from "../../Common/DataObjects/PointF_2D";
+import {StaffLine} from "./StaffLine";
+import {GraphicalLine} from "./GraphicalLine";
+import {SourceStaffEntry} from "../VoiceData/SourceStaffEntry";
+import {AbstractNotationInstruction} from "../VoiceData/Instructions/AbstractNotationInstruction";
+import {SystemLinesEnum} from "./SystemLinesEnum";
+export class MusicSystemBuilder {
+    private measureList: List<List<StaffMeasure>>;
+    private graphicalMusicSheet: GraphicalMusicSheet;
+    private currentMusicPage: GraphicalMusicPage;
+    private currentPageHeight: number;
+    private currentSystemParams: SystemBuildParameters;
+    private numberOfVisibleStaffLines: number;
+    private rules: EngravingRules;
+    private measureListIndex: number;
+    private visibleStaffIndices: number[];
+    private activeRhythm: RhythmInstruction[];
+    private activeKeys: KeyInstruction[];
+    private activeClefs: ClefInstruction[];
+    private globalSystemIndex: number = 0;
+    private leadSheet: boolean = false;
+    private symbolFactory: IGraphicalSymbolFactory;
+    public initialize(graphicalMusicSheet: GraphicalMusicSheet, measureList: List<List<StaffMeasure>>,
+        numberOfStaffLines: number, symbolFactory: IGraphicalSymbolFactory): void {
+        this.leadSheet = graphicalMusicSheet.LeadSheet;
+        this.graphicalMusicSheet = graphicalMusicSheet;
+        this.rules = this.graphicalMusicSheet.ParentMusicSheet.Rules;
+        this.measureList = measureList;
+        this.symbolFactory = symbolFactory;
+        this.currentMusicPage = this.createMusicPage();
+        this.currentPageHeight = 0.0f;
+        this.numberOfVisibleStaffLines = numberOfStaffLines;
+        this.activeRhythm = new Array(this.numberOfVisibleStaffLines);
+        this.activeKeys = new Array(this.numberOfVisibleStaffLines);
+        this.activeClefs = new Array(this.numberOfVisibleStaffLines);
+        initializeActiveInstructions(this.measureList[0]);
+    }
+    public buildMusicSystems(): void {
+        var previousMeasureEndsSystem: boolean = false;
+        var systemMaxWidth: number = this.getFullPageSystemWidth();
+        this.measureListIndex = 0;
+        this.currentSystemParams = new SystemBuildParameters();
+        this.currentSystemParams.currentSystem = this.initMusicSystem();
+        this.layoutSystemStaves();
+        this.currentSystemParams.currentSystem.createMusicSystemLabel(this.rules.InstrumentLabelTextHeight,
+            this.rules.SystemLabelsRightMargin,
+            this.rules.LabelMarginBorderFactor);
+        this.currentPageHeight += this.currentSystemParams.currentSystem.PositionAndShape.RelativePosition.Y;
+        var numberOfMeasures: number = this.measureList.Count(m => m.Any());
+        while (this.measureListIndex < numberOfMeasures) {
+            var staffMeasures: List<StaffMeasure> = this.measureList[this.measureListIndex];
+            for (var idx: number = 0, len = staffMeasures.Count; idx < len; ++idx)
+                staffMeasures[idx].ResetLayout();
+            var sourceMeasure: SourceMeasure = staffMeasures[0].ParentSourceMeasure;
+            var sourceMeasureEndsSystem: boolean = sourceMeasure.BreakSystemAfter;
+            var isSystemStartMeasure: boolean = this.currentSystemParams.IsSystemStartMeasure();
+            var isFirstSourceMeasure: boolean = sourceMeasure == this.graphicalMusicSheet.ParentMusicSheet.getFirstSourceMeasure();
+            var currentMeasureBeginInstructionsWidth: number = this.rules.MeasureLeftMargin;
+            var currentMeasureEndInstructionsWidth: number = 0;
+            var measureStartLine: SystemLinesEnum = this.getMeasureStartLine();
+            currentMeasureBeginInstructionsWidth += getLineWidth(staffMeasures[0], measureStartLine, isSystemStartMeasure);
+            if (!this.leadSheet) {
+                currentMeasureBeginInstructionsWidth += this.addBeginInstructions(staffMeasures, isSystemStartMeasure, isFirstSourceMeasure);
+                currentMeasureEndInstructionsWidth += this.addEndInstructions(staffMeasures);
+            }
+            var currentMeasureVarWidth: number = 0;
+            for (var i: number = 0; i < this.numberOfVisibleStaffLines; i++)
+                currentMeasureVarWidth = Math.Max(currentMeasureVarWidth, staffMeasures[i].MinimumStaffEntriesWidth);
+            var measureEndLine: SystemLinesEnum = this.getMeasureEndLine();
+            currentMeasureEndInstructionsWidth += getLineWidth(staffMeasures[0], measureEndLine, isSystemStartMeasure);
+            var nextMeasureBeginInstructionWidth: number = this.rules.MeasureLeftMargin;
+            if (this.measureListIndex + 1 < this.measureList.Count) {
+                var nextStaffMeasures: List<StaffMeasure> = this.measureList[this.measureListIndex + 1];
+                var nextSourceMeasure: SourceMeasure = nextStaffMeasures[0].ParentSourceMeasure;
+                if (nextSourceMeasure.hasBeginInstructions()) {
+                    nextMeasureBeginInstructionWidth += this.addBeginInstructions(nextStaffMeasures, false, false);
+                }
+            }
+            var totalMeasureWidth: number = currentMeasureBeginInstructionsWidth + currentMeasureEndInstructionsWidth + currentMeasureVarWidth;
+            var measureFitsInSystem: boolean = this.currentSystemParams.currentWidth + totalMeasureWidth + nextMeasureBeginInstructionWidth < systemMaxWidth;
+            if (isSystemStartMeasure || measureFitsInSystem) {
+                this.addMeasureToSystem(staffMeasures, measureStartLine, measureEndLine, totalMeasureWidth, currentMeasureBeginInstructionsWidth, currentMeasureVarWidth, currentMeasureEndInstructionsWidth);
+                this.updateActiveClefs(sourceMeasure, staffMeasures);
+                this.measureListIndex++;
+            }
+            else {
+                this.finalizeCurrentAndCreateNewSystem(staffMeasures, previousMeasureEndsSystem);
+            }
+            previousMeasureEndsSystem = sourceMeasureEndsSystem;
+        }
+        finalizeCurrentAndCreateNewSystem(this.measureList[this.measureList.Count - 1], true);
+    }
+    private setMeasureWidth(staffMeasures: List<StaffMeasure>, width: number, beginInstrWidth: number, endInstrWidth: number): void {
+        for (var idx: number = 0, len = staffMeasures.Count; idx < len; ++idx) {
+            var measure: StaffMeasure = staffMeasures[idx];
+            measure.SetWidth(width);
+            if (beginInstrWidth > 0)
+                measure.BeginInstructionsWidth = beginInstrWidth;
+            if (endInstrWidth > 0)
+                measure.EndInstructionsWidth = endInstrWidth;
+        }
+    }
+    private finalizeCurrentAndCreateNewSystem(measures: List<StaffMeasure>, isPartEndingSystem: boolean = false): void {
+        this.adaptRepetitionLineWithIfNeeded();
+        if (!isPartEndingSystem) {
+            this.checkAndCreateExtraInstructionMeasure(measures);
+        }
+        this.stretchMusicSystem(isPartEndingSystem);
+        if (this.currentPageHeight + this.currentSystemParams.currentSystem.PositionAndShape.Size.Height + this.rules.SystemDistance <= this.rules.PageHeight) {
+            this.currentPageHeight += this.currentSystemParams.currentSystem.PositionAndShape.Size.Height + this.rules.SystemDistance;
+            if (this.currentPageHeight + this.currentSystemParams.currentSystem.PositionAndShape.Size.Height + this.rules.SystemDistance >= this.rules.PageHeight) {
+                this.currentMusicPage = this.createMusicPage();
+                this.currentPageHeight = this.rules.PageTopMargin + this.rules.TitleTopDistance;
+            }
+        }
+        else {
+            this.currentMusicPage = this.createMusicPage();
+            this.currentPageHeight = this.rules.PageTopMargin + this.rules.TitleTopDistance;
+        }
+        this.currentSystemParams = new SystemBuildParameters();
+        if (this.measureListIndex < this.measureList.Count) {
+            this.currentSystemParams.currentSystem = this.initMusicSystem();
+            this.layoutSystemStaves();
+        }
+    }
+    private adaptRepetitionLineWithIfNeeded(): void {
+        var systemMeasures: List<MeasureBuildParameters> = this.currentSystemParams.systemMeasures;
+        if (systemMeasures.Count >= 1) {
+            var measures: List<StaffMeasure> = this.currentSystemParams.currentSystem.GraphicalMeasures[this.currentSystemParams.currentSystem.GraphicalMeasures.Count - 1];
+            var measureParams: MeasureBuildParameters = systemMeasures[systemMeasures.Count - 1];
+            var diff: number = 0.0f;
+            if (measureParams.endLine == SystemLinesEnum.DotsBoldBoldDots) {
+                measureParams.endLine = SystemLinesEnum.DotsThinBold;
+                diff = measures[0].GetLineWidth(SystemLinesEnum.DotsBoldBoldDots) / 2 - measures[0].GetLineWidth(SystemLinesEnum.DotsThinBold);
+            }
+            this.currentSystemParams.currentSystemFixWidth -= diff;
+            for (var idx: number = 0, len = measures.Count; idx < len; ++idx) {
+                var measure: StaffMeasure = measures[idx];
+                measure.EndInstructionsWidth -= diff;
+            }
+        }
+    }
+    private addMeasureToSystem(staffMeasures: List<StaffMeasure>, measureStartLine: SystemLinesEnum, measureEndLine: SystemLinesEnum, totalMeasureWidth: number, currentMeasureBeginInstructionsWidth: number, currentVarWidth: number, currentMeasureEndInstructionsWidth: number): void {
+        this.currentSystemParams.systemMeasures.Add(__init(new MeasureBuildParameters(), { beginLine: measureStartLine, endLine: measureEndLine }));
+        this.setMeasureWidth(staffMeasures, totalMeasureWidth, currentMeasureBeginInstructionsWidth,
+            currentMeasureEndInstructionsWidth);
+        this.addStaveMeasuresToSystem(staffMeasures);
+        this.currentSystemParams.currentWidth += totalMeasureWidth;
+        this.currentSystemParams.currentSystemFixWidth += currentMeasureBeginInstructionsWidth + currentMeasureEndInstructionsWidth;
+        this.currentSystemParams.currentSystemVarWidth += currentVarWidth;
+        this.currentSystemParams.systemMeasureIndex++;
+    }
+    private createMusicPage(): GraphicalMusicPage {
+        var page: GraphicalMusicPage = new GraphicalMusicPage(this.graphicalMusicSheet);
+        this.graphicalMusicSheet.MusicPages.Add(page);
+        page.PositionAndShape.BorderLeft = 0.0f;
+        page.PositionAndShape.BorderRight = this.graphicalMusicSheet.ParentMusicSheet.PageWidth;
+        page.PositionAndShape.BorderTop = 0.0f;
+        page.PositionAndShape.BorderBottom = this.rules.PageHeight;
+        page.PositionAndShape.RelativePosition = new PointF_2D(0.0f, 0.0f);
+        return page;
+    }
+    private initMusicSystem(): MusicSystem {
+        var musicSystem: MusicSystem = this.symbolFactory.createMusicSystem(this.currentMusicPage, this.globalSystemIndex++);
+        this.currentMusicPage.MusicSystems.Add(musicSystem);
+        var boundingBox: BoundingBox = musicSystem.PositionAndShape;
+        this.currentMusicPage.PositionAndShape.ChildElements.Add(boundingBox);
+        return musicSystem;
+    }
+    private getFullPageSystemWidth(): number {
+        return this.currentMusicPage.PositionAndShape.Size.Width - this.rules.PageLeftMargin - this.rules.PageRightMargin - this.rules.SystemLeftMargin - this.rules.SystemRightMargin;
+    }
+    private layoutSystemStaves(): void {
+        var systemWidth: number = this.getFullPageSystemWidth();
+        var musicSystem: MusicSystem = this.currentSystemParams.currentSystem;
+        var boundingBox: BoundingBox = musicSystem.PositionAndShape;
+        boundingBox.BorderLeft = 0.0f;
+        boundingBox.BorderRight = systemWidth;
+        boundingBox.BorderTop = 0.0f;
+        var staffList: List<Staff> = new List<Staff>();
+        var musicSheet: MusicSheet = this.graphicalMusicSheet.ParentMusicSheet;
+        var instruments: Instrument[] = musicSheet.Instruments.Where(i => i.Voices.Count > 0 && i.Voices[0].Visible).ToArray();
+        for (var idx: number = 0, len = instruments.length; idx < len; ++idx) {
+            var instrument: Instrument = instruments[idx];
+            for (var idx2: number = 0, len2 = instrument.Staves.Count; idx2 < len2; ++idx2) {
+                var staff: Staff = instrument.Staves[idx2];
+                staffList.Add(staff);
+            }
+        }
+        var multiLyrics: boolean = false;
+        if (this.leadSheet) {
+            for (var idx: number = 0, len = staffList.Count; idx < len; ++idx) {
+                var staff: Staff = staffList[idx];
+                if (staff.ParentInstrument.LyricVersesNumbers.Count > 1) {
+                    multiLyrics = true;
+                    break;
+                }
+            }
+        }
+        var yOffsetSum: number = 0;
+        for (var i: number = 0; i < staffList.Count; i++) {
+            this.addStaffLineToMusicSystem(musicSystem, yOffsetSum, staffList[i]);
+            yOffsetSum += this.rules.StaffHeight;
+            if (i + 1 < staffList.Count) {
+                var yOffset: number = 0;
+                if (this.leadSheet && !multiLyrics) {
+                    yOffset = 2.5f;
+                }
+                else {
+                    if (staffList[i].ParentInstrument == staffList[i + 1].ParentInstrument)
+                        yOffset = this.rules.BetweenStaffDistance;
+                    else yOffset = this.rules.StaffDistance;
+                }
+                yOffsetSum += yOffset;
+            }
+        }
+        boundingBox.BorderBottom = yOffsetSum;
+    }
+    private addStaffLineToMusicSystem(musicSystem: MusicSystem, relativeYPosition: number, staff: Staff): void {
+        if (musicSystem != null) {
+            var staffLine: StaffLine = this.symbolFactory.createStaffLine(musicSystem, staff);
+            musicSystem.StaffLines.Add(staffLine);
+            var boundingBox: BoundingBox = staffLine.PositionAndShape;
+            musicSystem.PositionAndShape.ChildElements.Add(boundingBox);
+            var relativePosition: PointF_2D = new PointF_2D();
+            if (musicSystem.Parent.MusicSystems[0] == musicSystem && musicSystem.Parent == musicSystem.Parent.Parent.MusicPages[0])
+                relativePosition.X = this.rules.FirstSystemMargin;
+            else relativePosition.X = 0.0f;
+            relativePosition.Y = relativeYPosition;
+            boundingBox.RelativePosition = relativePosition;
+            if (musicSystem.Parent.MusicSystems[0] == musicSystem && musicSystem.Parent == musicSystem.Parent.Parent.MusicPages[0])
+                boundingBox.BorderRight = musicSystem.PositionAndShape.Size.Width - this.rules.FirstSystemMargin;
+            else boundingBox.BorderRight = musicSystem.PositionAndShape.Size.Width;
+            boundingBox.BorderLeft = 0.0f;
+            boundingBox.BorderTop = 0.0f;
+            boundingBox.BorderBottom = this.rules.StaffHeight;
+            for (var i: number = 0; i < 5; i++) {
+                var start: PointF_2D = new PointF_2D();
+                start.X = 0.0f;
+                start.Y = i * this.rules.StaffHeight / 4;
+                var end: PointF_2D = new PointF_2D();
+                end.X = staffLine.PositionAndShape.Size.Width;
+                end.Y = i * this.rules.StaffHeight / 4;
+                if (this.leadSheet)
+                    start.Y = end.Y = 0;
+                staffLine.StaffLines[i] = new GraphicalLine(start, end, this.rules.StaffLineWidth);
+            }
+        }
+    }
+    private initializeActiveInstructions(measureList: List<StaffMeasure>): void {
+        var firstSourceMeasure: SourceMeasure = this.graphicalMusicSheet.ParentMusicSheet.getFirstSourceMeasure();
+        if (firstSourceMeasure != null) {
+            this.visibleStaffIndices = this.graphicalMusicSheet.getVisibleStavesIndecesFromSourceMeasure(measureList).ToArray();
+            for (var i: number = 0, len = this.visibleStaffIndices.length; i < len; i++) {
+                var staffIndex: number = this.visibleStaffIndices[i];
+                var graphicalMeasure: StaffMeasure = this.graphicalMusicSheet.getGraphicalMeasureFromSourceMeasureAndIndex(firstSourceMeasure, staffIndex);
+                this.activeClefs[i] = <ClefInstruction>firstSourceMeasure.FirstInstructionsStaffEntries[staffIndex].Instructions[0];
+                var keyInstruction: KeyInstruction = new KeyInstruction(<KeyInstruction>firstSourceMeasure.FirstInstructionsStaffEntries[staffIndex].Instructions[1]);
+                keyInstruction = this.transposeKeyInstruction(keyInstruction, graphicalMeasure);
+                this.activeKeys[i] = keyInstruction;
+                this.activeRhythm[i] = <RhythmInstruction>firstSourceMeasure.FirstInstructionsStaffEntries[staffIndex].Instructions[2];
+            }
+        }
+    }
+    private transposeKeyInstruction(keyInstruction: KeyInstruction, graphicalMeasure: StaffMeasure): KeyInstruction {
+        if (this.graphicalMusicSheet.ParentMusicSheet.Transpose != 0 && graphicalMeasure.ParentStaff.ParentInstrument.MidiInstrumentId != Common.Enums.MidiInstrument.Percussion && MusicSheetCalculator.TransposeCalculator != null)
+            MusicSheetCalculator.TransposeCalculator.TransposeKey(keyInstruction,
+                this.graphicalMusicSheet.ParentMusicSheet.Transpose);
+        return keyInstruction;
+    }
+    private addBeginInstructions(measures: List<StaffMeasure>, isSystemFirstMeasure: boolean, isFirstSourceMeasure: boolean): number {
+        var measureCount: number = measures.Count;
+        if (measureCount == 0)
+            return 0;
+        var totalBeginInstructionLengthX: number = 0.0f;
+        var sourceMeasure: SourceMeasure = measures[0].ParentSourceMeasure;
+        for (var idx: number = 0; idx < measureCount; ++idx) {
+            var measure: StaffMeasure = measures[idx];
+            var staffIndex: number = this.visibleStaffIndices[idx];
+            var beginInstructionsStaffEntry: SourceStaffEntry = sourceMeasure.FirstInstructionsStaffEntries[staffIndex];
+            var beginInstructionLengthX: number = this.AddInstructionsAtMeasureBegin(beginInstructionsStaffEntry, measure,
+                idx, isFirstSourceMeasure,
+                isSystemFirstMeasure);
+            totalBeginInstructionLengthX = Math.Max(totalBeginInstructionLengthX, beginInstructionLengthX);
+        }
+        return totalBeginInstructionLengthX;
+    }
+    private addEndInstructions(measures: List<StaffMeasure>): number {
+        var measureCount: number = measures.Count;
+        if (measureCount == 0)
+            return 0;
+        var totalEndInstructionLengthX: number = 0.5f;
+        var sourceMeasure: SourceMeasure = measures[0].ParentSourceMeasure;
+        for (var idx: number = 0; idx < measureCount; idx++) {
+            var measure: StaffMeasure = measures[idx];
+            var staffIndex: number = this.visibleStaffIndices[idx];
+            var endInstructionsStaffEntry: SourceStaffEntry = sourceMeasure.LastInstructionsStaffEntries[staffIndex];
+            var endInstructionLengthX: number = this.addInstructionsAtMeasureEnd(endInstructionsStaffEntry, measure);
+            totalEndInstructionLengthX = Math.Max(totalEndInstructionLengthX, endInstructionLengthX);
+        }
+        return totalEndInstructionLengthX;
+    }
+    private AddInstructionsAtMeasureBegin(firstEntry: SourceStaffEntry, measure: StaffMeasure,
+        visibleStaffIdx: number, isFirstSourceMeasure: boolean, isSystemStartMeasure: boolean): number {
+        var instructionsLengthX: number = 0;
+        var currentClef: ClefInstruction = null;
+        var currentKey: KeyInstruction = null;
+        var currentRhythm: RhythmInstruction = null;
+        if (firstEntry != null) {
+            for (var idx: number = 0, len = firstEntry.Instructions.Count; idx < len; ++idx) {
+                var abstractNotationInstruction: AbstractNotationInstruction = firstEntry.Instructions[idx];
+                if (abstractNotationInstruction instanceof ClefInstruction) {
+                    currentClef = <ClefInstruction>abstractNotationInstruction;
+                }
+                else if (abstractNotationInstruction instanceof KeyInstruction) {
+                    currentKey = <KeyInstruction>abstractNotationInstruction;
+                }
+                else if (abstractNotationInstruction instanceof RhythmInstruction) {
+                    currentRhythm = <RhythmInstruction>abstractNotationInstruction;
+                }
+            }
+        }
+        if (isSystemStartMeasure) {
+            if (currentClef == null) {
+                currentClef = this.activeClefs[visibleStaffIdx];
+            }
+            if (currentKey == null) {
+                currentKey = this.activeKeys[visibleStaffIdx];
+            }
+            if (isFirstSourceMeasure && currentRhythm == null) {
+                currentRhythm = this.activeRhythm[visibleStaffIdx];
+            }
+        }
+        var clefAdded: boolean = false;
+        var keyAdded: boolean = false;
+        var rhythmAdded: boolean = false;
+        if (currentClef != null) {
+            measure.AddClefAtBegin(currentClef);
+            clefAdded = true;
+        }
+        else {
+            currentClef = this.activeClefs[visibleStaffIdx];
+        }
+        if (currentKey != null) {
+            currentKey = this.transposeKeyInstruction(currentKey, measure);
+            var previousKey: KeyInstruction = isSystemStartMeasure ? null : this.activeKeys[visibleStaffIdx];
+            measure.AddKeyAtBegin(currentKey, previousKey, currentClef);
+            keyAdded = true;
+        }
+        if (currentRhythm != null) {
+            measure.AddRhythmAtBegin(currentRhythm);
+            rhythmAdded = true;
+        }
+        if (clefAdded || keyAdded || rhythmAdded) {
+            instructionsLengthX += measure.BeginInstructionsWidth;
+            if (rhythmAdded)
+                instructionsLengthX += this.rules.RhythmRightMargin;
+        }
+        return instructionsLengthX;
+    }
+    private addInstructionsAtMeasureEnd(lastEntry: SourceStaffEntry, measure: StaffMeasure): number {
+        if (lastEntry == null || lastEntry.Instructions == null || lastEntry.Instructions.Count == 0)
+            return 0;
+        for (var idx: number = 0, len = lastEntry.Instructions.Count; idx < len; ++idx) {
+            var abstractNotationInstruction: AbstractNotationInstruction = lastEntry.Instructions[idx];
+            if (abstractNotationInstruction instanceof ClefInstruction) {
+                var activeClef: ClefInstruction = <ClefInstruction>abstractNotationInstruction;
+                measure.AddClefAtEnd(activeClef);
+            }
+        }
+        return this.rules.MeasureRightMargin + measure.EndInstructionsWidth;
+    }
+    private updateActiveClefs(measure: SourceMeasure, staffMeasures: List<StaffMeasure>): void {
+        for (var visStaffIdx: number = 0, len = staffMeasures.Count; visStaffIdx < len; visStaffIdx++) {
+            var staffIndex: number = this.visibleStaffIndices[visStaffIdx];
+            var firstEntry: SourceStaffEntry = measure.FirstInstructionsStaffEntries[staffIndex];
+            if (firstEntry != null) {
+                for (var idx: number = 0, len2 = firstEntry.Instructions.Count; idx < len2; ++idx) {
+                    var abstractNotationInstruction: AbstractNotationInstruction = firstEntry.Instructions[idx];
+                    if (abstractNotationInstruction instanceof ClefInstruction) {
+                        this.activeClefs[visStaffIdx] = <ClefInstruction>abstractNotationInstruction;
+                    }
+                    else if (abstractNotationInstruction instanceof KeyInstruction) {
+                        this.activeKeys[visStaffIdx] = <KeyInstruction>abstractNotationInstruction;
+                    }
+                    else if (abstractNotationInstruction instanceof RhythmInstruction) {
+                        this.activeRhythm[visStaffIdx] = <RhythmInstruction>abstractNotationInstruction;
+                    }
+                }
+            }
+            var entries: List<SourceStaffEntry> = measure.getEntriesPerStaff(staffIndex);
+            for (var idx: number = 0, len2 = entries.Count; idx < len2; ++idx) {
+                var staffEntry: SourceStaffEntry = entries[idx];
+                if (staffEntry.Instructions != null) {
+                    for (var idx2: number = 0, len3 = staffEntry.Instructions.Count; idx2 < len3; ++idx2) {
+                        var abstractNotationInstruction: AbstractNotationInstruction = staffEntry.Instructions[idx2];
+                        if (abstractNotationInstruction instanceof ClefInstruction) {
+                            this.activeClefs[visStaffIdx] = <ClefInstruction>abstractNotationInstruction;
+                        }
+                    }
+                }
+            }
+            var lastEntry: SourceStaffEntry = measure.LastInstructionsStaffEntries[staffIndex];
+            if (lastEntry != null) {
+                var instructions: List<AbstractNotationInstruction> = lastEntry.Instructions;
+                for (var idx: number = 0, len3 = instructions.Count; idx < len3; ++idx) {
+                    var abstractNotationInstruction: AbstractNotationInstruction = instructions[idx];
+                    if (abstractNotationInstruction instanceof ClefInstruction) {
+                        this.activeClefs[visStaffIdx] = <ClefInstruction>abstractNotationInstruction;
+                    }
+                }
+            }
+        }
+    }
+    private checkAndCreateExtraInstructionMeasure(measures: List<StaffMeasure>): void {
+        var firstStaffEntries: List<SourceStaffEntry> = measures[0].ParentSourceMeasure.FirstInstructionsStaffEntries;
+        var visibleInstructionEntries: List<SourceStaffEntry> = new List<SourceStaffEntry>();
+        for (var idx: number = 0, len = measures.Count; idx < len; ++idx) {
+            var measure: StaffMeasure = measures[idx];
+            visibleInstructionEntries.Add(firstStaffEntries[measure.ParentStaff.IdInMusicSheet]);
+        }
+        var maxMeasureWidth: number = 0;
+        for (var visStaffIdx: number = 0, len = visibleInstructionEntries.Count; visStaffIdx < len; ++visStaffIdx) {
+            var sse: SourceStaffEntry = visibleInstructionEntries[visStaffIdx];
+            if (sse == null)
+                continue;
+            var instructions: List<AbstractNotationInstruction> = sse.Instructions;
+            var keyInstruction: KeyInstruction = null;
+            var rhythmInstruction: RhythmInstruction = null;
+            for (var idx2: number = 0, len2 = instructions.Count; idx2 < len2; ++idx2) {
+                var instruction: AbstractNotationInstruction = instructions[idx2];
+                if (instruction instanceof KeyInstruction && (<KeyInstruction>instruction).Key != this.activeKeys[visStaffIdx].Key)
+                    keyInstruction = <KeyInstruction>instruction;
+                if (instruction instanceof RhythmInstruction && (<RhythmInstruction>instruction) != this.activeRhythm[visStaffIdx])
+                    rhythmInstruction = <RhythmInstruction>instruction;
+            }
+            if (keyInstruction != null || rhythmInstruction != null) {
+                var measureWidth: number = this.addExtraInstructionMeasure(visStaffIdx, keyInstruction, rhythmInstruction);
+                maxMeasureWidth = Math.Max(maxMeasureWidth, measureWidth);
+            }
+        }
+        if (maxMeasureWidth > 0) {
+            this.currentSystemParams.systemMeasures.Add(__init(new MeasureBuildParameters(), { beginLine: SystemLinesEnum.None, endLine: SystemLinesEnum.None }));
+            this.currentSystemParams.currentWidth += maxMeasureWidth;
+            this.currentSystemParams.currentSystemFixWidth += maxMeasureWidth;
+        }
+    }
+    private addExtraInstructionMeasure(visStaffIdx: number, keyInstruction: KeyInstruction, rhythmInstruction: RhythmInstruction): number {
+        var currentSystem: MusicSystem = this.currentSystemParams.currentSystem;
+        var measures: List<StaffMeasure> = new List<StaffMeasure>();
+        var measure: StaffMeasure = this.symbolFactory.createExtraStaffMeasure(currentSystem.StaffLines[visStaffIdx]);
+        measures.Add(measure);
+        if (keyInstruction != null) {
+            measure.AddKeyAtBegin(keyInstruction, this.activeKeys[visStaffIdx], this.activeClefs[visStaffIdx]);
+        }
+        if (rhythmInstruction != null) {
+            measure.AddRhythmAtBegin(rhythmInstruction);
+        }
+        measure.PositionAndShape.BorderLeft = 0.0f;
+        measure.PositionAndShape.BorderTop = 0.0f;
+        measure.PositionAndShape.BorderBottom = this.rules.StaffHeight;
+        var width: number = this.rules.MeasureLeftMargin + measure.BeginInstructionsWidth + this.rules.MeasureRightMargin;
+        measure.PositionAndShape.BorderRight = width;
+        currentSystem.StaffLines[visStaffIdx].Measures.Add(measure);
+        measure.ParentStaffLine = currentSystem.StaffLines[visStaffIdx];
+        currentSystem.StaffLines[visStaffIdx].PositionAndShape.ChildElements.Add(measure.PositionAndShape);
+        return width;
+    }
+    private addStaveMeasuresToSystem(staffMeasures: List<StaffMeasure>): void {
+        if (staffMeasures[0] != null) {
+            var gmeasures: List<StaffMeasure> = new List<StaffMeasure>();
+            for (var i: number = 0; i < staffMeasures.Count; i++)
+                gmeasures.Add(staffMeasures[i]);
+            var currentSystem: MusicSystem = this.currentSystemParams.currentSystem;
+            for (var visStaffIdx: number = 0; visStaffIdx < this.numberOfVisibleStaffLines; visStaffIdx++) {
+                var measure: StaffMeasure = gmeasures[visStaffIdx];
+                currentSystem.StaffLines[visStaffIdx].Measures.Add(measure);
+                measure.ParentStaffLine = currentSystem.StaffLines[visStaffIdx];
+                currentSystem.StaffLines[visStaffIdx].PositionAndShape.ChildElements.Add(measure.PositionAndShape);
+            }
+            currentSystem.AddStaffMeasures(gmeasures);
+        }
+    }
+    private getMeasureStartLine(): SystemLinesEnum {
+        var thisMeasureBeginsLineRep: boolean = this.thisMeasureBeginsLineRepetition();
+        if (thisMeasureBeginsLineRep) {
+            var isSystemStartMeasure: boolean = this.currentSystemParams.IsSystemStartMeasure();
+            var isGlobalFirstMeasure: boolean = this.measureListIndex == 0;
+            if (this.previousMeasureEndsLineRepetition() && !isSystemStartMeasure) {
+                return SystemLinesEnum.DotsBoldBoldDots;
+            }
+            if (!isGlobalFirstMeasure)
+                return SystemLinesEnum.BoldThinDots;
+        }
+        return SystemLinesEnum.None;
+    }
+    private getMeasureEndLine(): SystemLinesEnum {
+        if (this.nextMeasureBeginsLineRepetition() && this.thisMeasureEndsLineRepetition()) {
+            return SystemLinesEnum.DotsBoldBoldDots;
+        }
+        if (this.thisMeasureEndsLineRepetition()) {
+            return SystemLinesEnum.DotsThinBold;
+        }
+        if (this.measureListIndex == this.measureList.Count - 1 || this.measureList[this.measureListIndex][0].ParentSourceMeasure.EndsPiece) {
+            return SystemLinesEnum.ThinBold;
+        }
+        if (this.nextMeasureHasKeyInstructionChange() || this.thisMeasureEndsWordRepetition() || this.nextMeasureBeginsWordRepetition()) {
+            return SystemLinesEnum.DoubleThin;
+        }
+        return SystemLinesEnum.SingleThin;
+    }
+    private getLineWidth(measure: StaffMeasure, systemLineEnum: SystemLinesEnum, isSystemStartMeasure: boolean): number {
+        var width: number = measure.GetLineWidth(systemLineEnum);
+        if (systemLineEnum == SystemLinesEnum.DotsBoldBoldDots) {
+            width /= 2;
+        }
+        if (isSystemStartMeasure && systemLineEnum == SystemLinesEnum.BoldThinDots) {
+            width += this.rules.DistanceBetweenLastInstructionAndRepetitionBarline;
+        }
+        return width;
+    }
+    private previousMeasureEndsLineRepetition(): boolean {
+        if (this.measureListIndex == 0)
+            return false;
+        for (var idx: number = 0, len = this.measureList[this.measureListIndex - 1].Count; idx < len; ++idx) {
+            var measure: StaffMeasure = this.measureList[this.measureListIndex - 1][idx];
+            if (measure.endsWithLineRepetition())
+                return true;
+        }
+        return false;
+    }
+    private thisMeasureBeginsLineRepetition(): boolean {
+        for (var idx: number = 0, len = this.measureList[this.measureListIndex].Count; idx < len; ++idx) {
+            var measure: StaffMeasure = this.measureList[this.measureListIndex][idx];
+            if (measure.beginsWithLineRepetition())
+                return true;
+        }
+        return false;
+    }
+    private nextMeasureBeginsLineRepetition(): boolean {
+        var nextMeasureIndex: number = this.measureListIndex + 1;
+        if (nextMeasureIndex >= this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.Count)
+            return false;
+        for (var idx: number = 0, len = this.measureList[nextMeasureIndex].Count; idx < len; ++idx) {
+            var measure: StaffMeasure = this.measureList[nextMeasureIndex][idx];
+            if (measure.beginsWithLineRepetition())
+                return true;
+        }
+        return false;
+    }
+    private thisMeasureEndsLineRepetition(): boolean {
+        for (var idx: number = 0, len = this.measureList[this.measureListIndex].Count; idx < len; ++idx) {
+            var measure: StaffMeasure = this.measureList[this.measureListIndex][idx];
+            if (measure.endsWithLineRepetition())
+                return true;
+        }
+        return false;
+    }
+    private nextMeasureBeginsWordRepetition(): boolean {
+        var nextMeasureIndex: number = this.measureListIndex + 1;
+        if (nextMeasureIndex >= this.graphicalMusicSheet.ParentMusicSheet.SourceMeasures.Count)
+            return false;
+        for (var idx: number = 0, len = this.measureList[nextMeasureIndex].Count; idx < len; ++idx) {
+            var measure: StaffMeasure = this.measureList[nextMeasureIndex][idx];
+            if (measure.beginsWithWordRepetition())
+                return true;
+        }
+        return false;
+    }
+    private thisMeasureEndsWordRepetition(): boolean {
+        for (var idx: number = 0, len = this.measureList[this.measureListIndex].Count; idx < len; ++idx) {
+            var measure: StaffMeasure = this.measureList[this.measureListIndex][idx];
+            if (measure.endsWithWordRepetition())
+                return true;
+        }
+        return false;
+    }
+    private nextMeasureHasKeyInstructionChange(): boolean {
+        return this.getNextMeasureKeyInstruction() != null;
+    }
+    private getNextMeasureKeyInstruction(): KeyInstruction {
+        if (this.measureListIndex < this.measureList.Count - 1) {
+            for (var visIndex: number = 0; visIndex < this.measureList[this.measureListIndex].Count; visIndex++) {
+                var sourceMeasure: SourceMeasure = this.measureList[this.measureListIndex + 1][visIndex].ParentSourceMeasure;
+                if (sourceMeasure == null)
+                    return null;
+                return sourceMeasure.getKeyInstruction(this.visibleStaffIndices[visIndex]);
+            }
+        }
+        return null;
+    }
+    private calculateXScalingFactor(systemFixWidth: number, systemVarWidth: number): number {
+        if (Math.Abs(systemVarWidth - 0) < 0.00001f || Math.Abs(systemFixWidth - 0) < 0.00001f)
+        return 1.0f;
+        var systemEndX: number;
+        var currentSystem: MusicSystem = this.currentSystemParams.currentSystem;
+        systemEndX = currentSystem.StaffLines[0].PositionAndShape.Size.Width;
+        var scalingFactor: number = (systemEndX - systemFixWidth) / systemVarWidth;
+        return scalingFactor;
+    }
+    private stretchMusicSystem(isPartEndingSystem: boolean): void {
+        var scalingFactor: number = this.calculateXScalingFactor(this.currentSystemParams.currentSystemFixWidth, this.currentSystemParams.currentSystemVarWidth);
+        if (isPartEndingSystem)
+            scalingFactor = Math.Min(scalingFactor, this.rules.LastSystemMaxScalingFactor);
+        var currentSystem: MusicSystem = this.currentSystemParams.currentSystem;
+        for (var visStaffIdx: number = 0, len = currentSystem.StaffLines.Count; visStaffIdx < len; ++visStaffIdx) {
+            var staffLine: StaffLine = currentSystem.StaffLines[visStaffIdx];
+            var currentXPosition: number = 0.0f;
+            for (var i: number = 0; i < staffLine.Measures.Count; i++) {
+                var measure: StaffMeasure = staffLine.Measures[i];
+                measure.SetPositionInStaffline(currentXPosition);
+                measure.SetWidth(measure.BeginInstructionsWidth + measure.MinimumStaffEntriesWidth * scalingFactor + measure.EndInstructionsWidth);
+                if (i < this.currentSystemParams.systemMeasures.Count) {
+                    var startLine: SystemLinesEnum = this.currentSystemParams.systemMeasures[i].beginLine;
+                    var lineWidth: number = measure.GetLineWidth(SystemLinesEnum.BoldThinDots);
+                    switch (startLine) {
+                        case SystemLinesEnum.BoldThinDots:
+                            {
+                                var xPosition: number = currentXPosition;
+                                if (i == 0) {
+                                    xPosition = currentXPosition + measure.BeginInstructionsWidth - lineWidth;
+                                }
+                                currentSystem.createVerticalLineForMeasure(xPosition, SystemLinesEnum.BoldThinDots, lineWidth, visStaffIdx);
+                                break;
+                            }
+                    }
+                }
+                measure.StaffEntriesScaleFactor = scalingFactor;
+                measure.LayoutSymbols();
+                var nextMeasureHasRepStartLine: boolean = i + 1 < this.currentSystemParams.systemMeasures.Count && this.currentSystemParams.systemMeasures[i + 1].beginLine == SystemLinesEnum.BoldThinDots;
+                if (!nextMeasureHasRepStartLine) {
+                    var endLine: SystemLinesEnum = SystemLinesEnum.SingleThin;
+                    if (i < this.currentSystemParams.systemMeasures.Count) {
+                        endLine = this.currentSystemParams.systemMeasures[i].endLine;
+                    }
+                    var lineWidth: number = measure.GetLineWidth(endLine);
+                    var xPos: number = measure.PositionAndShape.RelativePosition.X + measure.PositionAndShape.BorderRight - lineWidth;
+                    if (endLine == SystemLinesEnum.DotsBoldBoldDots)
+                        xPos -= lineWidth / 2;
+                    currentSystem.createVerticalLineForMeasure(xPos, endLine, lineWidth, visStaffIdx);
+                }
+                currentXPosition = measure.PositionAndShape.RelativePosition.X + measure.PositionAndShape.BorderRight;
+            }
+        }
+        if (isPartEndingSystem)
+            this.decreaseMusicSystemBorders();
+    }
+    private decreaseMusicSystemBorders(): void {
+        var currentSystem: MusicSystem = this.currentSystemParams.currentSystem;
+        var width: number = currentSystem.StaffLines[0].Measures.Last().PositionAndShape.RelativePosition.X + currentSystem.StaffLines[0].Measures.Last().PositionAndShape.Size.Width;
+        for (var idx: number = 0, len = currentSystem.StaffLines.Count; idx < len; ++idx) {
+            var staffLine: StaffLine = currentSystem.StaffLines[idx];
+            staffLine.PositionAndShape.BorderRight = width;
+            for (var idx2: number = 0, len2 = staffLine.StaffLines.Length; idx2 < len2; ++idx2) {
+                var graphicalLine: GraphicalLine = staffLine.StaffLines[idx2];
+                graphicalLine.End = new PointF_2D(width, graphicalLine.End.Y);
+            }
+        }
+        currentSystem.PositionAndShape.BorderRight = width + this.currentSystemParams.MaxLabelLength + this.rules.SystemLabelsRightMargin;
+    }
+}
+export class SystemBuildParameters {
+    public currentSystem: MusicSystem;
+    public systemMeasures: List<MeasureBuildParameters> = new List<MeasureBuildParameters>();
+    public systemMeasureIndex: number = 0;
+    public currentWidth: number = 0;
+    public currentSystemFixWidth: number = 0;
+    public currentSystemVarWidth: number = 0;
+    public MaxLabelLength: number = 0;
+    public IsSystemStartMeasure(): boolean {
+        return this.systemMeasureIndex == 0;
+    }
+}
+
+export class MeasureBuildParameters {
+    public beginLine: SystemLinesEnum;
+    public endLine: SystemLinesEnum;
+}

+ 15 - 0
src/MusicalScore/Graphical/SystemLinesEnum.ts

@@ -0,0 +1,15 @@
+export enum SystemLinesEnum {
+    SingleThin = 0,
+
+    DoubleThin = 1,
+
+    ThinBold = 2,
+
+    BoldThinDots = 3,
+
+    DotsThinBold = 4,
+
+    DotsBoldBoldDots = 5,
+
+    None = 6
+}