Open main menu

CDOT Wiki β

Changes

User:Dhhodgin

49,984 bytes added, 08:10, 30 September 2010
About Me
== About Me ==
I'm a 5th 7th Semester BSD student taking DPS909DPS901. Working part time on an ASP.NET c# application.
==Technical Qualifications==
0.1 - [http://dhodgin.wordpress.com/2009/10/29/release-0-1-for-my-processing-js-work/ Full Details] shorten(), expand(), nfs(), unhex(), bug fixes on nf() and fill()<br/>
0.2 - [http://dhodgin.wordpress.com/2009/11/19/processing-js-0-2-release/ Full Details] nfc(), exp(), log(), map(), asin(), acos(), atan(), tan()<br/>
0.3 - wip[http: //dhodgin.wordpress.com/2009/12/15/my-great-white-vs-killer-whale-0-3-patch/ Full Details] blendColor(), blend(), copy(), filter()<br/>
=== Contributions ===
=== Week 1 stuff ===
* Create Zenit Wiki (done)
* Create Blog ([http://dhodgin.wordpress.com done])
* Update wiki (done)
=== Week 2 stuff ===
* Create MDC account (done)
* join Mozilla Fennec mailing list (done)
* watch learning to be at the festival and blog about it (done)
=== Week 3 stuff ===
* watch online lectures about build system by Paul Reed (done)
* build Firefox at school on Linux (fedora) (done)
* choose subject for project and write project plan on blog (done)
=== Week 4 stuff ===
* spend time searching through MXR and familiarizing myself with it (done)
* lab, working with patches (to do)
=== Week 5 stuff ===
* create Bugzilla account (done)
* Find 3+ bugs related to your project, and add them to your project wiki page ([http://zenit.senecac.on.ca/wiki/index.php/Fennec_and_@font-face done])
* Register for FSOSS or join as a volunteer. (done)
=== Week 6 stuff ===
* work on [http://dhodgin.wordpress.com/2009/10/29/release-0-1-for-my-processing-js-work/ 0.1 release] (done)
=== Week 7 stuff ===
* Firefox tab ordering lab
* Watch [http://www.youtube.com/watch?v=hQVTIJBZook JavaScript online talk] (done)
=== Week 8 stuff ===
* Release 0.2 ([http://dhodgin.wordpress.com/2009/11/19/processing-js-0-2-release/ done])
=== Week 9 stuff ===
* tba
 
==DPS911 Projects==
[[http://zenit.senecac.on.ca/wiki/index.php/Processing.js Processing.js]] - Active project<br />
 
=== Releases ===
0.4 - [http://dhodgin.wordpress.com/2010/01/25/0-4-and-triage-for-processing-js/ Full Details] Triage and peer-review of outstanding 0.2 and 0.3 code<br/>
0.5 - [http://dhodgin.wordpress.com/2010/02/06/0-5-processing-js-release-contribution/ Full Details] Review of binary() and sort(), rewrote hex(), trim(), some code efficiency cleanup<br />
0.6 - wip <br />
 
 
 
=== Weekly stuff ===
* Update Wiki
* Prepare for 0.4 release
* schedule demos for Dave in weeks 3, 7, and 10 for 0.4, 0.6, and 0.8 releases.
* Demo 1 - Feb 4 (completed)
 
== Code Blocks ==
Here is a list of code blocks I have written for the processing.js project<br />
=== trim() ===
Trim leading and trailing whitespace from strings as well as tab characters, newlines, and nbsp characters<br/>
Commit [http://github.com/dhodgin/processing-js/commit/e7f258eec8f566a0da39c23f964280637e8e2a4b trim() commit]<br />
Test available [http://matrix.senecac.on.ca/~dhhodgin/dps911/examples/seneca/trim/trimtest.htm here]<br />
p.trim = function( str ) {
var newstr;
if (typeof str === "object") {
// if str is an array recursivly loop through each element
// and drill down into multiple arrays trimming whitespace
newstr = new Array(0);
for (var i = 0; i < str.length; i++) {
newstr[i] = p.trim(str[i]);
}
} else {
// if str is not an array then remove all whitespace, tabs, and returns
newstr = str.replace(/^\s*/,'').replace(/\s*$/,'').replace(/\r*$/,'');
}
return newstr;
};
=== decimalToHex() ===
A helper function used with hex to convert a number passed in to hex and add any specified padding
 
var decimalToHex = function decimalToHex(d, padding) {
//if there is no padding value added, default padding to 8 else go into while statement.
padding = typeof(padding) === "undefined" || padding === null ? padding = 8 : padding;
if (d < 0) {
d = 0xFFFFFFFF + d + 1;
}
var hex = Number(d).toString(16).toUpperCase();
while (hex.length < padding) {
hex = "0" + hex;
}
if (hex.length >= padding){
hex = hex.substring(hex.length - padding, hex.length);
}
return hex;
};
 
=== hex() ===
hex(x, y) function for processing. x is a byte, char, int, or color. y is the length of the string to return.<br />
Commit [http://github.com/dhodgin/processing-js/commit/d51adccc9acfeb4fa286366c98e06a33ad296524 hex() commit]<br />
Test available [http://matrix.senecac.on.ca/~dhhodgin/dps911/hextest.htm here]<br />
<br />
// note: since we cannot keep track of byte, char, and int types by default the returned string is 8 chars long
// if no 2nd argument is passed. closest compromise we can use to match java implementation Feb 5 2010
// also the char parser has issues with chars that are not digits or letters IE: !@#$%^&*
p.hex = function hex(value, len) {
var hexstring = "";
var patternRGBa = /^rgba?\((\d{1,3}),(\d{1,3}),(\d{1,3})(,\d?\.?\d*)?\)$/i; //match rgba(20,20,20,0) or rgba(20,20,20)
if (arguments.length === 1) {
hexstring = hex(value, 8);
} else {
if (patternRGBa.test(value)) {
// its a color
hexstring = decimalToHex(p.rgbaToInt(value),len);
} else {
// its a byte, char, or int
hexstring = decimalToHex(value, len);
}
}
return hexstring;
};
 
=== copy() ===
p.copy = function copy(src, sx, sy, sw, sh, dx, dy, dw, dh) {
if(arguments.length==8){
p.copy(this, src, sx, sy, sw, sh, dx, dy, dw);
}
p.blend(src, sx, sy, sw, sh, dx, dy, dw, dh, p.REPLACE);
};
 
=== blend() ===
p.blend = function blend(src, sx, sy, sw, sh, dx, dy, dw, dh, mode){
if(arguments.length==9){
p.blend(this, src, sx, sy, sw, sh, dx, dy, dw, dh);
} else if (arguments.length==10){
var sx2 = sx + sw;
var sy2 = sy + sh;
var dx2 = dx + dw;
var dy2 = dy + dh;
p.loadPixels();
if (src == this) {
if (p.intersect(sx, sy, sx2, sy2, dx, dy, dx2, dy2)) {
p.blit_resize(p.get(sx, sy, sx2 - sx, sy2 - sy), // 4 argument get doesnt exist i think
0, 0, sx2 - sx - 1, sy2 - sy - 1,
pixels, width, height, dx, dy, dx2, dy2, mode);
} else {
// same as below, except skip the loadPixels() because it'd be redundant
p.blit_resize(src, sx, sy, sx2, sy2, pixels, width, height, dx, dy, dx2, dy2, mode);
}
} else {
src.loadPixels();
p.blit_resize(src, sx, sy, sx2, sy2, pixels, width, height, dx, dy, dx2, dy2, mode);
}
p.updatePixels();
}
};
 
=== blit_resize() ===
blit_resize is a helper function for image manipulation used with blend() and copy()
 
/**
* Internal blitter/resizer/copier from toxi.
* Uses bilinear filtering if smooth() has been enabled
* 'mode' determines the blending mode used in the process.
* ported from JAVA version
*/
p.blit_resize = function blit_resize(img, srcX1, srcY1, srcX2, srcY2, destPixels, screenW, screenH,
destX1, destY1, destX2, destY2, mode) {
if (srcX1 < 0) srcX1 = 0;
if (srcY1 < 0) srcY1 = 0;
if (srcX2 >= img.width) srcX2 = img.width - 1;
if (srcY2 >= img.height) srcY2 = img.height - 1;
var srcW = srcX2 - srcX1;
var srcH = srcY2 - srcY1;
var destW = destX2 - destX1;
var destH = destY2 - destY1;
var smooth = true; // may as well go with the smoothing these days
if (!smooth) {
srcW++; srcH++;
}
if (destW <= 0 || destH <= 0 ||
srcW <= 0 || srcH <= 0 ||
destX1 >= screenW || destY1 >= screenH ||
srcX1 >= img.width || srcY1 >= img.height) {
return;
}
var dx = Math.floor(srcW / destW * p.PRECISIONF);
var dy = Math.floor(srcH / destH * p.PRECISIONF);
p.shared.srcXOffset = Math.floor(destX1 < 0 ? -destX1 * dx : srcX1 * p.PRECISIONF);
p.shared.srcYOffset = Math.floor(destY1 < 0 ? -destY1 * dy : srcY1 * p.PRECISIONF);
if (destX1 < 0) {
destW += destX1;
destX1 = 0;
}
if (destY1 < 0) {
destH += destY1;
destY1 = 0;
}
destW = Math.min(destW, screenW - destX1);
destH = Math.min(destH, screenH - destY1);
var destOffset = destY1 * screenW + destX1;
p.shared.srcBuffer = img.pixels;
if (smooth) {
// use bilinear filtering
p.shared.iw = img.width;
p.shared.iw1 = img.width - 1;
p.shared.ih1 = img.height - 1;
switch (mode) {
case p.BLEND:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_blend(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
p.shared.srcYOffset += dy;
}
break;
case p.ADD:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_add_pin(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.SUBTRACT:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_sub_pin(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.LIGHTEST:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_lightest(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.DARKEST:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_darkest(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.REPLACE:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] = p.filter_bilinear();
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.DIFFERENCE:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_difference(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.EXCLUSION:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_exclusion(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.MULTIPLY:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_multiply(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.SCREEN:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_screen(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.OVERLAY:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_overlay(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.HARD_LIGHT:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_hard_light(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.SOFT_LIGHT:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_soft_light(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
// davbol - proposed 2007-01-09
case p.DODGE:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_dodge(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.BURN:
for (var y = 0; y < destH; y++) {
p.filter_new_scanline();
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_burn(destPixels[destOffset + x], p.filter_bilinear());
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
}
} else {
// nearest neighbour scaling (++fast!)
switch (mode) {
case p.BLEND:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
// davbol - renamed old blend_multiply to blend_blend
destPixels[destOffset + x] =
p.modes.blend_blend(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.ADD:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_add_pin(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.SUBTRACT:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_sub_pin(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.LIGHTEST:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_lightest(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.DARKEST:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_darkest(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.REPLACE:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] = srcBuffer[sY + (sX >> p.PRECISIONB)];
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.DIFFERENCE:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_difference(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.EXCLUSION:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_exclusion(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.MULTIPLY:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_multiply(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.SCREEN:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_screen(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.OVERLAY:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_overlay(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.HARD_LIGHT:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_hard_light(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.SOFT_LIGHT:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_soft_light(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
// davbol - proposed 2007-01-09
case p.DODGE:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_dodge(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
case p.BURN:
for (var y = 0; y < destH; y++) {
sX = srcXOffset;
sY = (srcYOffset >> p.PRECISIONB) * img.width;
for (var x = 0; x < destW; x++) {
destPixels[destOffset + x] =
p.modes.blend_burn(destPixels[destOffset + x],
srcBuffer[sY + (sX >> p.PRECISIONB)]);
sX += dx;
}
destOffset += screenW;
srcYOffset += dy;
}
break;
}
}
};
 
=== blend() helper functions===
 
// shared variables for blit_resize(), filter_new_scanline(), filter_bilinear()
// change this in the future
p.shared = {
fracU : 0, ifU : 0, fracV : 0, ifV : 0, u1 : 0, u2 : 0, v1 : 0, v2 : 0, sX : 0, sY : 0,
iw : 0, iw1 : 0, ih1 : 0, ul : 0, ll : 0, ur : 0, lr : 0, cUL : 0, cLL : 0, cUR : 0, cLR : 0,
srcXOffset : 0, srcYOffset : 0, r : 0, g : 0, b : 0, a : 0,srcBuffer : null
};
p.intersect = function intersect(sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2) {
var sw = sx2 - sx1 + 1;
var sh = sy2 - sy1 + 1;
var dw = dx2 - dx1 + 1;
var dh = dy2 - dy1 + 1;
if (dx1 < sx1) {
dw += dx1 - sx1;
if (dw > sw) {
dw = sw;
}
} else {
var w = sw + sx1 - dx1;
if (dw > w) {
dw = w;
}
}
if (dy1 < sy1) {
dh += dy1 - sy1;
if (dh > sh) {
dh = sh;
}
} else {
var h = sh + sy1 - dy1;
if (dh > h) {
dh = h;
}
}
return !(dw <= 0 || dh <= 0);
};
p.filter_new_scanline = function filter_new_scanline() {
p.shared.sX = p.shared.srcXOffset;
p.shared.fracV = p.shared.srcYOffset & p.PREC_MAXVAL;
p.shared.ifV = p.PREC_MAXVAL - p.shared.fracV;
p.shared.v1 = (p.shared.srcYOffset >> p.PRECISIONB) * p.shared.iw;
p.shared.v2 = Math.min((p.shared.srcYOffset >> p.PRECISIONB) + 1, p.shared.ih1) * p.shared.iw;
};
p.filter_bilinear = function filter_bilinear() {
p.shared.fracU = p.shared.sX & p.PREC_MAXVAL;
p.shared.ifU = p.PREC_MAXVAL - p.shared.fracU;
p.shared.ul = (p.shared.ifU * p.shared.ifV) >> p.PRECISIONB;
p.shared.ll = (p.shared.ifU * p.shared.fracV) >> p.PRECISIONB;
p.shared.ur = (p.shared.fracU * p.shared.ifV) >> p.PRECISIONB;
p.shared.lr = (p.shared.fracU * p.shared.fracV) >> p.PRECISIONB;
p.shared.u1 = (p.shared.sX >> p.PRECISIONB);
p.shared.u2 = Math.min(p.shared.u1 + 1, p.shared.iw1);
// get color values of the 4 neighbouring texels
p.shared.cUL = p.shared.srcBuffer[p.shared.v1 + p.shared.u1];
p.shared.cUR = p.shared.srcBuffer[p.shared.v1 + p.shared.u2];
p.shared.cLL = p.shared.srcBuffer[p.shared.v2 + p.shared.u1];
p.shared.cLR = p.shared.srcBuffer[p.shared.v2 + p.shared.u2];
p.shared.r = ((p.shared.ul*((p.shared.cUL&p.RED_MASK)>>16) + p.shared.ll*((p.shared.cLL&p.RED_MASK)>>16) +
p.shared.ur*((p.shared.cUR&p.RED_MASK)>>16) + p.shared.lr*((p.shared.cLR&p.RED_MASK)>>16))
<< p.PREC_RED_SHIFT) & p.RED_MASK;
p.shared.g = ((p.shared.ul*(p.shared.cUL&p.GREEN_MASK) + p.shared.ll*(p.shared.cLL&p.GREEN_MASK) +
p.shared.ur*(p.shared.cUR&p.GREEN_MASK) + p.shared.lr*(p.shared.cLR&p.GREEN_MASK))
>>> p.PRECISIONB) & p.GREEN_MASK;
p.shared.b = (p.shared.ul*(p.shared.cUL&p.BLUE_MASK) + p.shared.ll*(p.shared.cLL&p.BLUE_MASK) +
p.shared.ur*(p.shared.cUR&p.BLUE_MASK) + p.shared.lr*(p.shared.cLR&p.BLUE_MASK))
>>> p.PRECISIONB;
p.shared.a = ((p.shared.ul*((p.shared.cUL&p.ALPHA_MASK)>>>24) + p.shared.ll*((p.shared.cLL&p.ALPHA_MASK)>>>24) +
p.shared.ur*((p.shared.cUR&p.ALPHA_MASK)>>>24) + p.shared.lr*((p.shared.cLR&p.ALPHA_MASK)>>>24))
<< p.PREC_ALPHA_SHIFT) & p.ALPHA_MASK;
return p.shared.a | p.shared.r | p.shared.g | p.shared.b;
};
 
=== CONSTANTS ADDED ===
p.ALPHA_MASK = 0xff000000;
p.RED_MASK = 0x00ff0000;
p.GREEN_MASK = 0x0000ff00;
p.BLUE_MASK = 0x000000ff;
p.REPLACE = 0;
p.BLEND = 1 << 0;
p.ADD = 1 << 1;
p.SUBTRACT = 1 << 2;
p.LIGHTEST = 1 << 3;
p.DARKEST = 1 << 4;
p.DIFFERENCE = 1 << 5;
p.EXCLUSION = 1 << 6;
p.MULTIPLY = 1 << 7;
p.SCREEN = 1 << 8;
p.OVERLAY = 1 << 9;
p.HARD_LIGHT = 1 << 10;
p.SOFT_LIGHT = 1 << 11;
p.DODGE = 1 << 12;
p.BURN = 1 << 13;
// fixed point precision is limited to 15 bits!!
p.PRECISIONB = 15;
p.PRECISIONF = 1 << p.PRECISIONB;
p.PREC_MAXVAL = p.PRECISIONF-1;
p.PREC_ALPHA_SHIFT= 24-p.PRECISIONB;
p.PREC_RED_SHIFT = 16-p.PRECISIONB;
 
=== blendColor() ===
p.blendColor = function(c1, c2, mode){
var color = 0;
switch(mode){
case p.REPLACE : color = p.modes.replace(c1, c2); break;
case p.BLEND : color = p.modes.blend(c1, c2); break;
case p.ADD : color = p.modes.add(c1, c2); break;
case p.SUBTRACT : color = p.modes.subtract(c1, c2); break;
case p.LIGHTEST : color = p.modes.lightest(c1, c2); break;
case p.DARKEST : color = p.modes.darkest(c1, c2); break;
case p.DIFFERENCE : color = p.modes.difference(c1, c2); break;
case p.EXCLUSION : color = p.modes.exclusion(c1, c2); break;
case p.MULTIPLY : color = p.modes.multiply(c1, c2); break;
case p.SCREEN : color = p.modes.screen(c1, c2); break;
case p.HARD_LIGHT : color = p.modes.hard_light(c1, c2); break;
case p.SOFT_LIGHT : color = p.modes.soft_light(c1, c2); break;
case p.OVERLAY : color = p.modes.overlay(c1, c2); break;
case p.DODGE : color = p.modes.dodge(c1, c2); break;
case p.BURN : color = p.modes.burn(c1, c2); break;
}
return color;
}
=== blendColor() helper functions ===
// helper functions for internal blending modes
// convert rgba color strings to integer
p.rgbaToInt = function(color){
var rgbaAry = /\(([^\)]+)\)/.exec(color).slice(1,2)[0].split(',');
return (rgbaAry[3] << 24) | (rgbaAry[0] << 16) | (rgbaAry[1] << 8) | (rgbaAry[2]);
}
p.mix = function(a, b, f) {
return a + (((b - a) * f) >> 8);
}
p.peg = function(n) {
return (n < 0) ? 0 : ((n > 255) ? 255 : n);
}
=== blendColor() blending modes ===
// blending modes
p.modes = {
replace: function(a, b){
return p.rgbaToInt(b);
},
blend: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
p.mix(c1 & p.RED_MASK, c2 & p.RED_MASK, f) & p.RED_MASK |
p.mix(c1 & p.GREEN_MASK, c2 & p.GREEN_MASK, f) & p.GREEN_MASK |
p.mix(c1 & p.BLUE_MASK, c2 & p.BLUE_MASK, f));
},
add: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
Math.min(((c1 & p.RED_MASK) +
((c2 & p.RED_MASK) >> 8) * f), p.RED_MASK) & p.RED_MASK |
Math.min(((c1 & p.GREEN_MASK) +
((c2 & p.GREEN_MASK) >> 8) * f), p.GREEN_MASK) & p.GREEN_MASK |
Math.min((c1 & p.BLUE_MASK) +
(((c2 & p.BLUE_MASK) * f) >> 8), p.BLUE_MASK));
},
subtract: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
Math.max(((c1 & p.RED_MASK) - ((c2 & p.RED_MASK) >> 8) * f),
p.GREEN_MASK) & p.RED_MASK |
Math.max(((c1 & p.GREEN_MASK) - ((c2 & p.GREEN_MASK) >> 8) * f),
p.BLUE_MASK) & p.GREEN_MASK |
Math.max((c1 & p.BLUE_MASK) - (((c2 & p.BLUE_MASK) * f) >> 8), 0));
},
lightest: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
Math.max(c1 & p.RED_MASK, ((c2 & p.RED_MASK) >> 8) * f) & p.RED_MASK |
Math.max(c1 & p.GREEN_MASK, ((c2 & p.GREEN_MASK) >> 8) * f) & p.GREEN_MASK |
Math.max(c1 & p.BLUE_MASK, ((c2 & p.BLUE_MASK) * f) >> 8));
},
darkest: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
p.mix(c1 & p.RED_MASK,
Math.min(c1 & p.RED_MASK, ((c2 & p.RED_MASK) >> 8) * f), f) & p.RED_MASK |
p.mix(c1 & p.GREEN_MASK,
Math.min(c1 & p.GREEN_MASK, ((c2 & p.GREEN_MASK) >> 8) * f), f) & p.GREEN_MASK |
p.mix(c1 & p.BLUE_MASK,
Math.min(c1 & p.BLUE_MASK, ((c2 & p.BLUE_MASK) * f) >> 8), f));
},
difference: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
var ar = (c1 & p.RED_MASK) >> 16;
var ag = (c1 & p.GREEN_MASK) >> 8;
var ab = (c1 & p.BLUE_MASK);
var br = (c2 & p.RED_MASK) >> 16;
var bg = (c2 & p.GREEN_MASK) >> 8;
var bb = (c2 & p.BLUE_MASK);
// formula:
var cr = (ar > br) ? (ar-br) : (br-ar);
var cg = (ag > bg) ? (ag-bg) : (bg-ag);
var cb = (ab > bb) ? (ab-bb) : (bb-ab);
// alpha blend (this portion will always be the same)
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
(p.peg(ar + (((cr - ar) * f) >> 8)) << 16) |
(p.peg(ag + (((cg - ag) * f) >> 8)) << 8) |
(p.peg(ab + (((cb - ab) * f) >> 8)) ) );
},
exclusion: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
var ar = (c1 & p.RED_MASK) >> 16;
var ag = (c1 & p.GREEN_MASK) >> 8;
var ab = (c1 & p.BLUE_MASK);
var br = (c2 & p.RED_MASK) >> 16;
var bg = (c2 & p.GREEN_MASK) >> 8;
var bb = (c2 & p.BLUE_MASK);
// formula:
var cr = ar + br - ((ar * br) >> 7);
var cg = ag + bg - ((ag * bg) >> 7);
var cb = ab + bb - ((ab * bb) >> 7);
// alpha blend (this portion will always be the same)
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
(p.peg(ar + (((cr - ar) * f) >> 8)) << 16) |
(p.peg(ag + (((cg - ag) * f) >> 8)) << 8) |
(p.peg(ab + (((cb - ab) * f) >> 8)) ) );
},
multiply: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
var ar = (c1 & p.RED_MASK) >> 16;
var ag = (c1 & p.GREEN_MASK) >> 8;
var ab = (c1 & p.BLUE_MASK);
var br = (c2 & p.RED_MASK) >> 16;
var bg = (c2 & p.GREEN_MASK) >> 8;
var bb = (c2 & p.BLUE_MASK);
// formula:
var cr = (ar * br) >> 8;
var cg = (ag * bg) >> 8;
var cb = (ab * bb) >> 8;
// alpha blend (this portion will always be the same)
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
(p.peg(ar + (((cr - ar) * f) >> 8)) << 16) |
(p.peg(ag + (((cg - ag) * f) >> 8)) << 8) |
(p.peg(ab + (((cb - ab) * f) >> 8)) ) );
},
screen: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
var ar = (c1 & p.RED_MASK) >> 16;
var ag = (c1 & p.GREEN_MASK) >> 8;
var ab = (c1 & p.BLUE_MASK);
var br = (c2 & p.RED_MASK) >> 16;
var bg = (c2 & p.GREEN_MASK) >> 8;
var bb = (c2 & p.BLUE_MASK);
// formula:
var cr = 255 - (((255 - ar) * (255 - br)) >> 8);
var cg = 255 - (((255 - ag) * (255 - bg)) >> 8);
var cb = 255 - (((255 - ab) * (255 - bb)) >> 8);
// alpha blend (this portion will always be the same)
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
(p.peg(ar + (((cr - ar) * f) >> 8)) << 16) |
(p.peg(ag + (((cg - ag) * f) >> 8)) << 8) |
(p.peg(ab + (((cb - ab) * f) >> 8)) ) );
},
hard_light: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
var ar = (c1 & p.RED_MASK) >> 16;
var ag = (c1 & p.GREEN_MASK) >> 8;
var ab = (c1 & p.BLUE_MASK);
var br = (c2 & p.RED_MASK) >> 16;
var bg = (c2 & p.GREEN_MASK) >> 8;
var bb = (c2 & p.BLUE_MASK);
// formula:
var cr = (br < 128) ? ((ar*br)>>7) : (255-(((255-ar)*(255-br))>>7));
var cg = (bg < 128) ? ((ag*bg)>>7) : (255-(((255-ag)*(255-bg))>>7));
var cb = (bb < 128) ? ((ab*bb)>>7) : (255-(((255-ab)*(255-bb))>>7));
// alpha blend (this portion will always be the same)
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
(p.peg(ar + (((cr - ar) * f) >> 8)) << 16) |
(p.peg(ag + (((cg - ag) * f) >> 8)) << 8) |
(p.peg(ab + (((cb - ab) * f) >> 8)) ) );
},
soft_light: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
var ar = (c1 & p.RED_MASK) >> 16;
var ag = (c1 & p.GREEN_MASK) >> 8;
var ab = (c1 & p.BLUE_MASK);
var br = (c2 & p.RED_MASK) >> 16;
var bg = (c2 & p.GREEN_MASK) >> 8;
var bb = (c2 & p.BLUE_MASK);
// formula:
var cr = ((ar*br)>>7) + ((ar*ar)>>8) - ((ar*ar*br)>>15);
var cg = ((ag*bg)>>7) + ((ag*ag)>>8) - ((ag*ag*bg)>>15);
var cb = ((ab*bb)>>7) + ((ab*ab)>>8) - ((ab*ab*bb)>>15);
// alpha blend (this portion will always be the same)
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
(p.peg(ar + (((cr - ar) * f) >> 8)) << 16) |
(p.peg(ag + (((cg - ag) * f) >> 8)) << 8) |
(p.peg(ab + (((cb - ab) * f) >> 8)) ) );
},
overlay: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
var ar = (c1 & p.RED_MASK) >> 16;
var ag = (c1 & p.GREEN_MASK) >> 8;
var ab = (c1 & p.BLUE_MASK);
var br = (c2 & p.RED_MASK) >> 16;
var bg = (c2 & p.GREEN_MASK) >> 8;
var bb = (c2 & p.BLUE_MASK);
// formula:
var cr = (ar < 128) ? ((ar*br)>>7) : (255-(((255-ar)*(255-br))>>7));
var cg = (ag < 128) ? ((ag*bg)>>7) : (255-(((255-ag)*(255-bg))>>7));
var cb = (ab < 128) ? ((ab*bb)>>7) : (255-(((255-ab)*(255-bb))>>7));
// alpha blend (this portion will always be the same)
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
(p.peg(ar + (((cr - ar) * f) >> 8)) << 16) |
(p.peg(ag + (((cg - ag) * f) >> 8)) << 8) |
(p.peg(ab + (((cb - ab) * f) >> 8)) ) );
},
dodge: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
var ar = (c1 & p.RED_MASK) >> 16;
var ag = (c1 & p.GREEN_MASK) >> 8;
var ab = (c1 & p.BLUE_MASK);
var br = (c2 & p.RED_MASK) >> 16;
var bg = (c2 & p.GREEN_MASK) >> 8;
var bb = (c2 & p.BLUE_MASK);
// formula:
var cr = (br==255) ? 255 : p.peg((ar << 8) / (255 - br)); // division requires pre-peg()-ing
var cg = (bg==255) ? 255 : p.peg((ag << 8) / (255 - bg)); // "
var cb = (bb==255) ? 255 : p.peg((ab << 8) / (255 - bb)); // "
// alpha blend (this portion will always be the same)
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
(p.peg(ar + (((cr - ar) * f) >> 8)) << 16) |
(p.peg(ag + (((cg - ag) * f) >> 8)) << 8) |
(p.peg(ab + (((cb - ab) * f) >> 8)) ) );
},
burn: function(a, b){
var c1 = p.rgbaToInt(a);
var c2 = p.rgbaToInt(b);
var f = (c2 & p.ALPHA_MASK) >>> 24;
var ar = (c1 & p.RED_MASK) >> 16;
var ag = (c1 & p.GREEN_MASK) >> 8;
var ab = (c1 & p.BLUE_MASK);
var br = (c2 & p.RED_MASK) >> 16;
var bg = (c2 & p.GREEN_MASK) >> 8;
var bb = (c2 & p.BLUE_MASK);
// formula:
var cr = (br==0) ? 0 : 255 - p.peg(((255 - ar) << 8) / br); // division requires pre-peg()-ing
var cg = (bg==0) ? 0 : 255 - p.peg(((255 - ag) << 8) / bg); // "
var cb = (bb==0) ? 0 : 255 - p.peg(((255 - ab) << 8) / bb); // "
// alpha blend (this portion will always be the same)
return (Math.min(((c1 & p.ALPHA_MASK) >>> 24) + f, 0xff) << 24 |
(p.peg(ar + (((cr - ar) * f) >> 8)) << 16) |
(p.peg(ag + (((cg - ag) * f) >> 8)) << 8) |
(p.peg(ab + (((cb - ab) * f) >> 8)) ) );
}
};
=== screen ===
p.screen = {
width:screen.width,
height:screen.height
}
=== log() ===
p.log = function( num ) {
return Math.log(num > 0 ? num : 0);
}
=== exp() ===
p.exp = function( num ){
return Math.exp(num > 0 ? num : 0);
}
=== asin() ===
p.asin = function( num ){
return Math.asin(num);
}
=== acos() ===
p.acos = function( num ){
return Math.acos(num);
}
=== atan() ===
p.atan = function( num ){
return Math.atan(num);
}
=== tan() ===
p.tan = function( num ){
return Math.tan(num);
}
=== map() ===
p.map = function( value, low1, high1, low2, high2 ){
return (((value-low1)/(high1-low1))*(high2-low2))+low2;
}
=== nfc() ===
Specification for nfc() in processing [http://processing.org/reference/nfc_.html here].<br />
nfc() is a function used to format numbers with commas every 3rd digit and optionally how many decimal places to show right of the decimal place. It accepts int, int[], float, and float[] types and returns either a single string or array of strings depending on the input.
 
p.nfc = function( num, right ){
var str;
var decimals = right >= 0 ? right : 0;
if (typeof num == "object"){
str = new Array();
for(var i=0; i < num.length; i++){
str[i] = p.nfc(num[i], decimals);
}
}
else if (arguments.length == 2){
var rawStr = p.nfs(num, 0, decimals);
var digits = ("" + Math.floor(Math.abs(rawStr))).length;
var ary = new Array();
ary = rawStr.split('.');
// ary[0] contains left of decimal, ary[1] contains decimal places if they exist
// insert commas now, then append ary[1] if it exists
var leftStr = ary[0];
var rightStr = ary.length > 1 ? '.' + ary[1] : '';
var commas = /(\d+)(\d{3})/;
while (commas.test(leftStr)){
leftStr = leftStr.replace(commas, '$1' + ',' + '$2');
}
str = leftStr + rightStr;
}
else if (arguments.length == 1){
str = p.nfc(num, 0);
}
return str;
}
 
Example of this function and test is [http://matrix.senecac.on.ca/~dhhodgin/dps909/nfc_test.htm here].<br />
'''Known issues:''' None.
=== shorten() ===
Specification for shorten() in processing [http://processing.org/reference/shorten_.html here].<br />
Arrays in JS have no type, the elements in them can contain any type and do not all have to match. Arrays are also passed by reference which means a reference to the object is passed in not the entire object. so my code creates a new array and then copies the passed in array first and then pops one element off the new array and the newary object is returned. This is built to accept a processing type of String, int, boolean, char, byte, and float. Support for arrays of objects will be added in 0.2.
 
p.shorten = function( ary ) {
var newary = new Array();
// copy ary into newary
for ( var i = 0; i < size; i++ ) {
newary[ i ] = ary[ i ];
}
newary.pop();
return newary;
}
 
Example of this function and test is [http://matrix.senecac.on.ca/~dhhodgin/dps909/shorten_test.html here].<br />
'''Known issues:''' This has not been tested with arrays of objects. I'm assuming it will copy object elements in an array by reference and not produce a proper deep copy. I plan to fix this by 0.2. (confirmed, needs deep copy support for arrays of objects).
 
=== expand() ===
Specification for expand() in processing [http://processing.org/reference/expand_.html here].<br />
Expand takes an array as its argument and returns a copy of the array with its length doubled. There is an optional 2nd parameter to specify the new size of the array as well.
 
p.expand = function( ary, newSize ) {
var newary = new Array();
for ( var i = 0; i < ary.length; i++ ) {
newary[ i ] = ary[ i ];
}
if (arguments.length == 1) {
// double size of array
newary.length *= 2;
}
else if (arguments.length == 2) {
// size is newSize
newary.length = newSize;
}
return newary;
}
 
Example of this function and test is [http://matrix.senecac.on.ca/~dhhodgin/dps909/expand_test.htm here].<br />
'''Known issues:''' Not yet tested with arrays of objects.
 
=== unhex() ===
Specification for unhex() in processing [http://processing.org/reference/unhex_.html here].<br />
unhex takes a string representing a 8 digit hex code as its only argument and returns an int representation of the string. JavaScript supports 64 bit floats as var's so it took a little number crunching to make it output an exact replication of the Java implementation with signed int's.
 
p.unhex = function( str ) {
var value = 0;
var multiplier = 1;
var num = 0;
for (var i = str.length-1; i >= 0; i--){
try{
switch(str[i]){
case "0": num = 0; break;
case "1": num = 1; break;
case "2": num = 2; break;
case "3": num = 3; break;
case "4": num = 4; break;
case "5": num = 5; break;
case "6": num = 6; break;
case "7": num = 7; break;
case "8": num = 8; break;
case "9": num = 9; break;
case "A":
case "a": num = 10; break;
case "B":
case "b": num = 11; break;
case "C":
case "c": num = 12; break;
case "D":
case "d": num = 13; break;
case "E":
case "e": num = 14; break;
case "F":
case "f": num = 15; break;
default:return 0; break;
}
value += num * multiplier;
multiplier *= 16;
}catch(e){;}
// correct for int overflow java expectation
if (value > 2147483647)
{
value -= 4294967296;
}
}
return value;
}
 
Example of this function and test is [http://matrix.senecac.on.ca/~dhhodgin/dps909/unhex_test.htm here].<br />
'''Known issues:''' None.
 
=== nfs() ===
Specification for nfs() in processing [http://processing.org/reference/nfs_.html here].<br />
nfs() is a function used to format numbers as strings with padding of 0's on either the left or right of the decimal place. It accepts int, int[], float, and float[] types and returns either a single string or array of strings depending on the input.
 
p.nfs = function( num, left, right){
var str;
// array handling
if (typeof num == "object"){
str = new Array();
for(var i=0; i < num.length; i++){
str[i] = p.nfs(num[i], left, right);
}
}
else if (arguments.length == 3){
var negative = false;
if (num < 0)
negative = true;
str = "" + Math.abs(num);
var digits = ("" + Math.floor(Math.abs(num))).length;
var count = left - digits;
while (count > 0){
str = "0" + str;
count--;
}
// get the number of decimal places, if none will be -1
var decimals = ("" + Math.abs(num)).length - digits - 1;
if (decimals == -1 && right > 0)
str = str + ".";
if (decimals != -1)
count = right - decimals;
else if (decimals == -1 && right > 0){
count = right;
}
else
count = 0;
while (count > 0){
str = str + "0";
count--;
}
str = (negative ? "-" : " ") + str;
}
else if (arguments.length == 2){
str = p.nfs(num, left, 0);
}
return str;
}
 
Example of this function and test is [http://matrix.senecac.on.ca/~dhhodgin/dps909/nfs_test.htm here].<br />
'''Known issues:''' None.
1
edit