Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 // -*- mode: js2; indent-tabs-mode: nil; -*-
3 // A RectArray<X,k> is a subclass of Array with 'width', 'height',
4 // and 'payload' properties (where payload holds 'k').
5 // properties, and 'width*height*k' elements (each an X) in the array.
6 //
7 // A RectTypedByteArray<k> is a subclass of ArrayBuffer with 'width'
8 // and 'height' properties, and 'width*height*k' bytes in the buffer.
9 //
10 // The 'payload' property is initialized with the value of 'k'.
11 //
12 // (Felix would have used Array or ArrayView, but for the following bug:
13 // Bug 695438 - TypedArrays don't support new named properties
14 // https://bugzilla.mozilla.org/show_bug.cgi?id=695438
15 // and so he is resorting to extending ArrayBuffer instead.)
16 //
17 // Both classes add a .get(x,y[,k]) method that eases access to the
18 // contents, and a set(x,y[,k],value) method that eases modifying
19 // their entries.
20 //
21 // In addition, for those who prefer functional-style,
22 // RectArray.build,
23 // and RectByteTypedArray.build
25 var RectArray, RectByteTypedArray;
27 // This is a variant of RectArray that supports the same interface,
28 // but instead of attempting to extend Array (a practice fraught with
29 // peril), it instead makes a wrapper around another array.
31 var WrapArray, WrapByteTypedArray;
33 (function (){
35 function defineReadOnly(x, name, value) {
36 Object.defineProperty(x, name, {
37 value: value,
38 writable: false,
39 enumerable: true,
40 configurable: true });
41 }
43 RectArray = function RectArray(w,h,k) {
44 if (k === undefined)
45 k = 1;
46 this.length = w*h*k;
47 defineReadOnly(this, "width", w);
48 defineReadOnly(this, "height", h);
49 defineReadOnly(this, "payload", k);
50 };
52 RectByteTypedArray = function RectByteTypedArray(w,h,k) {
53 if (k === undefined)
54 k = 1;
55 ArrayBuffer.call(this, w*h*k);
56 defineReadOnly(this, "width", w);
57 defineReadOnly(this, "height", h);
58 defineReadOnly(this, "payload", k);
59 };
61 WrapArray = function WrapArray(w,h,k) {
62 if (k === undefined)
63 k = 1;
64 this.backingArray = new Array(w*h*k);
65 defineReadOnly(this, "width", w);
66 defineReadOnly(this, "height", h);
67 defineReadOnly(this, "payload", k);
68 };
70 WrapByteTypedArray = function WrapByteTypedArray(w,h,k) {
71 if (k === undefined)
72 k = 1;
73 this.backingArray = new Uint8Array(new ArrayBuffer(w*h*k));
74 defineReadOnly(this, "width", w);
75 defineReadOnly(this, "height", h);
76 defineReadOnly(this, "payload", k);
77 };
79 WrapArray.prototype.slice = function(a,b) this.backingArray.slice(a,b);
80 WrapArray.prototype.join = function(a) this.backingArray.join(a);
82 RectArray.prototype = new Array();
83 RectByteTypedArray.prototype = new ArrayBuffer();
85 RectArray.prototype.get = function get(x,y,j) {
86 if (j === undefined) j = 0;
87 return this[(y*this.width+x)*this.payload+j];
88 };
90 RectArray.prototype.set = function set(x,y,j,value) {
91 if (value === undefined) {
92 value = j;
93 j = 0;
94 }
95 this[(y*this.width+x)*this.payload+j] = value;
96 };
98 RectByteTypedArray.prototype.get = function get(x,y,j) {
99 if (j === undefined) j = 0;
100 return (new Uint8Array(this))[(y*this.width+x)*this.payload+j];
101 };
103 RectByteTypedArray.prototype.set = function set(x,y,j,value) {
104 if (value === undefined) {
105 value = j;
106 j = 0;
107 }
108 (new Uint8Array(this))[(y*this.width+x)*this.payload+j] = value;
109 };
111 WrapArray.prototype.get = function get(x,y,j) {
112 if (j === undefined) j = 0;
113 return this.backingArray[(y*this.width+x)*this.payload+j];
114 };
116 WrapArray.prototype.set = function set(x,y,j,value) {
117 if (value === undefined) {
118 value = j;
119 j = 0;
120 }
121 this.backingArray[(y*this.width+x)*this.payload+j] = value;
122 };
124 WrapByteTypedArray.prototype.get = function get(x,y,j) {
125 if (j === undefined) j = 0;
126 return this.backingArray[(y*this.width+x)*this.payload+j];
127 };
129 WrapByteTypedArray.prototype.set = function set(x,y,j,value) {
130 if (value === undefined) {
131 value = j;
132 j = 0;
133 }
134 this.backingArray[(y*this.width+x)*this.payload+j] = value;
135 };
137 function viewToSource(view, width, height, payload) {
138 var ret = "[";
139 var i=0;
140 var matrixNeedsNewline = false;
141 for (var row=0; row < height; row++) {
142 if (matrixNeedsNewline)
143 ret += ",\n ";
144 ret += "[";
145 var rowNeedsComma = false;
146 for (var x=0; x < width; x++) {
147 if (rowNeedsComma)
148 ret += ", ";
149 if (payload == 1) {
150 if (view[i] !== undefined)
151 ret += view[i];
152 i++;
153 } else {
154 var entryNeedsComma = false;
155 ret += "(";
156 for (var k=0; k < payload; k++) {
157 // Might be inefficient (does JavaScript have
158 // StringBuffers?, or use them internally, like Tamarin?)
159 if (entryNeedsComma)
160 ret += ", ";
161 if (view[i] !== undefined)
162 ret += view[i];
163 entryNeedsComma = true;
164 i++;
165 }
166 ret += ")";
167 }
168 rowNeedsComma = true;
169 }
170 ret += "]";
171 matrixNeedsNewline = true;
172 }
173 ret += "]";
174 return ret;
175 }
177 RectArray.prototype.toSource = function toSource() {
178 return viewToSource(this,
179 this.width, this.height, this.payload);
180 };
182 RectByteTypedArray.prototype.toSource = function toSource() {
183 return viewToSource(new Uint8Array(this),
184 this.width, this.height, this.payload);
185 };
187 WrapArray.prototype.toSource = function toSource() {
188 return viewToSource(this.backingArray,
189 this.width, this.height, this.payload);
190 };
192 WrapByteTypedArray.prototype.toSource = function toSource() {
193 return viewToSource(this.backingArray,
194 this.width, this.height, this.payload);
195 };
197 RectArray.prototype.map = function map(f) {
198 var ret = Array.map(this, f);
199 ret.__proto__ = RectArray.prototype;
200 defineReadOnly(ret, "width", this.width);
201 defineReadOnly(ret, "height", this.height);
202 defineReadOnly(ret, "payload", this.payload);
203 return ret;
204 };
206 WrapArray.prototype.map = function map(f) {
207 var ret = new WrapArray(this.width, this.height, this.payload);
208 ret.backingArray = this.backingArray.map(f);
209 return ret;
210 };
212 // (Array<X>|ArrayView<X>) Nat Nat Nat (Nat Nat Nat -> X) -> void
213 function fillArrayView(view, width, height, k, fill) {
214 var i = 0;
215 for (var y=0; y < height; y++) {
216 for (var x=0; x < width; x++) {
217 for (var j=0; j < k; j++) {
218 view[i++] = fill(x, y, j);
219 }
220 }
221 }
222 }
225 // Nat Nat (Nat Nat [Nat] -> X) -> RectArray<X,1>
226 RectArray.build =
227 function buildRectArray1(width, height, fill) {
228 var a = new RectArray(width, height, 1);
229 fillArrayView(a, width, height, 1, fill);
230 return a;
231 };
233 RectArray.buildA =
234 function buildRectArrayA(width, height, fill) {
235 var a = new Array(width*height);
236 fillArrayView(a, width, height, 1, fill);
237 a.width = width;
238 a.height = height;
239 a.payload = 1;
240 function F() { }
241 F.prototype = RectArray.prototype;
242 a.__proto__ = new F();
243 return a;
244 };
246 // Nat Nat (Nat Nat Nat -> X) -> RectArray<X,4>
247 RectArray.build4 =
248 function buildRectArray4(width, height, fill) {
249 var a = new RectArray(width, height, 4);
250 fillArrayView(a, width, height, 4, fill);
251 return a;
252 };
254 // Nat Nat (Nat Nat Nat -> X) -> RectArray<X,1>
255 RectArray.buildN =
256 function buildRectArrayN(width, height, n, fill) {
257 var a = new RectArray(width, height, n);
258 fillArrayView(a, width, height, n, fill);
259 return a;
260 };
263 // Nat Nat (Nat Nat [Nat] -> Byte) -> RectTypedByteArray<4>
264 RectByteTypedArray.build =
265 function buildRectByteTypedArray1(width, height, fill) {
266 var buf = new RectByteTypedArray(width, height, 1);
267 fillArrayView(new Uint8Array(buf), width, height, 1, fill);
268 return buf;
269 };
271 // Nat Nat (Nat Nat Nat -> Byte) -> RectTypedByteArray<4>
272 RectByteTypedArray.build4 =
273 function buildRectByteTypedArray4(width, height, fill) {
274 var buf = new RectByteTypedArray(width, height, 4);
275 fillArrayView(new Uint8Array(buf), width, height, 4, fill);
276 return buf;
277 };
279 // Nat Nat (Nat Nat Nat -> Byte) -> RectTypedByteArray<4>
280 RectByteTypedArray.buildN =
281 function buildRectByteTypedArray4(width, height, n, fill) {
282 var buf = new RectByteTypedArray(width, height, n);
283 fillArrayView(new Uint8Array(buf), width, height, n, fill);
284 return buf;
285 };
287 WrapArray.build =
288 function buildWrapArray1(width, height, fill) {
289 var a = new WrapArray(width, height, 1);
290 fillArrayView(a, width, height, 1, fill);
291 return a;
292 };
294 WrapArray.build =
295 function buildWrapArray1(width, height, fill) {
296 var a = new WrapArray(width, height, 1);
297 fillArrayView(a.backingArray, width, height, 1, fill);
298 return a;
299 };
301 WrapArray.build4 =
302 function buildWrapArray1(width, height, fill) {
303 var a = new WrapArray(width, height, 4);
304 fillArrayView(a.backingArray, width, height, 4, fill);
305 return a;
306 };
308 WrapArray.buildN =
309 function buildWrapArray1(width, height, n, fill) {
310 var a = new WrapArray(width, height, n);
311 fillArrayView(a.backingArray, width, height, n, fill);
312 return a;
313 };
315 })();