Browse Source

merge osmd-public 1.8.4: fix iOS memory leak on Canvas backend, fix repetition volta number

the memory leak only affected iOS and only on the canvas backend (it's recommended to use the default SVG backend),
see osmd issue 1411.
sschmidTU 1 year ago
parent
commit
ce3e44cda0

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "osmd-extended",
-  "version": "1.8.3",
+  "version": "1.8.4",
   "description": "Private / sponsor exclusive OSMD mirror/audio player.",
   "main": "build/opensheetmusicdisplay.min.js",
   "types": "build/dist/src/index.d.ts",

+ 12 - 0
src/MusicalScore/Graphical/VexFlow/CanvasVexFlowBackend.ts

@@ -74,6 +74,18 @@ export class CanvasVexFlowBackend extends VexFlowBackend {
         return this.ctx;
     }
 
+    public free(): void {
+        if (this.canvas) {
+            // the following seems to only be necessary on iOS, preventing a memory leak (#1411)
+            (this.canvas as any).width = 0;
+            (this.canvas as any).height = 0;
+
+            this.canvas.remove();
+            delete this.canvas;
+            this.canvas = null;
+        }
+    }
+
     public clear(): void {
         (<any>this.ctx).clearRect(0, 0, (<any>this.canvas).width, (<any>this.canvas).height);
 

+ 8 - 4
src/MusicalScore/Graphical/VexFlow/SvgVexFlowBackend.ts

@@ -74,10 +74,7 @@ export class SvgVexFlowBackend extends VexFlowBackend {
         return true;
     }
 
-    public clear(): void {
-        if (!this.ctx) {
-            return;
-        }
+    public free(): void {
         //const { svg } = this.ctx; // seems to make svg static between osmd instances.
         const svg: SVGElement = this.ctx.svg;
         // removes all children from the SVG element,
@@ -85,6 +82,13 @@ export class SvgVexFlowBackend extends VexFlowBackend {
         while (svg.lastChild) {
             svg.removeChild(svg.lastChild);
         }
+    }
+
+    public clear(): void {
+        if (!this.ctx) {
+            return;
+        }
+        this.free();
 
         // set background color if not transparent
         if (this.rules.PageBackgroundColor) {

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

@@ -87,6 +87,8 @@ public abstract getContext(): Vex.IRenderContext;
   }
 
   public abstract clear(): void;
+  /** (Try to) free memory. Currently only relevant on iOS. */
+  public abstract free(): void;
 
   public abstract translate(x: number, y: number): void;
   public abstract renderText(fontHeight: number, fontStyle: FontStyles, font: Fonts, text: string,

+ 11 - 1
src/MusicalScore/ScoreIO/MusicSymbolModules/RepetitionInstructionReader.ts

@@ -60,8 +60,18 @@ export class RepetitionInstructionReader {
           direction = childNode.attribute("direction").value;
         } else if ( "ending" === childNode.name && childNode.hasAttributes &&
                     childNode.attribute("type") !== undefined && childNode.attribute("number")) {
+          if (childNode.attribute("print-object")?.value === "no") {
+            continue;
+            // Finale only puts print-object="no" at the (duplicated) <ending> node at thestart of measure barline,
+            //   making this uneffective. Unclear whether the intention is to render the volta or not. (See #1367)
+          }
           type = childNode.attribute("type").value;
-          const num: string = childNode.attribute("number").value;
+          let num: string = childNode.attribute("number").value;
+          if (childNode.value) {
+            num = childNode.value;
+            // MusicXML spec: "The element text is used when the text displayed in the ending is different than what appears in the number attribute."
+            //   Finale v27.3 accordingly seems to put the desired printed number here instead of in "number" (#1367)
+          }
 
           // Parse the given ending indices:
           // handle cases like: "1, 2" or "1 + 2" or even "1 - 3, 6"

+ 7 - 1
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -35,7 +35,7 @@ import { DynamicsCalculator } from "../MusicalScore/ScoreIO/MusicSymbolModules/D
  * After the constructor, use load() and render() to load and render a MusicXML file.
  */
 export class OpenSheetMusicDisplay {
-    private version: string = "1.8.3-audio-extended"; // getter: this.Version
+    private version: string = "1.8.4-audio-extended"; // getter: this.Version
     // at release, bump version and change to -release, afterwards to -dev again
 
     /**
@@ -244,6 +244,9 @@ export class OpenSheetMusicDisplay {
                     // error loading sheet, probably already logged, do nothing
                     mainReject(new Error("given music sheet was incomplete or could not be loaded."));
                 }
+                // if (this.sheet.TitleString === "osmd.Version") {
+                //     this.sheet.TitleString = "OSMD version: " + this.Version; // useful for debug e.g. when console not available
+                // }
                 log.info(`[OSMD] Loaded sheet ${self.sheet.TitleString} successfully.`);
 
                 //If we have a comment XML, read it
@@ -363,6 +366,9 @@ export class OpenSheetMusicDisplay {
             if (this.drawer.Backends[0]) {
                 this.drawer.Backends[0].removeAllChildrenFromContainer(this.container);
             }
+            for (const backend of this.drawer.Backends) {
+                backend.free();
+            }
             this.drawer.Backends.clear();
         }
 

+ 102 - 0
test/data/osmd.Version.musicxml

@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 3.1 Partwise//EN" "http://www.musicxml.org/dtds/partwise.dtd">
+<score-partwise version="3.1">
+  <work>
+    <work-title>osmd.Version</work-title>
+    </work>
+  <identification>
+    <creator type="composer">Composer</creator>
+    <encoding>
+      <software>MuseScore 3.6.2</software>
+      <encoding-date>2022-07-12</encoding-date>
+      <supports element="accidental" type="yes"/>
+      <supports element="beam" type="yes"/>
+      <supports element="print" attribute="new-page" type="yes" value="yes"/>
+      <supports element="print" attribute="new-system" type="yes" value="yes"/>
+      <supports element="stem" type="yes"/>
+      </encoding>
+    </identification>
+  <defaults>
+    <scaling>
+      <millimeters>6.99911</millimeters>
+      <tenths>40</tenths>
+      </scaling>
+    <page-layout>
+      <page-height>1596.77</page-height>
+      <page-width>1233.87</page-width>
+      <page-margins type="even">
+        <left-margin>85.7252</left-margin>
+        <right-margin>85.7252</right-margin>
+        <top-margin>85.7252</top-margin>
+        <bottom-margin>85.7252</bottom-margin>
+        </page-margins>
+      <page-margins type="odd">
+        <left-margin>85.7252</left-margin>
+        <right-margin>85.7252</right-margin>
+        <top-margin>85.7252</top-margin>
+        <bottom-margin>85.7252</bottom-margin>
+        </page-margins>
+      </page-layout>
+    <word-font font-family="Edwin" font-size="10"/>
+    <lyric-font font-family="Edwin" font-size="10"/>
+    </defaults>
+  <credit page="1">
+    <credit-type>title</credit-type>
+    <credit-words default-x="616.935" default-y="1511.05" justify="center" valign="top" font-size="22">osmd.Version</credit-words>
+    </credit>
+  <credit page="1">
+    <credit-type>composer</credit-type>
+    <credit-words default-x="1148.15" default-y="1411.05" justify="right" valign="bottom">Composer</credit-words>
+    </credit>
+  <part-list>
+    <score-part id="P1">
+      <part-name>Piano</part-name>
+      <part-abbreviation>Pno.</part-abbreviation>
+      <score-instrument id="P1-I1">
+        <instrument-name>Piano</instrument-name>
+        </score-instrument>
+      <midi-device id="P1-I1" port="1"></midi-device>
+      <midi-instrument id="P1-I1">
+        <midi-channel>1</midi-channel>
+        <midi-program>1</midi-program>
+        <volume>78.7402</volume>
+        <pan>0</pan>
+        </midi-instrument>
+      </score-part>
+    </part-list>
+  <part id="P1">
+    <measure number="1" width="299.94">
+      <print>
+        <system-layout>
+          <system-margins>
+            <left-margin>50.00</left-margin>
+            <right-margin>678.77</right-margin>
+            </system-margins>
+          <top-system-distance>170.00</top-system-distance>
+          </system-layout>
+        </print>
+      <attributes>
+        <divisions>1</divisions>
+        <key>
+          <fifths>0</fifths>
+          </key>
+        <time>
+          <beats>4</beats>
+          <beat-type>4</beat-type>
+          </time>
+        <clef>
+          <sign>G</sign>
+          <line>2</line>
+          </clef>
+        </attributes>
+      <note>
+        <rest measure="yes"/>
+        <duration>4</duration>
+        <voice>1</voice>
+        </note>
+      <barline location="right">
+        <bar-style>light-heavy</bar-style>
+        </barline>
+      </measure>
+    </part>
+  </score-partwise>