From 9411b2e3aee3e40e42d1176810e82018d54a79c1 Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 12:24:55 +0200 Subject: [PATCH 1/5] Moving (rendering related) DPI into FrameRenderer domain object --- js/controller/AnimatedPreviewController.js | 4 ++-- js/controller/DrawingController.js | 8 ++++---- js/controller/PreviewFilmController.js | 4 ++-- js/rendering/FrameRenderer.js | 21 +++++++++++++++------ 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/js/controller/AnimatedPreviewController.js b/js/controller/AnimatedPreviewController.js index fd99578b..235b74b9 100644 --- a/js/controller/AnimatedPreviewController.js +++ b/js/controller/AnimatedPreviewController.js @@ -8,7 +8,7 @@ this.fps = parseInt($("#preview-fps")[0].value, 10); - this.renderer = new pskl.rendering.FrameRenderer(); + this.renderer = new pskl.rendering.FrameRenderer(dpi); }; ns.AnimatedPreviewController.prototype.init = function () { @@ -55,7 +55,7 @@ this.animIndex = 0; } - this.renderer.render(this.framesheet.getFrameByIndex(this.animIndex), this.previewCanvas, this.dpi); + this.renderer.render(this.framesheet.getFrameByIndex(this.animIndex), this.previewCanvas); this.animIndex++; this.startAnimationTimer(); }; diff --git a/js/controller/DrawingController.js b/js/controller/DrawingController.js index 3752bd52..901261e3 100644 --- a/js/controller/DrawingController.js +++ b/js/controller/DrawingController.js @@ -11,19 +11,19 @@ this.container = container; this.mainCanvas = this.createMainCanvas(); this.overlayCanvas = this.createOverlayCanvas(); - this.renderer = new pskl.rendering.FrameRenderer(); + this.renderer = new pskl.rendering.FrameRenderer(dpi); }; ns.DrawingController.prototype.renderFrame = function () { - this.renderer.render(this.frame, this.mainCanvas, this.dpi); + this.renderer.render(this.frame, this.mainCanvas); }; ns.DrawingController.prototype.renderFramePixel = function (col, row) { - this.renderer.drawPixel(col, row, this.frame, this.mainCanvas, this.dpi); + this.renderer.drawPixel(col, row, this.frame, this.mainCanvas); }; ns.DrawingController.prototype.renderOverlay = function () { - this.renderer.render(this.overlay, this.overlayCanvas, this.dpi); + this.renderer.render(this.overlay, this.overlayCanvas); }; ns.DrawingController.prototype.clearOverlay = function () { diff --git a/js/controller/PreviewFilmController.js b/js/controller/PreviewFilmController.js index 9b5c2244..949b6de4 100644 --- a/js/controller/PreviewFilmController.js +++ b/js/controller/PreviewFilmController.js @@ -6,7 +6,7 @@ this.framesheet = framesheet; this.container = container; - this.renderer = new pskl.rendering.FrameRenderer(); + this.renderer = new pskl.rendering.FrameRenderer(dpi); }; ns.PreviewFilmController.prototype.init = function() { @@ -69,7 +69,7 @@ piskel.duplicateFrame(tileNumber); }); - this.renderer.render(this.framesheet.getFrameByIndex(tileNumber), canvasPreview, this.dpi); + this.renderer.render(this.framesheet.getFrameByIndex(tileNumber), canvasPreview); canvasContainer.appendChild(canvasPreview); previewTileRoot.appendChild(canvasContainer); previewTileRoot.appendChild(canvasPreviewDuplicateAction); diff --git a/js/rendering/FrameRenderer.js b/js/rendering/FrameRenderer.js index 8b630579..e4fb6c27 100644 --- a/js/rendering/FrameRenderer.js +++ b/js/rendering/FrameRenderer.js @@ -1,20 +1,29 @@ (function () { var ns = $.namespace("pskl.rendering"); - ns.FrameRenderer = function () {}; - ns.FrameRenderer.prototype.render = function (frame, canvas, dpi) { + this.dpi = null; + + ns.FrameRenderer = function (dpi) { + if(dpi == undefined || isNaN(dpi)) { + throw "Bad FrameRenderer initialization. not well defined."; + } + + this.dpi = dpi; + }; + + ns.FrameRenderer.prototype.render = function (frame, canvas) { for(var col = 0, width = frame.getWidth(); col < width; col++) { for(var row = 0, height = frame.getHeight(); row < height; row++) { - this.drawPixel(col, row, frame, canvas, dpi); + this.drawPixel(col, row, frame, canvas, this.dpi); } } }; - ns.FrameRenderer.prototype.drawPixel = function (col, row, frame, canvas, dpi) { + ns.FrameRenderer.prototype.drawPixel = function (col, row, frame, canvas) { var context = canvas.getContext('2d'); var color = frame.getPixel(col, row); if(color == Constants.TRANSPARENT_COLOR) { - context.clearRect(col * dpi, row * dpi, dpi, dpi); + context.clearRect(col * this.dpi, row * this.dpi, this.dpi, this.dpi); } else { if(color != Constants.SELECTION_TRANSPARENT_COLOR) { @@ -22,7 +31,7 @@ $.publish(Events.COLOR_USED, [color]); } context.fillStyle = color; - context.fillRect(col * dpi, row * dpi, dpi, dpi); + context.fillRect(col * this.dpi, row * this.dpi, this.dpi, this.dpi); } }; })(); \ No newline at end of file From eb7511c721dacaaf894f728d76078dad9edb91d6 Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 15:08:00 +0200 Subject: [PATCH 2/5] Encapsulate canvas element in FrameRenderer From this change set, the HTML canvas element, which is the frame view, is encapsulated inside the FrameRenderer. You won't need to give the view handle from the controller layer anymore. It will make view alteration implementations much easier (like grid for instance) --- index.html | 2 +- js/controller/AnimatedPreviewController.js | 22 ++------- js/controller/DrawingController.js | 57 +++++++--------------- js/controller/PreviewFilmController.js | 26 ++++++---- js/rendering/FrameRenderer.js | 50 +++++++++++++++++-- 5 files changed, 85 insertions(+), 72 deletions(-) diff --git a/index.html b/index.html index ef1cf081..9da8adc3 100644 --- a/index.html +++ b/index.html @@ -89,10 +89,10 @@ + - diff --git a/js/controller/AnimatedPreviewController.js b/js/controller/AnimatedPreviewController.js index 235b74b9..0bb60dd7 100644 --- a/js/controller/AnimatedPreviewController.js +++ b/js/controller/AnimatedPreviewController.js @@ -8,29 +8,18 @@ this.fps = parseInt($("#preview-fps")[0].value, 10); - this.renderer = new pskl.rendering.FrameRenderer(dpi); + this.renderer = new pskl.rendering.FrameRenderer(this.container, this.dpi); }; ns.AnimatedPreviewController.prototype.init = function () { this.initDom(); + + this.renderer.init(this.framesheet.getFrameByIndex(this.animIndex)); + this.startAnimationTimer(); }; ns.AnimatedPreviewController.prototype.initDom = function () { - var frame = this.framesheet.getFrameByIndex(0); - var height = frame.getHeight() * this.dpi, - width = frame.getWidth() * this.dpi; - - previewCanvas = document.createElement('canvas'); - previewCanvas.className = 'canvas'; - - this.container.setAttribute('style', 'width:' + width + 'px; height:' + height + 'px;'); - previewCanvas.setAttribute('width', width); - previewCanvas.setAttribute('height', height); - - this.container.appendChild(previewCanvas); - this.previewCanvas = previewCanvas; - $("#preview-fps")[0].addEventListener('change', this.onFPSSliderChange.bind(this)); }; @@ -54,8 +43,7 @@ if (!this.framesheet.hasFrameAtIndex(this.animIndex)) { this.animIndex = 0; } - - this.renderer.render(this.framesheet.getFrameByIndex(this.animIndex), this.previewCanvas); + this.renderer.render(this.framesheet.getFrameByIndex(this.animIndex)); this.animIndex++; this.startAnimationTimer(); }; diff --git a/js/controller/DrawingController.js b/js/controller/DrawingController.js index 901261e3..a71e5eb3 100644 --- a/js/controller/DrawingController.js +++ b/js/controller/DrawingController.js @@ -5,60 +5,37 @@ // Public this.frame = frame; - this.overlay = pskl.model.Frame.createEmptyFromFrame(frame); + this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(frame); // Type is frame // Private this.container = container; - this.mainCanvas = this.createMainCanvas(); - this.overlayCanvas = this.createOverlayCanvas(); - this.renderer = new pskl.rendering.FrameRenderer(dpi); + this.renderer = new pskl.rendering.FrameRenderer(this.container, dpi, "drawing-canvas"); + this.overlayRenderer = new pskl.rendering.FrameRenderer(this.container, dpi, "canvas-overlay"); + //this.mainCanvas = this.createMainCanvas(); + //this.overlayCanvas = this.createOverlayCanvas(); + this.renderer.init(this.frame); + this.overlayRenderer.init(this.frame); + }; + + ns.DrawingController.prototype.updateDPI = function (newDPI) { + //this.renderer.updateDPI(newDPI); + //this.overlayRenderer.updateDPI(newDPI); }; ns.DrawingController.prototype.renderFrame = function () { - this.renderer.render(this.frame, this.mainCanvas); + this.renderer.render(this.frame); }; ns.DrawingController.prototype.renderFramePixel = function (col, row) { - this.renderer.drawPixel(col, row, this.frame, this.mainCanvas); + this.renderer.drawPixel(col, row, this.frame); }; ns.DrawingController.prototype.renderOverlay = function () { - this.renderer.render(this.overlay, this.overlayCanvas); + this.overlayRenderer.render(this.overlayFrame); }; ns.DrawingController.prototype.clearOverlay = function () { - this.overlay = pskl.model.Frame.createEmptyFromFrame(this.frame); - this.overlayCanvas.getContext("2d").clearRect(0, 0, this.overlayCanvas.width, this.overlayCanvas.height); - }; - - ns.DrawingController.prototype.createMainCanvas = function () { - var mainCanvas = this.createCanvas(); - mainCanvas.className = "drawing-canvas"; - this.container.appendChild(mainCanvas); - return mainCanvas; - }; - - // For some tools, we need a fake canvas that overlay the drawing canvas. These tools are - // generally 'drap and release' based tools (stroke, selection, etc) and the fake canvas - // will help to visualize the tool interaction (without modifying the canvas). - ns.DrawingController.prototype.createOverlayCanvas = function () { - var overlayCanvas = this.createCanvas(); - overlayCanvas.className = "canvas-overlay"; - this.container.appendChild(overlayCanvas); - return overlayCanvas; - }; - - // For some tools, we need a fake canvas that overlay the drawing canvas. These tools are - // generally 'drap and release' based tools (stroke, selection, etc) and the fake canvas - // will help to visualize the tool interaction (without modifying the canvas). - ns.DrawingController.prototype.createCanvas = function () { - var width = this.frame.getWidth(), - height = this.frame.getHeight(); - - var canvas = document.createElement("canvas"); - canvas.setAttribute("width", width * this.dpi); - canvas.setAttribute("height", height * this.dpi); - - return canvas; + this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(this.frame); + this.overlayRenderer.clear(); }; })(); \ No newline at end of file diff --git a/js/controller/PreviewFilmController.js b/js/controller/PreviewFilmController.js index 949b6de4..072d9c2b 100644 --- a/js/controller/PreviewFilmController.js +++ b/js/controller/PreviewFilmController.js @@ -6,13 +6,15 @@ this.framesheet = framesheet; this.container = container; - this.renderer = new pskl.rendering.FrameRenderer(dpi); + //this.renderer = new pskl.rendering.FrameRenderer(this.container, dpi); }; ns.PreviewFilmController.prototype.init = function() { var addFrameButton = $('#add-frame-button')[0]; addFrameButton.addEventListener('mousedown', this.addFrame.bind(this)); this.createPreviews(); + + }; ns.PreviewFilmController.prototype.addFrame = function () { @@ -28,9 +30,9 @@ }; ns.PreviewFilmController.prototype.createPreviewTile = function(tileNumber) { - var frame = this.framesheet.getFrameByIndex(tileNumber); - var width = frame.getWidth() * this.dpi, - height = frame.getHeight() * this.dpi; + var currentFrame = this.framesheet.getFrameByIndex(tileNumber); + //var width = frame.getWidth() * this.dpi, + // height = frame.getHeight() * this.dpi; var previewTileRoot = document.createElement("li"); var classname = "preview-tile"; @@ -42,18 +44,19 @@ var canvasContainer = document.createElement("div"); canvasContainer.className = "canvas-container"; - canvasContainer.setAttribute('style', 'width:' + width + 'px; height:' + height + 'px;'); + //canvasContainer.setAttribute('style', 'width:' + width + 'px; height:' + height + 'px;'); var canvasBackground = document.createElement("div"); canvasBackground.className = "canvas-background"; canvasContainer.appendChild(canvasBackground); - + /* var canvasPreview = document.createElement("canvas"); canvasPreview.className = "canvas tile-view" canvasPreview.setAttribute('width', width); canvasPreview.setAttribute('height', height); - + */ + previewTileRoot.addEventListener('click', function(evt) { // has not class tile-action: if(!evt.target.classList.contains('tile-action')) { @@ -69,8 +72,13 @@ piskel.duplicateFrame(tileNumber); }); - this.renderer.render(this.framesheet.getFrameByIndex(tileNumber), canvasPreview); - canvasContainer.appendChild(canvasPreview); + //this.renderer.render(this.framesheet.getFrameByIndex(tileNumber), canvasPreview); + + // TODO(vincz): Eventually optimize this part by not recreating a FrameRenderer. Note that the real optim + // is to make this update function (#createPreviewTile) less aggressive. + var currentFrameRenderer = new pskl.rendering.FrameRenderer(canvasContainer, this.dpi, "tile-view"); + currentFrameRenderer.init(currentFrame); + previewTileRoot.appendChild(canvasContainer); previewTileRoot.appendChild(canvasPreviewDuplicateAction); diff --git a/js/rendering/FrameRenderer.js b/js/rendering/FrameRenderer.js index e4fb6c27..55d51b65 100644 --- a/js/rendering/FrameRenderer.js +++ b/js/rendering/FrameRenderer.js @@ -2,25 +2,38 @@ var ns = $.namespace("pskl.rendering"); this.dpi = null; + this.canvas = null; + + ns.FrameRenderer = function (container, dpi, className) { + if(container == undefined) { + throw "Bad FrameRenderer initialization. undefined."; + } - ns.FrameRenderer = function (dpi) { if(dpi == undefined || isNaN(dpi)) { throw "Bad FrameRenderer initialization. not well defined."; } + this.container = container; this.dpi = dpi; + this.className = className; }; - ns.FrameRenderer.prototype.render = function (frame, canvas) { + ns.FrameRenderer.prototype.init = function (frame) { + + this.createCanvas_(frame); + this.render(frame); + }; + + ns.FrameRenderer.prototype.render = function (frame) { for(var col = 0, width = frame.getWidth(); col < width; col++) { for(var row = 0, height = frame.getHeight(); row < height; row++) { - this.drawPixel(col, row, frame, canvas, this.dpi); + this.drawPixel(col, row, frame, this.canvas, this.dpi); } } }; - ns.FrameRenderer.prototype.drawPixel = function (col, row, frame, canvas) { - var context = canvas.getContext('2d'); + ns.FrameRenderer.prototype.drawPixel = function (col, row, frame) { + var context = this.canvas.getContext('2d'); var color = frame.getPixel(col, row); if(color == Constants.TRANSPARENT_COLOR) { context.clearRect(col * this.dpi, row * this.dpi, this.dpi, this.dpi); @@ -34,4 +47,31 @@ context.fillRect(col * this.dpi, row * this.dpi, this.dpi, this.dpi); } }; + + ns.FrameRenderer.prototype.clear = function (col, row, frame) { + this.canvas.getContext("2d").clearRect(0, 0, this.canvas.width, this.canvas.height); + }; + + /** + * @private + */ + ns.FrameRenderer.prototype.createCanvas_ = function (frame) { + if(this.canvas == undefined) { + var width = frame.getWidth(), + height = frame.getHeight(); + + var canvas = document.createElement("canvas"); + canvas.setAttribute("width", width * this.dpi); + canvas.setAttribute("height", height * this.dpi); + + var canvasClassname = "canvas"; + if(this.className) { + canvasClassname += " " + this.className; + } + canvas.setAttribute("class", canvasClassname); + + this.canvas = canvas; + } + this.container.appendChild(this.canvas); + }; })(); \ No newline at end of file From cc22a2693397b4577508e720460ff73156179d76 Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 15:21:22 +0200 Subject: [PATCH 3/5] Fix overlayFrame reference --- js/drawingtools/Rectangle.js | 4 ++-- js/drawingtools/Stroke.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/js/drawingtools/Rectangle.js b/js/drawingtools/Rectangle.js index 87709026..36967878 100644 --- a/js/drawingtools/Rectangle.js +++ b/js/drawingtools/Rectangle.js @@ -24,7 +24,7 @@ this.startRow = row; // Drawing the first point of the rectangle in the fake overlay canvas: - drawer.overlay.setPixel(col, row, color); + drawer.overlayFrame.setPixel(col, row, color); drawer.renderOverlay(); }; @@ -42,7 +42,7 @@ if(color == Constants.TRANSPARENT_COLOR) { color = Constants.SELECTION_TRANSPARENT_COLOR; } - drawer.overlay.setPixel(strokePoints[i].col, strokePoints[i].row, color); + drawer.overlayFrame.setPixel(strokePoints[i].col, strokePoints[i].row, color); } drawer.renderOverlay(); }; diff --git a/js/drawingtools/Stroke.js b/js/drawingtools/Stroke.js index 92bb8450..13dabac3 100644 --- a/js/drawingtools/Stroke.js +++ b/js/drawingtools/Stroke.js @@ -34,7 +34,7 @@ // The fake canvas where we will draw the preview of the stroke: // Drawing the first point of the stroke in the fake overlay canvas: - drawer.overlay.setPixel(col, row, color); + drawer.overlayFrame.setPixel(col, row, color); drawer.renderOverlay(); }; @@ -57,7 +57,7 @@ // eg deleting the equivalent of a stroke. color = Constants.SELECTION_TRANSPARENT_COLOR; } - drawer.overlay.setPixel(strokePoints[i].col, strokePoints[i].row, color); + drawer.overlayFrame.setPixel(strokePoints[i].col, strokePoints[i].row, color); } drawer.renderOverlay(); }; From bca16a39643fd9bc7e963461c3256cf8b1fa65f8 Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 15:34:13 +0200 Subject: [PATCH 4/5] Creating renderingOptions object for FrameRenderer Contains dpi, grid info, etc --- js/controller/AnimatedPreviewController.js | 6 ++++-- js/controller/DrawingController.js | 9 +++++++-- js/controller/PreviewFilmController.js | 5 ++--- js/rendering/FrameRenderer.js | 9 +++++---- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/js/controller/AnimatedPreviewController.js b/js/controller/AnimatedPreviewController.js index 0bb60dd7..c8b7f51a 100644 --- a/js/controller/AnimatedPreviewController.js +++ b/js/controller/AnimatedPreviewController.js @@ -1,14 +1,16 @@ (function () { var ns = $.namespace("pskl.controller"); ns.AnimatedPreviewController = function (framesheet, container, dpi) { - this.dpi = dpi; this.framesheet = framesheet; this.container = container; this.animIndex = 0; this.fps = parseInt($("#preview-fps")[0].value, 10); - this.renderer = new pskl.rendering.FrameRenderer(this.container, this.dpi); + var renderingOptions = { + "dpi": dpi + }; + this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions); }; ns.AnimatedPreviewController.prototype.init = function () { diff --git a/js/controller/DrawingController.js b/js/controller/DrawingController.js index a71e5eb3..d0741280 100644 --- a/js/controller/DrawingController.js +++ b/js/controller/DrawingController.js @@ -3,14 +3,19 @@ ns.DrawingController = function (frame, container, dpi) { this.dpi = dpi; + var renderingOptions = { + "dpi": dpi, + "displayGrid": true // Retrieve from localsotrage config + } + // Public this.frame = frame; this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(frame); // Type is frame // Private this.container = container; - this.renderer = new pskl.rendering.FrameRenderer(this.container, dpi, "drawing-canvas"); - this.overlayRenderer = new pskl.rendering.FrameRenderer(this.container, dpi, "canvas-overlay"); + this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, "drawing-canvas"); + this.overlayRenderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, "canvas-overlay"); //this.mainCanvas = this.createMainCanvas(); //this.overlayCanvas = this.createOverlayCanvas(); this.renderer.init(this.frame); diff --git a/js/controller/PreviewFilmController.js b/js/controller/PreviewFilmController.js index 8f218d53..8317066e 100644 --- a/js/controller/PreviewFilmController.js +++ b/js/controller/PreviewFilmController.js @@ -5,8 +5,6 @@ this.dpi = dpi; this.framesheet = framesheet; this.container = container; - - //this.renderer = new pskl.rendering.FrameRenderer(this.container, dpi); }; ns.PreviewFilmController.prototype.init = function() { @@ -189,7 +187,8 @@ // TODO(vincz): Eventually optimize this part by not recreating a FrameRenderer. Note that the real optim // is to make this update function (#createPreviewTile) less aggressive. - var currentFrameRenderer = new pskl.rendering.FrameRenderer(canvasContainer, this.dpi, "tile-view"); + var renderingOptions = {"dpi": this.dpi }; + var currentFrameRenderer = new pskl.rendering.FrameRenderer(canvasContainer, renderingOptions, "tile-view"); currentFrameRenderer.init(currentFrame); previewTileRoot.appendChild(canvasContainer); diff --git a/js/rendering/FrameRenderer.js b/js/rendering/FrameRenderer.js index 55d51b65..56089285 100644 --- a/js/rendering/FrameRenderer.js +++ b/js/rendering/FrameRenderer.js @@ -4,17 +4,18 @@ this.dpi = null; this.canvas = null; - ns.FrameRenderer = function (container, dpi, className) { + ns.FrameRenderer = function (container, renderingOptions, className) { if(container == undefined) { throw "Bad FrameRenderer initialization. undefined."; } + this.container = container; - if(dpi == undefined || isNaN(dpi)) { + if(renderingOptions == undefined || renderingOptions.dpi == undefined || isNaN(dpi)) { throw "Bad FrameRenderer initialization. not well defined."; } - this.container = container; - this.dpi = dpi; + this.displayGrid = !!renderingOptions.displayGrid; + this.dpi = renderingOptions.dpi; this.className = className; }; From ba5500b4b0c86b8765e56a915f583ec95f99b4d3 Mon Sep 17 00:00:00 2001 From: Vince Date: Sat, 8 Sep 2012 16:32:28 +0200 Subject: [PATCH 5/5] Dynamic DPIs ! --- css/style.css | 5 +--- js/controller/DrawingController.js | 10 ++++--- js/piskel.js | 47 +++++++++++++++++++++--------- js/rendering/FrameRenderer.js | 29 ++++++++++++------ 4 files changed, 60 insertions(+), 31 deletions(-) diff --git a/css/style.css b/css/style.css index 63e082c9..fb44b886 100644 --- a/css/style.css +++ b/css/style.css @@ -73,10 +73,7 @@ } .drawing-canvas { - position: absolute; - top: 0; - left: 0; - z-index: 1; + float: left; } .canvas-overlay { diff --git a/js/controller/DrawingController.js b/js/controller/DrawingController.js index d0741280..f6043669 100644 --- a/js/controller/DrawingController.js +++ b/js/controller/DrawingController.js @@ -16,15 +16,17 @@ this.container = container; this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, "drawing-canvas"); this.overlayRenderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, "canvas-overlay"); - //this.mainCanvas = this.createMainCanvas(); - //this.overlayCanvas = this.createOverlayCanvas(); + this.renderer.init(this.frame); this.overlayRenderer.init(this.frame); }; ns.DrawingController.prototype.updateDPI = function (newDPI) { - //this.renderer.updateDPI(newDPI); - //this.overlayRenderer.updateDPI(newDPI); + this.renderer.updateDPI(newDPI); + this.overlayRenderer.updateDPI(newDPI); + + this.renderer.render(this.frame); + this.overlayRenderer.render(this.frame); }; ns.DrawingController.prototype.renderFrame = function () { diff --git a/js/piskel.js b/js/piskel.js index e195c05d..af4f7a79 100644 --- a/js/piskel.js +++ b/js/piskel.js @@ -11,23 +11,18 @@ $.namespace("pskl"); */ var frameSheet, - // Temporary zoom implementation to easily get bigger canvases to - // see how good perform critical algorithms on big canvas. - zoom = 1, - // Configuration: // Canvas size in pixel size (not dpi related) - framePixelWidth = 32 * zoom, - framePixelHeight = 32 * zoom, - + framePixelWidth = 32, + framePixelHeight = 32, // Scaling factors for a given frameSheet rendering: // Main drawing area: - drawingCanvasDpi = Math.ceil(20/ zoom), - // Canvas previous in the slideshow: - previewTileCanvasDpi = Math.ceil(4 / zoom), - // Ainmated canvas preview: - previewAnimationCanvasDpi = Math.ceil(8 / zoom), + drawingCanvasDpi = 20, + // Canvas preview film canvases: + previewTileCanvasDpi = 4, + // Animated canvas preview: + previewAnimationCanvasDpi = 8, // DOM references: drawingAreaContainer, @@ -53,6 +48,9 @@ $.namespace("pskl"); var piskel = { init : function () { + + piskel.initDPIs_(); + frameSheet = new pskl.model.FrameSheet(framePixelWidth, framePixelHeight); frameSheet.addEmptyFrame(); @@ -95,6 +93,29 @@ $.namespace("pskl"); } }, + /** + * Override default DPIs. + * @private + */ + initDPIs_ : function() { + + drawingCanvasDpi = piskel.calculateDPIsForDrawingCanvas_(); + // TODO(vincz): Add throttling on window.resize event. + $(window).resize($.proxy(function() { + drawingCanvasDpi = piskel.calculateDPIsForDrawingCanvas_(); + this.drawingController.updateDPI(drawingCanvasDpi); + }, this)); + // TODO(vincz): Check for user settings eventually from localstorage. + }, + + /** + * @private + */ + calculateDPIsForDrawingCanvas_ : function() { + var availableViewportHeight = $('.main-panel').height(); + return Math.floor(availableViewportHeight / framePixelHeight); + }, + finishInit : function () { $.subscribe(Events.TOOL_SELECTED, function(evt, toolBehavior) { @@ -186,8 +207,6 @@ $.namespace("pskl"); document.body.addEventListener('mouseup', this.onMouseup.bind(this)); drawingAreaContainer.addEventListener('mousedown', this.onMousedown.bind(this)); drawingAreaContainer.addEventListener('mousemove', this.onMousemove.bind(this)); - drawingAreaContainer.style.width = framePixelWidth * drawingCanvasDpi + "px"; - drawingAreaContainer.style.height = framePixelHeight * drawingCanvasDpi + "px"; document.body.addEventListener('contextmenu', this.onCanvasContextMenu); }, diff --git a/js/rendering/FrameRenderer.js b/js/rendering/FrameRenderer.js index 56089285..63b96533 100644 --- a/js/rendering/FrameRenderer.js +++ b/js/rendering/FrameRenderer.js @@ -17,24 +17,30 @@ this.displayGrid = !!renderingOptions.displayGrid; this.dpi = renderingOptions.dpi; this.className = className; + + // Flag to know if the config was altered + this.canvasConfigDirty = true; }; ns.FrameRenderer.prototype.init = function (frame) { - - this.createCanvas_(frame); this.render(frame); }; + ns.FrameRenderer.prototype.updateDPI = function (newDPI) { + this.dpi = newDPI; + this.canvasConfigDirty = true; + }; + ns.FrameRenderer.prototype.render = function (frame) { for(var col = 0, width = frame.getWidth(); col < width; col++) { for(var row = 0, height = frame.getHeight(); row < height; row++) { - this.drawPixel(col, row, frame, this.canvas, this.dpi); + this.drawPixel(col, row, frame, this.getCanvas_(frame), this.dpi); } } }; ns.FrameRenderer.prototype.drawPixel = function (col, row, frame) { - var context = this.canvas.getContext('2d'); + var context = this.getCanvas_(frame).getContext('2d'); var color = frame.getPixel(col, row); if(color == Constants.TRANSPARENT_COLOR) { context.clearRect(col * this.dpi, row * this.dpi, this.dpi, this.dpi); @@ -50,17 +56,19 @@ }; ns.FrameRenderer.prototype.clear = function (col, row, frame) { - this.canvas.getContext("2d").clearRect(0, 0, this.canvas.width, this.canvas.height); + var canvas = this.getCanvas_(frame) + canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height); }; /** * @private */ - ns.FrameRenderer.prototype.createCanvas_ = function (frame) { - if(this.canvas == undefined) { + ns.FrameRenderer.prototype.getCanvas_ = function (frame) { + if(this.canvasConfigDirty) { + $(this.canvas).remove(); var width = frame.getWidth(), height = frame.getHeight(); - + var canvas = document.createElement("canvas"); canvas.setAttribute("width", width * this.dpi); canvas.setAttribute("height", height * this.dpi); @@ -72,7 +80,10 @@ canvas.setAttribute("class", canvasClassname); this.canvas = canvas; + this.container.appendChild(this.canvas); + + this.canvasConfigDirty = false; } - this.container.appendChild(this.canvas); + return this.canvas; }; })(); \ No newline at end of file