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.
7
// A RectTypedByteArray<k> is a subclass of ArrayBuffer with 'width'
8
// and 'height' properties, and 'width*height*k' bytes in the buffer.
10
// The 'payload' property is initialized with the value of 'k'.
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.)
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
21
// In addition, for those who prefer functional-style,
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;
35
function defineReadOnly(x, name, value) {
36
Object.defineProperty(x, name, {
40
configurable: true });
43
RectArray = function RectArray(w,h,k) {
47
defineReadOnly(this, "width", w);
48
defineReadOnly(this, "height", h);
49
defineReadOnly(this, "payload", k);
52
RectByteTypedArray = function RectByteTypedArray(w,h,k) {
55
ArrayBuffer.call(this, w*h*k);
56
defineReadOnly(this, "width", w);
57
defineReadOnly(this, "height", h);
58
defineReadOnly(this, "payload", k);
61
WrapArray = function WrapArray(w,h,k) {
64
this.backingArray = new Array(w*h*k);
65
defineReadOnly(this, "width", w);
66
defineReadOnly(this, "height", h);
67
defineReadOnly(this, "payload", k);
70
WrapByteTypedArray = function WrapByteTypedArray(w,h,k) {
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);
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];
90
RectArray.prototype.set = function set(x,y,j,value) {
91
if (value === undefined) {
95
this[(y*this.width+x)*this.payload+j] = value;
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];
103
RectByteTypedArray.prototype.set = function set(x,y,j,value) {
104
if (value === undefined) {
108
(new Uint8Array(this))[(y*this.width+x)*this.payload+j] = value;
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];
116
WrapArray.prototype.set = function set(x,y,j,value) {
117
if (value === undefined) {
121
this.backingArray[(y*this.width+x)*this.payload+j] = value;
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];
129
WrapByteTypedArray.prototype.set = function set(x,y,j,value) {
130
if (value === undefined) {
134
this.backingArray[(y*this.width+x)*this.payload+j] = value;
137
function viewToSource(view, width, height, payload) {
140
var matrixNeedsNewline = false;
141
for (var row=0; row < height; row++) {
142
if (matrixNeedsNewline)
145
var rowNeedsComma = false;
146
for (var x=0; x < width; x++) {
150
if (view[i] !== undefined)
154
var entryNeedsComma = false;
156
for (var k=0; k < payload; k++) {
157
// Might be inefficient (does JavaScript have
158
// StringBuffers?, or use them internally, like Tamarin?)
161
if (view[i] !== undefined)
163
entryNeedsComma = true;
168
rowNeedsComma = true;
171
matrixNeedsNewline = true;
177
RectArray.prototype.toSource = function toSource() {
178
return viewToSource(this,
179
this.width, this.height, this.payload);
182
RectByteTypedArray.prototype.toSource = function toSource() {
183
return viewToSource(new Uint8Array(this),
184
this.width, this.height, this.payload);
187
WrapArray.prototype.toSource = function toSource() {
188
return viewToSource(this.backingArray,
189
this.width, this.height, this.payload);
192
WrapByteTypedArray.prototype.toSource = function toSource() {
193
return viewToSource(this.backingArray,
194
this.width, this.height, this.payload);
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);
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);
212
// (Array<X>|ArrayView<X>) Nat Nat Nat (Nat Nat Nat -> X) -> void
213
function fillArrayView(view, width, height, k, fill) {
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);
225
// Nat Nat (Nat Nat [Nat] -> X) -> RectArray<X,1>
227
function buildRectArray1(width, height, fill) {
228
var a = new RectArray(width, height, 1);
229
fillArrayView(a, width, height, 1, fill);
234
function buildRectArrayA(width, height, fill) {
235
var a = new Array(width*height);
236
fillArrayView(a, width, height, 1, fill);
241
F.prototype = RectArray.prototype;
242
a.__proto__ = new F();
246
// Nat Nat (Nat Nat Nat -> X) -> RectArray<X,4>
248
function buildRectArray4(width, height, fill) {
249
var a = new RectArray(width, height, 4);
250
fillArrayView(a, width, height, 4, fill);
254
// Nat Nat (Nat Nat Nat -> X) -> RectArray<X,1>
256
function buildRectArrayN(width, height, n, fill) {
257
var a = new RectArray(width, height, n);
258
fillArrayView(a, width, height, n, fill);
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);
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);
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);
288
function buildWrapArray1(width, height, fill) {
289
var a = new WrapArray(width, height, 1);
290
fillArrayView(a, width, height, 1, fill);
295
function buildWrapArray1(width, height, fill) {
296
var a = new WrapArray(width, height, 1);
297
fillArrayView(a.backingArray, width, height, 1, fill);
302
function buildWrapArray1(width, height, fill) {
303
var a = new WrapArray(width, height, 4);
304
fillArrayView(a.backingArray, width, height, 4, fill);
309
function buildWrapArray1(width, height, n, fill) {
310
var a = new WrapArray(width, height, n);
311
fillArrayView(a.backingArray, width, height, n, fill);