Quellcode durchsuchen

feat(Lyrics): Left-Alignment (default), Center optional, fix lyricsSpacing (#356)

summary:
feat(Lyrics): now left-aligned (default), Center-aligned can be set in EngravingRules
fix(lyricsSpacing): space lyrics to end of measure in addition to previous lyrics
differentiate spacing for left- and center-aligned

refactor(TextAlignment): rename TextAlignmentEnum to TextAlignmentAndPlacement
add methods IsLeft, IsCenterAligned, IsRight
further refactor into <Alignment, Placement> planned

fix(LyricsReader): SyllableIndex set for more cases

Squashed commits:

* lyrics now left-aligned, but spacing too wide and dashes missing.

also, TextAlignment checks need to be done for all Left alignments, not just LeftBottom. IsLeft() static func would be good.
the -1 shifts in multiple classes are only necessary because without it our left alignment isn't left-aligned.
this needs some more reasonable and structured fixes.

* left-aligned lyrics spacing optimized, dashes fixed. center-aligned lyrics spacing still too wide

* feat(lyricsAlignment): support left-aligned lyrics (new standard). improve spacing.

fix(VexFlowMusicSheetCalculator.ts): consider alignment, space lyrics to measure end with small overlap, space shorter notes more
fix(LyricsReader): SyllableIndex set for more cases
handling of incorrect word begin information in xml could perhaps be improved (add to last word)
fix(demo): correct lyric word information in xml of Land der Berge

minor changes:
index.js indentation
rename TextAlignment to TextAlignmentEnum to allow a class TextAlignment with IsLeft functions etc

* lyrics: fix bboxes for left-aligned lyrics, remove ungeneralized x-shift code

rename psi to bbox

* rename TextAlignmentEnum to TextAlignmentAndPlacement

further refactor to split into two enums planned

* change back label placement for non-lyrics to previous state, it affected layout

add comment about the dependency of MusicSheetDrawer.drawLabel on GraphicalLabel

* change back label placement for non-lyrics to previous state (fix previous commit)

* lyrics: adjust overlap into next measure

index.js indentation

* lyrics: spacing optimizations for dashes and centered lyrics

* fix github merge
sschmidTU vor 6 Jahren
Ursprung
Commit
6205fe3e13

+ 48 - 48
demo/index.js

@@ -8,56 +8,56 @@ import { OpenSheetMusicDisplay } from '../src/OpenSheetMusicDisplay/OpenSheetMus
     // folder of the sample files
     var sampleFolder = process.env.STATIC_FILES_SUBFOLDER ? process.env.STATIC_FILES_SUBFOLDER + "/" : "",
     samples = {
-            "Beethoven, L.v. - An die ferne Geliebte": "Beethoven_AnDieFerneGeliebte.xml",
-            "Clementi, M. - Sonatina Op.36 No.1 Pt.1": "MuzioClementi_SonatinaOpus36No1_Part1.xml",
-            "Clementi, M. - Sonatina Op.36 No.1 Pt.2": "MuzioClementi_SonatinaOpus36No1_Part2.xml",
-            "Clementi, M. - Sonatina Op.36 No.3 Pt.1": "MuzioClementi_SonatinaOpus36No3_Part1.xml",
-            "Clementi, M. - Sonatina Op.36 No.3 Pt.2": "MuzioClementi_SonatinaOpus36No3_Part2.xml",
-            "Bach, J.S. - Praeludium in C-Dur BWV846 1": "JohannSebastianBach_PraeludiumInCDur_BWV846_1.xml",
-            "Bach, J.S. - Air": "JohannSebastianBach_Air.xml",
-            "Gounod, C. - Meditation": "CharlesGounod_Meditation.xml",
-            "Haydn, J. - Concertante Cello": "JosephHaydn_ConcertanteCello.xml",
-            "Joplin, S. - Elite Syncopations": "ScottJoplin_EliteSyncopations.xml",
-            "Joplin, S. - The Entertainer": "ScottJoplin_The_Entertainer.xml",
-            "Mozart, W.A. - An Chloe": "Mozart_AnChloe.xml",
-            "Mozart, W.A. - Das Veilchen": "Mozart_DasVeilchen.xml",
-            "Mozart, W.A.- Clarinet Quintet (Excerpt)": "Mozart_Clarinet_Quintet_Excerpt.mxl",
-            "Mozart/Holzer - Land der Berge (national anthem of Austria)": "Land_der_Berge.musicxml",
-            "OSMD Function Test - All": "OSMD_function_test_all.xml",
-            "OSMD Function Test - Grace Notes": "OSMD_function_test_GraceNotes.xml",
-            "OSMD Function Test - Ornaments": "OSMD_function_test_Ornaments.xml",
-            "OSMD Function Test - Accidentals": "OSMD_function_test_accidentals.musicxml",
-            "OSMD Function Test - Expressions": "OSMD_function_test_expressions.musicxml",
-            "OSMD Function Test - NoteHeadShapes": "OSMD_function_test_noteHeadShapes.musicxml",
-            "OSMD Function Test - Drumset": "OSMD_function_test_drumset.musicxml",
-            "Schubert, F. - An Die Musik": "Schubert_An_die_Musik.xml",
-            "Actor, L. - Prelude (Sample)": "ActorPreludeSample.xml",
-            "Anonymous - Saltarello": "Saltarello.mxl",
-            "Debussy, C. - Mandoline": "Debussy_Mandoline.xml",
-            "Levasseur, F. - Parlez Mois": "Parlez-moi.mxl",
-            "Schumann, R. - Dichterliebe": "Dichterliebe01.xml",
-            "Telemann, G.P. - Sonate-Nr.1.1-Dolce": "TelemannWV40.102_Sonate-Nr.1.1-Dolce.xml",
-            "Telemann, G.P. - Sonate-Nr.1.2-Allegro": "TelemannWV40.102_Sonate-Nr.1.2-Allegro-F-Dur.xml",
-        },
+        "Beethoven, L.v. - An die ferne Geliebte": "Beethoven_AnDieFerneGeliebte.xml",
+        "Clementi, M. - Sonatina Op.36 No.1 Pt.1": "MuzioClementi_SonatinaOpus36No1_Part1.xml",
+        "Clementi, M. - Sonatina Op.36 No.1 Pt.2": "MuzioClementi_SonatinaOpus36No1_Part2.xml",
+        "Clementi, M. - Sonatina Op.36 No.3 Pt.1": "MuzioClementi_SonatinaOpus36No3_Part1.xml",
+        "Clementi, M. - Sonatina Op.36 No.3 Pt.2": "MuzioClementi_SonatinaOpus36No3_Part2.xml",
+        "Bach, J.S. - Praeludium in C-Dur BWV846 1": "JohannSebastianBach_PraeludiumInCDur_BWV846_1.xml",
+        "Bach, J.S. - Air": "JohannSebastianBach_Air.xml",
+        "Gounod, C. - Méditation": "CharlesGounod_Meditation.xml",
+        "Haydn, J. - Concertante Cello": "JosephHaydn_ConcertanteCello.xml",
+        "Joplin, S. - Elite Syncopations": "ScottJoplin_EliteSyncopations.xml",
+        "Joplin, S. - The Entertainer": "ScottJoplin_The_Entertainer.xml",
+        "Mozart, W.A. - An Chloe": "Mozart_AnChloe.xml",
+        "Mozart, W.A. - Das Veilchen": "Mozart_DasVeilchen.xml",
+        "Mozart, W.A.- Clarinet Quintet (Excerpt)": "Mozart_Clarinet_Quintet_Excerpt.mxl",
+        "Mozart/Holzer - Land der Berge (national anthem of Austria)": "Land_der_Berge.musicxml",
+        "OSMD Function Test - All": "OSMD_function_test_all.xml",
+        "OSMD Function Test - Grace Notes": "OSMD_function_test_GraceNotes.xml",
+        "OSMD Function Test - Ornaments": "OSMD_function_test_Ornaments.xml",
+        "OSMD Function Test - Accidentals": "OSMD_function_test_accidentals.musicxml",
+        "OSMD Function Test - Expressions": "OSMD_function_test_expressions.musicxml",
+        "OSMD Function Test - NoteHeadShapes": "OSMD_function_test_noteHeadShapes.musicxml",
+        "OSMD Function Test - Drumset": "OSMD_function_test_drumset.musicxml",
+        "Schubert, F. - An Die Musik": "Schubert_An_die_Musik.xml",
+        "Actor, L. - Prelude (Sample)": "ActorPreludeSample.xml",
+        "Anonymous - Saltarello": "Saltarello.mxl",
+        "Debussy, C. - Mandoline": "Debussy_Mandoline.xml",
+        "Levasseur, F. - Parlez Mois": "Parlez-moi.mxl",
+        "Schumann, R. - Dichterliebe": "Dichterliebe01.xml",
+        "Telemann, G.P. - Sonate-Nr.1.1-Dolce": "TelemannWV40.102_Sonate-Nr.1.1-Dolce.xml",
+        "Telemann, G.P. - Sonate-Nr.1.2-Allegro": "TelemannWV40.102_Sonate-Nr.1.2-Allegro-F-Dur.xml",
+    },
 
-        zoom = 1.0,
+    zoom = 1.0,
     // HTML Elements in the page
-        err,
-        error_tr,
-        canvas,
-        selectSample,
-        selectBounding,
-        skylineDebug,
-        bottomlineDebug,
-        zoomIn,
-        zoomOut,
-        zoomDiv,
-        custom,
-        nextCursorBtn,
-        resetCursorBtn,
-        showCursorBtn,
-        hideCursorBtn,
-        backendSelect;
+    err,
+    error_tr,
+    canvas,
+    selectSample,
+    selectBounding,
+    skylineDebug,
+    bottomlineDebug,
+    zoomIn,
+    zoomOut,
+    zoomDiv,
+    custom,
+    nextCursorBtn,
+    resetCursorBtn,
+    showCursorBtn,
+    hideCursorBtn,
+    backendSelect;
 
     // Initialization code
     function init() {

+ 25 - 1
src/Common/Enums/TextAlignment.ts

@@ -1,8 +1,12 @@
 /**
  * The possible positioning of text on the sheet music
  * (used for example with title, composer, author, etc.)
+ * TODO this should be split into alignment and placement, e.g. <Left, Top> for LeftTop.
+ * Right now "LeftTop" means left-aligned and top-placed. This is ambiguous for center,
+ * which can be alignment or placement.
+ * A function like "IsLeft" would be easier with the split.
  */
-export enum TextAlignment {
+export enum TextAlignmentAndPlacement {
     LeftTop,
     LeftCenter,
     LeftBottom,
@@ -13,3 +17,23 @@ export enum TextAlignment {
     RightCenter,
     RightBottom
 }
+
+export class TextAlignment {
+    public static IsLeft(textAlignment: TextAlignmentAndPlacement): boolean {
+        return textAlignment === TextAlignmentAndPlacement.LeftTop
+            || textAlignment === TextAlignmentAndPlacement.LeftCenter
+            || textAlignment === TextAlignmentAndPlacement.LeftBottom;
+    }
+
+    public static IsCenterAligned(textAlignment: TextAlignmentAndPlacement): boolean {
+        return textAlignment === TextAlignmentAndPlacement.CenterTop
+            || textAlignment === TextAlignmentAndPlacement.CenterCenter
+            || textAlignment === TextAlignmentAndPlacement.CenterBottom;
+    }
+
+    public static IsRight(textAlignment: TextAlignmentAndPlacement): boolean {
+        return textAlignment === TextAlignmentAndPlacement.RightTop
+            || textAlignment === TextAlignmentAndPlacement.RightCenter
+            || textAlignment === TextAlignmentAndPlacement.RightBottom;
+    }
+}

+ 30 - 13
src/MusicalScore/Graphical/EngravingRules.ts

@@ -1,6 +1,7 @@
 import {PagePlacementEnum} from "./GraphicalMusicPage";
 //import {MusicSymbol} from "./MusicSymbol";
 import * as log from "loglevel";
+import { TextAlignmentAndPlacement } from "../../Common/Enums/TextAlignment";
 
 export class EngravingRules {
     private static rules: EngravingRules;
@@ -87,12 +88,14 @@ export class EngravingRules {
     private repetitionEndingLabelYOffset: number;
     private repetitionEndingLineYLowerOffset: number;
     private repetitionEndingLineYUpperOffset: number;
+    private lyricsAlignmentStandard: TextAlignmentAndPlacement;
     private lyricsHeight: number;
     private lyricsYOffsetToStaffHeight: number;
     private verticalBetweenLyricsDistance: number;
     private horizontalBetweenLyricsDistance: number;
-    private betweenSyllabelMaximumDistance: number;
-    private betweenSyllabelMinimumDistance: number;
+    private betweenSyllableMaximumDistance: number;
+    private betweenSyllableMinimumDistance: number;
+    private lyricOverlapAllowedIntoNextMeasure: number;
     private minimumDistanceBetweenDashes: number;
     private bezierCurveStepSize: number;
     private tPower3: number[];
@@ -271,12 +274,14 @@ export class EngravingRules {
         this.repetitionEndingLineYUpperOffset = 0.3;
 
         // Lyrics
+        this.lyricsAlignmentStandard = TextAlignmentAndPlacement.LeftBottom; // CenterBottom and LeftBottom tested, spacing-optimized
         this.lyricsHeight = 2.0; // actually size of lyrics
         this.lyricsYOffsetToStaffHeight = 3.0; // distance between lyrics and staff. could partly be even lower/dynamic
         this.verticalBetweenLyricsDistance = 0.5;
-        this.horizontalBetweenLyricsDistance = 0.4;
-        this.betweenSyllabelMaximumDistance = 10.0;
-        this.betweenSyllabelMinimumDistance = 0.5;
+        this.horizontalBetweenLyricsDistance = 0.2;
+        this.betweenSyllableMaximumDistance = 10.0;
+        this.betweenSyllableMinimumDistance = 0.5; // + 1.0 for CenterAlignment added in lyrics spacing
+        this.lyricOverlapAllowedIntoNextMeasure = 3.4; // optimal for dashed last lyric, see Land der Berge
         this.minimumDistanceBetweenDashes = 10;
 
         // expressions variables
@@ -811,6 +816,12 @@ export class EngravingRules {
     public set RepetitionEndingLineYUpperOffset(value: number) {
         this.repetitionEndingLineYUpperOffset = value;
     }
+    public get LyricsAlignmentStandard(): TextAlignmentAndPlacement {
+        return this.lyricsAlignmentStandard;
+    }
+    public set LyricsAlignmentStandard(value: TextAlignmentAndPlacement) {
+        this.lyricsAlignmentStandard = value;
+    }
     public get LyricsHeight(): number {
         return this.lyricsHeight;
     }
@@ -835,17 +846,23 @@ export class EngravingRules {
     public set HorizontalBetweenLyricsDistance(value: number) {
         this.horizontalBetweenLyricsDistance = value;
     }
-    public get BetweenSyllabelMaximumDistance(): number {
-        return this.betweenSyllabelMaximumDistance;
+    public get BetweenSyllableMaximumDistance(): number {
+        return this.betweenSyllableMaximumDistance;
+    }
+    public set BetweenSyllableMaximumDistance(value: number) {
+        this.betweenSyllableMaximumDistance = value;
+    }
+    public get BetweenSyllableMinimumDistance(): number {
+        return this.betweenSyllableMinimumDistance;
     }
-    public set BetweenSyllabelMaximumDistance(value: number) {
-        this.betweenSyllabelMaximumDistance = value;
+    public set BetweenSyllableMinimumDistance(value: number) {
+        this.betweenSyllableMinimumDistance = value;
     }
-    public get BetweenSyllabelMinimumDistance(): number {
-        return this.betweenSyllabelMinimumDistance;
+    public get LyricOverlapAllowedIntoNextMeasure(): number {
+        return this.lyricOverlapAllowedIntoNextMeasure;
     }
-    public set BetweenSyllabelMinimumDistance(value: number) {
-        this.betweenSyllabelMinimumDistance = value;
+    public set LyricOverlapAllowedIntoNextMeasure(value: number) {
+        this.lyricOverlapAllowedIntoNextMeasure = value;
     }
     public get MinimumDistanceBetweenDashes(): number {
         return this.minimumDistanceBetweenDashes;

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

@@ -1,4 +1,4 @@
-import {TextAlignment} from "../../Common/Enums/TextAlignment";
+import {TextAlignmentAndPlacement} from "../../Common/Enums/TextAlignment";
 import {Label} from "../Label";
 import {GraphicalLabel} from "./GraphicalLabel";
 import {ChordSymbolContainer} from "../VoiceData/ChordSymbolContainer";
@@ -23,7 +23,7 @@ export class GraphicalChordSymbolContainer extends GraphicalObject {
     }
     private calculateLabel(textHeight: number, transposeHalftones: number): void {
         const text: string = ChordSymbolContainer.calculateChordText(this.chordSymbolContainer, transposeHalftones);
-        this.graphicalLabel = new GraphicalLabel(new Label(text), textHeight, TextAlignment.CenterBottom, this.boundingBox);
+        this.graphicalLabel = new GraphicalLabel(new Label(text), textHeight, TextAlignmentAndPlacement.CenterBottom, this.boundingBox);
         this.graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0.0, 0.0);
     }
 }

+ 52 - 52
src/MusicalScore/Graphical/GraphicalLabel.ts

@@ -1,5 +1,5 @@
 import {Label} from "../Label";
-import {TextAlignment} from "../../Common/Enums/TextAlignment";
+import {TextAlignmentAndPlacement} from "../../Common/Enums/TextAlignment";
 import {Clickable} from "./Clickable";
 import {BoundingBox} from "./BoundingBox";
 import {EngravingRules} from "./EngravingRules";
@@ -18,7 +18,7 @@ export class GraphicalLabel extends Clickable {
      * @param alignment Alignement like left, right, top, ...
      * @param parent Parent Bounding Box where the label is attached to
      */
-    constructor(label: Label, textHeight: number, alignment: TextAlignment, parent: BoundingBox = undefined) {
+    constructor(label: Label, textHeight: number, alignment: TextAlignmentAndPlacement, parent: BoundingBox = undefined) {
         super();
         this.label = label;
         this.boundingBox = new BoundingBox(this, parent);
@@ -47,68 +47,68 @@ export class GraphicalLabel extends Clickable {
             MusicSheetCalculator.TextMeasurer.computeTextWidthToHeightRatio(this.Label.text, this.Label.font, this.Label.fontStyle);
         const height: number = this.Label.fontHeight;
         const width: number = height * widthToHeightRatio;
-        const psi: BoundingBox = this.PositionAndShape;
+        const bbox: BoundingBox = this.PositionAndShape;
 
         switch (this.Label.textAlignment) {
-            case TextAlignment.CenterBottom:
-                psi.BorderTop = -height;
-                psi.BorderLeft = -width / 2;
-                psi.BorderBottom = 0;
-                psi.BorderRight = width / 2;
+            case TextAlignmentAndPlacement.CenterBottom:
+                bbox.BorderTop = -height;
+                bbox.BorderLeft = -width / 2;
+                bbox.BorderBottom = 0;
+                bbox.BorderRight = width / 2;
                 break;
-            case TextAlignment.CenterCenter:
-                psi.BorderTop = -height / 2;
-                psi.BorderLeft = -width / 2;
-                psi.BorderBottom = height / 2;
-                psi.BorderRight = width / 2;
+            case TextAlignmentAndPlacement.CenterCenter:
+                bbox.BorderTop = -height / 2;
+                bbox.BorderLeft = -width / 2;
+                bbox.BorderBottom = height / 2;
+                bbox.BorderRight = width / 2;
                 break;
-            case TextAlignment.CenterTop:
-                psi.BorderTop = 0;
-                psi.BorderLeft = -width / 2;
-                psi.BorderBottom = height;
-                psi.BorderRight = width / 2;
+            case TextAlignmentAndPlacement.CenterTop:
+                bbox.BorderTop = 0;
+                bbox.BorderLeft = -width / 2;
+                bbox.BorderBottom = height;
+                bbox.BorderRight = width / 2;
                 break;
-            case TextAlignment.LeftBottom:
-                psi.BorderTop = -height;
-                psi.BorderLeft = 0;
-                psi.BorderBottom = 0;
-                psi.BorderRight = width;
+            case TextAlignmentAndPlacement.LeftBottom:
+                bbox.BorderTop = -height;
+                bbox.BorderLeft = -1;
+                bbox.BorderBottom = 0;
+                bbox.BorderRight = width - 1;
                 break;
-            case TextAlignment.LeftCenter:
-                psi.BorderTop = -height / 2;
-                psi.BorderLeft = 0;
-                psi.BorderBottom = height / 2;
-                psi.BorderRight = width;
+            case TextAlignmentAndPlacement.LeftCenter:
+                bbox.BorderTop = -height / 2;
+                bbox.BorderLeft = 0;
+                bbox.BorderBottom = height / 2;
+                bbox.BorderRight = width;
                 break;
-            case TextAlignment.LeftTop:
-                psi.BorderTop = 0;
-                psi.BorderLeft = 0;
-                psi.BorderBottom = height;
-                psi.BorderRight = width;
+            case TextAlignmentAndPlacement.LeftTop:
+                bbox.BorderTop = 0;
+                bbox.BorderLeft = 0;
+                bbox.BorderBottom = height;
+                bbox.BorderRight = width;
                 break;
-            case TextAlignment.RightBottom:
-                psi.BorderTop = -height;
-                psi.BorderLeft = -width;
-                psi.BorderBottom = 0;
-                psi.BorderRight = 0;
+            case TextAlignmentAndPlacement.RightBottom:
+                bbox.BorderTop = -height;
+                bbox.BorderLeft = -width;
+                bbox.BorderBottom = 0;
+                bbox.BorderRight = 0;
                 break;
-            case TextAlignment.RightCenter:
-                psi.BorderTop = -height / 2;
-                psi.BorderLeft = -width;
-                psi.BorderBottom = height / 2;
-                psi.BorderRight = 0;
+            case TextAlignmentAndPlacement.RightCenter:
+                bbox.BorderTop = -height / 2;
+                bbox.BorderLeft = -width;
+                bbox.BorderBottom = height / 2;
+                bbox.BorderRight = 0;
                 break;
-            case TextAlignment.RightTop:
-                psi.BorderTop = 0;
-                psi.BorderLeft = -width;
-                psi.BorderBottom = height;
-                psi.BorderRight = 0;
+            case TextAlignmentAndPlacement.RightTop:
+                bbox.BorderTop = 0;
+                bbox.BorderLeft = -width;
+                bbox.BorderBottom = height;
+                bbox.BorderRight = 0;
                 break;
             default:
         }
-        psi.BorderMarginTop = psi.BorderTop - height * labelMarginBorderFactor;
-        psi.BorderMarginLeft = psi.BorderLeft - height * labelMarginBorderFactor;
-        psi.BorderMarginBottom = psi.BorderBottom + height * labelMarginBorderFactor;
-        psi.BorderMarginRight = psi.BorderRight + height * labelMarginBorderFactor;
+        bbox.BorderMarginTop = bbox.BorderTop - height * labelMarginBorderFactor;
+        bbox.BorderMarginLeft = bbox.BorderLeft - height * labelMarginBorderFactor;
+        bbox.BorderMarginBottom = bbox.BorderBottom + height * labelMarginBorderFactor;
+        bbox.BorderMarginRight = bbox.BorderRight + height * labelMarginBorderFactor;
     }
 }

+ 13 - 5
src/MusicalScore/Graphical/GraphicalLyricEntry.ts

@@ -3,8 +3,9 @@ import {GraphicalLyricWord} from "./GraphicalLyricWord";
 import {GraphicalLabel} from "./GraphicalLabel";
 import {GraphicalStaffEntry} from "./GraphicalStaffEntry";
 import {Label} from "../Label";
-import {TextAlignment} from "../../Common/Enums/TextAlignment";
 import {PointF2D} from "../../Common/DataObjects/PointF2D";
+import { EngravingRules } from "./EngravingRules";
+import { TextAlignmentAndPlacement } from "../../Common/Enums/TextAlignment";
 
 /**
  * The graphical counterpart of a [[LyricsEntry]]
@@ -18,17 +19,24 @@ export class GraphicalLyricEntry {
     constructor(lyricsEntry: LyricsEntry, graphicalStaffEntry: GraphicalStaffEntry, lyricsHeight: number, staffHeight: number) {
         this.lyricsEntry = lyricsEntry;
         this.graphicalStaffEntry = graphicalStaffEntry;
+        let lyricsTextAlignment: TextAlignmentAndPlacement = EngravingRules.Rules.LyricsAlignmentStandard;
+        // for small notes with long text, use center alignment
+        // TODO use this, fix center+left alignment combination spacing
+        if (lyricsEntry.Text.length >= 4
+            && lyricsEntry.Parent.Notes[0].Length.Denominator > 4
+            && lyricsTextAlignment === TextAlignmentAndPlacement.LeftBottom) {
+            lyricsTextAlignment = TextAlignmentAndPlacement.CenterBottom;
+        }
         this.graphicalLabel = new GraphicalLabel(
             new Label(lyricsEntry.Text),
             lyricsHeight,
-            TextAlignment.CenterBottom,
+            EngravingRules.Rules.LyricsAlignmentStandard,
             graphicalStaffEntry.PositionAndShape
         );
-        this.graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0.0, staffHeight);
+        this.graphicalLabel.PositionAndShape.RelativePosition = new PointF2D(0, staffHeight); // TODO gets reset later
     }
 
-    // FIXME: This should actually be called LyricsEntry or be a function
-    public get GetLyricsEntry(): LyricsEntry {
+    public get LyricsEntry(): LyricsEntry {
         return this.lyricsEntry;
     }
     public get ParentLyricWord(): GraphicalLyricWord {

+ 16 - 16
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -31,7 +31,7 @@ import {SourceStaffEntry} from "../VoiceData/SourceStaffEntry";
 import {BoundingBox} from "./BoundingBox";
 import {Instrument} from "../Instrument";
 import {GraphicalLabel} from "./GraphicalLabel";
-import {TextAlignment} from "../../Common/Enums/TextAlignment";
+import {TextAlignmentAndPlacement} from "../../Common/Enums/TextAlignment";
 import {VerticalGraphicalStaffEntryContainer} from "./VerticalGraphicalStaffEntryContainer";
 import {KeyInstruction} from "../VoiceData/Instructions/KeyInstruction";
 import {AbstractNotationInstruction} from "../VoiceData/Instructions/AbstractNotationInstruction";
@@ -58,7 +58,6 @@ import { VerticalSourceStaffEntryContainer } from "../VoiceData/VerticalSourceSt
 import { SkyBottomLineCalculator } from "./SkyBottomLineCalculator";
 import { PlacementEnum } from "../VoiceData/Expressions/AbstractExpression";
 import { AbstractGraphicalInstruction } from "./AbstractGraphicalInstruction";
-import { GraphicalObject } from "./GraphicalObject";
 import { GraphicalInstantaneousTempoExpression } from "./GraphicalInstantaneousTempoExpression";
 import { InstantaneousTempoExpression, TempoEnum } from "../VoiceData/Expressions/InstantaneousTempoExpression";
 import { ContinuousTempoExpression } from "../VoiceData/Expressions/ContinuousExpressions/ContinuousTempoExpression";
@@ -423,7 +422,7 @@ export abstract class MusicSheetCalculator {
     private calculateSingleMeasureNumberPlacement(measure: GraphicalMeasure, staffLine: StaffLine, musicSystem: MusicSystem): void {
         const labelNumber: string = measure.MeasureNumber.toString();
         const graphicalLabel: GraphicalLabel = new GraphicalLabel(new Label(labelNumber), this.rules.MeasureNumberLabelHeight,
-                                                                  TextAlignment.LeftBottom);
+                                                                  TextAlignmentAndPlacement.LeftBottom);
 
         const skyBottomLineCalculator: SkyBottomLineCalculator = staffLine.SkyBottomLineCalculator;
 
@@ -534,7 +533,7 @@ export abstract class MusicSheetCalculator {
 
                 // read the verseNumber and get index of this number in the sorted LyricVerseNumbersList of Instrument
                 // eg verseNumbers: 2,3,4,6 => 1,2,3,4
-                const verseNumber: number = lyricEntry.GetLyricsEntry.VerseNumber;
+                const verseNumber: number = lyricEntry.LyricsEntry.VerseNumber;
                 const sortedLyricVerseNumberIndex: number = lyricVersesNumber.indexOf(verseNumber);
                 const firstPosition: number = lyricsStartYPosition + this.rules.LyricsHeight + this.rules.VerticalBetweenLyricsDistance;
 
@@ -576,7 +575,7 @@ export abstract class MusicSheetCalculator {
                     this.calculateSingleLyricWord(lyricEntry);
                 }
                 // calculate the underscore line extend if needed
-                if (lyricEntry.GetLyricsEntry.extend) {
+                if (lyricEntry.LyricsEntry.extend) {
                     this.calculateLyricExtend(lyricEntry);
                 }
             }
@@ -902,12 +901,12 @@ export abstract class MusicSheetCalculator {
         label.fontHeight = fontHeight;
 
         // TODO_RR: TextHeight from first Entry
-        const graphLabel: GraphicalLabel = new GraphicalLabel(label, fontHeight, TextAlignment.CenterBottom, staffLine.PositionAndShape);
+        const graphLabel: GraphicalLabel = new GraphicalLabel(label, fontHeight, TextAlignmentAndPlacement.CenterBottom, staffLine.PositionAndShape);
         graphLabel.Label.fontStyle = style;
         const marginFactor: number = 1.1;
 
         if (placement === PlacementEnum.Below) {
-            graphLabel.Label.textAlignment = TextAlignment.LeftTop;
+            graphLabel.Label.textAlignment = TextAlignmentAndPlacement.LeftTop;
         }
 
         graphLabel.setLabelPositionAndShapeBorders();
@@ -1167,7 +1166,8 @@ export abstract class MusicSheetCalculator {
         let maxLabelLength: number = 0.0;
         for (const instrument of this.graphicalMusicSheet.ParentMusicSheet.Instruments) {
             if (instrument.Voices.length > 0 && instrument.Voices[0].Visible) {
-                const graphicalLabel: GraphicalLabel = new GraphicalLabel(instrument.NameLabel, this.rules.InstrumentLabelTextHeight, TextAlignment.LeftCenter);
+                const graphicalLabel: GraphicalLabel = new GraphicalLabel(
+                    instrument.NameLabel, this.rules.InstrumentLabelTextHeight, TextAlignmentAndPlacement.LeftCenter);
                 graphicalLabel.setLabelPositionAndShapeBorders();
                 maxLabelLength = Math.max(maxLabelLength, graphicalLabel.PositionAndShape.MarginSize.width);
             }
@@ -1178,22 +1178,22 @@ export abstract class MusicSheetCalculator {
     protected calculateSheetLabelBoundingBoxes(): void {
         const musicSheet: MusicSheet = this.graphicalMusicSheet.ParentMusicSheet;
         if (musicSheet.Title !== undefined) {
-            const title: GraphicalLabel = new GraphicalLabel(musicSheet.Title, this.rules.SheetTitleHeight, TextAlignment.CenterBottom);
+            const title: GraphicalLabel = new GraphicalLabel(musicSheet.Title, this.rules.SheetTitleHeight, TextAlignmentAndPlacement.CenterBottom);
             this.graphicalMusicSheet.Title = title;
             title.setLabelPositionAndShapeBorders();
         }
         if (musicSheet.Subtitle !== undefined) {
-            const subtitle: GraphicalLabel = new GraphicalLabel(musicSheet.Subtitle, this.rules.SheetSubtitleHeight, TextAlignment.CenterCenter);
+            const subtitle: GraphicalLabel = new GraphicalLabel(musicSheet.Subtitle, this.rules.SheetSubtitleHeight, TextAlignmentAndPlacement.CenterCenter);
             this.graphicalMusicSheet.Subtitle = subtitle;
             subtitle.setLabelPositionAndShapeBorders();
         }
         if (musicSheet.Composer !== undefined) {
-            const composer: GraphicalLabel = new GraphicalLabel(musicSheet.Composer, this.rules.SheetComposerHeight, TextAlignment.RightCenter);
+            const composer: GraphicalLabel = new GraphicalLabel(musicSheet.Composer, this.rules.SheetComposerHeight, TextAlignmentAndPlacement.RightCenter);
             this.graphicalMusicSheet.Composer = composer;
             composer.setLabelPositionAndShapeBorders();
         }
         if (musicSheet.Lyricist !== undefined) {
-            const lyricist: GraphicalLabel = new GraphicalLabel(musicSheet.Lyricist, this.rules.SheetAuthorHeight, TextAlignment.LeftCenter);
+            const lyricist: GraphicalLabel = new GraphicalLabel(musicSheet.Lyricist, this.rules.SheetAuthorHeight, TextAlignmentAndPlacement.LeftCenter);
             this.graphicalMusicSheet.Lyricist = lyricist;
             lyricist.setLabelPositionAndShapeBorders();
         }
@@ -1984,7 +1984,7 @@ export abstract class MusicSheetCalculator {
      * @param {number} y
      */
     private calculateSingleDashForLyricWord(staffLine: StaffLine, startX: number, endX: number, y: number): void {
-        const dash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignment.CenterBottom);
+        const dash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignmentAndPlacement.CenterBottom);
         dash.setLabelPositionAndShapeBorders();
         staffLine.LyricsDashes.push(dash);
         if (this.staffLinesWithLyricWords.indexOf(staffLine) === -1) {
@@ -2032,8 +2032,8 @@ export abstract class MusicSheetCalculator {
             // start- and End margins from the text Labels
             const startX: number = startStaffEntry.parentMeasure.PositionAndShape.RelativePosition.x +
                 startStaffEntry.PositionAndShape.RelativePosition.x +
-                //lyricEntry.GraphicalLabel.PositionAndShape.BorderMarginRight;
                 startStaffEntry.PositionAndShape.BorderMarginRight;
+                // + lyricEntry.GraphicalLabel.PositionAndShape.BorderMarginLeft;
                 // + startStaffLine.PositionAndShape.AbsolutePosition.x; // doesn't work, done in drawer
             const endX: number = endStaffEntry.parentMeasure.PositionAndShape.RelativePosition.x +
                 endStaffEntry.PositionAndShape.RelativePosition.x +
@@ -2099,7 +2099,7 @@ export abstract class MusicSheetCalculator {
      * @returns {number}
      */
     private calculateRightAndLeftDashesForLyricWord(staffLine: StaffLine, startX: number, endX: number, y: number): number {
-        const leftDash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignment.CenterBottom);
+        const leftDash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignmentAndPlacement.CenterBottom);
         leftDash.setLabelPositionAndShapeBorders();
         staffLine.LyricsDashes.push(leftDash);
         if (this.staffLinesWithLyricWords.indexOf(staffLine) === -1) {
@@ -2108,7 +2108,7 @@ export abstract class MusicSheetCalculator {
         leftDash.PositionAndShape.Parent = staffLine.PositionAndShape;
         const leftDashRelative: PointF2D = new PointF2D(startX, y);
         leftDash.PositionAndShape.RelativePosition = leftDashRelative;
-        const rightDash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignment.CenterBottom);
+        const rightDash: GraphicalLabel = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignmentAndPlacement.CenterBottom);
         rightDash.setLabelPositionAndShapeBorders();
         staffLine.LyricsDashes.push(rightDash);
         rightDash.PositionAndShape.Parent = staffLine.PositionAndShape;

+ 15 - 11
src/MusicalScore/Graphical/MusicSheetDrawer.ts

@@ -10,7 +10,7 @@ import {PointF2D} from "../../Common/DataObjects/PointF2D";
 import {GraphicalRectangle} from "./GraphicalRectangle";
 import {GraphicalLabel} from "./GraphicalLabel";
 import {Label} from "../Label";
-import {TextAlignment} from "../../Common/Enums/TextAlignment";
+import {TextAlignmentAndPlacement} from "../../Common/Enums/TextAlignment";
 import {ArgumentOutOfRangeException} from "../Exceptions";
 import {SelectionStartSymbol} from "./SelectionStartSymbol";
 import {SelectionEndSymbol} from "./SelectionEndSymbol";
@@ -24,6 +24,7 @@ import {Instrument} from "../Instrument";
 import {MusicSymbolDrawingStyle, PhonicScoreModes} from "./DrawingMode";
 import {GraphicalObject} from "./GraphicalObject";
 import { GraphicalInstantaneousDynamicExpression } from "./GraphicalInstantaneousDynamicExpression";
+import { unitInPixels } from "./VexFlow/VexFlowMusicSheetDrawer";
 
 /**
  * Draw a [[GraphicalMusicSheet]] (through the .drawSheet method)
@@ -149,33 +150,36 @@ export abstract class MusicSheetDrawer {
         const bitmapWidth: number = Math.ceil(widthInPixel);
         const bitmapHeight: number = Math.ceil(heightInPixel * 1.2);
         switch (label.textAlignment) {
-            case TextAlignment.LeftTop:
+            // the following have to match the Border settings in GraphicalLabel.setLabelPositionAndShapeBorders()
+            // TODO unify alignment shifts and our label/bbox position, which does not correspond to screenposition
+            case TextAlignmentAndPlacement.LeftTop:
                 break;
-            case TextAlignment.LeftCenter:
+            case TextAlignmentAndPlacement.LeftCenter:
                 screenPosition.y -= bitmapHeight / 2;
                 break;
-            case TextAlignment.LeftBottom:
+            case TextAlignmentAndPlacement.LeftBottom:
                 screenPosition.y -= bitmapHeight;
+                screenPosition.x -= unitInPixels; // lyrics-specific to align with notes
                 break;
-            case TextAlignment.CenterTop:
+            case TextAlignmentAndPlacement.CenterTop:
                 screenPosition.x -= bitmapWidth / 2;
                 break;
-            case TextAlignment.CenterCenter:
+            case TextAlignmentAndPlacement.CenterCenter:
                 screenPosition.x -= bitmapWidth / 2;
                 screenPosition.y -= bitmapHeight / 2;
                 break;
-            case TextAlignment.CenterBottom:
+            case TextAlignmentAndPlacement.CenterBottom:
                 screenPosition.x -= bitmapWidth / 2;
                 screenPosition.y -= bitmapHeight;
                 break;
-            case TextAlignment.RightTop:
+            case TextAlignmentAndPlacement.RightTop:
                 screenPosition.x -= bitmapWidth;
                 break;
-            case TextAlignment.RightCenter:
+            case TextAlignmentAndPlacement.RightCenter:
                 screenPosition.x -= bitmapWidth;
                 screenPosition.y -= bitmapHeight / 2;
                 break;
-            case TextAlignment.RightBottom:
+            case TextAlignmentAndPlacement.RightBottom:
                 screenPosition.x -= bitmapWidth;
                 screenPosition.y -= bitmapHeight;
                 break;
@@ -506,7 +510,7 @@ export abstract class MusicSheetDrawer {
 
             tmpRect = this.applyScreenTransformationForRect(tmpRect);
             this.renderRectangle(tmpRect, <number>GraphicalLayers.Background, layer, 0.5);
-            this.renderLabel(new GraphicalLabel(new Label(dataObjectString), 0.8, TextAlignment.CenterCenter),
+            this.renderLabel(new GraphicalLabel(new Label(dataObjectString), 0.8, TextAlignmentAndPlacement.CenterCenter),
                              layer, tmpRect.width, tmpRect.height, tmpRect.height, new PointF2D(tmpRect.x, tmpRect.y + 12));
         }
         layer++;

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

@@ -4,7 +4,7 @@ import {BoundingBox} from "./BoundingBox";
 import {Fraction} from "../../Common/DataObjects/Fraction";
 import {SourceMeasure} from "../VoiceData/SourceMeasure";
 import {InstrumentalGroup} from "../InstrumentalGroup";
-import {TextAlignment} from "../../Common/Enums/TextAlignment";
+import {TextAlignmentAndPlacement} from "../../Common/Enums/TextAlignment";
 import {GraphicalMusicPage} from "./GraphicalMusicPage";
 import {GraphicalLabel} from "./GraphicalLabel";
 import {GraphicalMeasure} from "./GraphicalMeasure";
@@ -279,7 +279,7 @@ export abstract class MusicSystem extends GraphicalObject {
             for (let idx: number = 0, len: number = instruments.length; idx < len; ++idx) {
                 const instrument: Instrument = instruments[idx];
                 const graphicalLabel: GraphicalLabel = new GraphicalLabel(
-                    instrument.NameLabel, instrumentLabelTextHeight, TextAlignment.LeftCenter, this.boundingBox
+                    instrument.NameLabel, instrumentLabelTextHeight, TextAlignmentAndPlacement.LeftCenter, this.boundingBox
                 );
                 graphicalLabel.setLabelPositionAndShapeBorders();
                 this.labels.setValue(graphicalLabel, instrument);

+ 2 - 2
src/MusicalScore/Graphical/VexFlow/VexFlowInstantaneousDynamicExpression.ts

@@ -2,7 +2,7 @@ import { GraphicalInstantaneousDynamicExpression } from "../GraphicalInstantaneo
 import { InstantaneousDynamicExpression, DynamicEnum } from "../../VoiceData/Expressions/InstantaneousDynamicExpression";
 import { GraphicalLabel } from "../GraphicalLabel";
 import { Label } from "../../Label";
-import { TextAlignment } from "../../../Common/Enums/TextAlignment";
+import { TextAlignmentAndPlacement } from "../../../Common/Enums/TextAlignment";
 import { EngravingRules } from "../EngravingRules";
 import { FontStyles } from "../../../Common/Enums/FontStyles";
 import { StaffLine } from "../StaffLine";
@@ -16,7 +16,7 @@ export class VexFlowInstantaneousDynamicExpression extends GraphicalInstantaneou
 
         this.mLabel = new GraphicalLabel(new Label(this.Expression),
                                          EngravingRules.Rules.ContinuousDynamicTextHeight,
-                                         TextAlignment.CenterTop,
+                                         TextAlignmentAndPlacement.CenterTop,
                                          this.PositionAndShape);
 
         this.mLabel.Label.fontStyle = FontStyles.BoldItalic;

+ 101 - 33
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -46,9 +46,12 @@ import { GraphicalInstantaneousDynamicExpression } from "../GraphicalInstantaneo
 import { SkyBottomLineCalculator } from "../SkyBottomLineCalculator";
 import { PlacementEnum } from "../../VoiceData/Expressions/AbstractExpression";
 import { Staff } from "../../VoiceData/Staff";
+import { TextAlignmentAndPlacement, TextAlignment } from "../../../Common/Enums/TextAlignment";
 import { GraphicalSlur } from "../GraphicalSlur";
 
 export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
+  /** space needed for a dash for lyrics spacing, calculated once */
+  private dashSpace: number;
 
   constructor() {
     super();
@@ -162,13 +165,14 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
   }
 
   public calculateMeasureWidthFromLyrics(measuresVertical: GraphicalMeasure[], oldMinimumStaffEntriesWidth: number): number {
-    let elongationFactorMeasureWidth: number = 1;
+    let elongationFactorForMeasureWidth: number = 1;
 
     // information we need for the previous lyricsEntries to space the current one
     interface LyricEntryInfo {
       extend: boolean;
-      labelHalfWidth: number;
-      staffEntryXPosition: number;
+      labelWidth: number;
+      lyricsXPosition: number;
+      sourceNoteDuration: Fraction;
       text: string;
       measureNumber: number;
     }
@@ -178,65 +182,129 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
     }
 
     for (const measure of measuresVertical) {
-      const lastLyricEntryDict: LyricEntryDict = {}; // holds info about last lyrics entries for all verses
+      const lastLyricEntryDict: LyricEntryDict = {}; // holds info about last lyrics entries for all verses j
 
+      // for all staffEntries i, each containing the lyric entry for all verses at that timestamp in the measure
       for (let i: number = 0; i < measure.staffEntries.length; i++) {
         const staffEntry: GraphicalStaffEntry = measure.staffEntries[i];
         if (staffEntry.LyricsEntries.length === 0) {
           continue;
         }
-        // for all verses
+        // for all verses j
         for (let j: number = 0; j < staffEntry.LyricsEntries.length; j++) {
           const lyricsEntry: GraphicalLyricEntry = staffEntry.LyricsEntries[j];
-          // const lyricsEntryText = lyricsEntry.GetLyricsEntry.Text; // for easier debugging
+          // const lyricsEntryText = lyricsEntry.LyricsEntry.Text; // for easier debugging
+          const lyricAlignment: TextAlignmentAndPlacement = lyricsEntry.GraphicalLabel.Label.textAlignment;
           let minLyricsSpacing: number = EngravingRules.Rules.HorizontalBetweenLyricsDistance;
+          // for quarter note in Vexflow, where spacing is halfed for each smaller note duration.
+
+          let lyricOverlapAllowedIntoNextMeasure: number =
+            EngravingRules.Rules.LyricOverlapAllowedIntoNextMeasure;
+          // TODO allow more overlap if there are no lyrics in next measure
 
           // spacing for multi-syllable words
           if (lyricsEntry.ParentLyricWord) {
-            if (lyricsEntry.GetLyricsEntry.SyllableIndex > 0) { // syllables after first
+            if (lyricsEntry.LyricsEntry.SyllableIndex > 0) { // syllables after first
               // give a little more spacing for dash between syllables
-            minLyricsSpacing = EngravingRules.Rules.BetweenSyllabelMinimumDistance;
+              minLyricsSpacing = EngravingRules.Rules.BetweenSyllableMinimumDistance;
+              if (TextAlignment.IsCenterAligned(lyricsEntry.GraphicalLabel.Label.textAlignment)) {
+                minLyricsSpacing += 1.0; // TODO check for previous lyric alignment too. though center is not standard
+                // without this, there's not enough space for dashes between long syllables on eigth notes
+              }
+            }
+            const syllables: LyricsEntry[] = lyricsEntry.ParentLyricWord.GetLyricWord.Syllables;
+            if (syllables.length > 1) {
+              if (lyricsEntry.LyricsEntry.SyllableIndex < syllables.length - 1) {
+                // if a middle syllable of a word, give less measure overlap into next measure, to give room for dash
+                if (this.dashSpace === undefined) {
+                  this.dashSpace = 1.5;
+                  // better method, doesn't work:
+                  // this.dashLength = new GraphicalLabel(new Label("-"), this.rules.LyricsHeight, TextAlignmentEnum.CenterBottom)
+                  //   .PositionAndShape.Size.width; // always returns 0
+                }
+                lyricOverlapAllowedIntoNextMeasure -= this.dashSpace;
+              }
+            }
           }
-        }
 
           const lyricsBbox: BoundingBox = lyricsEntry.GraphicalLabel.PositionAndShape;
-          const lyricsLabelHalfWidth: number = lyricsBbox.Size.width / 2;
+          const lyricsLabelWidth: number = lyricsBbox.Size.width;
           const staffEntryXPosition: number = (staffEntry as VexFlowStaffEntry).PositionAndShape.RelativePosition.x;
+          const lyricsXPosition: number = staffEntryXPosition + lyricsBbox.BorderMarginLeft;
 
-          // if we don't have a previous lyricEntry, skip spacing, just save lastLyricEntry information
           if (lastLyricEntryDict[j] !== undefined) {
             if (lastLyricEntryDict[j].extend) {
               // TODO handle extend of last entry (extend is stored in lyrics entry of preceding syllable)
-        }
+              // only necessary for center alignment
+            }
+          }
 
-            const spaceNeededByLyrics: number =
-              lastLyricEntryDict[j].labelHalfWidth + lyricsLabelHalfWidth + minLyricsSpacing;
+          let spacingNeededToLastLyric: number;
+          let currentSpacingToLastLyric: number; // undefined for first lyric in measure
+          if (lastLyricEntryDict[j]) {
+            currentSpacingToLastLyric = lyricsXPosition - lastLyricEntryDict[j].lyricsXPosition;
+          }
+
+          let currentSpacingToMeasureEnd: number;
+          let spacingNeededToMeasureEnd: number;
+          const maxXInMeasure: number = oldMinimumStaffEntriesWidth * elongationFactorForMeasureWidth;
+
+          // when the lyrics are centered, we need to consider spacing differently than when they are left-aligned:
+          if (TextAlignment.IsCenterAligned(lyricAlignment)) {
+            lyricOverlapAllowedIntoNextMeasure /= 4; // reserve space for overlap from next measure. its first note can't be spaced.
+            currentSpacingToMeasureEnd = maxXInMeasure - lyricsXPosition;
+            spacingNeededToMeasureEnd = (lyricsLabelWidth / 2) - lyricOverlapAllowedIntoNextMeasure;
+            // spacing to last lyric only done if not first lyric in measure:
+            if (lastLyricEntryDict[j]) {
+              spacingNeededToLastLyric =
+                lastLyricEntryDict[j].labelWidth / 2 + lyricsLabelWidth / 2 + minLyricsSpacing;
+            }
+          } else if (TextAlignment.IsLeft(lyricAlignment)) {
+            currentSpacingToMeasureEnd = maxXInMeasure - lyricsXPosition;
+            spacingNeededToMeasureEnd = lyricsLabelWidth - lyricOverlapAllowedIntoNextMeasure;
+            if (lastLyricEntryDict[j]) {
+              spacingNeededToLastLyric = lastLyricEntryDict[j].labelWidth + minLyricsSpacing;
+            }
+          }
 
-            const staffEntrySpacing: number = staffEntryXPosition - lastLyricEntryDict[j].staffEntryXPosition;
-        // get factor of how much we need to stretch the measure to space the current lyric with the last one
-            const elongationFactorMeasureWidthForCurrentLabels: number = spaceNeededByLyrics / staffEntrySpacing;
-            elongationFactorMeasureWidth = Math.max(elongationFactorMeasureWidth, elongationFactorMeasureWidthForCurrentLabels);
+          // get factor of how much we need to stretch the measure to space the current lyric
+          let elongationFactorForMeasureWidthForCurrentLyric: number = 1;
+          const elongationFactorNeededForMeasureEnd: number =
+            spacingNeededToMeasureEnd / currentSpacingToMeasureEnd;
+          let elongationFactorNeededForLastLyric: number = 1;
+          if (lastLyricEntryDict[j]) { // if previous lyric needs more spacing than measure end, take that spacing
+            const lastNoteDuration: Fraction = lastLyricEntryDict[j].sourceNoteDuration;
+            elongationFactorNeededForLastLyric = spacingNeededToLastLyric / currentSpacingToLastLyric;
+            if (lastNoteDuration.Denominator > 4) {
+              elongationFactorNeededForLastLyric *= 1.1; // from 1.2 upwards, this unnecessarily bloats shorter measures
+              // spacing in Vexflow depends on note duration, our minSpacing is calibrated for quarter notes
+              // if we double the measure length, the distance between eigth notes only gets half of the added length
+              // compared to a quarter note.
+            }
           }
-          // TODO for spacing between last lyric of a measure and first lyric of the next measure,
-          // we need to look ahead into the next measure, because first note position is not affected
-          // by measure elongation. or return this elongation and let MusicSheetCalculator apply it to prev. measure
-          // e.g. for Austrian national hymn:
-          // if (lyricsEntry.GetLyricsEntry.Text === "kunfts") {
-          //   elongationFactorMeasureWidth *= 1.5;
-          // }
-
-          // set up last lyric entry information for next measure
+          elongationFactorForMeasureWidthForCurrentLyric = Math.max(
+            elongationFactorNeededForMeasureEnd,
+            elongationFactorNeededForLastLyric
+          );
+
+          elongationFactorForMeasureWidth = Math.max(
+            elongationFactorForMeasureWidth,
+            elongationFactorForMeasureWidthForCurrentLyric
+          );
+
+          // set up information about this lyric entry of verse j for next lyric entry of verse j
           lastLyricEntryDict[j] = {
-            extend: lyricsEntry.GetLyricsEntry.extend,
-            labelHalfWidth: lyricsLabelHalfWidth,
+            extend: lyricsEntry.LyricsEntry.extend,
+            labelWidth: lyricsLabelWidth,
+            lyricsXPosition: lyricsXPosition,
             measureNumber: measure.MeasureNumber,
-            staffEntryXPosition: staffEntryXPosition,
-            text: lyricsEntry.GetLyricsEntry.Text,
+            sourceNoteDuration: lyricsEntry.LyricsEntry.Parent.Notes[0].Length,
+            text: lyricsEntry.LyricsEntry.Text,
           };
+        }
       }
     }
-    }
-    return oldMinimumStaffEntriesWidth * elongationFactorMeasureWidth;
+    return oldMinimumStaffEntriesWidth * elongationFactorForMeasureWidth;
   }
 
   protected createGraphicalTie(tie: Tie, startGse: GraphicalStaffEntry, endGse: GraphicalStaffEntry,

+ 0 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.ts

@@ -324,7 +324,6 @@ export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
                           bitmapHeight: number, heightInPixel: number, screenPosition: PointF2D): void {
         const height: number = graphicalLabel.Label.fontHeight * unitInPixels;
         const { fontStyle, font, text } = graphicalLabel.Label;
-
         this.backend.renderText(height, fontStyle, font, text, heightInPixel, screenPosition);
     }
 

+ 3 - 3
src/MusicalScore/Label.ts

@@ -1,4 +1,4 @@
-import {TextAlignment} from "../Common/Enums/TextAlignment";
+import {TextAlignmentAndPlacement} from "../Common/Enums/TextAlignment";
 import {OSMDColor} from "../Common/DataObjects/OSMDColor";
 import {Fonts} from "../Common/Enums/Fonts";
 import {FontStyles} from "../Common/Enums/FontStyles";
@@ -9,7 +9,7 @@ import {FontStyles} from "../Common/Enums/FontStyles";
  */
 export class Label {
 
-    constructor(text: string = "", alignment: TextAlignment = TextAlignment.LeftBottom, font: Fonts = Fonts.TimesNewRoman) {
+    constructor(text: string = "", alignment: TextAlignmentAndPlacement = TextAlignmentAndPlacement.LeftBottom, font: Fonts = Fonts.TimesNewRoman) {
         this.text = text;
         this.textAlignment = alignment;
         this.font = font;
@@ -20,7 +20,7 @@ export class Label {
     public font: Fonts;
     public fontStyle: FontStyles;
     public fontHeight: number;
-    public textAlignment: TextAlignment;
+    public textAlignment: TextAlignmentAndPlacement;
 
     public ToString(): string {
         return this.text;

+ 3 - 2
src/MusicalScore/ScoreIO/MusicSymbolModules/ExpressionReader.ts

@@ -13,7 +13,7 @@ import {InstantaneousTempoExpression} from "../../VoiceData/Expressions/Instanta
 import {MoodExpression} from "../../VoiceData/Expressions/MoodExpression";
 import {UnknownExpression} from "../../VoiceData/Expressions/UnknownExpression";
 import {PlacementEnum} from "../../VoiceData/Expressions/AbstractExpression";
-import {TextAlignment} from "../../../Common/Enums/TextAlignment";
+import {TextAlignmentAndPlacement} from "../../../Common/Enums/TextAlignment";
 import {ITextTranslation} from "../../Interfaces/ITextTranslation";
 import * as log from "loglevel";
 
@@ -535,7 +535,8 @@ export class ExpressionReader {
                 }
             }
         }
-        const unknownExpression: UnknownExpression = new UnknownExpression(stringTrimmed, this.placement, TextAlignment.CenterBottom, this.staffNumber);
+        const unknownExpression: UnknownExpression = new UnknownExpression(
+            stringTrimmed, this.placement, TextAlignmentAndPlacement.CenterBottom, this.staffNumber);
         this.getMultiExpression.addExpression(unknownExpression, prefix);
 
         return false;

+ 5 - 4
src/MusicalScore/ScoreIO/MusicSymbolModules/LyricsReader.ts

@@ -86,8 +86,8 @@ export class LyricsReader {
                             if (syllabic === "single" || syllabic === "end") {
                                 if (this.openLyricWords[currentLyricVerseNumber] !== undefined) { // word end given or some word still open
                                     this.currentLyricWord = this.openLyricWords[currentLyricVerseNumber];
-                                    const syllabelNumber: number = this.currentLyricWord.Syllables.length;
-                                    lyricsEntry = new LyricsEntry(text, currentLyricVerseNumber, this.currentLyricWord, currentVoiceEntry, syllabelNumber);
+                                    const syllableNumber: number = this.currentLyricWord.Syllables.length;
+                                    lyricsEntry = new LyricsEntry(text, currentLyricVerseNumber, this.currentLyricWord, currentVoiceEntry, syllableNumber);
                                     this.currentLyricWord.Syllables.push(lyricsEntry);
                                     delete this.openLyricWords[currentLyricVerseNumber];
                                     this.currentLyricWord = undefined;
@@ -102,12 +102,13 @@ export class LyricsReader {
                                 }
                                 this.currentLyricWord = new LyricWord();
                                 this.openLyricWords[currentLyricVerseNumber] = this.currentLyricWord;
-                                lyricsEntry = new LyricsEntry(text, currentLyricVerseNumber, this.currentLyricWord, currentVoiceEntry);
+                                lyricsEntry = new LyricsEntry(text, currentLyricVerseNumber, this.currentLyricWord, currentVoiceEntry, 0);
                                 this.currentLyricWord.Syllables.push(lyricsEntry);
                             } else if (syllabic === "middle") {
                                 if (this.openLyricWords[currentLyricVerseNumber] !== undefined) {
                                     this.currentLyricWord = this.openLyricWords[currentLyricVerseNumber];
-                                    lyricsEntry = new LyricsEntry(text, currentLyricVerseNumber, this.currentLyricWord, currentVoiceEntry);
+                                    const syllableNumber: number = this.currentLyricWord.Syllables.length;
+                                    lyricsEntry = new LyricsEntry(text, currentLyricVerseNumber, this.currentLyricWord, currentVoiceEntry, syllableNumber);
                                     this.currentLyricWord.Syllables.push(lyricsEntry);
                                 } else {
                                     // in case the wrong syllabel information is given, create a single Entry and add it to currentVoiceEntry

+ 5 - 5
src/MusicalScore/VoiceData/Expressions/UnknownExpression.ts

@@ -1,20 +1,20 @@
 import {PlacementEnum, AbstractExpression} from "./AbstractExpression";
-import {TextAlignment} from "../../../Common/Enums/TextAlignment";
+import {TextAlignmentAndPlacement} from "../../../Common/Enums/TextAlignment";
 
 export class UnknownExpression extends AbstractExpression {
-    constructor(label: string, placementEnum: PlacementEnum, textAlignment: TextAlignment, staffNumber: number) {
+    constructor(label: string, placementEnum: PlacementEnum, textAlignment: TextAlignmentAndPlacement, staffNumber: number) {
         super();
         this.label = label;
         this.placement = placementEnum;
         this.staffNumber = staffNumber;
         if (textAlignment === undefined) {
-            textAlignment = TextAlignment.LeftBottom;
+            textAlignment = TextAlignmentAndPlacement.LeftBottom;
         }
         this.textAlignment = textAlignment;
     }
     private label: string;
     private placement: PlacementEnum;
-    private textAlignment: TextAlignment;
+    private textAlignment: TextAlignmentAndPlacement;
     private staffNumber: number;
 
     public get Label(): string {
@@ -32,7 +32,7 @@ export class UnknownExpression extends AbstractExpression {
     public set StaffNumber(value: number) {
         this.staffNumber = value;
     }
-    public get TextAlignment(): TextAlignment {
+    public get TextAlignment(): TextAlignmentAndPlacement {
         return this.textAlignment;
     }
 }

+ 106 - 105
test/data/Land_der_Berge.musicxml

@@ -12,14 +12,14 @@
     <rights>public domain</rights>
     <encoding>
       <software>MuseScore 2.3.2</software>
-      <encoding-date>2018-08-14</encoding-date>
+      <encoding-date>2018-08-29</encoding-date>
       <supports element="accidental" type="yes"/>
       <supports element="beam" type="yes"/>
       <supports element="print" attribute="new-page" type="yes" value="yes"/>
       <supports element="print" attribute="new-system" type="yes" value="yes"/>
       <supports element="stem" type="yes"/>
       </encoding>
-    <source>https://musescore.com/user/11881/scores/5196133</source>
+    <source>http://musescore.com/user/11881/scores/5196133</source>
     </identification>
   <defaults>
     <scaling>
@@ -27,7 +27,7 @@
       <tenths>40</tenths>
       </scaling>
     <page-layout>
-      <page-height>2176.91</page-height>
+      <page-height>2176.9</page-height>
       <page-width>1540.03</page-width>
       <page-margins type="even">
         <left-margin>73.3138</left-margin>
@@ -46,12 +46,12 @@
     <lyric-font font-family="FreeSerif" font-size="11"/>
     </defaults>
   <credit page="1">
-    <credit-words default-x="770.015" default-y="2103.59" justify="center" valign="top" font-size="22">Land der Berge, Land am Strome
+    <credit-words default-x="770.014" default-y="2103.59" justify="center" valign="top" font-size="22">Land der Berge, Land am Strome
 </credit-words>
     <credit-words font-size="14">Austrian National Anthem</credit-words>
     </credit>
   <credit page="1">
-    <credit-words default-x="1466.72" default-y="2003.59" justify="right" valign="bottom" font-size="12">J. Holzer / W.A. Mozart
+    <credit-words default-x="1466.71" default-y="2003.59" justify="right" valign="bottom" font-size="12">J. Holzer / W.A. Mozart
 </credit-words>
     <credit-words>arr. Viktor Keldorfer</credit-words>
     </credit>
@@ -59,7 +59,7 @@
     <credit-words default-x="73.3138" default-y="2003.59" justify="left" valign="bottom" font-size="12">Paula von Preadović</credit-words>
     </credit>
   <credit page="1">
-    <credit-words default-x="770.015" default-y="73.3138" justify="center" valign="bottom" font-size="8">public domain</credit-words>
+    <credit-words default-x="770.014" default-y="73.3138" justify="center" valign="bottom" font-size="8">public domain</credit-words>
     </credit>
   <part-list>
     <score-part id="P1">
@@ -97,7 +97,7 @@
         <system-layout>
           <system-margins>
             <left-margin>151.60</left-margin>
-            <right-margin>0.00</right-margin>
+            <right-margin>-0.00</right-margin>
             </system-margins>
           <top-system-distance>170.00</top-system-distance>
           </system-layout>
@@ -126,7 +126,7 @@
         <direction-type>
           <words default-x="-50.58" default-y="40.00" font-weight="bold" font-size="12"> Feierlich, doch nicht zu langsam</words>
           </direction-type>
-        <sound tempo="76"/>
+        <sound tempo="76.0002"/>
         </direction>
       <direction placement="below">
         <direction-type>
@@ -776,7 +776,7 @@
           <text>mit</text>
           </lyric>
         <lyric number="3" default-x="25.06" default-y="-156.90">
-          <syllabic>middle</syllabic>
+          <syllabic>begin</syllabic>
           <text>schrei</text>
           </lyric>
         </note>
@@ -875,7 +875,7 @@
         <system-layout>
           <system-margins>
             <left-margin>73.05</left-margin>
-            <right-margin>0.00</right-margin>
+            <right-margin>-0.00</right-margin>
             </system-margins>
           <system-distance>140.89</system-distance>
           </system-layout>
@@ -1068,7 +1068,7 @@
         <accidental>natural</accidental>
         <stem>up</stem>
         <lyric number="1" default-x="6.58" default-y="-100.00">
-          <syllabic>begin</syllabic>
+          <syllabic>middle</syllabic>
           <text>kunfts</text>
           </lyric>
         <lyric number="2" default-x="6.58" default-y="-128.45">
@@ -1076,7 +1076,7 @@
           <text>zen</text>
           </lyric>
         <lyric number="3" default-x="6.58" default-y="-156.90">
-          <syllabic>begin</syllabic>
+          <syllabic>middle</syllabic>
           <text>nungs</text>
           </lyric>
         </note>
@@ -1130,17 +1130,17 @@
         <voice>1</voice>
         <type>half</type>
         <stem>up</stem>
-        <lyric number="1" default-x="8.81" default-y="-100.00">
+        <lyric number="1" default-x="6.22" default-y="-100.00">
           <syllabic>end</syllabic>
-          <text>reich!</text>
+          <text>reich</text>
           </lyric>
         <lyric number="2" default-x="7.84" default-y="-128.45">
           <syllabic>single</syllabic>
           <text>gleich.</text>
           </lyric>
-        <lyric number="3" default-x="8.81" default-y="-156.90">
+        <lyric number="3" default-x="6.22" default-y="-156.90">
           <syllabic>end</syllabic>
-          <text>reich!</text>
+          <text>reich</text>
           </lyric>
         </note>
       <note>
@@ -1493,7 +1493,7 @@
           <text>ta</text>
           </lyric>
         <lyric number="3" default-x="6.58" default-y="-156.90">
-          <syllabic>begin</syllabic>
+          <syllabic>middle</syllabic>
           <text>chö</text>
           </lyric>
         </note>
@@ -1517,9 +1517,9 @@
           <syllabic>end</syllabic>
           <text>gen,</text>
           </lyric>
-        <lyric number="3" default-x="8.20" default-y="-156.90">
+        <lyric number="3" default-x="6.58" default-y="-156.90">
           <syllabic>end</syllabic>
-          <text>ren,</text>
+          <text>ren</text>
           </lyric>
         </note>
       <note>
@@ -1564,12 +1564,12 @@
         <duration>4</duration>
         </forward>
       </measure>
-    <measure number="17" width="203.61">
+    <measure number="17" width="203.95">
       <print new-system="yes">
         <system-layout>
           <system-margins>
             <left-margin>73.05</left-margin>
-            <right-margin>0.00</right-margin>
+            <right-margin>-0.00</right-margin>
             </system-margins>
           <system-distance>140.89</system-distance>
           </system-layout>
@@ -1599,7 +1599,7 @@
           <text>Va</text>
           </lyric>
         </note>
-      <note default-x="162.32" default-y="-25.00">
+      <note default-x="162.55" default-y="-25.00">
         <pitch>
           <step>A</step>
           <octave>4</octave>
@@ -1640,7 +1640,7 @@
           <slur type="start" number="1"/>
           </notations>
         </note>
-      <note default-x="162.32" default-y="-35.00">
+      <note default-x="162.55" default-y="-35.00">
         <pitch>
           <step>F</step>
           <octave>4</octave>
@@ -1654,7 +1654,7 @@
           </notations>
         </note>
       </measure>
-    <measure number="18" width="187.02">
+    <measure number="18" width="187.36">
       <note default-x="14.59" default-y="-15.00">
         <pitch>
           <step>C</step>
@@ -1668,7 +1668,7 @@
           <slur type="start" number="1"/>
           </notations>
         <lyric number="1" default-x="13.59" default-y="-100.00">
-          <syllabic>begin</syllabic>
+          <syllabic>middle</syllabic>
           <text>gna</text>
           </lyric>
         <lyric number="2" default-x="14.43" default-y="-128.45">
@@ -1681,7 +1681,7 @@
           <extend/>
           </lyric>
         </note>
-      <note default-x="71.53" default-y="-20.00">
+      <note default-x="71.64" default-y="-20.00">
         <pitch>
           <step>B</step>
           <alter>-1</alter>
@@ -1695,7 +1695,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="128.47" default-y="-30.00">
+      <note default-x="128.70" default-y="-30.00">
         <pitch>
           <step>G</step>
           <octave>4</octave>
@@ -1733,7 +1733,7 @@
           <slur type="start" number="1"/>
           </notations>
         </note>
-      <note default-x="71.53" default-y="-30.00">
+      <note default-x="71.64" default-y="-30.00">
         <pitch>
           <step>G</step>
           <octave>4</octave>
@@ -1746,7 +1746,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="128.47" default-y="-40.00">
+      <note default-x="128.70" default-y="-40.00">
         <pitch>
           <step>E</step>
           <octave>4</octave>
@@ -1757,7 +1757,7 @@
         <stem>down</stem>
         </note>
       </measure>
-    <measure number="19" width="165.14">
+    <measure number="19" width="165.48">
       <note default-x="26.99" default-y="-25.00">
         <pitch>
           <step>A</step>
@@ -1780,7 +1780,7 @@
           <text>Treu</text>
           </lyric>
         </note>
-      <note default-x="98.69" default-y="-10.00">
+      <note default-x="98.87" default-y="-10.00">
         <pitch>
           <step>D</step>
           <octave>5</octave>
@@ -1794,11 +1794,12 @@
           <slur type="start" number="1"/>
           </notations>
         <lyric number="1" default-x="12.54" default-y="-100.00">
-          <syllabic>begin</syllabic>
+          <syllabic>end</syllabic>
           <text>das</text>
+          <extend/>
           </lyric>
         <lyric number="2" default-x="8.02" default-y="-128.45">
-          <syllabic>middle</syllabic>
+          <syllabic>begin</syllabic>
           <text>ge</text>
           </lyric>
         <lyric number="3" default-x="2.59" default-y="-156.90">
@@ -1807,7 +1808,7 @@
           <extend/>
           </lyric>
         </note>
-      <note default-x="131.12" default-y="-20.00">
+      <note default-x="131.38" default-y="-20.00">
         <pitch>
           <step>B</step>
           <alter>-1</alter>
@@ -1835,7 +1836,7 @@
         <type>half</type>
         <stem>down</stem>
         </note>
-      <note default-x="98.69" default-y="-25.00">
+      <note default-x="98.87" default-y="-25.00">
         <pitch>
           <step>A</step>
           <octave>4</octave>
@@ -1849,7 +1850,7 @@
           <slur type="start" number="1"/>
           </notations>
         </note>
-      <note default-x="131.12" default-y="-35.00">
+      <note default-x="131.38" default-y="-35.00">
         <pitch>
           <step>F</step>
           <octave>4</octave>
@@ -1864,7 +1865,7 @@
           </notations>
         </note>
       </measure>
-    <measure number="20" width="183.82">
+    <measure number="20" width="181.44">
       <note default-x="34.33" default-y="-25.00">
         <pitch>
           <step>A</step>
@@ -1882,7 +1883,7 @@
           <text>Schö</text>
           </lyric>
         <lyric number="2" default-x="6.58" default-y="-128.45">
-          <syllabic>begin</syllabic>
+          <syllabic>middle</syllabic>
           <text>tra</text>
           </lyric>
         <lyric number="3" default-x="6.58" default-y="-156.90">
@@ -1890,7 +1891,7 @@
           <text>schwö</text>
           </lyric>
         </note>
-      <note default-x="83.63" default-y="-30.00">
+      <note default-x="82.84" default-y="-30.00">
         <pitch>
           <step>G</step>
           <octave>4</octave>
@@ -1906,9 +1907,9 @@
           <syllabic>end</syllabic>
           <text>ne,</text>
           </lyric>
-        <lyric number="2" default-x="8.20" default-y="-128.45">
+        <lyric number="2" default-x="6.58" default-y="-128.45">
           <syllabic>end</syllabic>
-          <text>gen,</text>
+          <text>gen</text>
           </lyric>
         <lyric number="3" default-x="8.20" default-y="-156.90">
           <syllabic>end</syllabic>
@@ -1940,7 +1941,7 @@
           <slur type="start" number="1"/>
           </notations>
         </note>
-      <note default-x="83.63" default-y="-40.00">
+      <note default-x="82.84" default-y="-40.00">
         <pitch>
           <step>E</step>
           <octave>4</octave>
@@ -1957,7 +1958,7 @@
         <duration>4</duration>
         </forward>
       </measure>
-    <measure number="21" width="130.26">
+    <measure number="21" width="130.60">
       <direction placement="above">
         <direction-type>
           <dynamics default-x="6.58" default-y="-80.00" relative-x="7.51" relative-y="101.99">
@@ -1989,7 +1990,7 @@
           <text>viel</text>
           </lyric>
         </note>
-      <note default-x="93.20" default-y="-25.00">
+      <note default-x="93.42" default-y="-25.00">
         <pitch>
           <step>A</step>
           <octave>4</octave>
@@ -2024,7 +2025,7 @@
         <type>half</type>
         <stem>down</stem>
         </note>
-      <note default-x="93.20" default-y="-35.00">
+      <note default-x="93.42" default-y="-35.00">
         <pitch>
           <step>F</step>
           <octave>4</octave>
@@ -2035,7 +2036,7 @@
         <stem>down</stem>
         </note>
       </measure>
-    <measure number="22" width="149.97">
+    <measure number="22" width="150.31">
       <note default-x="29.63" default-y="-10.00">
         <pitch>
           <step>D</step>
@@ -2058,7 +2059,7 @@
           <text>lieb</text>
           </lyric>
         </note>
-      <note default-x="108.91" default-y="-15.00">
+      <note default-x="109.14" default-y="-15.00">
         <pitch>
           <step>C</step>
           <octave>5</octave>
@@ -2094,7 +2095,7 @@
         <type>half</type>
         <stem>down</stem>
         </note>
-      <note default-x="108.91" default-y="-25.00">
+      <note default-x="109.14" default-y="-25.00">
         <pitch>
           <step>A</step>
           <octave>4</octave>
@@ -2105,7 +2106,7 @@
         <stem>down</stem>
         </note>
       </measure>
-    <measure number="23" width="162.86">
+    <measure number="23" width="163.19">
       <note default-x="14.59" default-y="-15.00">
         <pitch>
           <step>C</step>
@@ -2132,7 +2133,7 @@
           <text>Ö</text>
           </lyric>
         </note>
-      <note default-x="42.79" default-y="-20.00">
+      <note default-x="42.86" default-y="-20.00">
         <pitch>
           <step>B</step>
           <alter>-1</alter>
@@ -2144,7 +2145,7 @@
         <stem>up</stem>
         <beam number="1">end</beam>
         </note>
-      <note default-x="71.00" default-y="-25.00">
+      <note default-x="71.13" default-y="-25.00">
         <pitch>
           <step>A</step>
           <octave>4</octave>
@@ -2157,7 +2158,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="116.13" default-y="-30.00">
+      <note default-x="116.36" default-y="-30.00">
         <pitch>
           <step>G</step>
           <octave>4</octave>
@@ -2196,7 +2197,7 @@
           <slur type="start" number="1"/>
           </notations>
         </note>
-      <note default-x="42.79" default-y="-30.00">
+      <note default-x="42.86" default-y="-30.00">
         <pitch>
           <step>G</step>
           <octave>4</octave>
@@ -2207,7 +2208,7 @@
         <stem>down</stem>
         <beam number="1">end</beam>
         </note>
-      <note default-x="71.00" default-y="-35.00">
+      <note default-x="71.13" default-y="-35.00">
         <pitch>
           <step>F</step>
           <octave>4</octave>
@@ -2220,7 +2221,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="116.13" default-y="-40.00">
+      <note default-x="116.36" default-y="-40.00">
         <pitch>
           <step>E</step>
           <octave>4</octave>
@@ -2231,7 +2232,7 @@
         <stem>down</stem>
         </note>
       </measure>
-    <measure number="24" width="137.66">
+    <measure number="24" width="138.00">
       <note default-x="29.73" default-y="-25.00">
         <pitch>
           <step>A</step>
@@ -2285,7 +2286,7 @@
         <system-layout>
           <system-margins>
             <left-margin>73.05</left-margin>
-            <right-margin>0.00</right-margin>
+            <right-margin>-0.00</right-margin>
             </system-margins>
           <system-distance>140.89</system-distance>
           </system-layout>
@@ -4462,7 +4463,7 @@
         <staff>2</staff>
         </note>
       </measure>
-    <measure number="17" width="203.61">
+    <measure number="17" width="203.95">
       <print new-system="yes">
         <staff-layout number="1">
           <staff-distance>156.90</staff-distance>
@@ -4497,7 +4498,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="162.32" default-y="-231.90">
+      <note default-x="162.55" default-y="-231.90">
         <pitch>
           <step>F</step>
           <octave>4</octave>
@@ -4511,7 +4512,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="162.32" default-y="-221.90">
+      <note default-x="162.55" default-y="-221.90">
         <chord/>
         <pitch>
           <step>A</step>
@@ -4555,7 +4556,7 @@
           <slur type="start" number="1"/>
           </notations>
         </note>
-      <note default-x="122.62" default-y="-296.90">
+      <note default-x="122.74" default-y="-296.90">
         <pitch>
           <step>B</step>
           <alter>-1</alter>
@@ -4567,7 +4568,7 @@
         <stem>down</stem>
         <staff>2</staff>
         </note>
-      <note default-x="162.32" default-y="-301.90">
+      <note default-x="162.55" default-y="-301.90">
         <pitch>
           <step>A</step>
           <octave>3</octave>
@@ -4582,7 +4583,7 @@
           </notations>
         </note>
       </measure>
-    <measure number="18" width="187.02">
+    <measure number="18" width="187.36">
       <note default-x="14.59" default-y="-221.90">
         <pitch>
           <step>A</step>
@@ -4609,7 +4610,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="71.53" default-y="-226.90">
+      <note default-x="71.64" default-y="-226.90">
         <pitch>
           <step>G</step>
           <octave>4</octave>
@@ -4623,7 +4624,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="71.53" default-y="-216.90">
+      <note default-x="71.64" default-y="-216.90">
         <chord/>
         <pitch>
           <step>B</step>
@@ -4636,7 +4637,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="128.47" default-y="-236.90">
+      <note default-x="128.70" default-y="-236.90">
         <pitch>
           <step>E</step>
           <octave>4</octave>
@@ -4647,7 +4648,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="128.47" default-y="-226.90">
+      <note default-x="128.70" default-y="-226.90">
         <chord/>
         <pitch>
           <step>G</step>
@@ -4673,7 +4674,7 @@
         <stem>down</stem>
         <staff>1</staff>
         </note>
-      <note default-x="128.47" default-y="-246.90">
+      <note default-x="128.70" default-y="-246.90">
         <pitch>
           <step>C</step>
           <octave>4</octave>
@@ -4698,7 +4699,7 @@
         <stem>down</stem>
         <staff>2</staff>
         </note>
-      <note default-x="128.47" default-y="-291.90">
+      <note default-x="128.70" default-y="-291.90">
         <pitch>
           <step>C</step>
           <octave>4</octave>
@@ -4710,7 +4711,7 @@
         <staff>2</staff>
         </note>
       </measure>
-    <measure number="19" width="165.14">
+    <measure number="19" width="165.48">
       <note default-x="26.99" default-y="-231.90">
         <pitch>
           <step>F</step>
@@ -4734,7 +4735,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="98.69" default-y="-226.90">
+      <note default-x="98.87" default-y="-226.90">
         <pitch>
           <step>G</step>
           <octave>4</octave>
@@ -4746,7 +4747,7 @@
         <staff>1</staff>
         <beam number="1">begin</beam>
         </note>
-      <note default-x="98.69" default-y="-216.90">
+      <note default-x="98.87" default-y="-216.90">
         <chord/>
         <pitch>
           <step>B</step>
@@ -4759,7 +4760,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="131.12" default-y="-226.90">
+      <note default-x="131.38" default-y="-226.90">
         <pitch>
           <step>G</step>
           <octave>4</octave>
@@ -4771,7 +4772,7 @@
         <staff>1</staff>
         <beam number="1">end</beam>
         </note>
-      <note default-x="131.12" default-y="-216.90">
+      <note default-x="131.38" default-y="-216.90">
         <chord/>
         <pitch>
           <step>B</step>
@@ -4798,7 +4799,7 @@
         <stem>down</stem>
         <staff>1</staff>
         </note>
-      <note default-x="98.69" default-y="-241.90">
+      <note default-x="98.87" default-y="-241.90">
         <pitch>
           <step>D</step>
           <octave>4</octave>
@@ -4823,7 +4824,7 @@
         <stem>down</stem>
         <staff>2</staff>
         </note>
-      <note default-x="98.69" default-y="-331.90">
+      <note default-x="98.87" default-y="-331.90">
         <pitch>
           <step>B</step>
           <alter>-1</alter>
@@ -4836,7 +4837,7 @@
         <staff>2</staff>
         </note>
       </measure>
-    <measure number="20" width="183.82">
+    <measure number="20" width="181.44">
       <note default-x="34.33" default-y="-231.90">
         <pitch>
           <step>F</step>
@@ -4860,7 +4861,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="83.63" default-y="-236.90">
+      <note default-x="82.84" default-y="-236.90">
         <pitch>
           <step>E</step>
           <octave>4</octave>
@@ -4871,7 +4872,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="83.63" default-y="-226.90">
+      <note default-x="82.84" default-y="-226.90">
         <chord/>
         <pitch>
           <step>G</step>
@@ -4929,7 +4930,7 @@
         <staff>2</staff>
         </note>
       </measure>
-    <measure number="21" width="130.26">
+    <measure number="21" width="130.60">
       <direction placement="below">
         <direction-type>
           <dynamics default-x="6.58" default-y="-80.00">
@@ -4966,7 +4967,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="93.20" default-y="-231.90">
+      <note default-x="93.42" default-y="-231.90">
         <pitch>
           <step>F</step>
           <octave>4</octave>
@@ -4980,7 +4981,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="93.20" default-y="-221.90">
+      <note default-x="93.42" default-y="-221.90">
         <chord/>
         <pitch>
           <step>A</step>
@@ -5005,7 +5006,7 @@
         <type>quarter</type>
         <staff>2</staff>
         </note>
-      <note default-x="57.73" default-y="-316.90">
+      <note default-x="57.85" default-y="-316.90">
         <pitch>
           <step>E</step>
           <octave>3</octave>
@@ -5019,7 +5020,7 @@
           <slur type="start" number="1"/>
           </notations>
         </note>
-      <note default-x="93.20" default-y="-311.90">
+      <note default-x="93.42" default-y="-311.90">
         <pitch>
           <step>F</step>
           <octave>3</octave>
@@ -5036,7 +5037,7 @@
       <backup>
         <duration>8</duration>
         </backup>
-      <note default-x="57.73" default-y="-326.90">
+      <note default-x="57.85" default-y="-326.90">
         <pitch>
           <step>C</step>
           <octave>3</octave>
@@ -5050,7 +5051,7 @@
           <slur type="start" number="1"/>
           </notations>
         </note>
-      <note default-x="93.20" default-y="-346.90">
+      <note default-x="93.42" default-y="-346.90">
         <pitch>
           <step>F</step>
           <octave>2</octave>
@@ -5065,7 +5066,7 @@
           </notations>
         </note>
       </measure>
-    <measure number="22" width="149.97">
+    <measure number="22" width="150.31">
       <note default-x="29.63" default-y="-216.90">
         <pitch>
           <step>B</step>
@@ -5093,7 +5094,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="108.91" default-y="-221.90">
+      <note default-x="109.14" default-y="-221.90">
         <pitch>
           <step>A</step>
           <octave>4</octave>
@@ -5107,7 +5108,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="108.91" default-y="-211.90">
+      <note default-x="109.14" default-y="-211.90">
         <chord/>
         <pitch>
           <step>C</step>
@@ -5129,7 +5130,7 @@
         <type>quarter</type>
         <staff>2</staff>
         </note>
-      <note default-x="69.45" default-y="-316.90">
+      <note default-x="69.56" default-y="-316.90">
         <pitch>
           <step>E</step>
           <octave>3</octave>
@@ -5140,7 +5141,7 @@
         <stem>down</stem>
         <staff>2</staff>
         </note>
-      <note default-x="69.45" default-y="-306.90">
+      <note default-x="69.56" default-y="-306.90">
         <chord/>
         <pitch>
           <step>G</step>
@@ -5152,7 +5153,7 @@
         <stem>down</stem>
         <staff>2</staff>
         </note>
-      <note default-x="108.91" default-y="-311.90">
+      <note default-x="109.14" default-y="-311.90">
         <pitch>
           <step>F</step>
           <octave>3</octave>
@@ -5163,7 +5164,7 @@
         <stem>down</stem>
         <staff>2</staff>
         </note>
-      <note default-x="108.91" default-y="-301.90">
+      <note default-x="109.14" default-y="-301.90">
         <chord/>
         <pitch>
           <step>A</step>
@@ -5176,7 +5177,7 @@
         <staff>2</staff>
         </note>
       </measure>
-    <measure number="23" width="162.86">
+    <measure number="23" width="163.19">
       <note default-x="14.59" default-y="-221.90">
         <pitch>
           <step>A</step>
@@ -5204,7 +5205,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="42.79" default-y="-226.90">
+      <note default-x="42.86" default-y="-226.90">
         <pitch>
           <step>G</step>
           <octave>4</octave>
@@ -5216,7 +5217,7 @@
         <staff>1</staff>
         <beam number="1">end</beam>
         </note>
-      <note default-x="42.79" default-y="-216.90">
+      <note default-x="42.86" default-y="-216.90">
         <chord/>
         <pitch>
           <step>B</step>
@@ -5229,7 +5230,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="71.00" default-y="-231.90">
+      <note default-x="71.13" default-y="-231.90">
         <pitch>
           <step>F</step>
           <octave>4</octave>
@@ -5243,7 +5244,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="71.00" default-y="-221.90">
+      <note default-x="71.13" default-y="-221.90">
         <chord/>
         <pitch>
           <step>A</step>
@@ -5255,7 +5256,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="116.13" default-y="-236.90">
+      <note default-x="116.36" default-y="-236.90">
         <pitch>
           <step>E</step>
           <octave>4</octave>
@@ -5266,7 +5267,7 @@
         <stem>up</stem>
         <staff>1</staff>
         </note>
-      <note default-x="116.13" default-y="-226.90">
+      <note default-x="116.36" default-y="-226.90">
         <chord/>
         <pitch>
           <step>G</step>
@@ -5295,7 +5296,7 @@
           <slur type="start" number="1"/>
           </notations>
         </note>
-      <note default-x="71.00" default-y="-246.90">
+      <note default-x="71.13" default-y="-246.90">
         <pitch>
           <step>C</step>
           <octave>4</octave>
@@ -5309,7 +5310,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="116.13" default-y="-246.90">
+      <note default-x="116.36" default-y="-246.90">
         <pitch>
           <step>C</step>
           <octave>4</octave>
@@ -5338,7 +5339,7 @@
           <slur type="start" number="1"/>
           </notations>
         </note>
-      <note default-x="71.00" default-y="-326.90">
+      <note default-x="71.13" default-y="-326.90">
         <pitch>
           <step>C</step>
           <octave>3</octave>
@@ -5352,7 +5353,7 @@
           <slur type="stop" number="1"/>
           </notations>
         </note>
-      <note default-x="116.13" default-y="-326.90">
+      <note default-x="116.36" default-y="-326.90">
         <pitch>
           <step>C</step>
           <octave>3</octave>
@@ -5364,7 +5365,7 @@
         <staff>2</staff>
         </note>
       </measure>
-    <measure number="24" width="137.66">
+    <measure number="24" width="138.00">
       <note default-x="29.73" default-y="-231.90">
         <pitch>
           <step>F</step>