Merge branch 'master' into gh-pages

This commit is contained in:
juliandescottes
2012-09-08 17:35:36 +02:00
10 changed files with 213 additions and 110 deletions

View File

@@ -73,10 +73,7 @@
} }
.drawing-canvas { .drawing-canvas {
position: absolute; float: left;
top: 0;
left: 0;
z-index: 1;
} }
.canvas-overlay { .canvas-overlay {

View File

@@ -91,10 +91,10 @@
<!-- Application libraries--> <!-- Application libraries-->
<script src="js/model/Frame.js"></script> <script src="js/model/Frame.js"></script>
<script src="js/model/FrameSheet.js"></script> <script src="js/model/FrameSheet.js"></script>
<script src="js/rendering/FrameRenderer.js"></script>
<script src="js/controller/DrawingController.js"></script> <script src="js/controller/DrawingController.js"></script>
<script src="js/controller/PreviewFilmController.js"></script> <script src="js/controller/PreviewFilmController.js"></script>
<script src="js/controller/AnimatedPreviewController.js"></script> <script src="js/controller/AnimatedPreviewController.js"></script>
<script src="js/rendering/FrameRenderer.js"></script>
<script src="js/LocalStorageService.js"></script> <script src="js/LocalStorageService.js"></script>
<script src="js/HistoryManager.js"></script> <script src="js/HistoryManager.js"></script>
<script src="js/Palette.js"></script> <script src="js/Palette.js"></script>

View File

@@ -1,36 +1,27 @@
(function () { (function () {
var ns = $.namespace("pskl.controller"); var ns = $.namespace("pskl.controller");
ns.AnimatedPreviewController = function (framesheet, container, dpi) { ns.AnimatedPreviewController = function (framesheet, container, dpi) {
this.dpi = dpi;
this.framesheet = framesheet; this.framesheet = framesheet;
this.container = container; this.container = container;
this.animIndex = 0; this.animIndex = 0;
this.fps = parseInt($("#preview-fps")[0].value, 10); this.fps = parseInt($("#preview-fps")[0].value, 10);
this.renderer = new pskl.rendering.FrameRenderer(); var renderingOptions = {
"dpi": dpi
};
this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions);
}; };
ns.AnimatedPreviewController.prototype.init = function () { ns.AnimatedPreviewController.prototype.init = function () {
this.initDom(); this.initDom();
this.renderer.init(this.framesheet.getFrameByIndex(this.animIndex));
this.startAnimationTimer(); this.startAnimationTimer();
}; };
ns.AnimatedPreviewController.prototype.initDom = function () { 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)); $("#preview-fps")[0].addEventListener('change', this.onFPSSliderChange.bind(this));
}; };
@@ -54,8 +45,7 @@
if (!this.framesheet.hasFrameAtIndex(this.animIndex)) { if (!this.framesheet.hasFrameAtIndex(this.animIndex)) {
this.animIndex = 0; this.animIndex = 0;
} }
this.renderer.render(this.framesheet.getFrameByIndex(this.animIndex));
this.renderer.render(this.framesheet.getFrameByIndex(this.animIndex), this.previewCanvas, this.dpi);
this.animIndex++; this.animIndex++;
this.startAnimationTimer(); this.startAnimationTimer();
}; };

View File

@@ -3,62 +3,46 @@
ns.DrawingController = function (frame, container, dpi) { ns.DrawingController = function (frame, container, dpi) {
this.dpi = dpi; this.dpi = dpi;
var renderingOptions = {
"dpi": dpi,
"displayGrid": true // Retrieve from localsotrage config
}
// Public // Public
this.frame = frame; this.frame = frame;
this.overlay = pskl.model.Frame.createEmptyFromFrame(frame); this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(frame); // Type is frame
// Private // Private
this.container = container; this.container = container;
this.mainCanvas = this.createMainCanvas(); this.renderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, "drawing-canvas");
this.overlayCanvas = this.createOverlayCanvas(); this.overlayRenderer = new pskl.rendering.FrameRenderer(this.container, renderingOptions, "canvas-overlay");
this.renderer = new pskl.rendering.FrameRenderer();
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.render(this.frame);
this.overlayRenderer.render(this.frame);
}; };
ns.DrawingController.prototype.renderFrame = function () { ns.DrawingController.prototype.renderFrame = function () {
this.renderer.render(this.frame, this.mainCanvas, this.dpi); this.renderer.render(this.frame);
}; };
ns.DrawingController.prototype.renderFramePixel = function (col, row) { 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);
}; };
ns.DrawingController.prototype.renderOverlay = function () { ns.DrawingController.prototype.renderOverlay = function () {
this.renderer.render(this.overlay, this.overlayCanvas, this.dpi); this.overlayRenderer.render(this.overlayFrame);
}; };
ns.DrawingController.prototype.clearOverlay = function () { ns.DrawingController.prototype.clearOverlay = function () {
this.overlay = pskl.model.Frame.createEmptyFromFrame(this.frame); this.overlayFrame = pskl.model.Frame.createEmptyFromFrame(this.frame);
this.overlayCanvas.getContext("2d").clearRect(0, 0, this.overlayCanvas.width, this.overlayCanvas.height); this.overlayRenderer.clear();
};
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;
}; };
})(); })();

View File

@@ -5,14 +5,14 @@
this.dpi = dpi; this.dpi = dpi;
this.framesheet = framesheet; this.framesheet = framesheet;
this.container = container; this.container = container;
this.renderer = new pskl.rendering.FrameRenderer();
}; };
ns.PreviewFilmController.prototype.init = function() { ns.PreviewFilmController.prototype.init = function() {
var addFrameButton = $('#add-frame-button')[0]; var addFrameButton = $('#add-frame-button')[0];
addFrameButton.addEventListener('mousedown', this.addFrame.bind(this)); addFrameButton.addEventListener('mousedown', this.addFrame.bind(this));
this.createPreviews(); this.createPreviews();
}; };
ns.PreviewFilmController.prototype.addFrame = function () { ns.PreviewFilmController.prototype.addFrame = function () {
@@ -92,7 +92,10 @@
*/ */
ns.PreviewFilmController.prototype.onDrop_ = function( event, ui ) { ns.PreviewFilmController.prototype.onDrop_ = function( event, ui ) {
var activeFrame; var activeFrame;
var originFrameId = parseInt($(event.srcElement).data("tile-number"), 10); // When we drag from an element, the drag could start from a nested DOM element
// inside the drag target. We normalize that by taking the correct ancestor:
var originTile = $(event.srcElement).closest(".preview-tile");
var originFrameId = parseInt(originTile.data("tile-number"), 10);
var dropTarget = $(event.target); var dropTarget = $(event.target);
if(dropTarget.data("tile-type") == "interstitial") { if(dropTarget.data("tile-type") == "interstitial") {
@@ -101,7 +104,7 @@
if(isNaN(originFrameId) || isNaN(targetInsertionId)) { if(isNaN(originFrameId) || isNaN(targetInsertionId)) {
return; return;
} }
console.log("origin-frame: "+originFrameId+" - targetInsertionId: "+ targetInsertionId) //console.log("origin-frame: "+originFrameId+" - targetInsertionId: "+ targetInsertionId)
this.framesheet.moveFrame(originFrameId, targetInsertionId); this.framesheet.moveFrame(originFrameId, targetInsertionId);
activeFrame = targetInsertionId; activeFrame = targetInsertionId;
@@ -119,7 +122,7 @@
if(isNaN(originFrameId) || isNaN(targetSwapId)) { if(isNaN(originFrameId) || isNaN(targetSwapId)) {
return; return;
} }
console.log("origin-frame: "+originFrameId+" - targetSwapId: "+ targetSwapId) //console.log("origin-frame: "+originFrameId+" - targetSwapId: "+ targetSwapId)
this.framesheet.swapFrames(originFrameId, targetSwapId); this.framesheet.swapFrames(originFrameId, targetSwapId);
activeFrame = targetSwapId; activeFrame = targetSwapId;
} }
@@ -140,9 +143,9 @@
* TODO(vincz): clean this giant rendering function & remove listeners. * TODO(vincz): clean this giant rendering function & remove listeners.
*/ */
ns.PreviewFilmController.prototype.createPreviewTile_ = function(tileNumber) { ns.PreviewFilmController.prototype.createPreviewTile_ = function(tileNumber) {
var frame = this.framesheet.getFrameByIndex(tileNumber); var currentFrame = this.framesheet.getFrameByIndex(tileNumber);
var width = frame.getWidth() * this.dpi, //var width = frame.getWidth() * this.dpi,
height = frame.getHeight() * this.dpi; // height = frame.getHeight() * this.dpi;
var previewTileRoot = document.createElement("li"); var previewTileRoot = document.createElement("li");
var classname = "preview-tile"; var classname = "preview-tile";
@@ -155,18 +158,19 @@
var canvasContainer = document.createElement("div"); var canvasContainer = document.createElement("div");
canvasContainer.className = "canvas-container"; 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"); var canvasBackground = document.createElement("div");
canvasBackground.className = "canvas-background"; canvasBackground.className = "canvas-background";
canvasContainer.appendChild(canvasBackground); canvasContainer.appendChild(canvasBackground);
/*
var canvasPreview = document.createElement("canvas"); var canvasPreview = document.createElement("canvas");
canvasPreview.className = "canvas tile-view" canvasPreview.className = "canvas tile-view"
canvasPreview.setAttribute('width', width); canvasPreview.setAttribute('width', width);
canvasPreview.setAttribute('height', height); canvasPreview.setAttribute('height', height);
*/
previewTileRoot.addEventListener('click', function(evt) { previewTileRoot.addEventListener('click', function(evt) {
// has not class tile-action: // has not class tile-action:
if(!evt.target.classList.contains('tile-action')) { if(!evt.target.classList.contains('tile-action')) {
@@ -182,8 +186,14 @@
piskel.duplicateFrame(tileNumber); piskel.duplicateFrame(tileNumber);
}); });
this.renderer.render(this.framesheet.getFrameByIndex(tileNumber), canvasPreview, this.dpi); //this.renderer.render(this.framesheet.getFrameByIndex(tileNumber), canvasPreview);
canvasContainer.appendChild(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 renderingOptions = {"dpi": this.dpi };
var currentFrameRenderer = new pskl.rendering.FrameRenderer(canvasContainer, renderingOptions, "tile-view");
currentFrameRenderer.init(currentFrame);
previewTileRoot.appendChild(canvasContainer); previewTileRoot.appendChild(canvasContainer);
previewTileRoot.appendChild(canvasPreviewDuplicateAction); previewTileRoot.appendChild(canvasPreviewDuplicateAction);

View File

@@ -24,7 +24,7 @@
this.startRow = row; this.startRow = row;
// Drawing the first point of the rectangle in the fake overlay canvas: // 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(); drawer.renderOverlay();
}; };
@@ -42,7 +42,7 @@
if(color == Constants.TRANSPARENT_COLOR) { if(color == Constants.TRANSPARENT_COLOR) {
color = Constants.SELECTION_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(); drawer.renderOverlay();
}; };

View File

@@ -34,7 +34,7 @@
// The fake canvas where we will draw the preview of the stroke: // The fake canvas where we will draw the preview of the stroke:
// Drawing the first point of the stroke in the fake overlay canvas: // 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(); drawer.renderOverlay();
}; };
@@ -57,7 +57,7 @@
// eg deleting the equivalent of a stroke. // eg deleting the equivalent of a stroke.
color = Constants.SELECTION_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(); drawer.renderOverlay();
}; };

View File

@@ -3,7 +3,7 @@
ns.Frame = function (pixels) { ns.Frame = function (pixels) {
this.pixels = pixels; this.pixels = pixels;
this.previousStates = [this._clonePixels()]; this.previousStates = [this.getPixels()];
this.stateIndex = 0; this.stateIndex = 0;
}; };
@@ -27,12 +27,30 @@
return new ns.Frame(this._clonePixels()); return new ns.Frame(this._clonePixels());
}; };
ns.Frame.prototype._clonePixels = function () { /**
var pixels = []; * Returns a copy of the pixels used by the frame
for (var col = 0 ; col < this.getWidth() ; col++) { */
pixels[col] = this.pixels[col].slice(0 , this.getHeight()); ns.Frame.prototype.getPixels = function () {
return this.clonePixels_(this.pixels)
};
/**
* Copies the passed pixels into the frame.
*/
ns.Frame.prototype.setPixels = function (pixels) {
this.pixels = this.clonePixels_(pixels);
};
/**
* Clone a set of pixels. Should be static utility method
* @private
*/
ns.Frame.prototype.clonePixels_ = function (pixels) {
var clonedPixels = [];
for (var col = 0 ; col < pixels.length ; col++) {
clonedPixels[col] = pixels[col].slice(0 , this.getHeight());
} }
return pixels; return clonedPixels;
}; };
ns.Frame.prototype.serialize = function () { ns.Frame.prototype.serialize = function () {
@@ -63,7 +81,7 @@
// remove all states past current state // remove all states past current state
this.previousStates.length = this.stateIndex + 1; this.previousStates.length = this.stateIndex + 1;
// push new state // push new state
this.previousStates.push(this._clonePixels()); this.previousStates.push(this.getPixels());
// set the stateIndex to latest saved state // set the stateIndex to latest saved state
this.stateIndex = this.previousStates.length - 1; this.stateIndex = this.previousStates.length - 1;
}; };
@@ -71,14 +89,14 @@
ns.Frame.prototype.loadPreviousState = function () { ns.Frame.prototype.loadPreviousState = function () {
if (this.stateIndex > 0) { if (this.stateIndex > 0) {
this.stateIndex--; this.stateIndex--;
this.pixels = this.previousStates[this.stateIndex]; this.setPixels(this.previousStates[this.stateIndex]);
} }
}; };
ns.Frame.prototype.loadNextState = function () { ns.Frame.prototype.loadNextState = function () {
if (this.stateIndex < this.previousStates.length - 1) { if (this.stateIndex < this.previousStates.length - 1) {
this.stateIndex++; this.stateIndex++;
this.pixels = this.previousStates[this.stateIndex]; this.setPixels(this.previousStates[this.stateIndex]);
} }
}; };
})(); })();

View File

@@ -11,23 +11,18 @@ $.namespace("pskl");
*/ */
var frameSheet, var frameSheet,
// Temporary zoom implementation to easily get bigger canvases to
// see how good perform critical algorithms on big canvas.
zoom = 1,
// Configuration: // Configuration:
// Canvas size in pixel size (not dpi related) // Canvas size in pixel size (not dpi related)
framePixelWidth = 32 * zoom, framePixelWidth = 32,
framePixelHeight = 32 * zoom, framePixelHeight = 32,
// Scaling factors for a given frameSheet rendering: // Scaling factors for a given frameSheet rendering:
// Main drawing area: // Main drawing area:
drawingCanvasDpi = Math.ceil(20/ zoom), drawingCanvasDpi = 20,
// Canvas previous in the slideshow: // Canvas preview film canvases:
previewTileCanvasDpi = Math.ceil(4 / zoom), previewTileCanvasDpi = 4,
// Ainmated canvas preview: // Animated canvas preview:
previewAnimationCanvasDpi = Math.ceil(8 / zoom), previewAnimationCanvasDpi = 8,
// DOM references: // DOM references:
drawingAreaContainer, drawingAreaContainer,
@@ -53,6 +48,9 @@ $.namespace("pskl");
var piskel = { var piskel = {
init : function () { init : function () {
piskel.initDPIs_();
frameSheet = new pskl.model.FrameSheet(framePixelWidth, framePixelHeight); frameSheet = new pskl.model.FrameSheet(framePixelWidth, framePixelHeight);
frameSheet.addEmptyFrame(); frameSheet.addEmptyFrame();
@@ -95,6 +93,53 @@ $.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(),
availableViewportWidth = $('.main-panel').width(),
previewHeight = $(".preview-container").height(),
previewWidth = $(".preview-container").width();
var heightBoundDpi = Math.floor(availableViewportHeight / framePixelHeight),
widthBoundDpi = Math.floor(availableViewportWidth / framePixelWidth);
var dpi = Math.min(heightBoundDpi, widthBoundDpi);
var drawingCanvasHeight = dpi * framePixelHeight;
var drawingCanvasWidth = dpi * framePixelWidth;
// Check if preview and drawing canvas overlap
var heightGap = drawingCanvasHeight + previewHeight - availableViewportHeight,
widthGap = drawingCanvasWidth + previewWidth - availableViewportWidth;
if (heightGap > 0 && widthGap > 0) {
// Calculate the DPI change needed to bridge height and width gap
var heightGapDpi = Math.ceil(heightGap / framePixelHeight),
widthGapDpi = Math.ceil(widthGap / framePixelWidth);
// substract smallest dpi change to initial dpi
dpi -= Math.min(heightGapDpi, widthGapDpi);
}
return dpi;
},
finishInit : function () { finishInit : function () {
$.subscribe(Events.TOOL_SELECTED, function(evt, toolBehavior) { $.subscribe(Events.TOOL_SELECTED, function(evt, toolBehavior) {
@@ -186,8 +231,6 @@ $.namespace("pskl");
document.body.addEventListener('mouseup', this.onMouseup.bind(this)); document.body.addEventListener('mouseup', this.onMouseup.bind(this));
drawingAreaContainer.addEventListener('mousedown', this.onMousedown.bind(this)); drawingAreaContainer.addEventListener('mousedown', this.onMousedown.bind(this));
drawingAreaContainer.addEventListener('mousemove', this.onMousemove.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); document.body.addEventListener('contextmenu', this.onCanvasContextMenu);
}, },

View File

@@ -1,20 +1,49 @@
(function () { (function () {
var ns = $.namespace("pskl.rendering"); var ns = $.namespace("pskl.rendering");
ns.FrameRenderer = function () {};
ns.FrameRenderer.prototype.render = function (frame, canvas, dpi) { this.dpi = null;
this.canvas = null;
ns.FrameRenderer = function (container, renderingOptions, className) {
if(container == undefined) {
throw "Bad FrameRenderer initialization. <container> undefined.";
}
this.container = container;
if(renderingOptions == undefined || renderingOptions.dpi == undefined || isNaN(dpi)) {
throw "Bad FrameRenderer initialization. <dpi> not well defined.";
}
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.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 col = 0, width = frame.getWidth(); col < width; col++) {
for(var row = 0, height = frame.getHeight(); row < height; row++) { for(var row = 0, height = frame.getHeight(); row < height; row++) {
this.drawPixel(col, row, frame, canvas, dpi); this.drawPixel(col, row, frame, this.getCanvas_(frame), this.dpi);
} }
} }
}; };
ns.FrameRenderer.prototype.drawPixel = function (col, row, frame, canvas, dpi) { ns.FrameRenderer.prototype.drawPixel = function (col, row, frame) {
var context = canvas.getContext('2d'); var context = this.getCanvas_(frame).getContext('2d');
var color = frame.getPixel(col, row); var color = frame.getPixel(col, row);
if(color == Constants.TRANSPARENT_COLOR) { 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 { else {
if(color != Constants.SELECTION_TRANSPARENT_COLOR) { if(color != Constants.SELECTION_TRANSPARENT_COLOR) {
@@ -22,7 +51,39 @@
$.publish(Events.COLOR_USED, [color]); $.publish(Events.COLOR_USED, [color]);
} }
context.fillStyle = color; context.fillStyle = color;
context.fillRect(col * dpi, row * dpi, dpi, dpi); context.fillRect(col * this.dpi, row * this.dpi, this.dpi, this.dpi);
} }
}; };
ns.FrameRenderer.prototype.clear = function (col, row, frame) {
var canvas = this.getCanvas_(frame)
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
};
/**
* @private
*/
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);
var canvasClassname = "canvas";
if(this.className) {
canvasClassname += " " + this.className;
}
canvas.setAttribute("class", canvasClassname);
this.canvas = canvas;
this.container.appendChild(this.canvas);
this.canvasConfigDirty = false;
}
return this.canvas;
};
})(); })();