From a6e52102d206e8eed811c0ba8df14e42614ca276 Mon Sep 17 00:00:00 2001 From: Karlen Manaseryan Date: Mon, 27 Sep 2021 18:55:49 +0400 Subject: [PATCH 1/4] Issue #231 - remove extra if condition which will never be entered --- src/js/core/base-layers.js | 71 +++++++++++++------------------------- 1 file changed, 24 insertions(+), 47 deletions(-) diff --git a/src/js/core/base-layers.js b/src/js/core/base-layers.js index 3be5666..cc0c96c 100644 --- a/src/js/core/base-layers.js +++ b/src/js/core/base-layers.js @@ -300,60 +300,37 @@ class Base_layers_class { //example with canvas object - other types should overwrite this method if (object.type == "image") { //image - default behavior - var rotateSupport = true; - if (rotateSupport == false) { - if (object.link_canvas != null) { - //we have draft canvas - use it - ctx.drawImage( - object.link_canvas, - object.x, - object.y, - object.width, - object.height - ); - } else { - ctx.drawImage( - object.link, - object.x, - object.y, - object.width, - object.height - ); - } - } else { - ctx.save(); + ctx.save(); - ctx.translate( - object.x + object.width / 2, - object.y + object.height / 2 + ctx.translate( + object.x + object.width / 2, + object.y + object.height / 2 + ); + ctx.rotate((object.rotate * Math.PI) / 180); + if (object.link_canvas != null) { + //we have draft canvas - use it + ctx.drawImage( + object.link_canvas, + -object.width / 2, + -object.height / 2, + object.width, + object.height + ); + } else { + ctx.drawImage( + object.link, + -object.width / 2, + -object.height / 2, + object.width, + object.height ); - ctx.rotate((object.rotate * Math.PI) / 180); - if (object.link_canvas != null) { - //we have draft canvas - use it - ctx.drawImage( - object.link_canvas, - -object.width / 2, - -object.height / 2, - object.width, - object.height - ); - } else { - ctx.drawImage( - object.link, - -object.width / 2, - -object.height / 2, - object.width, - object.height - ); - } - - ctx.restore(); } + + ctx.restore(); } else { //call render function from other module var render_class = object.render_function[0]; var render_function = object.render_function[1]; - if ( typeof this.Base_gui.GUI_tools.tools_modules[render_class] != "undefined" From 497b0054a5a8e16cec6d8f603f60d3ca1343ca36 Mon Sep 17 00:00:00 2001 From: Karlen Manaseryan Date: Tue, 28 Sep 2021 18:37:02 +0400 Subject: [PATCH 2/4] Issue #231 - Code refactoring for render_object() method --- src/js/core/base-layers.js | 103 ++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/src/js/core/base-layers.js b/src/js/core/base-layers.js index cc0c96c..b0183ad 100644 --- a/src/js/core/base-layers.js +++ b/src/js/core/base-layers.js @@ -268,6 +268,55 @@ class Base_layers_class { render_object(ctx, object, is_preview) { if (object.visible == false || object.type == null) return; + this.pre_render_object(ctx, object); + + //example with canvas object - other types should overwrite this method + if (object.type == "image") { + //image - default behavior + ctx.save(); + + ctx.translate( + object.x + object.width / 2, + object.y + object.height / 2 + ); + ctx.rotate((object.rotate * Math.PI) / 180); + // TODO - Not sure why the check should be with null, + // if nothing will break, then better to check if it's just truthy + ctx.drawImage( + object.link_canvas != null ? object.link_canvas : object.link, + -object.width / 2, + -object.height / 2, + object.width, + object.height + ); + + ctx.restore(); + } else { + //call render function from other module + var render_class = object.render_function[0]; + var render_function = object.render_function[1]; + if ( + typeof this.Base_gui.GUI_tools.tools_modules[render_class] != + "undefined" + ) { + this.Base_gui.GUI_tools.tools_modules[render_class].object[ + render_function + ](ctx, object, is_preview); + } else { + this.render_success = false; + console.log("Error: unknown layer type: " + object.type); + } + } + + this.after_render_object(ctx, object); + } + + /** + * Gets called before render_object starts it's job + * @param {canvas.context} ctx + * @param {object} object + */ + pre_render_object(ctx, object) { //apply pre-filters for (var i in object.filters) { var filter = object.filters[i]; @@ -296,54 +345,14 @@ class Base_layers_class { console.log("Error: can not find filter: " + filter.name); } } + } - //example with canvas object - other types should overwrite this method - if (object.type == "image") { - //image - default behavior - ctx.save(); - - ctx.translate( - object.x + object.width / 2, - object.y + object.height / 2 - ); - ctx.rotate((object.rotate * Math.PI) / 180); - if (object.link_canvas != null) { - //we have draft canvas - use it - ctx.drawImage( - object.link_canvas, - -object.width / 2, - -object.height / 2, - object.width, - object.height - ); - } else { - ctx.drawImage( - object.link, - -object.width / 2, - -object.height / 2, - object.width, - object.height - ); - } - - ctx.restore(); - } else { - //call render function from other module - var render_class = object.render_function[0]; - var render_function = object.render_function[1]; - if ( - typeof this.Base_gui.GUI_tools.tools_modules[render_class] != - "undefined" - ) { - this.Base_gui.GUI_tools.tools_modules[render_class].object[ - render_function - ](ctx, object, is_preview); - } else { - this.render_success = false; - console.log("Error: unknown layer type: " + object.type); - } - } - + /** + * Gets called after when render_object finishes it's job + * @param {canvas.context} ctx + * @param {object} object + */ + after_render_object(ctx, object) { //apply post-filters for (var i in object.filters) { var filter = object.filters[i]; From e6923445dcdc07f0f3787631db990107d5ecd089 Mon Sep 17 00:00:00 2001 From: Karlen Manaseryan Date: Tue, 28 Sep 2021 20:29:50 +0400 Subject: [PATCH 3/4] Issue #231 - Changes in main render funciton for the clipping mask --- src/js/core/base-layers.js | 71 ++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/src/js/core/base-layers.js b/src/js/core/base-layers.js index b0183ad..c25b986 100644 --- a/src/js/core/base-layers.js +++ b/src/js/core/base-layers.js @@ -170,13 +170,38 @@ class Base_layers_class { zoomView.apply(); + const newCanvas = this.createNewCanvas(this.ctx); + const ctxForSourceAtop = newCanvas.getContext("2d"); + let hasSourceAtopLayer = false; + + // TODO - this line might be removed, it's added for later restore function + this.ctx.save(); + //render main canvas for (var i = layers_sorted.length - 1; i >= 0; i--) { var value = layers_sorted[i]; - this.ctx.globalAlpha = value.opacity / 100; - this.ctx.globalCompositeOperation = value.composition; + const nextValue = layers[i - 1]; - this.render_object(this.ctx, value); + if ( + value.composition === "source-atop1" || + (nextValue && nextValue.composition === "source-atop1") + ) { + hasSourceAtopLayer = true; + ctxForSourceAtop.globalAlpha = value.opacity / 100; + ctxForSourceAtop.globalCompositeOperation = + value.composition; + this.render_object(ctxForSourceAtop, value); + } else { + this.ctx.globalAlpha = value.opacity / 100; + this.ctx.globalCompositeOperation = value.composition; + this.render_object(this.ctx, value); + } + } + + // TODO - need some investigation here + if (hasSourceAtopLayer) { + this.ctx.restore(); + this.ctx.drawImage(newCanvas, 0, 0); } //grid @@ -196,6 +221,7 @@ class Base_layers_class { //reset this.after_render(); + this.last_zoom = config.ZOOM; this.Base_gui.GUI_details.render_details(); @@ -226,6 +252,17 @@ class Base_layers_class { } } + /** + * Creates a fresh new canvas with the same height and width as the provided one + * @param {canvas.context} ctx + */ + createNewCanvas(ctx) { + const newCanvas = document.createElement("canvas"); + newCanvas.height = ctx.canvas.height; + newCanvas.width = ctx.canvas.width; + return newCanvas; + } + render_preview(layers) { var w = this.Base_gui.GUI_preview.PREVIEW_SIZE.w; var h = this.Base_gui.GUI_preview.PREVIEW_SIZE.h; @@ -236,8 +273,14 @@ class Base_layers_class { //prepare scale this.ctx_preview.scale(w / config.WIDTH, h / config.HEIGHT); + const newCanvas = this.createNewCanvas(this.ctx_preview); + const ctxForSourceAtop = newCanvas.getContext("2d"); + ctxForSourceAtop.scale(w / config.WIDTH, h / config.HEIGHT); + let hasSourceAtopLayer = false; + for (var i = layers.length - 1; i >= 0; i--) { - var value = layers[i]; + const value = layers[i]; + const nextValue = layers[i - 1]; if (value.visible == false) { //not visible @@ -248,10 +291,24 @@ class Base_layers_class { continue; } - this.ctx_preview.globalAlpha = value.opacity / 100; - this.ctx_preview.globalCompositeOperation = value.composition; + if ( + value.composition === "source-atop" || + (nextValue && nextValue.composition === "source-atop") + ) { + hasSourceAtopLayer = true; + ctxForSourceAtop.globalAlpha = value.opacity / 100; + ctxForSourceAtop.globalCompositeOperation = value.composition; + this.render_object(ctxForSourceAtop, value); + } else { + this.ctx_preview.globalAlpha = value.opacity / 100; + this.ctx_preview.globalCompositeOperation = value.composition; + this.render_object(this.ctx_preview, value); + } + } - this.render_object(this.ctx_preview, value); + if (hasSourceAtopLayer) { + this.ctx_preview.restore(); + this.ctx_preview.drawImage(newCanvas, 0, 0); } this.ctx_preview.restore(); From 5d489738f64c35f8ad619deb17e43d3e923ac4b9 Mon Sep 17 00:00:00 2001 From: Karlen Manaseryan Date: Sun, 17 Oct 2021 18:16:43 +0400 Subject: [PATCH 4/4] Issue #231 - Implement Clipping Mask for render() method --- src/js/core/base-layers.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/js/core/base-layers.js b/src/js/core/base-layers.js index c25b986..d54b92c 100644 --- a/src/js/core/base-layers.js +++ b/src/js/core/base-layers.js @@ -170,21 +170,24 @@ class Base_layers_class { zoomView.apply(); - const newCanvas = this.createNewCanvas(this.ctx); + const newCanvas = this.createNewCanvas( + this.ctx, + config.HEIGHT, + config.WIDTH + ); const ctxForSourceAtop = newCanvas.getContext("2d"); let hasSourceAtopLayer = false; - // TODO - this line might be removed, it's added for later restore function this.ctx.save(); //render main canvas for (var i = layers_sorted.length - 1; i >= 0; i--) { var value = layers_sorted[i]; - const nextValue = layers[i - 1]; + const nextValue = layers_sorted[i - 1]; if ( - value.composition === "source-atop1" || - (nextValue && nextValue.composition === "source-atop1") + value.composition === "source-atop" || + (nextValue && nextValue.composition === "source-atop") ) { hasSourceAtopLayer = true; ctxForSourceAtop.globalAlpha = value.opacity / 100; @@ -198,7 +201,6 @@ class Base_layers_class { } } - // TODO - need some investigation here if (hasSourceAtopLayer) { this.ctx.restore(); this.ctx.drawImage(newCanvas, 0, 0); @@ -255,11 +257,13 @@ class Base_layers_class { /** * Creates a fresh new canvas with the same height and width as the provided one * @param {canvas.context} ctx + * @param {number} [h] + * @param {number} [w] */ - createNewCanvas(ctx) { + createNewCanvas(ctx, h, w) { const newCanvas = document.createElement("canvas"); - newCanvas.height = ctx.canvas.height; - newCanvas.width = ctx.canvas.width; + newCanvas.height = h || ctx.canvas.height; + newCanvas.width = w || ctx.canvas.width; return newCanvas; }