Просмотр исходного кода

fix autoMultiRest: respect expressions, clefInstruction (#861)

previously, when there were expressions in a measure (e.g. "Solo", Haydn sample bar 128),
the measure was reduced to a multirest measure, because it only checked whether the measure was all rests.

same applies to a clef change for the following measure (e.g. Haydn sample,
the two rest measures right before the end, with a clef change to tenor clef,
would have been hidden by the multirest measure)

This also affected measures with only tempo expressions (metronome marks),
see function test metronome marks
sschmid 4 лет назад
Родитель
Сommit
ed06811474

+ 1 - 0
demo/index.js

@@ -36,6 +36,7 @@ import * as svg2pdf from '../node_modules/svg2pdf.js/dist/svg2pdf.min';
             "OSMD Function Test - Expressions": "OSMD_function_test_expressions.musicxml",
             "OSMD Function Test - Expressions Overlap": "OSMD_function_test_expressions_overlap.musicxml",
             "OSMD Function Test - Grace Notes": "OSMD_function_test_GraceNotes.xml",
+            "OSMD Function Test - Metronome Marks": "OSMD_function_test_metronome_marks.mxl",
             "OSMD Function Test - Multiple Rest Measures": "OSMD_function_test_multiple_rest_measures.musicxml",
             "OSMD Function Test - Invisible Notes": "OSMD_function_test_invisible_notes.musicxml",
             "OSMD Function Test - Notehead Shapes": "OSMD_function_test_noteheadShapes.musicxml",

+ 6 - 3
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -186,7 +186,7 @@ export abstract class MusicSheetCalculator {
             //go through all source measures again. Need to calc auto-multi-rests
             for (let idx: number = 0, len: number = musicSheet.SourceMeasures.length; idx < len; ++idx) {
                 const sourceMeasure: SourceMeasure = musicSheet.SourceMeasures[idx];
-                if (sourceMeasure.allRests) {
+                if (sourceMeasure.canBeReducedToMultiRest()) {
                     //we've already been initialized, we are in the midst of a multirest sequence
                     if (multiRestCount > 0) {
                         multiRestCount++;
@@ -198,8 +198,8 @@ export abstract class MusicSheetCalculator {
                         beginMultiRestMeasure = sourceMeasure;
                         multiRestCount = 1;
                     }
-                } else {//not multirest measure
-                    if (multiRestCount > 1) {//Actual multirest sequence just happened. Process
+                } else { //not multirest measure
+                    if (multiRestCount > 1) { //Actual multirest sequence just happened. Process
                         beginMultiRestMeasure.multipleRestMeasures = multiRestCount;
                         //regen graphical measures for this source measure
                         const graphicalMeasures: GraphicalMeasure[] = this.createGraphicalMeasuresForSourceMeasure(
@@ -1436,6 +1436,9 @@ export abstract class MusicSheetCalculator {
             if (this.rules.MinMeasureToDrawIndex > 0) {
                 return; // assuming that the tempo is always in measure 1 (idx 0), adding the expression causes issues when we don't draw measure 1
             }
+            if (!measures[0]) {
+                return;
+            }
             let staffLine: StaffLine = measures[0].ParentStaffLine;
             let firstVisibleMeasureX: number = measures[0].PositionAndShape.RelativePosition.x;
             let verticalIndex: number = 0;

+ 1 - 0
src/MusicalScore/ScoreIO/MusicSymbolModules/ExpressionReader.ts

@@ -537,6 +537,7 @@ export class ExpressionReader {
         }
         if (MoodExpression.isInputStringMood(stringTrimmed)) {
             this.createNewMultiExpressionIfNeeded(currentMeasure);
+            currentMeasure.hasMoodExpressions = true;
             const moodExpression: MoodExpression = new MoodExpression(stringTrimmed, this.placement, this.staffNumber);
             this.getMultiExpression.addExpression(moodExpression, prefix);
             return true;

+ 25 - 1
src/MusicalScore/VoiceData/SourceMeasure.ts

@@ -8,8 +8,9 @@ import {Voice} from "./Voice";
 import {MusicSheet} from "../MusicSheet";
 import {MultiExpression} from "./Expressions/MultiExpression";
 import {MultiTempoExpression} from "./Expressions/MultiTempoExpression";
-import {KeyInstruction} from "./Instructions/KeyInstruction";
 import {AbstractNotationInstruction} from "./Instructions/AbstractNotationInstruction";
+import {ClefInstruction} from "./Instructions/ClefInstruction";
+import {KeyInstruction} from "./Instructions/KeyInstruction";
 import {Repetition} from "../MusicSource/Repetition";
 import {SystemLinesEnum} from "../Graphical/SystemLinesEnum";
 import {EngravingRules} from "../Graphical/EngravingRules";
@@ -65,6 +66,7 @@ export class SourceMeasure {
     private duration: Fraction;
     private activeTimeSignature: Fraction;
     public hasLyrics: boolean = false;
+    public hasMoodExpressions: boolean = false;
     public allRests: boolean = false;
     private staffLinkedExpressions: MultiExpression[][] = [];
     private tempoExpressions: MultiTempoExpression[] = [];
@@ -573,4 +575,26 @@ export class SourceMeasure {
         }
         return entry;
     }
+
+    public canBeReducedToMultiRest(): boolean {
+        if (!this.allRests || this.hasLyrics || this.hasMoodExpressions || this.tempoExpressions.length > 0) {
+            return false;
+        }
+        // check for StaffLinkedExpressions (e.g. MultiExpression, StaffText) (per staff)
+        for (const multiExpressions of this.staffLinkedExpressions) {
+            if (multiExpressions.length > 0) {
+                return false;
+            }
+        }
+        // check for clef instruction for next measure
+        for (const lastStaffEntry of this.lastInstructionsStaffEntries) {
+            for (let idx: number = 0, len: number = lastStaffEntry?.Instructions.length; idx < len; ++idx) {
+                const abstractNotationInstruction: AbstractNotationInstruction = lastStaffEntry.Instructions[idx];
+                if (abstractNotationInstruction instanceof ClefInstruction) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
 }