소스 검색

Implemented Page rendering using multiple backends

Matthias Uiberacker 5 년 전
부모
커밋
e0cf6eed71

+ 23 - 20
src/MusicalScore/Graphical/GraphicalMusicPage.ts

@@ -48,26 +48,29 @@ export class GraphicalMusicPage extends GraphicalObject {
      * @returns {PointF2D}
      */
     public setMusicPageAbsolutePosition(pageIndex: number, rules: EngravingRules): PointF2D {
-        if (rules.PagePlacement === PagePlacementEnum.Down) {
-            return new PointF2D(0.0, pageIndex * rules.PageHeight);
-        } else if (rules.PagePlacement === PagePlacementEnum.Right) {
-            return new PointF2D(pageIndex * this.parent.ParentMusicSheet.pageWidth, 0.0);
-        } else {
-            // placement RightDown
-            if (pageIndex % 2 === 0) {
-                if (pageIndex === 0) {
-                    return new PointF2D(0.0, pageIndex * rules.PageHeight);
-                } else {
-                    return new PointF2D(0.0, (pageIndex - 1) * rules.PageHeight);
-                }
-            } else {
-                if (pageIndex === 1) {
-                    return new PointF2D(this.parent.ParentMusicSheet.pageWidth, (pageIndex - 1) * rules.PageHeight);
-                } else {
-                    return new PointF2D(this.parent.ParentMusicSheet.pageWidth, (pageIndex - 2) * rules.PageHeight);
-                }
-            }
-        }
+        return new PointF2D(0.0, 0.0);
+
+        // use this code if pages are rendered on only one canvas:
+        // if (rules.PagePlacement === PagePlacementEnum.Down) {
+        //     return new PointF2D(0.0, pageIndex * rules.PageHeight);
+        // } else if (rules.PagePlacement === PagePlacementEnum.Right) {
+        //     return new PointF2D(pageIndex * this.parent.ParentMusicSheet.pageWidth, 0.0);
+        // } else {
+        //     // placement RightDown
+        //     if (pageIndex % 2 === 0) {
+        //         if (pageIndex === 0) {
+        //             return new PointF2D(0.0, pageIndex * rules.PageHeight);
+        //         } else {
+        //             return new PointF2D(0.0, (pageIndex - 1) * rules.PageHeight);
+        //         }
+        //     } else {
+        //         if (pageIndex === 1) {
+        //             return new PointF2D(this.parent.ParentMusicSheet.pageWidth, (pageIndex - 1) * rules.PageHeight);
+        //         } else {
+        //             return new PointF2D(this.parent.ParentMusicSheet.pageWidth, (pageIndex - 2) * rules.PageHeight);
+        //         }
+        //     }
+        // }
     }
 }
 

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

@@ -190,7 +190,7 @@ export abstract class MusicSheetCalculator {
         this.calculateMusicSystems();
 
         // Add some white space at the end of the piece:
-        this.graphicalMusicSheet.MusicPages[0].PositionAndShape.BorderMarginBottom += 9;
+        //this.graphicalMusicSheet.MusicPages[0].PositionAndShape.BorderMarginBottom += 9;
 
         // transform Relative to Absolute Positions
         GraphicalMusicSheet.transformRelativeToAbsolutePosition(this.graphicalMusicSheet);

+ 1 - 1
src/MusicalScore/Graphical/MusicSheetDrawer.ts

@@ -464,7 +464,7 @@ export abstract class MusicSheetDrawer {
         this.graphicalMusicSheet.LeadSheet = value;
     }
 
-    private drawPage(page: GraphicalMusicPage): void {
+    protected drawPage(page: GraphicalMusicPage): void {
         if (!this.isVisible(page.PositionAndShape)) {
             return;
         }

+ 2 - 9
src/MusicalScore/Graphical/MusicSystemBuilder.ts

@@ -48,7 +48,7 @@ export class MusicSystemBuilder {
         this.rules = this.graphicalMusicSheet.ParentMusicSheet.rules;
         this.measureList = measureList;
         this.currentMusicPage = this.createMusicPage();
-        this.currentPageHeight = 0.0;
+        this.currentPageHeight = this.rules.PageTopMargin + this.rules.TitleTopDistance;
         this.numberOfVisibleStaffLines = numberOfStaffLines;
         this.activeRhythm = new Array(this.numberOfVisibleStaffLines);
         this.activeKeys = new Array(this.numberOfVisibleStaffLines);
@@ -170,16 +170,9 @@ export class MusicSystemBuilder {
         this.stretchMusicSystem(isPartEndingSystem);
         if (this.currentPageHeight + this.currentSystemParams.currentSystem.PositionAndShape.Size.height + this.rules.SystemDistance <= this.rules.PageHeight) {
             this.currentPageHeight += this.currentSystemParams.currentSystem.PositionAndShape.Size.height + this.rules.SystemDistance;
-            if (
-                this.currentPageHeight + this.currentSystemParams.currentSystem.PositionAndShape.Size.height
-                + this.rules.SystemDistance >= this.rules.PageHeight
-            ) {
-                this.currentMusicPage = this.createMusicPage();
-                this.currentPageHeight = this.rules.PageTopMargin + this.rules.TitleTopDistance;
-            }
         } else {
             this.currentMusicPage = this.createMusicPage();
-            this.currentPageHeight = this.rules.PageTopMargin + this.rules.TitleTopDistance;
+            this.currentPageHeight = this.rules.PageTopMargin;
         }
         this.currentSystemParams = new SystemBuildParameters();
         if (this.measureListIndex < this.measureList.length) {

+ 32 - 22
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.ts

@@ -26,6 +26,8 @@ import log = require("loglevel");
 import { GraphicalContinuousDynamicExpression } from "../GraphicalContinuousDynamicExpression";
 import { VexFlowContinuousDynamicExpression } from "./VexFlowContinuousDynamicExpression";
 import { DrawingParameters } from "../DrawingParameters";
+import { GraphicalMusicPage } from "../GraphicalMusicPage";
+import { GraphicalMusicSheet } from "../GraphicalMusicSheet";
 
 /**
  * This is a global constant which denotes the height in pixels of the space between two lines of the stave
@@ -36,39 +38,47 @@ export const unitInPixels: number = 10;
 
 export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
     private backend: VexFlowBackend;
+    private backends: VexFlowBackend[] = [];
     private zoom: number = 1.0;
+    private pageIdx: number = 0;
 
-    constructor(element: HTMLElement,
-                backend: VexFlowBackend,
-                drawingParameters: DrawingParameters = new DrawingParameters()) {
+    constructor(drawingParameters: DrawingParameters = new DrawingParameters()) {
         super(new VexFlowTextMeasurer(), drawingParameters);
-        this.backend = backend;
     }
 
-    public clear(): void {
-        this.backend.clear();
+    public get Backends(): VexFlowBackend[] {
+        return this.backends;
     }
 
-    /**
-     * Zoom the rendering areas
-     * @param k is the zoom factor
-     */
-    public scale(k: number): void {
-        this.zoom = k;
-        this.backend.scale(this.zoom);
+    public drawSheet(graphicalMusicSheet: GraphicalMusicSheet): void {
+        this.pageIdx = 0;
+        for (const {} of graphicalMusicSheet.MusicPages) {
+            const backend: VexFlowBackend = this.backends[this.pageIdx];
+            backend.scale(this.zoom);
+            backend.resize(graphicalMusicSheet.ParentMusicSheet.pageWidth * unitInPixels * this.zoom,
+                           EngravingRules.Rules.PageHeight * unitInPixels * this.zoom);
+            this.pageIdx += 1;
+        }
+
+        this.pageIdx = 0;
+        this.backend = this.backends[0];
+        super.drawSheet(graphicalMusicSheet);
     }
 
-    /**
-     * Resize the rendering areas
-     * @param x
-     * @param y
-     */
-    public resize(x: number, y: number): void {
-        this.backend.resize(x, y);
+    protected drawPage(page: GraphicalMusicPage): void {
+        super.drawPage(page);
+        this.pageIdx += 1;
+        this.backend = this.backends[this.pageIdx];
+    }
+
+    public clear(): void {
+        for (const backend of this.backends) {
+            backend.clear();
+        }
     }
 
-    public translate(x: number, y: number): void {
-        this.backend.translate(x, y);
+    public setZoom(zoom: number): void {
+        this.zoom = zoom;
     }
 
     /**

+ 36 - 27
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -63,9 +63,7 @@ export class OpenSheetMusicDisplay {
     public zoom: number = 1.0;
 
     private container: HTMLElement;
-    private canvas: HTMLElement;
-    private backend: VexFlowBackend;
-    private innerElement: HTMLElement;
+    private backendType: any;
     private sheet: MusicSheet;
     private drawer: VexFlowMusicSheetDrawer;
     private graphic: GraphicalMusicSheet;
@@ -178,6 +176,7 @@ export class OpenSheetMusicDisplay {
         // Set page width
         const width: number = this.container.offsetWidth;
         this.sheet.pageWidth = width / this.zoom / 10.0;
+        EngravingRules.Rules.PageHeight = this.sheet.pageWidth * 1.41;
         // Before introducing the following optimization (maybe irrelevant), tests
         // have to be modified to ensure that width is > 0 when executed
         //if (isNaN(width) || width === 0) {
@@ -186,13 +185,17 @@ export class OpenSheetMusicDisplay {
 
         // Calculate again
         this.graphic.reCalculate();
-        const height: number = this.graphic.MusicPages[0].PositionAndShape.BorderBottom * 10.0 * this.zoom;
+
         if (this.drawingParameters.drawCursors) {
             this.graphic.Cursors.length = 0;
         }
+
         // Update Sheet Page
-        this.drawer.resize(width, height);
-        this.drawer.scale(this.zoom);
+        this.drawer.Backends.clear();
+        for (const {} of this.graphic.MusicPages) {
+            this.drawer.Backends.push(this.createBackend(this.backendType));
+        }
+        this.drawer.setZoom(this.zoom);
         // Finally, draw
         this.drawer.drawSheet(this.graphic);
         if (this.drawingParameters.drawCursors && this.cursor) {
@@ -230,28 +233,23 @@ export class OpenSheetMusicDisplay {
                 (<any>DrawingParametersEnum)[options.drawingParameters.toLowerCase()];
         }
 
-        const updateExistingBackend: boolean = this.backend !== undefined;
-        if (options.backend !== undefined || this.backend === undefined) {
-            if (updateExistingBackend) {
-                // TODO doesn't work yet, still need to create a new OSMD object
+        this.backendType = options.backend;
+        // const updateExistingBackend: boolean = this.backend !== undefined;
+        // if (options.backend !== undefined || this.backend === undefined) {
+        //     if (updateExistingBackend) {
+        //         // TODO doesn't work yet, still need to create a new OSMD object
 
-                this.drawer.clear();
+        //         this.drawer.clear();
 
-                // musicSheetCalculator.clearSystemsAndMeasures() // maybe? don't have reference though
-                // musicSheetCalculator.clearRecreatedObjects();
-            }
-            if (options.backend === undefined || options.backend.toLowerCase() === "svg") {
-                this.backend = new SvgVexFlowBackend();
-            } else {
-                this.backend = new CanvasVexFlowBackend();
-            }
-            this.backend.initialize(this.container);
-            this.canvas = this.backend.getCanvas();
-            this.innerElement = this.backend.getInnerElement();
-            this.enableOrDisableCursor(this.drawingParameters.drawCursors);
-            // Create the drawer
-            this.drawer = new VexFlowMusicSheetDrawer(this.canvas, this.backend, this.drawingParameters);
-        }
+        //         // musicSheetCalculator.clearSystemsAndMeasures() // maybe? don't have reference though
+        //         // musicSheetCalculator.clearRecreatedObjects();
+        //     }
+        // }
+
+        // Create the drawer
+        this.drawer = new VexFlowMusicSheetDrawer(this.drawingParameters);
+
+        //this.enableOrDisableCursor(this.drawingParameters.drawCursors);
 
         // individual drawing parameters options
         if (options.autoBeam !== undefined) {
@@ -552,7 +550,7 @@ export class OpenSheetMusicDisplay {
         this.drawingParameters.drawCursors = enable;
         if (enable) {
             if (!this.cursor) {
-                this.cursor = new Cursor(this.innerElement, this);
+                this.cursor = new Cursor(this.drawer.Backends[0].getInnerElement(), this);
                 if (this.sheet && this.graphic) { // else init is called in load()
                     this.cursor.init(this.sheet.MusicPartManager, this.graphic);
                 }
@@ -568,6 +566,17 @@ export class OpenSheetMusicDisplay {
         }
     }
 
+    public createBackend(type: any): VexFlowBackend {
+        let backend: VexFlowBackend;
+        if (type === undefined || type.toLowerCase() === "svg") {
+            backend = new SvgVexFlowBackend();
+        } else {
+            backend = new CanvasVexFlowBackend();
+        }
+        backend.initialize(this.container);
+        return backend;
+    }
+
     //#region GETTER / SETTER
     public set DrawSkyLine(value: boolean) {
         if (this.drawer) {

+ 4 - 2
test/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer_Test.ts

@@ -28,7 +28,8 @@ describe("VexFlow Music Sheet Drawer", () => {
         const canvas: HTMLCanvasElement = document.createElement("canvas");
         const backend: VexFlowBackend = new CanvasVexFlowBackend();
         backend.initialize(canvas);
-        const drawer: VexFlowMusicSheetDrawer = new VexFlowMusicSheetDrawer(canvas, backend);
+        const drawer: VexFlowMusicSheetDrawer = new VexFlowMusicSheetDrawer();
+        drawer.Backends.push(backend);
         drawer.drawSheet(gms);
         done();
     });
@@ -48,7 +49,8 @@ describe("VexFlow Music Sheet Drawer", () => {
         const canvas: HTMLCanvasElement = document.createElement("canvas");
         const backend: VexFlowBackend = new CanvasVexFlowBackend();
         backend.initialize(canvas);
-        const drawer: VexFlowMusicSheetDrawer = new VexFlowMusicSheetDrawer(canvas, backend, new DrawingParameters());
+        const drawer: VexFlowMusicSheetDrawer = new VexFlowMusicSheetDrawer(new DrawingParameters());
+        drawer.Backends.push(backend);
         drawer.drawSheet(gms);
         done();
     });