/* * Guacamole - Pure JavaScript/HTML VNC Client * Copyright (C) 2010 Michael Jumper * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ function Layer(width, height) { // Off-screen buffer var display = document.createElement("canvas"); display.style.position = "absolute"; display.style.left = "0px"; display.style.right = "0px"; display.width = width; display.height = height; var displayContext = display.getContext("2d"); var nextUpdateToDraw = 0; var currentUpdate = 0; var updates = new Array(); // Given an update ID, either call the provided update callback, or // schedule the update for later. function setUpdate(updateId, update) { // If this update is the next to draw... if (updateId == nextUpdateToDraw) { // Call provided update handler. update(); // Draw all pending updates. var updateCallback; while (updateCallback = updates[++nextUpdateToDraw]) { updateCallback(); delete updates[nextUpdateToDraw]; } } // If not next to draw, set callback and wait. else updates[updateId] = update; } display.drawImage = function(x, y, image) { var updateId = currentUpdate++; setUpdate(updateId, function() { displayContext.drawImage(image, x, y); }); } display.draw = function(x, y, url) { var updateId = currentUpdate++; var image = new Image(); image.onload = function() { setUpdate(updateId, function() { displayContext.drawImage(image, x, y); }); }; image.src = url; }; display.copyRect = function(srcx, srcy, w, h, x, y) { var updateId = currentUpdate++; setUpdate(updateId, function() { displayContext.drawImage(display, srcx, srcy, w, h, x, y, w, h); }); }; display.drawRect = function(x, y, w, h, color) { var updateId = currentUpdate++; setUpdate(updateId, function() { displayContext.fillStyle = color; displayContext.fillRect(x, y, w, h); }); }; display.clearRect = function(x, y, w, h) { var updateId = currentUpdate++; setUpdate(updateId, function() { displayContext.clearRect(x, y, w, h); }); }; display.filter = function(filter) { var updateId = currentUpdate++; setUpdate(updateId, function() { var imageData = displayContext.getImageData(0, 0, width, height); filter(imageData.data, width, height); displayContext.putImageData(imageData, 0, 0); }); }; return display; }