diff --git a/css/layers.css b/css/layers.css index 67edccf..6d426c0 100644 --- a/css/layers.css +++ b/css/layers.css @@ -60,5 +60,6 @@ } #layer-render.pixelated canvas { + image-rendering: pixelated; image-rendering: crisp-edges; } diff --git a/css/ui/generic.css b/css/ui/generic.css index bd673a7..eae9671 100644 --- a/css/ui/generic.css +++ b/css/ui/generic.css @@ -146,6 +146,7 @@ select > option:checked::after { flex: 1; margin: 3px; + -webkit-mask-position: center; mask-position: center; -webkit-mask-size: contain; diff --git a/js/initalize/layers.populate.js b/js/initalize/layers.populate.js index 01f88da..d6ee370 100644 --- a/js/initalize/layers.populate.js +++ b/js/initalize/layers.populate.js @@ -12,9 +12,11 @@ const bgLayer = imageCollection.registerLayer("bg", { }); const imgLayer = imageCollection.registerLayer("image", { name: "Image", + ctxOptions: {desynchronized: true}, }); const maskPaintLayer = imageCollection.registerLayer("mask", { name: "Mask Paint", + ctxOptions: {desynchronized: true}, }); const ovLayer = imageCollection.registerLayer("overlay", { name: "Overlay", @@ -42,7 +44,7 @@ const debugCtx = debugLayer.ctx; const uiCanvas = document.getElementById("layer-overlay"); // where mouse cursor renders uiCanvas.width = uiCanvas.clientWidth; uiCanvas.height = uiCanvas.clientHeight; -const uiCtx = uiCanvas.getContext("2d"); +const uiCtx = uiCanvas.getContext("2d", {desynchronized: true}); debugLayer.hide(); // Hidden by default diff --git a/js/lib/commands.js b/js/lib/commands.js index 99c4b84..42c5c6f 100644 --- a/js/lib/commands.js +++ b/js/lib/commands.js @@ -256,12 +256,6 @@ commands.createCommand( state.context = context; // Saving what was in the canvas before the command - const imgData = context.getImageData( - options.x, - options.y, - options.w, - options.h - ); state.box = { x: options.x, y: options.y, @@ -272,7 +266,19 @@ commands.createCommand( const cutout = document.createElement("canvas"); cutout.width = state.box.w; cutout.height = state.box.h; - cutout.getContext("2d").putImageData(imgData, 0, 0); + cutout + .getContext("2d") + .drawImage( + context.canvas, + options.x, + options.y, + options.w, + options.h, + 0, + 0, + options.w, + options.h + ); state.original = new Image(); state.original.src = cutout.toDataURL(); } diff --git a/js/lib/layers.js b/js/lib/layers.js index 908ae27..7c32372 100644 --- a/js/lib/layers.js +++ b/js/lib/layers.js @@ -87,6 +87,7 @@ const layers = { * @param {{w: number, h: number}} options.resolution * @param {?string} options.group * @param {object} options.after + * @param {object} options.ctxOptions * @returns */ registerLayer: (key = null, options = {}) => { @@ -108,6 +109,9 @@ const layers = { // If set, will insert the layer after the given one after: null, + + // Context creation options + ctxOptions: {}, }); // Calculate resolution @@ -137,7 +141,7 @@ const layers = { options.after.canvas.after(canvas); } - const ctx = canvas.getContext("2d"); + const ctx = canvas.getContext("2d", options.ctxOptions); // Path used for logging purposes const _layerlogpath = key diff --git a/js/ui/tool/colorbrush.js b/js/ui/tool/colorbrush.js index ea49547..738c6ae 100644 --- a/js/ui/tool/colorbrush.js +++ b/js/ui/tool/colorbrush.js @@ -56,9 +56,11 @@ const colorBrushTool = () => state.drawLayer = imageCollection.registerLayer(null, { after: imgLayer, + ctxOptions: {willReadFrequently: true}, }); state.eraseLayer = imageCollection.registerLayer(null, { after: imgLayer, + ctxOptions: {willReadFrequently: true}, }); state.eraseLayer.canvas.style.display = "none"; state.eraseLayer.hide();