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

merge osmd-public 1.4.1: add dark mode, justify label fix, etc.

sschmidTU 3 лет назад
Родитель
Сommit
62f5f74228

+ 3 - 7
demo/index.js

@@ -9,7 +9,7 @@ import { TransposeCalculator } from '../src/Plugins/Transpose/TransposeCalculato
 (function () {
     "use strict";
     var openSheetMusicDisplay;
-    var sampleFolder = process.env.STATIC_FILES_SUBFOLDER ? process.env.STATIC_FILES_SUBFOLDER + "/" : "",
+    var sampleFolder = "",
         samples = {
             "Beethoven, L.v. - An die ferne Geliebte": "Beethoven_AnDieFerneGeliebte.xml",
             "Clementi, M. - Sonatina Op.36 No.1 Pt.1": "MuzioClementi_SonatinaOpus36No1_Part1.xml",
@@ -135,9 +135,7 @@ import { TransposeCalculator } from '../src/Plugins/Transpose/TransposeCalculato
     var showHeader = true;
     var showDebugControls = false;
 
-    if (process.env.OSMD_DEMO_TITLE) {
-        document.title = process.env.OSMD_DEMO_TITLE;
-    }
+    document.title = "OpenSheetMusicDisplay Demo";
 
     // Initialization code
     function init() {
@@ -266,8 +264,7 @@ import { TransposeCalculator } from '../src/Plugins/Transpose/TransposeCalculato
 
         //var defaultDisplayVisibleValue = "block"; // TODO in some browsers flow could be the better/default value
         var defaultVisibilityValue = "visible";
-        var devDemoRunning = process.env.OSMD_DEBUG_CONTROLS;
-        showDebugControls = paramDebugControls === '1' || (devDemoRunning && paramDebugControls !== '0')
+        showDebugControls = paramDebugControls !== '0';
         if (showDebugControls) {
             var elementsToEnable = [
                 selectSample, selectBounding, selectPageSize, backendSelect, backendSelectDiv, divControls
@@ -781,7 +778,6 @@ import { TransposeCalculator } from '../src/Plugins/Transpose/TransposeCalculato
 
     function errorLoadingOrRenderingSheet(e, loadingOrRenderingString) {
         var errorString = "Error " + loadingOrRenderingString + " sheet: " + e;
-        // if (process.env.DEBUG) { // people may not set a debug environment variable for the demo.
         // Always giving a StackTrace might give us more and better error reports.
         // TODO for a release, StackTrace control could be reenabled
         errorString += "\n" + "StackTrace: \n" + e.stack;

+ 2 - 3
package.json

@@ -1,11 +1,11 @@
 {
   "name": "osmd-extended",
-  "version": "1.4.0",
+  "version": "1.4.1",
   "description": "Private / sponsor exclusive OSMD mirror/audio player.",
   "main": "build/opensheetmusicdisplay.min.js",
   "types": "dist/src/OpenSheetMusicDisplay/index.d.ts",
   "scripts": {
-    "docs": "typedoc --out ./build/docs --name OpenSheetMusicDisplay --module commonjs --target ES2017 --ignoreCompilerErrors --mode file ./src",
+    "docs": "typedoc --out ./build/docs --name OpenSheetMusicDisplay ./src",
     "eslint": "eslint -c .eslintrc.js --ext .ts .",
     "lint": "npm run eslint",
     "test": "karma start --single-run --no-auto-watch",
@@ -15,7 +15,6 @@
     "prebuildKarma": "ncp src/KarmaWebpackPatch/lib/ node_modules/karma-webpack/lib/",
     "prepare": "npm run build",
     "build": "npm-run-all lint build:webpack",
-    "build:doc": "cross-env STATIC_FILES_SUBFOLDER=sheets npm run build",
     "build:webpack": "webpack --progress --config webpack.prod.js",
     "build:webpack-dev": "webpack --progress --config webpack.dev.js",
     "build:webpack-sourcemap": "webpack --progress --config webpack.sourcemap.js",

+ 17 - 5
src/MusicalScore/Graphical/EngravingRules.ts

@@ -260,6 +260,8 @@ export class EngravingRules {
     public ColorFlags: boolean;
     public ColorBeams: boolean;
     public ColoringSetCurrent: Dictionary<NoteEnum|number, string>;
+    /** Default color for all musical elements including key signature etc. Default undefined. */
+    public DefaultColorMusic: string;
     public DefaultColorNotehead: string;
     public DefaultColorRest: string;
     public DefaultColorStem: string;
@@ -607,11 +609,7 @@ export class EngravingRules {
         this.ColorStemsLikeNoteheads = false;
         this.ColorBeams = true;
         this.ColorFlags = true;
-        this.DefaultColorNotehead = "#000000"; // black. undefined is only black if a note's color hasn't been changed before.
-        this.DefaultColorRest = this.DefaultColorNotehead;
-        this.DefaultColorStem = this.DefaultColorNotehead;
-        this.DefaultColorLabel = this.DefaultColorNotehead;
-        this.DefaultColorTitle = this.DefaultColorNotehead;
+        this.applyDefaultColorMusic("#000000"); // black. undefined is only black if a note's color hasn't been changed before.
         this.DefaultColorCursor = "#33e02f"; // green
         this.DefaultFontFamily = "Times New Roman"; // what OSMD was initially optimized for
         this.DefaultFontStyle = FontStyles.Regular;
@@ -683,6 +681,20 @@ export class EngravingRules {
         }
     }
 
+    /** Makes it so that all musical elements (including key/time signature)
+     *  are colored with the given color by default,
+     *  unless an element has a different color set (e.g. VoiceEntry.StemColor).
+     */
+    public applyDefaultColorMusic(color: string): void {
+        this.DefaultColorMusic = color;
+        this.DefaultColorNotehead = this.DefaultColorMusic;
+        this.DefaultColorRest = this.DefaultColorNotehead;
+        this.DefaultColorStem = this.DefaultColorNotehead;
+        this.DefaultColorLabel = this.DefaultColorNotehead;
+        this.DefaultColorTitle = this.DefaultColorNotehead;
+        this.LedgerLineColorDefault = this.DefaultColorNotehead;
+    }
+
     public addGraphicalNoteToNoteMap(note: Note, graphicalNote: GraphicalNote): void {
         note.NoteToGraphicalNoteObjectId = this.NoteToGraphicalNoteMapObjectCount;
         this.NoteToGraphicalNoteMap.setValue(note.NoteToGraphicalNoteObjectId, graphicalNote);

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

@@ -2122,7 +2122,9 @@ export abstract class MusicSheetCalculator {
             // const currentMin: number = skyBottomLineCalculator.getSkyLineMinInRange(startX, endX);
 
             relative.y += lyricist.PositionAndShape.BorderBottom;
-            relative.y = Math.min(relative.y, composerRelativeY); // same height as composer label (at least not lower)
+            if (composerRelativeY) {
+                relative.y = Math.min(relative.y, composerRelativeY); // same height as composer label (at least not lower)
+            } // else relative.y will be NaN
             //skyBottomLineCalculator.updateSkyLineInRange(startX, endX, currentMin - lyricist.PositionAndShape.MarginSize.height);
             //relative.y = Math.max(relative.y, composer.PositionAndShape.RelativePosition.y);
             lyricist.PositionAndShape.RelativePosition = relative;

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

@@ -13,7 +13,7 @@ import log from "loglevel";
 export class SvgVexFlowBackend extends VexFlowBackend {
 
     private ctx: Vex.Flow.SVGContext;
-    private zoom: number;
+    public zoom: number; // currently unused
 
     constructor(rules: EngravingRules) {
         super();
@@ -87,13 +87,17 @@ export class SvgVexFlowBackend extends VexFlowBackend {
 
         // set background color if not transparent
         if (this.rules.PageBackgroundColor) {
-            this.ctx.save();
-            // note that this will hide the cursor
-            this.ctx.setFillStyle(this.rules.PageBackgroundColor);
-            this.ctx.setStrokeStyle("#12345600"); // transparent
-
-            this.ctx.fillRect(0, 0, this.canvas.offsetWidth / this.zoom, this.canvas.offsetHeight / this.zoom);
-            this.ctx.restore();
+        //     this.ctx.save();
+        //     // note that this will hide the cursor if its zIndex is negative.
+        //     this.ctx.setFillStyle(this.rules.PageBackgroundColor);
+        //     this.ctx.setStrokeStyle("#12345600"); // transparent
+
+        //     this.ctx.fillRect(0, 0, this.canvas.offsetWidth / this.zoom, this.canvas.offsetHeight / this.zoom);
+        //     this.ctx.restore();
+            this.ctx.svg.style["background-color"] = this.rules.PageBackgroundColor;
+            // note that the cursor would be invisible if its zIndex remained negative here,
+            //   so we have to push it to a higher layer and make it more transparent.
+            // effectively, setting a background color will make the cursor more transparent.
         }
     }
 

+ 1 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowConverter.ts

@@ -497,7 +497,7 @@ export class VexFlowConverter {
             const stemStyle: Object = { fillStyle: stemColor, strokeStyle: stemColor };
 
             if (stemColor) {
-                gve.parentVoiceEntry.StemColor = stemColor;
+                //gve.parentVoiceEntry.StemColor = stemColor; // this shouldn't be set by DefaultColorStem
                 vfnote.setStemStyle(stemStyle);
                 if (vfnote.flag && rules.ColorFlags) {
                     vfnote.setFlagStyle(stemStyle);

+ 4 - 2
src/MusicalScore/Graphical/VexFlow/VexFlowVoiceEntry.ts

@@ -140,6 +140,7 @@ export class VexFlowVoiceEntry extends GraphicalVoiceEntry {
 
         // color stems
         let stemColor: string = defaultColorStem; // reset to black/default when coloring was disabled. maybe needed elsewhere too
+        let setVoiceEntryStemColor: boolean = false;
         if (this.rules.ColoringEnabled) {
             stemColor = this.parentVoiceEntry.StemColor; // TODO: once coloringSetCustom gets stem color, respect it
             if (!stemColor
@@ -149,6 +150,7 @@ export class VexFlowVoiceEntry extends GraphicalVoiceEntry {
             if (this.rules.ColorStemsLikeNoteheads && noteheadColor) {
                 // condition could be even more fine-grained by only recoloring if there was no custom StemColor set. will be more complex though
                 stemColor = noteheadColor;
+                setVoiceEntryStemColor = true;
             }
         }
         let stemTransparent: boolean = true;
@@ -164,8 +166,8 @@ export class VexFlowVoiceEntry extends GraphicalVoiceEntry {
         const stemStyle: Object = { fillStyle: stemColor, strokeStyle: stemColor };
 
         if (vfStaveNote && vfStaveNote.setStemStyle) {
-            if (!stemTransparent) {
-                this.parentVoiceEntry.StemColor = stemColor;
+            if (!stemTransparent && setVoiceEntryStemColor) {
+                this.parentVoiceEntry.StemColor = stemColor; // this shouldn't be set by DefaultColorStem
             }
             vfStaveNote.setStemStyle(stemStyle);
             if (vfStaveNote.flag && vfStaveNote.setFlagStyle && this.rules.ColorFlags) {

+ 19 - 2
src/OpenSheetMusicDisplay/Cursor.ts

@@ -45,9 +45,11 @@ export class Cursor implements IPlaybackListener {
     curs.id = this.cursorElementId;
     curs.style.position = "absolute";
     if (this.cursorOptions.follow === true) {
-      curs.style.zIndex = "-1";
+      this.wantedZIndex = "-1";
+      curs.style.zIndex = this.wantedZIndex;
     } else {
-      curs.style.zIndex = "-2";
+      this.wantedZIndex = "-2";
+      curs.style.zIndex = this.wantedZIndex;
     }
     this.cursorElement = <HTMLImageElement>curs;
     this.container.appendChild(curs);
@@ -77,6 +79,16 @@ export class Cursor implements IPlaybackListener {
     // throw new Error("Method not implemented.");
   }
 
+  public adjustToBackgroundColor(): void {
+    let zIndex: string;
+    if (!this.rules.PageBackgroundColor) {
+          zIndex = this.wantedZIndex;
+    } else {
+      zIndex = "1";
+    }
+    this.cursorElement.style.zIndex = zIndex;
+  }
+
   private container: HTMLElement;
   public cursorElement: HTMLImageElement;
   /** a unique id of the cursor's HTMLElement in the document.
@@ -84,6 +96,10 @@ export class Cursor implements IPlaybackListener {
    * but different between different OSMD objects on the same page.
    */
   public cursorElementId: string;
+  /** The desired zIndex (layer) of the cursor when no background color is set.
+   *  When a background color is set, using a negative zIndex would make the cursor invisible.
+   */
+  public wantedZIndex: string;
   private openSheetMusicDisplay: OpenSheetMusicDisplay;
   private rules: EngravingRules;
   private manager: MusicPartManager;
@@ -108,6 +124,7 @@ export class Cursor implements IPlaybackListener {
     this.hidden = false;
     //this.resetIterator(); // TODO maybe not here? though setting measure range to draw, rerendering, then handling cursor show is difficult
     this.update();
+    this.adjustToBackgroundColor();
   }
 
   public resetIterator(): void {

+ 4 - 0
src/OpenSheetMusicDisplay/OSMDOptions.ts

@@ -47,6 +47,10 @@ export interface IOSMDOptions {
     coloringEnabled?: boolean;
     /** Whether to color the stems of notes the same as their noteheads. Default false. */
     colorStemsLikeNoteheads?: boolean;
+    /** Dark mode (black background, white notes). Simply sets defaultColorMusic and EngravingRules.PageBackgroundColor. */
+    darkMode?: boolean;
+    /** Default color for all musical elements including key signature etc. Can be used for dark mode etc. Default undefined. */
+    defaultColorMusic?: string;
     /** Default color for a note head (without stem). Default black (undefined).
      * Only considered before loading a sample, not before render.
      * To change the color after loading a sample and before render, use note(.sourceNote).NoteheadColor.

+ 13 - 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.4.0-audio-extended"; // getter: this.Version
+    private version: string = "1.4.1-audio-extended"; // getter: this.Version
     // at release, bump version and change to -release, afterwards to -dev again
 
     /**
@@ -597,6 +597,16 @@ export class OpenSheetMusicDisplay {
         if (options.setWantedStemDirectionByXml !== undefined) {
             this.rules.SetWantedStemDirectionByXml = options.setWantedStemDirectionByXml;
         }
+        if (options.darkMode) {
+            this.rules.applyDefaultColorMusic("#FFFFFF");
+            this.rules.PageBackgroundColor = "#000000";
+        } else if (options.darkMode === false) { // not if undefined!
+            this.rules.applyDefaultColorMusic("#000000");
+            this.rules.PageBackgroundColor = undefined;
+        }
+        if (options.defaultColorMusic) {
+            this.rules.applyDefaultColorMusic(options.defaultColorMusic);
+        }
         if (options.defaultColorNotehead) {
             this.rules.DefaultColorNotehead = options.defaultColorNotehead;
         }
@@ -918,6 +928,8 @@ export class OpenSheetMusicDisplay {
         }
         backend.graphicalMusicPage = page; // the page the backend renders on. needed to identify DOM element to extract image/SVG
         backend.initialize(this.container, this.zoom);
+        backend.getContext().setFillStyle(this.rules.DefaultColorMusic);
+        backend.getContext().setStrokeStyle(this.rules.DefaultColorMusic);
         return backend;
     }
 

+ 11 - 0
src/VexFlowPatch/src/svgcontext.js

@@ -538,10 +538,21 @@ export class SVGContext {
     this.glow();
 
     const path = this.create('path');
+    let newAttributes = attributes;
     if (typeof attributes === 'undefined') {
         attributes = {};
         Vex.Merge(attributes, this.attributes);
         attributes.stroke = 'none';
+        newAttributes = attributes;
+    } else {
+      newAttributes = attributes;
+      Vex.Merge(newAttributes, this.attributes); // this overrides attributes either way
+      if (attributes.class) {
+        newAttributes.class = attributes.class;
+      }
+      if (attributes.id) {
+        newAttributes.id = attributes.id;
+      }
     }
     
     attributes.d = this.path;

+ 1 - 1
tsconfig.json

@@ -5,7 +5,7 @@
     "module": "commonjs",
     "moduleResolution": "node",
     "noUnusedLocals": true,
-    "outDir": "dist",
+    "outDir": "build/dist",
     "declaration": true,
     "sourceMap": true,
     "typeRoots": ["./node_modules/@types"],