blob: 0bd9ce54c0406eac4e0b2d8f6ff8d21b126a3dcd [file] [log] [blame]
// -*- mode: js2; indent-tabs-mode: nil; -*-
// A RectArray<X,k> is a subclass of Array with 'width', 'height',
// and 'payload' properties (where payload holds 'k').
// properties, and 'width*height*k' elements (each an X) in the array.
//
// A RectTypedByteArray<k> is a subclass of ArrayBuffer with 'width'
// and 'height' properties, and 'width*height*k' bytes in the buffer.
//
// The 'payload' property is initialized with the value of 'k'.
//
// (Felix would have used Array or ArrayView, but for the following bug:
// Bug 695438 - TypedArrays don't support new named properties
// https://bugzilla.mozilla.org/show_bug.cgi?id=695438
// and so he is resorting to extending ArrayBuffer instead.)
//
// Both classes add a .get(x,y[,k]) method that eases access to the
// contents, and a set(x,y[,k],value) method that eases modifying
// their entries.
//
// In addition, for those who prefer functional-style,
// RectArray.build,
// and RectByteTypedArray.build
var RectArray, RectByteTypedArray;
// This is a variant of RectArray that supports the same interface,
// but instead of attempting to extend Array (a practice fraught with
// peril), it instead makes a wrapper around another array.
var WrapArray, WrapByteTypedArray;
(function (){
function defineReadOnly(x, name, value) {
Object.defineProperty(x, name, {
value: value,
writable: false,
enumerable: true,
configurable: true });
}
RectArray = function RectArray(w,h,k) {
if (k === undefined)
k = 1;
this.length = w*h*k;
defineReadOnly(this, "width", w);
defineReadOnly(this, "height", h);
defineReadOnly(this, "payload", k);
};
RectByteTypedArray = function RectByteTypedArray(w,h,k) {
if (k === undefined)
k = 1;
ArrayBuffer.call(this, w*h*k);
defineReadOnly(this, "width", w);
defineReadOnly(this, "height", h);
defineReadOnly(this, "payload", k);
};
WrapArray = function WrapArray(w,h,k) {
if (k === undefined)
k = 1;
this.backingArray = new Array(w*h*k);
defineReadOnly(this, "width", w);
defineReadOnly(this, "height", h);
defineReadOnly(this, "payload", k);
};
WrapByteTypedArray = function WrapByteTypedArray(w,h,k) {
if (k === undefined)
k = 1;
this.backingArray = new Uint8Array(new ArrayBuffer(w*h*k));
defineReadOnly(this, "width", w);
defineReadOnly(this, "height", h);
defineReadOnly(this, "payload", k);
};
WrapArray.prototype.slice = function(a,b) this.backingArray.slice(a,b);
WrapArray.prototype.join = function(a) this.backingArray.join(a);
RectArray.prototype = new Array();
RectByteTypedArray.prototype = new ArrayBuffer();
RectArray.prototype.get = function get(x,y,j) {
if (j === undefined) j = 0;
return this[(y*this.width+x)*this.payload+j];
};
RectArray.prototype.set = function set(x,y,j,value) {
if (value === undefined) {
value = j;
j = 0;
}
this[(y*this.width+x)*this.payload+j] = value;
};
RectByteTypedArray.prototype.get = function get(x,y,j) {
if (j === undefined) j = 0;
return (new Uint8Array(this))[(y*this.width+x)*this.payload+j];
};
RectByteTypedArray.prototype.set = function set(x,y,j,value) {
if (value === undefined) {
value = j;
j = 0;
}
(new Uint8Array(this))[(y*this.width+x)*this.payload+j] = value;
};
WrapArray.prototype.get = function get(x,y,j) {
if (j === undefined) j = 0;
return this.backingArray[(y*this.width+x)*this.payload+j];
};
WrapArray.prototype.set = function set(x,y,j,value) {
if (value === undefined) {
value = j;
j = 0;
}
this.backingArray[(y*this.width+x)*this.payload+j] = value;
};
WrapByteTypedArray.prototype.get = function get(x,y,j) {
if (j === undefined) j = 0;
return this.backingArray[(y*this.width+x)*this.payload+j];
};
WrapByteTypedArray.prototype.set = function set(x,y,j,value) {
if (value === undefined) {
value = j;
j = 0;
}
this.backingArray[(y*this.width+x)*this.payload+j] = value;
};
function viewToSource(view, width, height, payload) {
var ret = "[";
var i=0;
var matrixNeedsNewline = false;
for (var row=0; row < height; row++) {
if (matrixNeedsNewline)
ret += ",\n ";
ret += "[";
var rowNeedsComma = false;
for (var x=0; x < width; x++) {
if (rowNeedsComma)
ret += ", ";
if (payload == 1) {
if (view[i] !== undefined)
ret += view[i];
i++;
} else {
var entryNeedsComma = false;
ret += "(";
for (var k=0; k < payload; k++) {
// Might be inefficient (does JavaScript have
// StringBuffers?, or use them internally, like Tamarin?)
if (entryNeedsComma)
ret += ", ";
if (view[i] !== undefined)
ret += view[i];
entryNeedsComma = true;
i++;
}
ret += ")";
}
rowNeedsComma = true;
}
ret += "]";
matrixNeedsNewline = true;
}
ret += "]";
return ret;
}
RectArray.prototype.toSource = function toSource() {
return viewToSource(this,
this.width, this.height, this.payload);
};
RectByteTypedArray.prototype.toSource = function toSource() {
return viewToSource(new Uint8Array(this),
this.width, this.height, this.payload);
};
WrapArray.prototype.toSource = function toSource() {
return viewToSource(this.backingArray,
this.width, this.height, this.payload);
};
WrapByteTypedArray.prototype.toSource = function toSource() {
return viewToSource(this.backingArray,
this.width, this.height, this.payload);
};
RectArray.prototype.map = function map(f) {
var ret = Array.map(this, f);
ret.__proto__ = RectArray.prototype;
defineReadOnly(ret, "width", this.width);
defineReadOnly(ret, "height", this.height);
defineReadOnly(ret, "payload", this.payload);
return ret;
};
WrapArray.prototype.map = function map(f) {
var ret = new WrapArray(this.width, this.height, this.payload);
ret.backingArray = this.backingArray.map(f);
return ret;
};
// (Array<X>|ArrayView<X>) Nat Nat Nat (Nat Nat Nat -> X) -> void
function fillArrayView(view, width, height, k, fill) {
var i = 0;
for (var y=0; y < height; y++) {
for (var x=0; x < width; x++) {
for (var j=0; j < k; j++) {
view[i++] = fill(x, y, j);
}
}
}
}
// Nat Nat (Nat Nat [Nat] -> X) -> RectArray<X,1>
RectArray.build =
function buildRectArray1(width, height, fill) {
var a = new RectArray(width, height, 1);
fillArrayView(a, width, height, 1, fill);
return a;
};
RectArray.buildA =
function buildRectArrayA(width, height, fill) {
var a = new Array(width*height);
fillArrayView(a, width, height, 1, fill);
a.width = width;
a.height = height;
a.payload = 1;
function F() { }
F.prototype = RectArray.prototype;
a.__proto__ = new F();
return a;
};
// Nat Nat (Nat Nat Nat -> X) -> RectArray<X,4>
RectArray.build4 =
function buildRectArray4(width, height, fill) {
var a = new RectArray(width, height, 4);
fillArrayView(a, width, height, 4, fill);
return a;
};
// Nat Nat (Nat Nat Nat -> X) -> RectArray<X,1>
RectArray.buildN =
function buildRectArrayN(width, height, n, fill) {
var a = new RectArray(width, height, n);
fillArrayView(a, width, height, n, fill);
return a;
};
// Nat Nat (Nat Nat [Nat] -> Byte) -> RectTypedByteArray<4>
RectByteTypedArray.build =
function buildRectByteTypedArray1(width, height, fill) {
var buf = new RectByteTypedArray(width, height, 1);
fillArrayView(new Uint8Array(buf), width, height, 1, fill);
return buf;
};
// Nat Nat (Nat Nat Nat -> Byte) -> RectTypedByteArray<4>
RectByteTypedArray.build4 =
function buildRectByteTypedArray4(width, height, fill) {
var buf = new RectByteTypedArray(width, height, 4);
fillArrayView(new Uint8Array(buf), width, height, 4, fill);
return buf;
};
// Nat Nat (Nat Nat Nat -> Byte) -> RectTypedByteArray<4>
RectByteTypedArray.buildN =
function buildRectByteTypedArray4(width, height, n, fill) {
var buf = new RectByteTypedArray(width, height, n);
fillArrayView(new Uint8Array(buf), width, height, n, fill);
return buf;
};
WrapArray.build =
function buildWrapArray1(width, height, fill) {
var a = new WrapArray(width, height, 1);
fillArrayView(a, width, height, 1, fill);
return a;
};
WrapArray.build =
function buildWrapArray1(width, height, fill) {
var a = new WrapArray(width, height, 1);
fillArrayView(a.backingArray, width, height, 1, fill);
return a;
};
WrapArray.build4 =
function buildWrapArray1(width, height, fill) {
var a = new WrapArray(width, height, 4);
fillArrayView(a.backingArray, width, height, 4, fill);
return a;
};
WrapArray.buildN =
function buildWrapArray1(width, height, n, fill) {
var a = new WrapArray(width, height, n);
fillArrayView(a.backingArray, width, height, n, fill);
return a;
};
})();