Quellcode durchsuchen

Merge branch 'feature/chordSymbols' into develop

# Conflicts:
#	src/MusicalScore/ScoreIO/InstrumentReader.ts
Matthias Uiberacker vor 7 Jahren
Ursprung
Commit
cd012fdd0d

+ 25 - 0
src/MusicalScore/Graphical/BoundingBox.ts

@@ -205,6 +205,20 @@ export class BoundingBox {
     }
 
     /**
+     * Calculate the the absolute position by adding up all relative positions of all parents (including the own rel. pos.)
+     */
+    public calculateAbsolutePosition(): void {
+      this.absolutePosition.x = this.relativePosition.x;
+      this.absolutePosition.y = this.relativePosition.y;
+      let parent: BoundingBox = this.parent;
+      while (parent !== undefined) {
+        this.absolutePosition.x += parent.relativePosition.x;
+        this.absolutePosition.y += parent.relativePosition.y;
+        parent = parent.parent;
+      }
+    }
+
+    /**
      * This method calculates the Absolute Positions recursively
      */
     public calculateAbsolutePositionsRecursiveWithoutTopelement(): void {
@@ -218,6 +232,7 @@ export class BoundingBox {
 
     /**
      * This method calculates the Absolute Positions recursively
+     * from the root element down to the leaf elements
      * @param x
      * @param y
      */
@@ -231,6 +246,16 @@ export class BoundingBox {
     }
 
     /**
+     * calculates the absolute positions of all children of this boundingBox
+     */
+    public calculateAbsolutePositionsOfChildren(): void {
+      for (let idx: number = 0, len: number = this.ChildElements.length; idx < len; ++idx) {
+        let child: BoundingBox = this.ChildElements[idx];
+        child.calculateAbsolutePositionsRecursive(this.absolutePosition.x, this.absolutePosition.y);
+      }
+    }
+
+    /**
      * This method calculates the BoundingBoxes
      */
     public calculateBoundingBox(): void {

+ 13 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowGraphicalSymbolFactory.ts

@@ -19,6 +19,9 @@ import {Pitch} from "../../../Common/DataObjects/Pitch";
 import {TechnicalInstruction} from "../../VoiceData/Instructions/TechnicalInstruction";
 import {VexFlowGraphicalNote} from "./VexFlowGraphicalNote";
 import {Fraction} from "../../../Common/DataObjects/Fraction";
+import {GraphicalChordSymbolContainer} from "../GraphicalChordSymbolContainer";
+import {GraphicalLabel} from "../GraphicalLabel";
+import {EngravingRules} from "../EngravingRules";
 
 export class VexFlowGraphicalSymbolFactory implements IGraphicalSymbolFactory {
     /**
@@ -172,6 +175,15 @@ export class VexFlowGraphicalSymbolFactory implements IGraphicalSymbolFactory {
      * @param transposeHalftones
      */
     public createChordSymbol(sourceStaffEntry: SourceStaffEntry, graphicalStaffEntry: GraphicalStaffEntry, transposeHalftones: number): void {
-        return;
+      let graphicalChordSymbolContainer: GraphicalChordSymbolContainer =
+        new GraphicalChordSymbolContainer(sourceStaffEntry.ChordContainer,
+                                          graphicalStaffEntry.PositionAndShape,
+                                          EngravingRules.Rules.ChordSymbolTextHeight,
+                                          transposeHalftones);
+      let graphicalLabel: GraphicalLabel = graphicalChordSymbolContainer.GetGraphicalLabel;
+      graphicalLabel.setLabelPositionAndShapeBorders();
+      graphicalChordSymbolContainer.PositionAndShape.calculateBoundingBox();
+      graphicalStaffEntry.graphicalChordContainer = graphicalChordSymbolContainer;
+      graphicalStaffEntry.PositionAndShape.ChildElements.push(graphicalChordSymbolContainer.PositionAndShape);
     }
 }

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

@@ -447,6 +447,8 @@ export class VexFlowMeasure extends StaffMeasure {
                 measure.ParentStaffLine.PositionAndShape.RelativePosition.x -
                 measure.parentMusicSystem.PositionAndShape.RelativePosition.x;
             gse.PositionAndShape.RelativePosition.x = x;
+            gse.PositionAndShape.calculateAbsolutePosition();
+            gse.PositionAndShape.calculateAbsolutePositionsOfChildren();
         }
     }
 }

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

@@ -8,6 +8,8 @@ import {VexFlowConverter} from "./VexFlowConverter";
 import {VexFlowTextMeasurer} from "./VexFlowTextMeasurer";
 import {MusicSystem} from "../MusicSystem";
 import {GraphicalObject} from "../GraphicalObject";
+import {GraphicalLayers} from "../DrawingEnums";
+import {GraphicalStaffEntry} from "../GraphicalStaffEntry";
 
 /**
  * This is a global contant which denotes the height in pixels of the space between two lines of the stave
@@ -68,7 +70,19 @@ export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
             measure.PositionAndShape.AbsolutePosition.x * unitInPixels,
             measure.PositionAndShape.AbsolutePosition.y * unitInPixels
         );
-        return measure.draw(this.vfctx);
+        measure.draw(this.vfctx);
+
+        // Draw the StaffEntries
+        for (let staffEntry of measure.staffEntries){
+            this.drawStaffEntry(staffEntry);
+        }
+    }
+
+    private drawStaffEntry(staffEntry: GraphicalStaffEntry): void {
+        // Draw ChordSymbol
+        if (staffEntry.graphicalChordContainer !== undefined) {
+            this.drawLabel(staffEntry.graphicalChordContainer.GetGraphicalLabel, <number>GraphicalLayers.Notes);
+        }
     }
 
     protected drawInstrumentBrace(bracket: GraphicalObject, system: MusicSystem): void {

+ 18 - 16
src/MusicalScore/ScoreIO/InstrumentReader.ts

@@ -19,6 +19,7 @@ import {IXmlAttribute} from "../../Common/FileIO/Xml";
 import {ChordSymbolContainer} from "../VoiceData/ChordSymbolContainer";
 import {Logging} from "../../Common/Logging";
 import {MidiInstrument} from "../VoiceData/Instructions/ClefInstruction";
+import {ChordSymbolReader} from "./MusicSymbolModules/ChordSymbolReader";
 //import Dictionary from "typescript-collections/dist/lib/Dictionary";
 
 // FIXME: The following classes are missing
@@ -55,20 +56,20 @@ export type RepetitionInstructionReader = any;
 export class InstrumentReader {
 
   constructor(repetitionInstructionReader: RepetitionInstructionReader, xmlMeasureList: IXmlElement[], instrument: Instrument) {
-    // (*) this.repetitionInstructionReader = repetitionInstructionReader;
-    this.xmlMeasureList = xmlMeasureList;
-    this.musicSheet = instrument.GetMusicSheet;
-    this.instrument = instrument;
-    this.activeClefs = new Array(instrument.Staves.length);
-    this.activeClefsHaveBeenInitialized = new Array(instrument.Staves.length);
-    for (let i: number = 0; i < instrument.Staves.length; i++) {
-      this.activeClefsHaveBeenInitialized[i] = false;
-    }
-    // FIXME createExpressionGenerators(instrument.Staves.length);
-    // (*) this.slurReader = MusicSymbolModuleFactory.createSlurReader(this.musicSheet);
+      this.repetitionInstructionReader = repetitionInstructionReader;
+      this.xmlMeasureList = xmlMeasureList;
+      this.musicSheet = instrument.GetMusicSheet;
+      this.instrument = instrument;
+      this.activeClefs = new Array(instrument.Staves.length);
+      this.activeClefsHaveBeenInitialized = new Array(instrument.Staves.length);
+      for (let i: number = 0; i < instrument.Staves.length; i++) {
+        this.activeClefsHaveBeenInitialized[i] = false;
+      }
+      // FIXME createExpressionGenerators(instrument.Staves.length);
+      // (*) this.slurReader = MusicSymbolModuleFactory.createSlurReader(this.musicSheet);
   }
 
-  // (*) private repetitionInstructionReader: RepetitionInstructionReader;
+  private repetitionInstructionReader: RepetitionInstructionReader;
   private xmlMeasureList: IXmlElement[];
   private musicSheet: MusicSheet;
   private slurReader: any; // (*) SlurReader;
@@ -312,8 +313,9 @@ export class InstrumentReader {
           if (this.activeRhythm !== undefined && this.activeRhythm.Rhythm !== undefined) {
             relativePositionInMeasure /= this.activeRhythm.Rhythm.RealValue;
           }
-          // unused: let handeled: boolean = false;
-          // (*) if (this.repetitionInstructionReader !== undefined) {
+                    // unused:
+                    // let handeled: boolean = false;
+                    // if (this.repetitionInstructionReader !== undefined) {
           //  handeled = this.repetitionInstructionReader.handleRepetitionInstructionsFromWordsOrSymbols(directionTypeNode,
           //                                                                                              relativePositionInMeasure);
           //}
@@ -337,7 +339,7 @@ export class InstrumentReader {
           //  }
           //}
         } else if (xmlNode.name === "barline") {
-          // (*)
+
           //if (this.repetitionInstructionReader !== undefined) {
           //  let measureEndsSystem: boolean = false;
           //  this.repetitionInstructionReader.handleLineRepetitionInstructions(xmlNode, measureEndsSystem);
@@ -349,7 +351,7 @@ export class InstrumentReader {
         } else if (xmlNode.name === "sound") {
           // (*) MetronomeReader.readTempoInstruction(xmlNode, this.musicSheet, this.currentXmlMeasureIndex);
         } else if (xmlNode.name === "harmony") {
-          // (*) this.openChordSymbolContainer = ChordSymbolReader.readChordSymbol(xmlNode, this.musicSheet, this.activeKey);
+                    this.openChordSymbolContainer = ChordSymbolReader.readChordSymbol(xmlNode, this.musicSheet, this.activeKey);
         }
       }
       for (let j in this.voiceGeneratorsDict) {

+ 145 - 0
src/MusicalScore/ScoreIO/MusicSymbolModules/ChordSymbolReader.ts

@@ -0,0 +1,145 @@
+import {IXmlElement} from "../../../Common/FileIO/Xml";
+import {MusicSheet} from "../../MusicSheet";
+import {ChordDegreeText, ChordSymbolContainer, ChordSymbolEnum, Degree} from "../../VoiceData/ChordSymbolContainer";
+import {AccidentalEnum, NoteEnum, Pitch} from "../../../Common/DataObjects/Pitch";
+import {KeyInstruction} from "../../VoiceData/Instructions/KeyInstruction";
+import {ITextTranslation} from "../../Interfaces/ITextTranslation";
+import {Logging} from "../../../Common/Logging";
+export class ChordSymbolReader {
+    public static readChordSymbol(xmlNode: IXmlElement, musicSheet: MusicSheet, activeKey: KeyInstruction): ChordSymbolContainer {
+        let root: IXmlElement = xmlNode.element("root");
+        let kind: IXmlElement = xmlNode.element("kind");
+
+        // must be always present
+        if (root === undefined || kind === undefined) {
+          return undefined;
+        }
+
+        let rootStep: IXmlElement = root.element("root-step");
+        let rootAlter: IXmlElement = root.element("root-alter");
+
+        // a valid NoteEnum value should be present
+        if (rootStep === undefined) {
+            return undefined;
+        }
+        let rootNote: NoteEnum;
+        try {
+            rootNote = NoteEnum[rootStep.value.trim()];
+        } catch (ex) {
+            let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/ChordSymbolError",
+                                                                  "Invalid chord symbol");
+            musicSheet.SheetErrors.pushMeasureError(errorMsg);
+            Logging.error(LogLevel.DEBUG, "InstrumentReader.readChordSymbol", errorMsg, ex);
+            return undefined;
+        }
+
+        // an alteration value isn't necessary
+        let rootAlteration: AccidentalEnum = AccidentalEnum.NONE;
+        if (rootAlter !== undefined) {
+            try {
+                rootAlteration = <AccidentalEnum>parseInt(rootAlter.value, undefined);
+            } catch (ex) {
+                let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/ChordSymbolError",
+                                                                      "Invalid chord symbol");
+                musicSheet.SheetErrors.pushMeasureError(errorMsg);
+                Logging.error(LogLevel.DEBUG, "InstrumentReader.readChordSymbol", errorMsg, ex);
+            }
+
+        }
+        // using default octave value, to be changed later
+        let rootPitch: Pitch = new Pitch(rootNote, 1, rootAlteration);
+        let kindValue: string = kind.value.trim().replace("-", "");
+        let chordKind: ChordSymbolEnum;
+        try {
+            chordKind = ChordSymbolEnum[kindValue];
+        } catch (ex) {
+            let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/ChordSymbolError",
+                                                                  "Invalid chord symbol");
+            musicSheet.SheetErrors.pushMeasureError(errorMsg);
+            Logging.error(LogLevel.DEBUG, "InstrumentReader.readChordSymbol", errorMsg, ex);
+            return undefined;
+        }
+
+        // bass is optional
+        let bassPitch: Pitch = undefined;
+        let bass: IXmlElement = xmlNode.element("bass");
+        if (bass !== undefined) {
+            let bassStep: IXmlElement = bass.element("bass-step");
+            let bassAlter: IXmlElement = bass.element("bass-alter");
+            let bassNote: NoteEnum = NoteEnum.C;
+            if (bassStep !== undefined) {
+                try {
+                    bassNote = NoteEnum[bassStep.value.trim()];
+                } catch (ex) {
+                    let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/ChordSymbolError",
+                                                                          "Invalid chord symbol");
+                    musicSheet.SheetErrors.pushMeasureError(errorMsg);
+                    Logging.error(LogLevel.DEBUG, "InstrumentReader.readChordSymbol", errorMsg, ex);
+                    return undefined;
+                }
+
+            }
+            let bassAlteration: AccidentalEnum = AccidentalEnum.NONE;
+            if (bassAlter !== undefined) {
+                try {
+                    bassAlteration = <AccidentalEnum>parseInt(bassAlter.value, undefined);
+                } catch (ex) {
+                    let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/ChordSymbolError",
+                                                                          "Invalid chord symbol");
+                    musicSheet.SheetErrors.pushMeasureError(errorMsg);
+                    Logging.error(LogLevel.DEBUG, "InstrumentReader.readChordSymbol", errorMsg, ex);
+                }
+
+            }
+            bassPitch = new Pitch(bassNote, 1, bassAlteration);
+        }
+
+        // degree is optional
+        let degree: Degree = undefined;
+        let degreeNode: IXmlElement = xmlNode.element("degree");
+        if (degreeNode !== undefined) {
+            let degreeValue: IXmlElement = degreeNode.element("degree-value");
+            let degreeAlter: IXmlElement = degreeNode.element("degree-alter");
+            let degreeType: IXmlElement = degreeNode.element("degree-type");
+            if (degreeValue === undefined || degreeAlter === undefined || degreeType === undefined) {
+              return undefined;
+            }
+
+            let value: number;
+            try {
+                value = parseInt(degreeValue.value.trim(), undefined);
+            } catch (ex) {
+                let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/ChordSymbolError",
+                                                                      "Invalid chord symbol");
+                musicSheet.SheetErrors.pushMeasureError(errorMsg);
+                Logging.error(LogLevel.DEBUG, "InstrumentReader.readChordSymbol", errorMsg, ex);
+                return undefined;
+            }
+
+            let alter: AccidentalEnum;
+            try {
+                alter = <AccidentalEnum>parseInt(degreeAlter.value, undefined);
+            } catch (ex) {
+                let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/ChordSymbolError",
+                                                                      "Invalid chord symbol");
+                musicSheet.SheetErrors.pushMeasureError(errorMsg);
+                Logging.error(LogLevel.DEBUG, "InstrumentReader.readChordSymbol", errorMsg, ex);
+                return undefined;
+            }
+
+            let text: ChordDegreeText;
+            try {
+                text = ChordDegreeText[degreeType.value.trim().toLowerCase()];
+            } catch (ex) {
+                let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/ChordSymbolError",
+                                                                      "Invalid chord symbol");
+                musicSheet.SheetErrors.pushMeasureError(errorMsg);
+                Logging.error(LogLevel.DEBUG, "InstrumentReader.readChordSymbol", errorMsg, ex);
+                return undefined;
+            }
+
+            degree = new Degree(value, alter, text);
+        }
+        return new ChordSymbolContainer(rootPitch, chordKind, bassPitch, degree, activeKey);
+    }
+}