<commit_before>/*jslint devel: true, bitwise: true, browser: true, white: true, nomen: true, plusplus: true, maxerr: 50, indent: 4 */
/*global Float32Array, Uint8Array, Uint16Array, WebGLTexture, HTMLInputElement, HTMLSelectElement, HTMLElement, WebGLFramebuffer, HTMLCanvasElement, WebGLRenderingContext */
(function (window, undefined) {
"use strict";

var document = window.document,
	console = window.console,

/*
	Global environment variables
*/

benchmarkResults,
incompatibility,
seriousEffects = {},
timeouts = [],
allEffectsByHook = {},
defaultTransform,

/*
	Global reference variables
*/

// http://www.w3.org/TR/css3-color/#svg-color
colorNames = {
	'transparent': [0,0,0,0],
	'aliceblue':	[240/255,248/255,255/255,1],
	'antiquewhite':	[250/255,235/255,215/255,1],
	'aqua':	[0,255/255,255/255,1],
	'aquamarine':	[127/255,255/255,212/255,1],
	'azure':	[240/255,255/255,255/255,1],
	'beige':	[245/255,245/255,220/255,1],
	'bisque':	[255/255,228/255,196/255,1],
	'black':	[0,0,0,1],
	'blanchedalmond':	[255/255,235/255,205/255,1],
	'blue':	[0,0,255/255,1],
	'blueviolet':	[138/255,43/255,226/255,1],
	'brown':	[165/255,42/255,42/255,1],
	'burlywood':	[222/255,184/255,135/255,1],
	'cadetblue':	[95/255,158/255,160/255,1],
	'chartreuse':	[127/255,255/255,0,1],
	'chocolate':	[210/255,105/255,30/255,1],
	'coral':	[255/255,127/255,80/255,1],
	'cornflowerblue':	[100/255,149/255,237/255,1],
	'cornsilk':	[255/255,248/255,220/255,1],
	'crimson':	[220/255,20/255,60/255,1],
	'cyan':	[0,255/255,255/255,1],
	'darkblue':	[0,0,139/255,1],
	'darkcyan':	[0,139/255,139/255,1],
	'darkgoldenrod':	[184/255,134/255,11/255,1],
	'darkgray':	[169/255,169/255,169/255,1],
	'darkgreen':	[0,100/255,0,1],
	'darkgrey':	[169/255,169/255,169/255,1],
	'darkkhaki':	[189/255,183/255,107/255,1],
	'darkmagenta':	[139/255,0,139/255,1],
	'darkolivegreen':	[85/255,107/255,47/255,1],
	'darkorange':	[255/255,140/255,0,1],
	'darkorchid':	[153/255,50/255,204/255,1],
	'darkred':	[139/255,0,0,1],
	'darksalmon':	[233/255,150/255,122/255,1],
	'darkseagreen':	[143/255,188/255,143/255,1],
	'darkslateblue':	[72/255,61/255,139/255,1],
	'darkslategray':	[47/255,79/255,79/255,1],
	'darkslategrey':	[47/255,79/255,79/255,1],
	'darkturquoise':	[0,206/255,209/255,1],
	'darkviolet':	[148/255,0,211/255,1],
	'deeppink':	[255/255,20/255,147/255,1],
	'deepskyblue':	[0,191/255,255/255,1],
	'dimgray':	[105/255,105/255,105/255,1],
	'dimgrey':	[105/255,105/255,105/255,1],
	'dodgerblue':	[30/255,144/255,255/255,1],
	'firebrick':	[178/255,34/255,34/255,1],
	'floralwhite':	[255/255,250/255,240/255,1],
	'forestgreen':	[34/255,139/255,34/255,1],
	'fuchsia':	[255/255,0,255/255,1],
	'gainsboro':	[220/255,220/255,220/255,1],
	'ghostwhite':	[248/255,248/255,255/255,1],
	'gold':	[255/255,215/255,0,1],
	'goldenrod':	[218/255,165/255,32/255,1],
	'gray':	[128/255,128/255,128/255,1],
	'green':	[0,128/255,0,1],
	'greenyellow':	[173/255,255/255,47/255,1],
	'grey':	[128/255,128/255,128/255,1],
	'honeydew':	[240/255,255/255,240/255,1],
	'hotpink':	[255/255,105/255,180/255,1],
	'indianred':	[205/255,92/255,92/255,1],
	'indigo':	[75/255,0,130/255,1],
	'ivory':	[255/255,255/255,240/255,1],
	'khaki':	[240/255,230/255,140/255,1],
	'lavender':	[230/255,230/255,250/255,1],
	'lavenderblush':	[255/255,240/255,245/255,1],
	'lawngreen':	[124/255,252/255,0,1],
	'lemonchiffon':	[255/255,250/255,205/255,1],
	'lightblue':	[173/255,216/255,230/255,1],
	'lightcoral':	[240/255,128/255,128/255,1],
	'lightcyan':	[224/255,255/255,255/255,1],
	'lightgoldenrodyellow':	[250/255,250/255,210/255,1],
	'lightgray':	[211/255,211/255,211/255,1],
	'lightgreen':	[144/255,238/255,144/255,1],
	'lightgrey':	[211/255,211/255,211/255,1],
	'lightpink':	[255/255,182/255,193/255,1],
	'lightsalmon':	[255/255,160/255,122/255,1],
	'lightseagreen':	[32/255,178/255,170/255,1],
	'lightskyblue':	[135/255,206/255,250/255,1],
	'lightslategray':	[119/255,136/255,153/255,1],
	'lightslategrey':	[119/255,136/255,153/255,1],
	'lightsteelblue':	[176/255,196/255,222/255,1],
	'lightyellow':	[255/255,255/255,224/255,1],
	'lime':	[0,255/255,0,1],
	'limegreen':	[50/255,205/255,50/255,1],
	'linen':	[250/255,240/255,230/255,1],
	'magenta':	[255/255,0,255/255,1],
	'maroon':	[128/255,0,0,1],
	'mediumaquamarine':	[102/255,205/255,170/255,1],
	'mediumblue':	[0,0,205/255,1],
	'mediumorchid':	[186/255,85/255,211/255,1],
	'mediumpurple':	[147/255,112/255,219/255,1],
	'mediumseagreen':	[60/255,179/255,113/255,1],
	'mediumslateblue':	[123/255,104/255,238/255,1],
	'mediumspringgreen':	[0,250/255,154/255,1],
	'mediumturquoise':	[72/255,209/255,204/255,1],
	'mediumvioletred':	[199/255,21/255,133/255,1],
	'midnightblue':	[25/255,25/255,112/255,1],
	'mintcream':	[245/255,255/255,250/255,1],
	'mistyrose':	[255/255,228/255,225/255,1],
	'moccasin':	[255/255,228/255,181/255,1],
	'navajowhite':	[255/255,222/255,173/255,1],
	'navy':	[0,0,128/255,1],
	'oldlace':	[253/255,245/255,230/255,1],
	'olive':	[128/255,128/255,0,1],
	'olivedrab':	[107/255,142/255,35/255,1],
	'orange':	[255/255,165/255,0,1],
	'orangered':	[255/255,69/255,0,1],
	'orchid':	[218/255,112/255,214/255,1],
	'palegoldenrod':	[238/255,232/255,170/255,1],
	'palegreen':	[152/255,251/255,152/255,1],
	'paleturquoise':	[175/255,238/255,238/255,1],
	'palevioletred':	[219/255,112/255,147/255,1],
	'papayawhip':	[255/255,239/255,213/255,1],
	'peachpuff':	[255/255,218/255,185/255,1],
	'peru':	[205/255,133/255,63/255,1],
	'pink':	[255/255,192/255,203/255,1],
	'plum':	[221/255,160/255,221/255,1],
	'powderblue':	[176/255,224/255,230/255,1],
	'purple':	[128/255,0,128/255,1],
	'red':	[255/255,0,0,1],
	'rosybrown':	[188/255,143/255,143/255,1],
	'royalblue':	[65/255,105/255,225/255,1],
	'saddlebrown':	[139/255,69/255,19/255,1],
	'salmon':	[250/255,128/255,114/255,1],
	'sandybrown':	[244/255,164/255,96/255,1],
	'seagreen':	[46/255,139/255,87/255,1],
	'seashell':	[255/255,245/255,238/255,1],
	'sienna':	[160/255,82/255,45/255,1],
	'silver':	[192/255,192/255,192/255,1],
	'skyblue':	[135/255,206/255,235/255,1],
	'slateblue':	[106/255,90/255,205/255,1],
	'slategray':	[112/255,128/255,144/255,1],
	'slategrey':	[112/255,128/255,144/255,1],
	'snow':	[255/255,250/255,250/255,1],
	'springgreen':	[0,255/255,127/255,1],
	'steelblue':	[70/255,130/255,180/255,1],
	'tan':	[210/255,180/255,140/255,1],
	'teal':	[0,128/255,128/255,1],
	'thistle':	[216/255,191/255,216/255,1],
	'tomato':	[255/255,99/255,71/255,1],
	'turquoise':	[64/255,224/255,208/255,1],
	'violet':	[238/255,130/255,238/255,1],
	'wheat':	[245/255,222/255,179/255,1],
	'white':	[255/255,255/255,255/255,1],
	'whitesmoke':	[245/255,245/255,245/255,1],
	'yellow':	[255/255,255/255,0,1],
	'yellowgreen':	[154/255,205/255,50/255,1]
},

/*
	utility functions
*/

mat4 = {
	/*
	 * mat4.frustum
	 * Generates a frustum matrix with the given bounds
	 *
	 * Params:
	 * left, right - scalar, left and right bounds of the frustum
	 * bottom, top - scalar, bottom and top bounds of the frustum
	 * near, far - scalar, near and far bounds of the frustum
	 * dest - Optional, mat4 frustum matrix will be written into
	 *
	 * Returns:
	 * dest if specified, a new mat4 otherwise
	 */
	frustum: function(left, right, bottom, top, near, far, dest) {
		if(!dest) { dest = mat4.create(); }
		var rl = (right - left),
			tb = (top - bottom),
			fn = (far - near);
		dest[0] = (near*2) / rl;
		dest[1] = 0;
		dest[2] = 0;
		dest[3] = 0;
		dest[4] = 0;
		dest[5] = (near*2) / tb;
		dest[6] = 0;
		dest[7] = 0;
		dest[8] = (right + left) / rl;
		dest[9] = (top + bottom) / tb;
		dest[10] = -(far + near) / fn;
		dest[11] = -1;
		dest[12] = 0;
		dest[13] = 0;
		dest[14] = -(far*near*2) / fn;
		dest[15] = 0;
		return dest;
	},

	perspective: function(fovy, aspect, near, far, dest) {
		var top = near*Math.tan(fovy*Math.PI / 360.0),
			right = top*aspect;
		return mat4.frustum(-right, right, -top, top, near, far, dest);
	}
},

requestAnimFrame = (function(){
	var lastTime = 0;
	return  window.requestAnimationFrame       ||
			window.webkitRequestAnimationFrame ||
			window.mozRequestAnimationFrame    ||
			window.oRequestAnimationFrame      ||
			window.msRequestAnimationFrame     ||
			function (callback) {
				var currTime, timeToCall, id;

				function timeoutCallback() {
					callback(currTime + timeToCall);
				}

				currTime = new Date().getTime();
				timeToCall = Math.max(0, 16 - (currTime - lastTime));
				id = window.setTimeout(timeoutCallback, timeToCall);
				lastTime = currTime + timeToCall;
				return id;
			};
}());

function getElement(input, tags) {
	var element,
		tag;
	if (typeof input === 'string') {
		//element = document.getElementById(input) || document.getElementsByTagName( input )[0];
		element = document.querySelector(input);
	} else if (!input) {
		return false;
	}

	if (input.tagName) {
		element = input;
	}

	if (!element) {
		return input;
	}

	tag = element.tagName.toLowerCase();
	if (tags && tags.indexOf(tag) < 0) {
		return input;
	}

	return element;
}

function extend(dest, src) {
	var property, g, s;

	//todo: are we sure this is safe?
	if (dest.prototype && src.prototype && dest.prototype !== src.prototype) {
		extend(dest.prototype, src.prototype);
	}

	for ( property in src ) {
		g = src.__lookupGetter__(property);
		s = src.__lookupSetter__(property);

		if (g || s) {
			if (g) {
				dest.__defineGetter__(property, g);
			}
			if (s) {
				dest.__defineSetter__(property, s);
			}
		} else {
			dest[ property ] = src[ property ];
		}
	}

	return dest;
}

//http://www.w3.org/TR/css3-color/#hsl-color
function hslToRgb(h, s, l, a) {
	function hueToRgb(m1, m2, h) {
		h = h % 1;
		if (h < 0) {
			h += 1;
		}
		if (h < 1 / 6) {
			return m1 + (m2 - m1) * h * 6;
		}
		if (h < 1 / 2) {
			return m2;
		}
		if (h < 2 / 3) {
			return m1 + (m2 - m1) * (2/3 - h) * 6;
		}
		return m1;
	}

	var m1, m2;
	if (l < 0.5) {
		m2 = l * (s + 1);
	} else {
		m2 = l + s - l * s;
	}
	m1 = l * 2 - m2;
	return [
		hueToRgb(m1, m2, h + 1/3),
		hueToRgb(m1, m2, h),
		hueToRgb(m1, m2, h - 1/3),
		a
	];
}

/*
faster than setTimeout(fn, 0);
http://dbaron.org/log/20100309-faster-timeouts
*/
function setTimeoutZero(fn) {
	/*
	Workaround for postMessage bug in Firefox if the page is loaded from the file system
	https://bugzilla.mozilla.org/show_bug.cgi?id=740576
	Should run fine, but maybe a few milliseconds slower per frame.
	*/
	function timeoutFunction() {
		if (timeouts.length) {
			(timeouts.shift())();
		}
	}

	if (typeof fn !== 'function') {
		throw 'setTimeoutZero argument is not a function';
	}

	timeouts.push(fn);
	if (window.location.protocol === 'file:') {
		setTimeout(timeoutFunction, 0);
		return;
	}

	window.postMessage('seriously-timeout-message', window.location);
}

window.addEventListener('message', function(event) {
	if (event.source === window && event.data === 'seriously-timeout-message') {
		event.stopPropagation();
		if (timeouts.length > 0) {
			var fn = timeouts.shift();
			fn();
		}
	}
}, true);

function checkSource(source) {
	var element, canvas, ctx, texture;
	
	element = getElement(source, ['img', 'canvas', 'video']);
	if (!element) {
		return false;
	}
	
	canvas = document.createElement('canvas');
	if (!canvas) {
		console.log('Browser does not support canvas or Seriously.js');
		return false;
	}
	
	if (window.WebGLRenderingContext) {
		try {
			ctx = canvas.getContext('experimental-webgl');
		} catch (webglError) {
			console.log('Unable to access WebGL. Trying 2D canvas.');
		}
	}

	if (ctx) {
		texture = ctx.createTexture();
		ctx.bindTexture(ctx.TEXTURE_2D, texture);

		try {
			ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, element);
		} catch (textureError) {
			if (textureError.name === 'SECURITY_ERR') {
				console.log('Unable to access cross-domain image');
			} else {
				console.log('Error: ' + textureError.message);
			}
			ctx.deleteTexture(texture);
			return false;
		}
		ctx.deleteTexture(texture);
	} else {
		ctx = canvas.getContext('2d');
		try {
			ctx.drawImage(element, 0, 0);
			ctx.getImageData(0, 0, 1, 1);
		} catch (drawImageError) {
			if (drawImageError.name === 'SECURITY_ERR') {
				console.log('Unable to access cross-domain image');
			} else {
				console.log('Error: ' + drawImageError.message);
			}
			return false;
		}
	}
		

	// This method will return a false positive for resources that aren't
	// actually images or haven't loaded yet
	
	return true;
}

/*
	helper Classes
*/

function FrameBuffer(gl, width, height, useFloat) {
	var frameBuffer,
		renderBuffer,
		tex,
		status;

	//todo: check float webgl extension
	useFloat = useFloat && !!gl.getExtension("OES_texture_float");
	if (useFloat) {
		this.type = gl.FLOAT;
	} else {
		this.type = gl.UNSIGNED_BYTE;
	}

	frameBuffer = gl.createFramebuffer();
	gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);

	this.texture = gl.createTexture();
	gl.bindTexture(gl.TEXTURE_2D, this.texture);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

	try {
		if (this.type === gl.FLOAT) {
			tex = new Float32Array(width * height * 4);
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, tex);
		} else {
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
			this.type = gl.UNSIGNED_BYTE;<commit_msg>float textures are not ready for prime time<commit_after>/*jslint devel: true, bitwise: true, browser: true, white: true, nomen: true, plusplus: true, maxerr: 50, indent: 4 */
/*global Float32Array, Uint8Array, Uint16Array, WebGLTexture, HTMLInputElement, HTMLSelectElement, HTMLElement, WebGLFramebuffer, HTMLCanvasElement, WebGLRenderingContext */
(function (window, undefined) {
"use strict";

var document = window.document,
	console = window.console,

/*
	Global environment variables
*/

benchmarkResults,
incompatibility,
seriousEffects = {},
timeouts = [],
allEffectsByHook = {},
defaultTransform,

/*
	Global reference variables
*/

// http://www.w3.org/TR/css3-color/#svg-color
colorNames = {
	'transparent': [0,0,0,0],
	'aliceblue':	[240/255,248/255,255/255,1],
	'antiquewhite':	[250/255,235/255,215/255,1],
	'aqua':	[0,255/255,255/255,1],
	'aquamarine':	[127/255,255/255,212/255,1],
	'azure':	[240/255,255/255,255/255,1],
	'beige':	[245/255,245/255,220/255,1],
	'bisque':	[255/255,228/255,196/255,1],
	'black':	[0,0,0,1],
	'blanchedalmond':	[255/255,235/255,205/255,1],
	'blue':	[0,0,255/255,1],
	'blueviolet':	[138/255,43/255,226/255,1],
	'brown':	[165/255,42/255,42/255,1],
	'burlywood':	[222/255,184/255,135/255,1],
	'cadetblue':	[95/255,158/255,160/255,1],
	'chartreuse':	[127/255,255/255,0,1],
	'chocolate':	[210/255,105/255,30/255,1],
	'coral':	[255/255,127/255,80/255,1],
	'cornflowerblue':	[100/255,149/255,237/255,1],
	'cornsilk':	[255/255,248/255,220/255,1],
	'crimson':	[220/255,20/255,60/255,1],
	'cyan':	[0,255/255,255/255,1],
	'darkblue':	[0,0,139/255,1],
	'darkcyan':	[0,139/255,139/255,1],
	'darkgoldenrod':	[184/255,134/255,11/255,1],
	'darkgray':	[169/255,169/255,169/255,1],
	'darkgreen':	[0,100/255,0,1],
	'darkgrey':	[169/255,169/255,169/255,1],
	'darkkhaki':	[189/255,183/255,107/255,1],
	'darkmagenta':	[139/255,0,139/255,1],
	'darkolivegreen':	[85/255,107/255,47/255,1],
	'darkorange':	[255/255,140/255,0,1],
	'darkorchid':	[153/255,50/255,204/255,1],
	'darkred':	[139/255,0,0,1],
	'darksalmon':	[233/255,150/255,122/255,1],
	'darkseagreen':	[143/255,188/255,143/255,1],
	'darkslateblue':	[72/255,61/255,139/255,1],
	'darkslategray':	[47/255,79/255,79/255,1],
	'darkslategrey':	[47/255,79/255,79/255,1],
	'darkturquoise':	[0,206/255,209/255,1],
	'darkviolet':	[148/255,0,211/255,1],
	'deeppink':	[255/255,20/255,147/255,1],
	'deepskyblue':	[0,191/255,255/255,1],
	'dimgray':	[105/255,105/255,105/255,1],
	'dimgrey':	[105/255,105/255,105/255,1],
	'dodgerblue':	[30/255,144/255,255/255,1],
	'firebrick':	[178/255,34/255,34/255,1],
	'floralwhite':	[255/255,250/255,240/255,1],
	'forestgreen':	[34/255,139/255,34/255,1],
	'fuchsia':	[255/255,0,255/255,1],
	'gainsboro':	[220/255,220/255,220/255,1],
	'ghostwhite':	[248/255,248/255,255/255,1],
	'gold':	[255/255,215/255,0,1],
	'goldenrod':	[218/255,165/255,32/255,1],
	'gray':	[128/255,128/255,128/255,1],
	'green':	[0,128/255,0,1],
	'greenyellow':	[173/255,255/255,47/255,1],
	'grey':	[128/255,128/255,128/255,1],
	'honeydew':	[240/255,255/255,240/255,1],
	'hotpink':	[255/255,105/255,180/255,1],
	'indianred':	[205/255,92/255,92/255,1],
	'indigo':	[75/255,0,130/255,1],
	'ivory':	[255/255,255/255,240/255,1],
	'khaki':	[240/255,230/255,140/255,1],
	'lavender':	[230/255,230/255,250/255,1],
	'lavenderblush':	[255/255,240/255,245/255,1],
	'lawngreen':	[124/255,252/255,0,1],
	'lemonchiffon':	[255/255,250/255,205/255,1],
	'lightblue':	[173/255,216/255,230/255,1],
	'lightcoral':	[240/255,128/255,128/255,1],
	'lightcyan':	[224/255,255/255,255/255,1],
	'lightgoldenrodyellow':	[250/255,250/255,210/255,1],
	'lightgray':	[211/255,211/255,211/255,1],
	'lightgreen':	[144/255,238/255,144/255,1],
	'lightgrey':	[211/255,211/255,211/255,1],
	'lightpink':	[255/255,182/255,193/255,1],
	'lightsalmon':	[255/255,160/255,122/255,1],
	'lightseagreen':	[32/255,178/255,170/255,1],
	'lightskyblue':	[135/255,206/255,250/255,1],
	'lightslategray':	[119/255,136/255,153/255,1],
	'lightslategrey':	[119/255,136/255,153/255,1],
	'lightsteelblue':	[176/255,196/255,222/255,1],
	'lightyellow':	[255/255,255/255,224/255,1],
	'lime':	[0,255/255,0,1],
	'limegreen':	[50/255,205/255,50/255,1],
	'linen':	[250/255,240/255,230/255,1],
	'magenta':	[255/255,0,255/255,1],
	'maroon':	[128/255,0,0,1],
	'mediumaquamarine':	[102/255,205/255,170/255,1],
	'mediumblue':	[0,0,205/255,1],
	'mediumorchid':	[186/255,85/255,211/255,1],
	'mediumpurple':	[147/255,112/255,219/255,1],
	'mediumseagreen':	[60/255,179/255,113/255,1],
	'mediumslateblue':	[123/255,104/255,238/255,1],
	'mediumspringgreen':	[0,250/255,154/255,1],
	'mediumturquoise':	[72/255,209/255,204/255,1],
	'mediumvioletred':	[199/255,21/255,133/255,1],
	'midnightblue':	[25/255,25/255,112/255,1],
	'mintcream':	[245/255,255/255,250/255,1],
	'mistyrose':	[255/255,228/255,225/255,1],
	'moccasin':	[255/255,228/255,181/255,1],
	'navajowhite':	[255/255,222/255,173/255,1],
	'navy':	[0,0,128/255,1],
	'oldlace':	[253/255,245/255,230/255,1],
	'olive':	[128/255,128/255,0,1],
	'olivedrab':	[107/255,142/255,35/255,1],
	'orange':	[255/255,165/255,0,1],
	'orangered':	[255/255,69/255,0,1],
	'orchid':	[218/255,112/255,214/255,1],
	'palegoldenrod':	[238/255,232/255,170/255,1],
	'palegreen':	[152/255,251/255,152/255,1],
	'paleturquoise':	[175/255,238/255,238/255,1],
	'palevioletred':	[219/255,112/255,147/255,1],
	'papayawhip':	[255/255,239/255,213/255,1],
	'peachpuff':	[255/255,218/255,185/255,1],
	'peru':	[205/255,133/255,63/255,1],
	'pink':	[255/255,192/255,203/255,1],
	'plum':	[221/255,160/255,221/255,1],
	'powderblue':	[176/255,224/255,230/255,1],
	'purple':	[128/255,0,128/255,1],
	'red':	[255/255,0,0,1],
	'rosybrown':	[188/255,143/255,143/255,1],
	'royalblue':	[65/255,105/255,225/255,1],
	'saddlebrown':	[139/255,69/255,19/255,1],
	'salmon':	[250/255,128/255,114/255,1],
	'sandybrown':	[244/255,164/255,96/255,1],
	'seagreen':	[46/255,139/255,87/255,1],
	'seashell':	[255/255,245/255,238/255,1],
	'sienna':	[160/255,82/255,45/255,1],
	'silver':	[192/255,192/255,192/255,1],
	'skyblue':	[135/255,206/255,235/255,1],
	'slateblue':	[106/255,90/255,205/255,1],
	'slategray':	[112/255,128/255,144/255,1],
	'slategrey':	[112/255,128/255,144/255,1],
	'snow':	[255/255,250/255,250/255,1],
	'springgreen':	[0,255/255,127/255,1],
	'steelblue':	[70/255,130/255,180/255,1],
	'tan':	[210/255,180/255,140/255,1],
	'teal':	[0,128/255,128/255,1],
	'thistle':	[216/255,191/255,216/255,1],
	'tomato':	[255/255,99/255,71/255,1],
	'turquoise':	[64/255,224/255,208/255,1],
	'violet':	[238/255,130/255,238/255,1],
	'wheat':	[245/255,222/255,179/255,1],
	'white':	[255/255,255/255,255/255,1],
	'whitesmoke':	[245/255,245/255,245/255,1],
	'yellow':	[255/255,255/255,0,1],
	'yellowgreen':	[154/255,205/255,50/255,1]
},

/*
	utility functions
*/

mat4 = {
	/*
	 * mat4.frustum
	 * Generates a frustum matrix with the given bounds
	 *
	 * Params:
	 * left, right - scalar, left and right bounds of the frustum
	 * bottom, top - scalar, bottom and top bounds of the frustum
	 * near, far - scalar, near and far bounds of the frustum
	 * dest - Optional, mat4 frustum matrix will be written into
	 *
	 * Returns:
	 * dest if specified, a new mat4 otherwise
	 */
	frustum: function(left, right, bottom, top, near, far, dest) {
		if(!dest) { dest = mat4.create(); }
		var rl = (right - left),
			tb = (top - bottom),
			fn = (far - near);
		dest[0] = (near*2) / rl;
		dest[1] = 0;
		dest[2] = 0;
		dest[3] = 0;
		dest[4] = 0;
		dest[5] = (near*2) / tb;
		dest[6] = 0;
		dest[7] = 0;
		dest[8] = (right + left) / rl;
		dest[9] = (top + bottom) / tb;
		dest[10] = -(far + near) / fn;
		dest[11] = -1;
		dest[12] = 0;
		dest[13] = 0;
		dest[14] = -(far*near*2) / fn;
		dest[15] = 0;
		return dest;
	},

	perspective: function(fovy, aspect, near, far, dest) {
		var top = near*Math.tan(fovy*Math.PI / 360.0),
			right = top*aspect;
		return mat4.frustum(-right, right, -top, top, near, far, dest);
	}
},

requestAnimFrame = (function(){
	var lastTime = 0;
	return  window.requestAnimationFrame       ||
			window.webkitRequestAnimationFrame ||
			window.mozRequestAnimationFrame    ||
			window.oRequestAnimationFrame      ||
			window.msRequestAnimationFrame     ||
			function (callback) {
				var currTime, timeToCall, id;

				function timeoutCallback() {
					callback(currTime + timeToCall);
				}

				currTime = new Date().getTime();
				timeToCall = Math.max(0, 16 - (currTime - lastTime));
				id = window.setTimeout(timeoutCallback, timeToCall);
				lastTime = currTime + timeToCall;
				return id;
			};
}());

function getElement(input, tags) {
	var element,
		tag;
	if (typeof input === 'string') {
		//element = document.getElementById(input) || document.getElementsByTagName( input )[0];
		element = document.querySelector(input);
	} else if (!input) {
		return false;
	}

	if (input.tagName) {
		element = input;
	}

	if (!element) {
		return input;
	}

	tag = element.tagName.toLowerCase();
	if (tags && tags.indexOf(tag) < 0) {
		return input;
	}

	return element;
}

function extend(dest, src) {
	var property, g, s;

	//todo: are we sure this is safe?
	if (dest.prototype && src.prototype && dest.prototype !== src.prototype) {
		extend(dest.prototype, src.prototype);
	}

	for ( property in src ) {
		g = src.__lookupGetter__(property);
		s = src.__lookupSetter__(property);

		if (g || s) {
			if (g) {
				dest.__defineGetter__(property, g);
			}
			if (s) {
				dest.__defineSetter__(property, s);
			}
		} else {
			dest[ property ] = src[ property ];
		}
	}

	return dest;
}

//http://www.w3.org/TR/css3-color/#hsl-color
function hslToRgb(h, s, l, a) {
	function hueToRgb(m1, m2, h) {
		h = h % 1;
		if (h < 0) {
			h += 1;
		}
		if (h < 1 / 6) {
			return m1 + (m2 - m1) * h * 6;
		}
		if (h < 1 / 2) {
			return m2;
		}
		if (h < 2 / 3) {
			return m1 + (m2 - m1) * (2/3 - h) * 6;
		}
		return m1;
	}

	var m1, m2;
	if (l < 0.5) {
		m2 = l * (s + 1);
	} else {
		m2 = l + s - l * s;
	}
	m1 = l * 2 - m2;
	return [
		hueToRgb(m1, m2, h + 1/3),
		hueToRgb(m1, m2, h),
		hueToRgb(m1, m2, h - 1/3),
		a
	];
}

/*
faster than setTimeout(fn, 0);
http://dbaron.org/log/20100309-faster-timeouts
*/
function setTimeoutZero(fn) {
	/*
	Workaround for postMessage bug in Firefox if the page is loaded from the file system
	https://bugzilla.mozilla.org/show_bug.cgi?id=740576
	Should run fine, but maybe a few milliseconds slower per frame.
	*/
	function timeoutFunction() {
		if (timeouts.length) {
			(timeouts.shift())();
		}
	}

	if (typeof fn !== 'function') {
		throw 'setTimeoutZero argument is not a function';
	}

	timeouts.push(fn);
	if (window.location.protocol === 'file:') {
		setTimeout(timeoutFunction, 0);
		return;
	}

	window.postMessage('seriously-timeout-message', window.location);
}

window.addEventListener('message', function(event) {
	if (event.source === window && event.data === 'seriously-timeout-message') {
		event.stopPropagation();
		if (timeouts.length > 0) {
			var fn = timeouts.shift();
			fn();
		}
	}
}, true);

function checkSource(source) {
	var element, canvas, ctx, texture;
	
	element = getElement(source, ['img', 'canvas', 'video']);
	if (!element) {
		return false;
	}
	
	canvas = document.createElement('canvas');
	if (!canvas) {
		console.log('Browser does not support canvas or Seriously.js');
		return false;
	}
	
	if (window.WebGLRenderingContext) {
		try {
			ctx = canvas.getContext('experimental-webgl');
		} catch (webglError) {
			console.log('Unable to access WebGL. Trying 2D canvas.');
		}
	}

	if (ctx) {
		texture = ctx.createTexture();
		ctx.bindTexture(ctx.TEXTURE_2D, texture);

		try {
			ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, element);
		} catch (textureError) {
			if (textureError.name === 'SECURITY_ERR') {
				console.log('Unable to access cross-domain image');
			} else {
				console.log('Error: ' + textureError.message);
			}
			ctx.deleteTexture(texture);
			return false;
		}
		ctx.deleteTexture(texture);
	} else {
		ctx = canvas.getContext('2d');
		try {
			ctx.drawImage(element, 0, 0);
			ctx.getImageData(0, 0, 1, 1);
		} catch (drawImageError) {
			if (drawImageError.name === 'SECURITY_ERR') {
				console.log('Unable to access cross-domain image');
			} else {
				console.log('Error: ' + drawImageError.message);
			}
			return false;
		}
	}
		

	// This method will return a false positive for resources that aren't
	// actually images or haven't loaded yet
	
	return true;
}

/*
	helper Classes
*/

function FrameBuffer(gl, width, height, useFloat) {
	var frameBuffer,
		renderBuffer,
		tex,
		status;

	useFloat = false && useFloat && !!gl.getExtension("OES_texture_float"); //useFloat is not ready!
	if (useFloat) {
		this.type = gl.FLOAT;
	} else {
		this.type = gl.UNSIGNED_BYTE;
	}

	frameBuffer = gl.createFramebuffer();
	gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);

	this.texture = gl.createTexture();
	gl.bindTexture(gl.TEXTURE_2D, this.texture);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
	gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

	try {
		if (this.type === gl.FLOAT) {
			tex = new Float32Array(width * height * 4);
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, tex);
		} else {
			gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
			this.type = gl.UNSIGNED_BYTE;
{'fraction_non_alphanumeric': 0.21341259520713357, 'fraction_numerical': 0.19810514582946312, 'mean_word_length': 4.290094339622642, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3337420', 'n_tokens_mistral': 15823, 'n_tokens_neox': 12016, 'n_words': 1938}