Parcourir la source

merge osmd-public: fix lyrics non-number handling and unnecessary space for unused lyrics lines

sschmidTU il y a 2 ans
Parent
commit
602f9d7032

+ 28 - 4
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -71,6 +71,7 @@ import { JustifiedMusicSystemBuilder } from "./JustifiedMusicSystemBuilder";
 import { IStafflineNoteCalculator } from "../Interfaces/IStafflineNoteCalculator";
 import { GraphicalUnknownExpression } from "./GraphicalUnknownExpression";
 import { GraphicalChordSymbolContainer } from ".";
+import { LyricsEntry } from "../VoiceData/Lyrics/LyricsEntry";
 
 /**
  * Class used to do all the calculations in a MusicSheet, which in the end populates a GraphicalMusicSheet.
@@ -548,9 +549,10 @@ export abstract class MusicSheetCalculator {
      * @param staffLine
      * @param lyricVersesNumber
      */
-    protected calculateSingleStaffLineLyricsPosition(staffLine: StaffLine, lyricVersesNumber: number[]): GraphicalStaffEntry[] {
+    protected calculateSingleStaffLineLyricsPosition(staffLine: StaffLine, lyricVersesNumber: string[]): GraphicalStaffEntry[] {
         let numberOfVerses: number = 0;
         let lyricsStartYPosition: number = this.rules.StaffHeight; // Add offset to prevent collision
+        const relevantVerseNumbers: Map<string, boolean> = new Map<string, boolean>();
         const lyricsStaffEntriesList: GraphicalStaffEntry[] = [];
         const skyBottomLineCalculator: SkyBottomLineCalculator = staffLine.SkyBottomLineCalculator;
 
@@ -562,7 +564,15 @@ export abstract class MusicSheetCalculator {
             const len2: number = measure.staffEntries.length;
             for (let idx2: number = 0; idx2 < len2; ++idx2) {
                 const staffEntry: GraphicalStaffEntry = measure.staffEntries[idx2];
-                if (staffEntry.LyricsEntries.length > 0) {
+
+                // Collect relevant verse numbers
+                const len3: number = staffEntry.LyricsEntries.length;
+                for (let idx3: number = 0; idx3 < len3; ++idx3) {
+                    const lyricsEntry: LyricsEntry = staffEntry.LyricsEntries[idx3].LyricsEntry;
+                    relevantVerseNumbers[lyricsEntry.VerseNumber] = lyricsEntry.IsChorus;
+                }
+
+                if (len3 > 0) {
                     lyricsStaffEntriesList.push(staffEntry);
                     numberOfVerses = Math.max(numberOfVerses, staffEntry.LyricsEntries.length);
 
@@ -591,6 +601,19 @@ export abstract class MusicSheetCalculator {
         // iterate again through the Staffentries with LyricEntries
         len = lyricsStaffEntriesList.length;
         for (const staffEntry of lyricsStaffEntriesList) {
+
+            // Filter verse numbers
+            const filteredLyricVersesNumber: string[] = [];
+            let isChorus: boolean = true;
+            for (let i: number = 0; i < staffEntry.LyricsEntries.length; i++) {
+                isChorus &&= staffEntry.LyricsEntries[i].LyricsEntry.IsChorus;
+            }
+            for (const lyricVerseNumber of lyricVersesNumber){
+                if (relevantVerseNumbers[lyricVerseNumber] === isChorus) {
+                    filteredLyricVersesNumber.push(lyricVerseNumber);
+                }
+            }
+
             // set LyricEntryLabel RelativePosition
             for (let i: number = 0; i < staffEntry.LyricsEntries.length; i++) {
                 const lyricEntry: GraphicalLyricEntry = staffEntry.LyricsEntries[i];
@@ -598,8 +621,8 @@ 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.LyricsEntry.VerseNumber;
-                const sortedLyricVerseNumberIndex: number = lyricVersesNumber.indexOf(verseNumber);
+                const verseNumber: string = lyricEntry.LyricsEntry.VerseNumber;
+                const sortedLyricVerseNumberIndex: number = filteredLyricVersesNumber.indexOf(verseNumber);
                 const firstPosition: number = lyricsStartYPosition + this.rules.LyricsHeight + this.rules.VerticalBetweenLyricsDistance +
                     this.rules.LyricsYOffsetToStaffHeight;
 
@@ -610,6 +633,7 @@ export abstract class MusicSheetCalculator {
                 }
                 const previousRelativeX: number = lyricsEntryLabel.PositionAndShape.RelativePosition.x;
                 lyricsEntryLabel.PositionAndShape.RelativePosition = new PointF2D(previousRelativeX, position);
+                lyricsEntryLabel.Label.fontStyle = lyricEntry.LyricsEntry.FontStyle;
                 maxPosition = Math.max(maxPosition, position);
             }
         }

+ 1 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -1671,7 +1671,7 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
   }
 
   protected handleVoiceEntryLyrics(voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry, lyricWords: LyricWord[]): void {
-    voiceEntry.LyricsEntries.forEach((key: number, lyricsEntry: LyricsEntry) => {
+    voiceEntry.LyricsEntries.forEach((key: string, lyricsEntry: LyricsEntry) => {
       const graphicalLyricEntry: GraphicalLyricEntry = new GraphicalLyricEntry(lyricsEntry,
                                                                                graphicalStaffEntry,
                                                                                this.rules.LyricsHeight,

+ 3 - 3
src/MusicalScore/Instrument.ts

@@ -32,7 +32,7 @@ export class Instrument extends InstrumentalGroup {
     private hasChordSymbols: boolean = false;
     private playbackTranspose: number = 0;
 
-    private lyricVersesNumbers: number[] = [];
+    private lyricVersesNumbers: string[] = [];
     private subInstruments: SubInstrument[] = [];
     private partAbbreviation: string;
 
@@ -57,10 +57,10 @@ export class Instrument extends InstrumentalGroup {
     public set HasChordSymbols(value: boolean) {
         this.hasChordSymbols = value;
     }
-    public get LyricVersesNumbers(): number[] {
+    public get LyricVersesNumbers(): string[] {
         return this.lyricVersesNumbers;
     }
-    public set LyricVersesNumbers(value: number[]) {
+    public set LyricVersesNumbers(value: string[]) {
         this.lyricVersesNumbers = value;
     }
     public get Name(): string {

+ 3 - 25
src/MusicalScore/ScoreIO/MusicSymbolModules/LyricsReader.ts

@@ -71,28 +71,9 @@ export class LyricsReader {
                                     syllabic = "middle";
                                 }
                             }
-                            let currentLyricVerseNumber: number = 1;
-                            let errorNumberParse1: boolean = false;
+                            let currentLyricVerseNumber: string = "1";
                             if (lyricNode.attributes() !== undefined && lyricNode.attribute("number")) {
-                                try {
-                                    currentLyricVerseNumber = parseInt(lyricNode.attribute("number").value, 10); // usually doesn't throw error, but returns NaN
-                                } catch (err) {
-                                    errorNumberParse1 = true;
-                                }
-                                errorNumberParse1 = errorNumberParse1 || isNaN(currentLyricVerseNumber);
-                                if (errorNumberParse1) {
-                                    try { // Sibelius format: "part1verse1"
-                                        const result: string[] = lyricNode.attribute("number").value.toLowerCase().split("verse");
-                                        if (result.length > 1) {
-                                            currentLyricVerseNumber = parseInt(result[1], 10);
-                                        }
-                                    } catch (err) {
-                                        const errorMsg: string =
-                                        ITextTranslation.translateText("ReaderErrorMessages/LyricVerseNumberError", "Invalid lyric verse number");
-                                        this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
-                                        continue;
-                                    }
-                                }
+                                currentLyricVerseNumber = lyricNode.attribute("number").value;
                             }
                             let lyricsEntry: LyricsEntry = undefined;
                             if (syllabic === "single" || syllabic === "end") {
@@ -138,7 +119,7 @@ export class LyricsReader {
                                     }
                                 }
                                 // save in currentInstrument the verseNumber (only once)
-                                if (!currentVoiceEntry.ParentVoice.Parent.LyricVersesNumbers[currentLyricVerseNumber]) {
+                                if (!currentVoiceEntry.ParentVoice.Parent.LyricVersesNumbers.includes(currentLyricVerseNumber)) {
                                     currentVoiceEntry.ParentVoice.Parent.LyricVersesNumbers.push(currentLyricVerseNumber);
                                 }
                             }
@@ -150,9 +131,6 @@ export class LyricsReader {
                     continue;
                 }
             }
-            // Squash to unique numbers
-            currentVoiceEntry.ParentVoice.Parent.LyricVersesNumbers =
-            currentVoiceEntry.ParentVoice.Parent.LyricVersesNumbers.filter((lvn, index, self) => self.indexOf(lvn) === index);
         }
     }
 }

+ 16 - 3
src/MusicalScore/VoiceData/Lyrics/LyricsEntry.ts

@@ -1,8 +1,9 @@
 import {LyricWord} from "./LyricsWord";
 import {VoiceEntry} from "../VoiceEntry";
+import { FontStyles } from "../../../Common/Enums/FontStyles";
 
 export class LyricsEntry {
-    constructor(text: string, verseNumber: number, word: LyricWord, parent: VoiceEntry, syllableNumber: number = -1) {
+    constructor(text: string, verseNumber: string, word: LyricWord, parent: VoiceEntry, syllableNumber: number = -1) {
         this.text = text;
         this.word = word;
         this.parent = parent;
@@ -14,7 +15,7 @@ export class LyricsEntry {
     private text: string;
     private word: LyricWord;
     private parent: VoiceEntry;
-    private verseNumber: number;
+    private verseNumber: string;
     private syllableIndex: number;
     public extend: boolean;
 
@@ -34,11 +35,23 @@ export class LyricsEntry {
         this.parent = value;
     }
 
-    public get VerseNumber(): number {
+    public get VerseNumber(): string {
         return this.verseNumber;
     }
 
     public get SyllableIndex(): number {
         return this.syllableIndex;
     }
+
+    public get IsTranslation(): boolean {
+        return this.VerseNumber.endsWith("translation");
+    }
+
+    public get IsChorus(): boolean {
+        return this.VerseNumber.startsWith("chorus");
+    }
+
+    public get FontStyle(): FontStyles {
+        return this.IsChorus || this.IsTranslation ? FontStyles.Italic : FontStyles.Regular;
+    }
 }

+ 5 - 5
src/MusicalScore/VoiceData/VoiceEntry.ts

@@ -66,7 +66,7 @@ export class VoiceEntry {
     private playbackEntries: PlaybackEntry[] = [];
     private fermata: Articulation;
     private technicalInstructions: TechnicalInstruction[] = [];
-    private lyricsEntries: Dictionary<number, LyricsEntry> = new Dictionary<number, LyricsEntry>();
+    private lyricsEntries: Dictionary<string, LyricsEntry> = new Dictionary<string, LyricsEntry>();
     /** The Arpeggio consisting of this VoiceEntry's notes. Undefined if no arpeggio exists. */
     private arpeggio: Arpeggio;
     private ornamentContainer: OrnamentContainer;
@@ -197,7 +197,7 @@ export class VoiceEntry {
     public get TechnicalInstructions(): TechnicalInstruction[] {
         return this.technicalInstructions;
     }
-    public get LyricsEntries(): Dictionary<number, LyricsEntry> {
+    public get LyricsEntries(): Dictionary<string, LyricsEntry> {
         return this.lyricsEntries;
     }
     public get Arpeggio(): Arpeggio {
@@ -322,9 +322,9 @@ export class VoiceEntry {
         }
         return false;
     }
-    public getVerseNumberForLyricEntry(lyricsEntry: LyricsEntry): number {
-        let verseNumber: number = 1;
-        this.lyricsEntries.forEach((key: number, value: LyricsEntry): void => {
+    public getVerseNumberForLyricEntry(lyricsEntry: LyricsEntry): string {
+        let verseNumber: string = "1";
+        this.lyricsEntries.forEach((key: string, value: LyricsEntry): void => {
             if (lyricsEntry === value) {
                 verseNumber = key;
             }