Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draw colored Background Layer #318

Open
wants to merge 16 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions external/vexflow/vexflow.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,12 +321,20 @@ declare namespace Vex {

export class CanvasContext extends RenderContext {
public vexFlowCanvasContext: CanvasRenderingContext2D;
// TODO CanvasRenderingContext2D isn't defined anywhere, and defining it leads to problems.
// this somehow works, though.
public background_fillStyle: { fill: string };
public setBackgroundFillStyle(style: string): void;
public clear(x: number, y: number, width: number, height: number): void;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't like the idea that I need to know my canvas size to clear it.

Copy link
Contributor Author

@sschmidTU sschmidTU Aug 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you only need to know it if you want to fill it with the background color though. with default arguments it behaves as before. Also, canvas.width and canvas.height is often wrong in the canvas backend, too small.


export class SVGContext extends RenderContext {
public svg: SVGElement;
public attributes: any;
public state: any;
public setBackgroundFillStyle(style: string): void;
public background_attributes: any;
public clear(x: number, y: number, width: number, height: number): void;
}

export class StaveConnector {
Expand Down
4 changes: 3 additions & 1 deletion src/MusicalScore/Graphical/DrawingEnums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export enum OutlineAndFillStyleEnum {
Comment7,
Comment8,
Comment9,
Comment10
Comment10,
BackgroundWhite,
}

// tslint:disable-next-line:max-line-length A linebreak would be more confusing here
Expand Down Expand Up @@ -74,6 +75,7 @@ OUTLINE_AND_FILL_STYLE_DICT.setValue(OutlineAndFillStyleEnum.Comment7, "Blanched
OUTLINE_AND_FILL_STYLE_DICT.setValue(OutlineAndFillStyleEnum.Comment8, "CornflowerBlue");
OUTLINE_AND_FILL_STYLE_DICT.setValue(OutlineAndFillStyleEnum.Comment9, "Cornsilk");
OUTLINE_AND_FILL_STYLE_DICT.setValue(OutlineAndFillStyleEnum.Comment10, "DarkGrey");
OUTLINE_AND_FILL_STYLE_DICT.setValue(OutlineAndFillStyleEnum.BackgroundWhite, "White");

export enum StyleSets {
MarkedArea,
Expand Down
7 changes: 7 additions & 0 deletions src/MusicalScore/Graphical/EngravingRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export class EngravingRules {
private noteDistancesScalingFactors: number[] = [1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0];
private durationDistanceDict: {[_: number]: number; } = {};
private durationScalingDistanceDict: {[_: number]: number; } = {};
private backgroundColorFillStyle: string = "#FFF"; // white

constructor() {
// global variables
Expand Down Expand Up @@ -1135,6 +1136,12 @@ export class EngravingRules {
public get DurationScalingDistanceDict(): {[_: number]: number; } {
return this.durationScalingDistanceDict;
}
public get BackgroundColorFillStyle(): string {
return this.backgroundColorFillStyle;
}
public set BackgroundColorFillStyle(value: string) {
this.backgroundColorFillStyle = value;
}

/**
* This method maps NoteDurations to Distances and DistancesScalingFactors.
Expand Down
31 changes: 29 additions & 2 deletions src/MusicalScore/Graphical/VexFlow/CanvasVexFlowBackend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import {Fonts} from "../../../Common/Enums/Fonts";
import {RectangleF2D} from "../../../Common/DataObjects/RectangleF2D";
import {PointF2D} from "../../../Common/DataObjects/PointF2D";
import {VexFlowConverter} from "./VexFlowConverter";
import { EngravingRules } from "../EngravingRules";

export class CanvasVexFlowBackend extends VexFlowBackend {
private backgroundFillStyle: string = EngravingRules.Rules.BackgroundColorFillStyle;

public getBackendType(): number {
return Vex.Flow.Renderer.Backends.CANVAS;
Expand All @@ -23,6 +25,8 @@ export class CanvasVexFlowBackend extends VexFlowBackend {
this.renderer = new Vex.Flow.Renderer(this.canvas, this.getBackendType());
this.ctx = <Vex.Flow.CanvasContext>this.renderer.getContext();
this.canvasRenderingCtx = this.ctx.vexFlowCanvasContext;
this.ctx.setBackgroundFillStyle(this.backgroundFillStyle);
(this.canvasRenderingCtx as any).setBackgroundFillStyle(this.backgroundFillStyle);
}

/**
Expand All @@ -36,15 +40,38 @@ export class CanvasVexFlowBackend extends VexFlowBackend {
(this.canvas as any).height = height;
this.renderer = new Vex.Flow.Renderer(this.canvas, this.getBackendType());
this.ctx = <Vex.Flow.CanvasContext>this.renderer.getContext();
this.ctx.setBackgroundFillStyle(this.backgroundFillStyle);
this.canvasRenderingCtx = this.ctx.vexFlowCanvasContext;
(this.canvasRenderingCtx as any).setBackgroundFillStyle(this.backgroundFillStyle);
}

public getContext(): Vex.Flow.CanvasContext {
return this.ctx;
}

public clear(): void {
(<any>this.ctx).clearRect(0, 0, (<any>this.canvas).width, (<any>this.canvas).height);
public clear(x: number = -1, y: number = -1, width: number = -1, height: number = -1): void {
if (x !== -1) {
if (this.backgroundFillStyle === "transparent") {
// (<any>this.ctx).clearRect(0, 0, (<any>this.canvas).width, (<any>this.canvas).height);
// TODO clearRect currently doesn't do anything in Vexflow for Canvas.
// Also, canvas width and height are often very small, smaller than sheet.pageWidth
} else {
// fill canvas with background color
// TODO currently this prevents the cursor from showing if it's on z=-1
const renderCtx: any = <any>this.canvasRenderingCtx;
renderCtx.save();
renderCtx.setFillStyle(this.backgroundFillStyle);
renderCtx.fillRect(x, y, width, height);
renderCtx.restore(); // there's no getFillStyle() right now.
}
}
}

public getBackgroundColor(): string {
return this.backgroundFillStyle;
}
public setBackgroundColor(colorOrStyle: string): void {
this.backgroundFillStyle = colorOrStyle;
}

public scale(k: number): void {
Expand Down
42 changes: 39 additions & 3 deletions src/MusicalScore/Graphical/VexFlow/SvgVexFlowBackend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import {FontStyles} from "../../../Common/Enums/FontStyles";
import {Fonts} from "../../../Common/Enums/Fonts";
import {RectangleF2D} from "../../../Common/DataObjects/RectangleF2D";
import {PointF2D} from "../../../Common/DataObjects/PointF2D";
import { EngravingRules } from "../EngravingRules";

export class SvgVexFlowBackend extends VexFlowBackend {
private backgroundFillStyle: string = EngravingRules.Rules.BackgroundColorFillStyle;

public getBackendType(): number {
return Vex.Flow.Renderer.Backends.SVG;
Expand All @@ -21,14 +23,14 @@ export class SvgVexFlowBackend extends VexFlowBackend {
container.appendChild(this.inner);
this.renderer = new Vex.Flow.Renderer(this.canvas, this.getBackendType());
this.ctx = <Vex.Flow.SVGContext>this.renderer.getContext();

this.ctx.setBackgroundFillStyle(this.backgroundFillStyle);
}

public getContext(): Vex.Flow.SVGContext {
return this.ctx;
}

public clear(): void {
public clear(x: number = -1, y: number = -1, width: number = -1, height: number = -1): void {
const { svg } = this.ctx;
if (!svg) {
return;
Expand All @@ -38,6 +40,34 @@ export class SvgVexFlowBackend extends VexFlowBackend {
while (svg.lastChild) {
svg.removeChild(svg.lastChild);
}

if (x !== -1) {
if (this.backgroundFillStyle === "transparent") {
(this.ctx as any).clearRect(x, y, width, height);
// should in theory fill with transparency
// currently fills with bgcolor in vexflow
} else {
// filling with background color currently prevents cursor showing if on z=-1
// note that rect works like canvascontext.fillRect right now
(this.ctx as any).rect(x, y, width, height, this.ctx.background_attributes);

// could also use clearRect for now
// (this.ctx as any).clearRect(x, y, width, height);

// this alternative prevents the cursor from showing (unless alpha<1)
// const backgroundRectangle: RectangleF2D = new RectangleF2D(x, y, width, height);
// this.renderRectangleByStyle(backgroundRectangle, this.backgroundFillStyle, 1);
}
}
}

public getBackgroundColor(): string {
return this.backgroundFillStyle;
}

public setBackgroundColor(colorOrStyle: string): void {
this.backgroundFillStyle = colorOrStyle;
this.ctx.setBackgroundFillStyle(colorOrStyle);
}

public scale(k: number): void {
Expand All @@ -59,10 +89,16 @@ export class SvgVexFlowBackend extends VexFlowBackend {
this.ctx.restore();
}
public renderRectangle(rectangle: RectangleF2D, styleId: number, alpha: number = 1): void {
const style: string = VexFlowConverter.style(styleId);
this.renderRectangleByStyle(rectangle, style, alpha);
}
private renderRectangleByStyle(rectangle: RectangleF2D, style: string, alpha: number = 1): void {
this.ctx.save();
this.ctx.attributes.fill = VexFlowConverter.style(styleId);
this.ctx.attributes.fill = style;
this.ctx.attributes["fill-opacity"] = alpha;
// this.ctx.attributes["stroke-width"] = 0;
this.ctx.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
// (<any>this.ctx).rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height, this.ctx.attributes);
this.ctx.restore();
this.ctx.attributes["fill-opacity"] = 1;
}
Expand Down
10 changes: 9 additions & 1 deletion src/MusicalScore/Graphical/VexFlow/VexFlowBackend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,15 @@ export abstract class VexFlowBackend {
this.renderer.resize(x, y);
}

public abstract clear(): void;
public abstract clear(x: number, y: number, width: number, height: number): void;
public abstract getBackgroundColor(): string;

/** sets background color.
* does not fill the background immediately, need rerender for that.
* setting color to "transparent" will skip drawing a background in clear().
* @param colorOrStyle color name (e.g. "white") or Vexflow style ("#FFF")
*/
public abstract setBackgroundColor(colorOrStyle: string): void;

public abstract translate(x: number, y: number): void;
public abstract renderText(fontHeight: number, fontStyle: FontStyles, font: Fonts, text: string,
Expand Down
4 changes: 2 additions & 2 deletions src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
this.backend = backend;
}

public clear(): void {
this.backend.clear();
public clear(x: number = -1, y: number = -1, width: number = -1, height: number = -1): void {
this.backend.clear(x, y, width, height);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/OpenSheetMusicDisplay/Cursor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class Cursor {
this.openSheetMusicDisplay = openSheetMusicDisplay;
const curs: HTMLElement = document.createElement("img");
curs.style.position = "absolute";
curs.style.zIndex = "-1";
curs.style.zIndex = "0";
this.cursorElement = <HTMLImageElement>curs;
this.container.appendChild(curs);
}
Expand Down Expand Up @@ -144,7 +144,7 @@ export class Cursor {
c.width = this.cursorElement.width;
c.height = 1;
const ctx: CanvasRenderingContext2D = c.getContext("2d");
ctx.globalAlpha = 0.5;
ctx.globalAlpha = 0.3;
// Generate the gradient
const gradient: CanvasGradient = ctx.createLinearGradient(0, 0, this.cursorElement.width, 0);
gradient.addColorStop(0, "white"); // it was: "transparent"
Expand Down
5 changes: 5 additions & 0 deletions src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,16 @@ export class OpenSheetMusicDisplay {
this.graphic.Cursors.push(this.graphic.calculateCursorLineAtTimestamp(new Fraction(7, 4), OutlineAndFillStyleEnum.PlaybackCursor));*/
// Update Sheet Page
const height: number = this.graphic.MusicPages[0].PositionAndShape.BorderBottom * 10.0 * this.zoom;

this.drawer.clear();
this.drawer.resize(width, height);
this.drawer.scale(this.zoom);
// clear and fill with background color
this.drawer.clear(0, 0, width, height);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are 2 clears. Why?

Copy link
Contributor Author

@sschmidTU sschmidTU Aug 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the first clear actually only removes the SVG children in the SVG backend in this case. I left it in in case the resizing and scaling is slower if we don't remove the SVG children beforehand.

So, clear without arguments behaves like before, clear with position and dimensions makes a colored background (rectangle).

We could separate these methods, of course. But i don't think removing children from a list or drawing a single rectangle costs much performance.


// Finally, draw
this.drawer.drawSheet(this.graphic);

// Update the cursor position
this.cursor.update();
}
Expand Down