-
Notifications
You must be signed in to change notification settings - Fork 10
/
undo_state.js
199 lines (185 loc) · 6.59 KB
/
undo_state.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
* Copyright Olli Etuaho 2013.
*/
'use strict';
/**
* Storage for bitmap data from a past PictureBuffer state.
* @constructor
* @param {number} index The index of the next event in the events array. The
* last event that takes part in this undo state is events[index - 1].
* @param {number} cost Regeneration cost of the undo state.
* @param {number} width Width of the undo state in pixels.
* @param {number} height Height of the undo state in pixels.
* @param {HTMLCanvasElement} srcCanvas Canvas containing the bitmap state
* corresponding to the given index. May be null to create an invalid state.
*/
var CanvasUndoState = function(index, cost, width, height, srcCanvas) {
this.width = width;
this.height = height;
this.canvas = null;
this.ctx = null;
this.invalid = true;
this.update(srcCanvas, new Rect(0, this.width, 0, this.height));
this.index = index;
this.cost = cost;
};
/**
* Set the bitmap dimensions of the undo state. Can only be done when the undo state is freed.
* @param {number} width The new width.
* @param {number} height The new height.
*/
CanvasUndoState.prototype.setDimensions = function(width, height) {
// TODO: assert(this.canvas === null);
this.width = width;
this.height = height;
};
/**
* Ensure that the undo state has a canvas to use.
* @protected
*/
CanvasUndoState.prototype.ensureCanvas = function() {
if (this.canvas === null) {
this.canvas = document.createElement('canvas');
this.canvas.width = this.width;
this.canvas.height = this.height;
this.ctx = this.canvas.getContext('2d');
}
};
/**
* Update this undo state in place.
* @param {HTMLCanvasElement} srcCanvas Canvas containing the bitmap state
* corresponding to the given index.
* @param {Rect} clipRect Area to update.
*/
CanvasUndoState.prototype.update = function(srcCanvas, clipRect) {
if (srcCanvas === null) {
return;
}
this.ensureCanvas();
var br = clipRect.getXYWHRoundedOut();
this.ctx.clearRect(br.x, br.y, br.w, br.h);
this.ctx.drawImage(srcCanvas, br.x, br.y, br.w, br.h,
br.x, br.y, br.w, br.h);
this.invalid = false;
};
/**
* Copy an area from this undo state to the given context.
* @param {CanvasRenderingContext2D} ctx Rendering context to draw with.
* @param {Rect} clipRect Clipping rectangle for the copy operation. Will be
* rounded outwards.
*/
CanvasUndoState.prototype.draw = function(ctx, clipRect) {
// TODO: assert(!this.invalid);
var r = clipRect.getXYWHRoundedOut();
ctx.clearRect(r.x, r.y, r.w, r.h);
ctx.drawImage(this.canvas, r.x, r.y, r.w, r.h, r.x, r.y, r.w, r.h);
};
/**
* Clean up any allocated resources. The undo state will become invalid, but can
* be restored by calling update().
*/
CanvasUndoState.prototype.free = function() {
this.ctx = null;
this.canvas = null;
this.invalid = true;
};
/**
* Storage for bitmap data from a past GLBuffer state.
* @constructor
* @param {number} index The index of the next event in the events array. The
* last event that takes part in this undo state is events[index - 1].
* @param {number} cost Regeneration cost of the undo state.
* @param {WebGLTexture} srcTex A texture containing the bitmap state
* corresponding to the given index. May be null to create an invalid state.
* @param {WebGLRenderingContext} gl The rendering context.
* @param {Object} glManager The state manager returned by glStateManager() in
* utilgl.
* @param {ShaderProgram} texBlitProgram Shader program to use for blits. Must
* have uniform sampler uSrcTex for the source texture.
* @param {number} width Width of the texture to copy.
* @param {number} height Height of the texture to copy.
* @param {boolean} hasAlpha Must alpha channel data be copied?
*/
var GLUndoState = function(index, cost, srcTex, gl, glManager, texBlitProgram,
width, height, hasAlpha) {
this.gl = gl;
this.glManager = glManager;
this.texBlitProgram = texBlitProgram;
this.texBlitUniforms = texBlitProgram.uniformParameters();
this.width = width;
this.height = height;
this.hasAlpha = hasAlpha;
this.tex = null;
this.invalid = true;
this.update(srcTex, new Rect(0, this.width, 0, this.height));
this.index = index;
this.cost = cost;
};
/**
* Set the bitmap dimensions of the undo state. Can only be done when the undo state is freed.
* @param {number} width The new width.
* @param {number} height The new height.
*/
GLUndoState.prototype.setDimensions = function(width, height) {
// TODO: assert(this.tex === null);
this.width = width;
this.height = height;
};
/**
* Ensure that the undo state has a texture to use.
* @protected
*/
GLUndoState.prototype.ensureTexture = function() {
if (this.tex === null) {
var format = this.hasAlpha ? this.gl.RGBA : this.gl.RGB;
this.tex = glUtils.createTexture(this.gl, this.width, this.height,
format);
}
};
/**
* Update this undo state in place.
* @param {WebGLTexture} srcTex A texture containing the bitmap state
* corresponding to the given index.
* @param {Rect} clipRect Area to update.
*/
GLUndoState.prototype.update = function(srcTex, clipRect) {
if (srcTex === null) {
return;
}
this.ensureTexture();
this.gl.viewport(0, 0, this.width, this.height);
this.glManager.useFboTex(this.tex);
glUtils.updateClip(this.gl, clipRect, this.height);
this.texBlitUniforms['uSrcTex'] = srcTex;
this.gl.clearColor(0, 0, 0, 0);
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
this.glManager.drawFullscreenQuad(this.texBlitProgram,
this.texBlitUniforms);
this.invalid = false;
};
/**
* Copy an area from this undo state to the context it was created in.
* @param {Rect} clipRect Clipping rectangle for the copy operation. Will be
* rounded outwards.
*/
GLUndoState.prototype.draw = function(clipRect) {
// TODO: assert(!this.invalid);
this.gl.viewport(0, 0, this.width, this.height);
this.texBlitUniforms['uSrcTex'] = this.tex;
glUtils.updateClip(this.gl, clipRect, this.height);
this.gl.clearColor(0, 0, 0, 0);
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
this.glManager.drawFullscreenQuad(this.texBlitProgram,
this.texBlitUniforms);
};
/**
* Clean up any allocated resources. The undo state will become invalid, but can
* be restored by calling update().
*/
GLUndoState.prototype.free = function() {
if (this.tex !== null) {
this.gl.deleteTexture(this.tex);
this.tex = null;
this.invalid = true;
}
};