Browse Source

merge osmd-public/develop: fix wrong end clef for certain Sibelius scores, fix tuplet show-number="none" not respected, fix subtitle not recognized

sschmidTU 1 year ago
parent
commit
75ba63a74a

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

@@ -180,6 +180,8 @@ export class EngravingRules {
     public TupletNumberLimitConsecutiveRepetitions: boolean;
     public TupletNumberMaxConsecutiveRepetitions: number;
     public TupletNumberAlwaysDisableAfterFirstMax: boolean;
+    /** Whether to use the <tuplet show-number="value"> value or to ignore it. */
+    public TupletNumberUseShowNoneXMLValue: boolean;
     public LabelMarginBorderFactor: number;
     public TupletVerticalLineLength: number;
     public TupletNumbersInTabs: boolean;
@@ -652,6 +654,7 @@ export class EngravingRules {
         this.TupletNumberLimitConsecutiveRepetitions = true;
         this.TupletNumberMaxConsecutiveRepetitions = 2;
         this.TupletNumberAlwaysDisableAfterFirstMax = true;
+        this.TupletNumberUseShowNoneXMLValue = true;
         this.LabelMarginBorderFactor = 0.1;
         this.TupletVerticalLineLength = 0.5;
         this.TupletNumbersInTabs = false; // disabled by default, nonstandard in tabs, at least how we show them in non-tabs.

+ 2 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -643,7 +643,8 @@ export class VexFlowMeasure extends GraphicalMeasure {
                         if (!vftuplet) { // see #1330, potentially to be investigated. why undefined?
                             continue;
                         }
-                        if (!tuplet.RenderTupletNumber) {
+                        if (!tuplet.RenderTupletNumber ||
+                            tuplet.ShowNumberNoneGivenInXml && this.rules.TupletNumberUseShowNoneXMLValue) {
                             // (vftuplet as any).numerator_glyphs_stored = [...(vftuplet as any).numerator_glyphs];
                             // (vftuplet as any).numerator_glyphs = [];
                             (vftuplet as any).RenderTupletNumber = false;

+ 7 - 5
src/MusicalScore/ScoreIO/InstrumentReader.ts

@@ -1080,11 +1080,13 @@ export class InstrumentReader {
             let lastStaffEntryBefore: SourceStaffEntry;
             const duration: Fraction = this.activeRhythm.Rhythm;
             if (duration.RealValue > 0 &&
-              instructionTimestamp.RealValue / duration.RealValue > 0.90) {
-                if (!this.currentMeasure.LastInstructionsStaffEntries[key - 1]) {
-                  this.currentMeasure.LastInstructionsStaffEntries[key - 1] = new SourceStaffEntry(undefined, this.instrument.Staves[key - 1]);
-                }
-                lastStaffEntryBefore = this.currentMeasure.LastInstructionsStaffEntries[key - 1];
+              instructionTimestamp.RealValue / duration.RealValue > 0.90 && // necessary for #1120
+              duration.RealValue !== instructionTimestamp.RealValue // necessary for #1461
+            ) {
+              if (!this.currentMeasure.LastInstructionsStaffEntries[key - 1]) {
+                this.currentMeasure.LastInstructionsStaffEntries[key - 1] = new SourceStaffEntry(undefined, this.instrument.Staves[key - 1]);
+              }
+              lastStaffEntryBefore = this.currentMeasure.LastInstructionsStaffEntries[key - 1];
             }
             // TODO figure out a more elegant way to do this. (see #1120)
             //   the problem is that not all the staffentries in the measure exist yet,

+ 8 - 3
src/MusicalScore/ScoreIO/MusicSheetReader.ts

@@ -607,8 +607,13 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
                     // eslint-disable-next-line no-null/no-null
                     const creditYGiven: boolean = creditY !== undefined && creditY !== null;
                     const creditYInfo: number = creditYGiven ? parseFloat(creditY) : Number.MIN_VALUE;
-                    if (creditYGiven && creditYInfo > systemYCoordinates) {
-                        if (!this.musicSheet.Title) {
+                    let isSubtitle: boolean = false;
+                    const typeChild: IXmlElement = credit.element("credit-type");
+                    if (typeChild?.value === "subtitle") {
+                        isSubtitle = true;
+                    }
+                    if ((creditYGiven && creditYInfo > systemYCoordinates) || isSubtitle) {
+                        if (!this.musicSheet.Title && !isSubtitle) {
                             const creditSize: string = creditChild.attribute("font-size")?.value;
                             if (creditSize) {
                                 const titleCreditSizeInt: number = parseFloat(creditSize);
@@ -619,7 +624,7 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
                             }
                         }
                         if (!this.musicSheet.Subtitle) {
-                            if (creditJustify !== "right" && creditJustify !== "left") {
+                            if (creditJustify !== "right" && creditJustify !== "left" || isSubtitle) {
                                 if (largestCreditYInfo < creditYInfo) {
                                     largestCreditYInfo = creditYInfo;
                                     if (possibleTitle) {

+ 15 - 0
src/MusicalScore/ScoreIO/VoiceGenerator.ts

@@ -752,6 +752,8 @@ export class VoiceGenerator {
             bracketedXmlValue = false;
           }
 
+          const showNumberNoneGiven: boolean = this.readShowNumberNoneGiven(tupletNode);
+
           const type: Attr = tupletNode.attribute("type");
           if (type && type.value === "start") {
             let tupletNumber: number = 1;
@@ -772,6 +774,7 @@ export class VoiceGenerator {
             }
             const tuplet: Tuplet = new Tuplet(tupletLabelNumber, bracketed);
             tuplet.BracketedXmlValue = bracketedXmlValue;
+            tuplet.ShowNumberNoneGivenInXml = showNumberNoneGiven;
             //Default to above
             tuplet.tupletLabelNumberPlacement = PlacementEnum.Above;
             //If we ever encounter a placement attribute for this tuplet, should override.
@@ -859,6 +862,7 @@ export class VoiceGenerator {
           tupletnumber = parseInt(n.attribute("number").value, 10);
         }
         const noTupletNumbering: boolean = isNaN(tupletnumber);
+        const showNumberNoneGiven: boolean = this.readShowNumberNoneGiven(n);
 
         const bracketAttr: Attr = n.attribute("bracket");
         if (bracketAttr && bracketAttr.value === "yes") {
@@ -892,6 +896,7 @@ export class VoiceGenerator {
           if (!tuplet) {
             tuplet = this.tupletDict[tupletnumber] = new Tuplet(tupletLabelNumber, bracketed);
             tuplet.BracketedXmlValue = bracketedXmlValue;
+            tuplet.ShowNumberNoneGivenInXml = showNumberNoneGiven;
             //Default to above
             tuplet.tupletLabelNumberPlacement = PlacementEnum.Above;
           }
@@ -967,6 +972,16 @@ export class VoiceGenerator {
     return this.openTupletNumber;
   }
 
+  private readShowNumberNoneGiven(tupletNode: IXmlElement): boolean {
+    const showNumber: Attr = tupletNode.attribute("show-number");
+    if (showNumber?.value) {
+      if (showNumber.value === "none") {
+        return true;
+      }
+    }
+    return false;
+  }
+
   /**
    * This method handles the time-modification IXmlElement for the Tuplet case (tupletNotes not at begin/end of Tuplet).
    * @param noteNode

+ 2 - 0
src/MusicalScore/VoiceData/Tuplet.ts

@@ -24,6 +24,8 @@ export class Tuplet {
     private bracket: boolean;
     /** Boolean if 'bracket="no"' or "yes" was explicitly requested in the XML, otherwise undefined. */
     public BracketedXmlValue: boolean;
+    /** Whether <tuplet show-number="none"> was given in the XML, indicating the tuplet number should not be rendered. */
+    public ShowNumberNoneGivenInXml: boolean;
 
     /** Determines whether the tuplet should be bracketed (arguments are EngravingRules). */
     public shouldBeBracketed(useXmlValue: boolean, tupletsBracketed: boolean, tripletsBracketed: boolean): boolean {