True layer and buffer support (not stub)
[guacamole-common-js.git] / src / main / resources / layer.js
1
2 /*
3  *  Guacamole - Clientless Remote Desktop
4  *  Copyright (C) 2010  Michael Jumper
5  *
6  *  This program is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU Affero General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU Affero General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Affero General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 function Layer(width, height) {
21
22     // Off-screen buffer
23     var display = document.createElement("canvas");
24     var displayContext = display.getContext("2d");
25
26     function resize(newWidth, newHeight) {
27         display.style.position = "absolute";
28         display.style.left = "0px";
29         display.style.right = "0px";
30
31         display.width = newWidth;
32         display.height = newHeight;
33
34         width = newWidth;
35         height = newHeight;
36     }
37
38     display.resize = function(newWidth, newHeight) {
39         if (newWidth != width || newHeight != height)
40             resize(newWidth, newHeight);
41     }
42
43     resize(width, height);
44
45     var readyHandler = null;
46     var nextUpdateToDraw = 0;
47     var currentUpdate = 0;
48     var updates = new Array();
49
50     // Given an update ID, either call the provided update callback, or
51     // schedule the update for later.
52     function setUpdate(updateId, update) {
53
54         // If this update is the next to draw...
55         if (updateId == nextUpdateToDraw) {
56
57             // Call provided update handler.
58             update();
59
60             // Draw all pending updates.
61             var updateCallback;
62             while ((updateCallback = updates[++nextUpdateToDraw])) {
63                 updateCallback();
64                 delete updates[nextUpdateToDraw];
65             }
66
67             // If done with updates, call ready handler
68             if (display.isReady() && readyHandler != null)
69                 readyHandler();
70
71         }
72
73         // If not next to draw, set callback and wait.
74         else
75             updates[updateId] = update;
76
77     }
78
79     display.isReady = function() {
80         return currentUpdate == nextUpdateToDraw;
81     }
82
83     display.setReadyHandler = function(handler) {
84         readyHandler = handler;
85     }
86
87
88     display.drawImage = function(x, y, image) {
89         var updateId = currentUpdate++;
90
91         setUpdate(updateId, function() {
92             displayContext.drawImage(image, x, y);
93         });
94
95     }
96
97
98     display.draw = function(x, y, url) {
99         var updateId = currentUpdate++;
100
101         var image = new Image();
102         image.onload = function() {
103             setUpdate(updateId, function() {
104                 displayContext.drawImage(image, x, y);
105             });
106         };
107         image.src = url;
108     };
109
110
111     display.copyRect = function(srcLayer, srcx, srcy, w, h, x, y) {
112         var updateId = currentUpdate++;
113     
114         setUpdate(updateId, function() {
115             displayContext.drawImage(srcLayer, srcx, srcy, w, h, x, y, w, h);
116         });
117
118     };
119
120     display.clearRect = function(x, y, w, h) {
121         var updateId = currentUpdate++;
122
123         setUpdate(updateId, function() {
124             displayContext.clearRect(x, y, w, h);
125         });
126
127     };
128
129     display.filter = function(filter) {
130         var updateId = currentUpdate++;
131
132         setUpdate(updateId, function() {
133             var imageData = displayContext.getImageData(0, 0, width, height);
134             filter(imageData.data, width, height);
135             displayContext.putImageData(imageData, 0, 0);
136         });
137
138     };
139
140     return display;
141
142 }
143