diff --git a/bin/pixi.js b/bin/pixi.js index 7bb4fa7..49a3d63 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -1,4 +1,4485 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.PIXI = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= data.byteLength) + { + gl.bufferSubData(this.type, offset, data); + } + else + { + gl.bufferData(this.type, data, this.drawType); + } + + this.data = data; +} +/** + * Binds the buffer + * + */ +Buffer.prototype.bind = function() +{ + var gl = this.gl; + gl.bindBuffer(this.type, this.buffer); +} + +Buffer.createVertexBuffer = function(gl, data, drawType) +{ + return new Buffer(gl, gl.ARRAY_BUFFER, data, drawType); +} + +Buffer.createIndexBuffer = function(gl, data, drawType) +{ + return new Buffer(gl, gl.ELEMENT_ARRAY_BUFFER, data, drawType); +} + +Buffer.create = function(gl, type, data, drawType) +{ + return new Buffer(gl, type, drawType); +} + +/** + * Destroys the buffer + * + */ +Buffer.prototype.destroy = function(){ + this.gl.deleteBuffer(this.buffer); +} + +module.exports = Buffer; + +},{}],3:[function(require,module,exports){ + +var Texture = require('./GLTexture'); + +/** + * Helper class to create a webGL Framebuffer + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + */ +var Framebuffer = function(gl, width, height) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * The frame buffer + * + * @member {WebGLFramebuffer} + */ + this.framebuffer = gl.createFramebuffer(); + + /** + * The stencil buffer + * + * @member {WebGLRenderbuffer} + */ + this.stencil = null; + + /** + * The stencil buffer + * + * @member {GLTexture} + */ + this.texture = null; + + /** + * The width of the drawing area of the buffer + * + * @member {Number} + */ + this.width = width || 100; + /** + * The height of the drawing area of the buffer + * + * @member {Number} + */ + this.height = height || 100; +} + +/** + * Adds a texture to the frame buffer + * @param texture {GLTexture} + */ +Framebuffer.prototype.enableTexture = function(texture) +{ + var gl = this.gl; + + this.texture = texture || new Texture(gl); + + this.texture.bind(); + + //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + this.bind(); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); +} + +/** + * Initialises the stencil buffer + * @mat maybe you can come up with a better explaination + */ +Framebuffer.prototype.enableStencil = function() +{ + if(this.stencil)return; + + var gl = this.gl; + + this.stencil = gl.createRenderbuffer(); + + gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); + + // TODO.. this is depth AND stencil? + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width , this.height ); +} + +/** + * Erases the drawing area and fills it with a colour + * @param r {Number} the red value of the clearing colour + * @param g {Number} the green value of the clearing colour + * @param b {Number} the blue value of the clearing colour + * @param a {Number} the alpha value of the clearing colour + */ +Framebuffer.prototype.clear = function( r, g, b, a ) +{ + this.bind(); + + var gl = this.gl; + + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT); +} + +/** + * Binds the frame buffer to the WebGL context + */ +Framebuffer.prototype.bind = function() +{ + var gl = this.gl; + + if(this.texture) + { + this.texture.unbind(); + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); +} + +/** + * Unbinds the frame buffer to the WebGL context + */ +Framebuffer.prototype.unbind = function() +{ + var gl = this.gl; + gl.bindFramebuffer(gl.FRAMEBUFFER, null ); +} +/** + * Resizes the drawing area of the buffer to the given width and height + * @param width {Number} the new width + * @param height {Number} the new height + */ +Framebuffer.prototype.resize = function(width, height) +{ + var gl = this.gl; + + this.width = width; + this.height = height; + + if ( this.texture ) + { + this.texture.uploadData(null, width, height); + } + + if ( this.stencil ) + { + // update the stencil buffer width and height + gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + } +} + +/** + * Destroys this buffer + */ +Framebuffer.prototype.destroy = function() +{ + var gl = this.gl; + + //TODO + if(this.texture) + { + this.texture.destroy(); + } + + gl.deleteFramebuffer(this.framebuffer); + + this.gl = null; + + this.stencil = null; + this.texture = null; +} + +/** + * Creates a frame buffer with a texture containing the given data + * @mat can you confirm ? :) + * @static + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data + */ +Framebuffer.createRGBA = function(gl, width, height, data) +{ + var texture = Texture.fromData(gl, null, width, height); + texture.enableNearestScaling(); + texture.enableWrapClamp(); + + //now create the framebuffer object and attach the texture to it. + var fbo = new Framebuffer(gl, width, height); + fbo.enableTexture(texture); + + fbo.unbind(); + + return fbo; +} + +/** + * Creates a frame buffer with a texture containing the given data + * @mat not sure what the difference is with the method above ? + * @static + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data + */ +Framebuffer.createFloat32 = function(gl, width, height, data) +{ + // create a new texture.. + var texture = new Texture.fromData(gl, data, width, height); + texture.enableNearestScaling(); + texture.enableWrapClamp(); + + //now create the framebuffer object and attach the texture to it. + var fbo = new Framebuffer(gl, width, height); + fbo.enableTexture(texture) + + fbo.unbind(); + + return fbo; +} + +module.exports = Framebuffer; + +},{"./GLTexture":5}],4:[function(require,module,exports){ + +var compileProgram = require('./shader/compileProgram'), + extractAttributes = require('./shader/extractAttributes'), + extractUniforms = require('./shader/extractUniforms'), + generateUniformAccessObject = require('./shader/generateUniformAccessObject'); + +/** + * Helper class to create a webGL Shader + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. + */ +var Shader = function(gl, vertexSrc, fragmentSrc) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * The shader program + * + * @member {WebGLProgram} + */ + // First compile the program.. + this.program = compileProgram(gl, vertexSrc, fragmentSrc); + + + /** + * The attributes of the shader as an object containing the following properties + * { + * type, + * size, + * location, + * pointer + * } + * @member {Object} + */ + // next extract the attributes + this.attributes = extractAttributes(gl, this.program); + + var uniformData = extractUniforms(gl, this.program); + + /** + * The uniforms of the shader as an object containing the following properties + * { + * gl, + * data + * } + * @member {Object} + */ + this.uniforms = generateUniformAccessObject( gl, uniformData ); +} +/** + * Uses this shader + */ +Shader.prototype.bind = function() +{ + this.gl.useProgram(this.program); +} + +/** + * Destroys this shader + * TODO + */ +Shader.prototype.destroy = function() +{ + var gl = this.gl; +} + +module.exports = Shader; + +},{"./shader/compileProgram":9,"./shader/extractAttributes":11,"./shader/extractUniforms":12,"./shader/generateUniformAccessObject":13}],5:[function(require,module,exports){ + +/** + * Helper class to create a WebGL Texture + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL context + * @param width {number} the width of the texture + * @param height {number} the height of the texture + * @param format {number} the pixel format of the texture. defaults to gl.RGBA + * @param type {number} the gl type of the texture. defaults to gl.UNSIGNED_BYTE + */ +var Texture = function(gl, width, height, format, type) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + + /** + * The WebGL texture + * + * @member {WebGLTexture} + */ + this.texture = gl.createTexture(); + + /** + * If mipmapping was used for this texture, enable and disable with enableMipmap() + * + * @member {Boolean} + */ + // some settings.. + this.mipmap = false; + + + /** + * Set to true to enable pre-multiplied alpha + * + * @member {Boolean} + */ + this.premultiplyAlpha = false; + + /** + * The width of texture + * + * @member {Number} + */ + this.width = width || 0; + /** + * The height of texture + * + * @member {Number} + */ + this.height = height || 0; + + /** + * The pixel format of the texture. defaults to gl.RGBA + * + * @member {Number} + */ + this.format = format || gl.RGBA; + + /** + * The gl type of the texture. defaults to gl.UNSIGNED_BYTE + * + * @member {Number} + */ + this.type = type || gl.UNSIGNED_BYTE; + + +} + +/** + * Uploads this texture to the GPU + * @param source {HTMLImageElement|ImageData} the source image of the texture + */ +Texture.prototype.upload = function(source) +{ + this.bind(); + + var gl = this.gl; + + this.width = source.width; + this.height = source.height; + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); + gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, source); +} + +var FLOATING_POINT_AVAILABLE = false; + +/** + * Use a data source and uploads this texture to the GPU + * @param data {TypedArray} the data to upload to the texture + * @param width {number} the new width of the texture + * @param height {number} the new height of the texture + */ +Texture.prototype.uploadData = function(data, width, height) +{ + this.bind(); + + var gl = this.gl; + + this.width = width || this.width; + this.height = height || this.height; + + if(data instanceof Float32Array) + { + if(!FLOATING_POINT_AVAILABLE) + { + var ext = gl.getExtension("OES_texture_float"); + + if(ext) + { + FLOATING_POINT_AVAILABLE = true; + } + else + { + throw new Error('floating point textures not available'); + } + } + + this.type = gl.FLOAT; + } + else + { + // TODO support for other types + this.type = gl.UNSIGNED_BYTE; + } + + + + // what type of data? + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); + gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, data || null); + +} + +/** + * Binds the texture + * @param location {@mat} + */ +Texture.prototype.bind = function(location) +{ + var gl = this.gl; + + if(location !== undefined) + { + gl.activeTexture(gl.TEXTURE0 + location); + } + + gl.bindTexture(gl.TEXTURE_2D, this.texture); +} + +/** + * Unbinds the texture + */ +Texture.prototype.unbind = function() +{ + var gl = this.gl; + gl.bindTexture(gl.TEXTURE_2D, null); +} + +/** + * @mat + * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation + */ +Texture.prototype.minFilter = function( linear ) +{ + var gl = this.gl; + + this.bind(); + + if(this.mipmap) + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); + } + else + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST); + } +} + +/** + * @mat + * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation + */ +Texture.prototype.magFilter = function( linear ) +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST); +} + +/** + * Enables mipmapping + */ +Texture.prototype.enableMipmap = function() +{ + var gl = this.gl; + + this.bind(); + + this.mipmap = true; + + gl.generateMipmap(gl.TEXTURE_2D); +} + +/** + * Enables linear filtering + */ +Texture.prototype.enableLinearScaling = function() +{ + this.minFilter(true); + this.magFilter(true); +} + +/** + * Enables nearest neighbour interpolation + */ +Texture.prototype.enableNearestScaling = function() +{ + this.minFilter(false); + this.magFilter(false); +} + +/** + * Enables clamping on the texture so WebGL will not repeat it + */ +Texture.prototype.enableWrapClamp = function() +{ + var gl = this.gl; + + this.bind(); + + 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); +} + +/** + * Enable tiling on the texture + */ +Texture.prototype.enableWrapRepeat = function() +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); +} + +/** + * @mat + */ +Texture.prototype.enableWrapMirrorRepeat = function() +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); +} + + +/** + * Destroys this texture + */ +Texture.prototype.destroy = function() +{ + var gl = this.gl; + //TODO + gl.deleteTexture(this.texture); +} + +/** + * @static + * @param gl {WebGLRenderingContext} The current WebGL context + * @param source {HTMLImageElement|ImageData} the source image of the texture + * @param premultiplyAlpha {Boolean} If we want to use pre-multiplied alpha + */ +Texture.fromSource = function(gl, source, premultiplyAlpha) +{ + var texture = new Texture(gl); + texture.premultiplyAlpha = premultiplyAlpha || false; + texture.upload(source); + + return texture; +} + +/** + * @static + * @param gl {WebGLRenderingContext} The current WebGL context + * @param data {TypedArray} the data to upload to the texture + * @param width {number} the new width of the texture + * @param height {number} the new height of the texture + */ +Texture.fromData = function(gl, data, width, height) +{ + //console.log(data, width, height); + var texture = new Texture(gl); + texture.uploadData(data, width, height); + + return texture; +} + + +module.exports = Texture; + +},{}],6:[function(require,module,exports){ + +// state object// +var setVertexAttribArrays = require( './setVertexAttribArrays' ); + +/** + * Helper class to work with WebGL VertexArrayObjects (vaos) + * Only works if WebGL extensions are enabled (they usually are) + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL rendering context + */ +function VertexArrayObject(gl, state) +{ + + this.nativeVaoExtension = ( + gl.getExtension('OES_vertex_array_object') || + gl.getExtension('MOZ_OES_vertex_array_object') || + gl.getExtension('WEBKIT_OES_vertex_array_object') + ); + + this.nativeState = state; + + if(this.nativeVaoExtension) + { + this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); + + var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + + // VAO - overwrite the state.. + this.nativeState = {tempAttribState:new Array(maxAttribs) + ,attribState:new Array(maxAttribs)}; + } + + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * An array of attributes ? @mat + * + * @member {Array} + */ + this.attributes = []; + + /** + * @mat + * + * @member {Array} + */ + this.indexBuffer = null; + + /** + * A boolean flag + * + * @member {Boolean} + */ + this.dirty = false; +} + +VertexArrayObject.prototype.constructor = VertexArrayObject; +module.exports = VertexArrayObject; + + +/** + * Binds the buffer + */ +VertexArrayObject.prototype.bind = function() +{ + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + + if(this.dirty) + { + this.dirty = false; + this.activate(); + } + } + else + { + + this.activate(); + } + + return this; +} + +/** + * Unbinds the buffer + */ +VertexArrayObject.prototype.unbind = function() +{ + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + return this; +} + +/** + * Uses this vao + */ +VertexArrayObject.prototype.activate = function() +{ + + var gl = this.gl; + var lastBuffer = null; + + for (var i = 0; i < this.attributes.length; i++) + { + var attrib = this.attributes[i]; + + if(lastBuffer !== attrib.buffer) + { + attrib.buffer.bind(); + lastBuffer = attrib.buffer; + } + + //attrib.attribute.pointer(attrib.type, attrib.normalized, attrib.stride, attrib.start); + gl.vertexAttribPointer(attrib.attribute.location, + attrib.attribute.size, attrib.type || gl.FLOAT, + attrib.normalized || false, + attrib.stride || 0, + attrib.start || 0); + + + }; + + setVertexAttribArrays(gl, this.attributes, this.nativeState); + + this.indexBuffer.bind(); + + return this; +} + +/** + * + * @param buffer {WebGLBuffer} + * @param attribute {[type]} + * @param type {[type]} + * @param normalized {[type]} + * @param stride {Number} + * @param start {Number} + */ +VertexArrayObject.prototype.addAttribute = function(buffer, attribute, type, normalized, stride, start) +{ + this.attributes.push({ + buffer: buffer, + attribute: attribute, + + location: attribute.location, + type: type || this.gl.FLOAT, + normalized: normalized || false, + stride: stride || 0, + start: start || 0 + }) + + this.dirty = true; + + return this; +} + +/** + * + * @param buffer {WebGLBuffer} + * @param options {Object} + */ +VertexArrayObject.prototype.addIndex = function(buffer, options) +{ + this.indexBuffer = buffer; + + this.dirty = true; + + return this; +} + +/** + * Unbinds this vao and disables it + */ +VertexArrayObject.prototype.clear = function() +{ + var gl = this.gl; + + // TODO - should this function unbind after clear? + // for now, no but lets see what happens in the real world! + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + } + + this.attributes.length = 0; + this.indexBuffer = null; + + return this; +} + +/** + * @mat + * @param type {Number} + * @param size {Number} + * @param start {Number} + */ +VertexArrayObject.prototype.draw = function(type, size, start) +{ + var gl = this.gl; + gl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0); + + return this; +} + +},{"./setVertexAttribArrays":8}],7:[function(require,module,exports){ + +/** + * Helper class to create a webGL Context + * + * @class + * @memberof pixi.gl + * @param canvas {HTMLCanvasElement} the canvas element that we will get the context from + * @param options {Object} An options object that gets passed in to the canvas element containing the context attributes, + * see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext for the options available + * @return {WebGLRenderingContext} the WebGL context + */ +var createContext = function(canvas, options) +{ + var gl = canvas.getContext('webgl', options) || + canvas.getContext('experimental-webgl', options); + + if (!gl) + { + // fail, not able to get a context + throw new Error('This browser does not support webGL. Try using the canvas renderer'); + } + + return gl; +} + +module.exports = createContext; + +},{}],8:[function(require,module,exports){ +var GL_MAP = {}; + +/** + * @mat + * @param gl {WebGLRenderingContext} The current WebGL context + * @param attribs {[type]} + */ +var setVertexAttribArrays = function (gl, attribs, state) +{ + + if(state) + { + + var i, + tempAttribState = state.tempAttribState, + attribState = state.attribState; + + for (i = 0; i < tempAttribState.length; i++) + { + tempAttribState[i] = false; + } + + // set the new attribs + for (i in attribs) + { + tempAttribState[attribs[i].attribute.location] = true; + } + + for (i = 0; i < attribState.length; i++) + { + if (attribState[i] !== tempAttribState[i]) + { + attribState[i] = tempAttribState[i]; + + if (state.attribState[i]) + { + gl.enableVertexAttribArray(i); + } + else + { + gl.disableVertexAttribArray(i); + } + } + } + + } + else + { + for (var i = 0; i < attribs.length; i++) + { + var attrib = attribs[i]; + gl.enableVertexAttribArray(attrib.attribute.location); + } + } +}; + +module.exports = setVertexAttribArrays; + +},{}],9:[function(require,module,exports){ + +/** + * + * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. + * @return {WebGLProgram} the shader program + */ +compileProgram = function(gl, vertexSrc, fragmentSrc) +{ + var glVertShader = compileShader(gl, gl.VERTEX_SHADER, vertexSrc); + var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc); + + var program = gl.createProgram(); + + gl.attachShader(program, glVertShader); + gl.attachShader(program, glFragShader); + gl.linkProgram(program); + + // if linking fails, then log and cleanup + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) + { + console.error('Pixi.js Error: Could not initialize shader.'); + console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS)); + console.error('gl.getError()', gl.getError()); + + // if there is a program info log, log it + if (gl.getProgramInfoLog(program) !== '') + { + console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program)); + } + + gl.deleteProgram(program); + program = null; + } + + // clean up some shaders + gl.deleteShader(glVertShader); + gl.deleteShader(glFragShader); + + return program; +} + +/** + * + * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} + * @param type {Number} the type, can be either VERTEX_SHADER or FRAGMENT_SHADER + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @return {WebGLShader} the shader + */ +var compileShader = function (gl, type, src) +{ + var shader = gl.createShader(type); + + gl.shaderSource(shader, src); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) + { + console.log(gl.getShaderInfoLog(shader)); + return null; + } + + return shader; +}; + +module.exports = compileProgram; + +},{}],10:[function(require,module,exports){ + + +var defaultValue = function(type, size) +{ + switch (type) + { + case 'float': + return 0; + + case 'vec2': + return new Float32Array(2 * size); + + case 'vec3': + return new Float32Array(3 * size); + + case 'vec4': + return new Float32Array(4 * size); + + case 'int': + case 'sampler2D': + return 0; + + case 'ivec2': + return new Int32Array(2 * size); + + case 'ivec3': + return new Int32Array(3 * size); + + case 'ivec4': + return new Int32Array(4 * size); + + case 'bool': + return false; + + case 'bvec2': + + return booleanArray( 2 * size); + + case 'bvec3': + return booleanArray(3 * size); + + case 'bvec4': + return booleanArray(4 * size); + + case 'mat2': + return new Float32Array([1, 0 + ,0, 1]); + + case 'mat3': + return new Float32Array([1, 0, 0 + ,0, 1, 0 + ,0, 0, 1]); + + case 'mat4': + return new Float32Array([1, 0, 0, 0 + ,0, 1, 0, 0 + ,0, 0, 1, 0 + ,0, 0, 0, 1]); + } +} + +var booleanArray = function(size) +{ + var array = new Array(size); + + for (var i = 0; i < array.length; i++) + { + array[i] = false; + }; + + return array; +} + +module.exports = defaultValue; + +},{}],11:[function(require,module,exports){ + +var mapType = require('./mapType'); +var mapSize = require('./mapSize'); + +/** + * Extracts the attributes + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param program {WebGLProgram} The shader program to get the attributes from + * @return attributes {Object} + */ +var extractAttributes = function(gl, program) +{ + var attributes = {}; + + var totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES) + + for (var i = 0; i < totalAttributes; i++) + { + var attribData = gl.getActiveAttrib(program, i); + var type = mapType(gl, attribData.type); + + attributes[attribData.name] = { + type:type, + size:mapSize(type), + location:gl.getAttribLocation(program, attribData.name), + //TODO - make an attribute object + pointer:function(type, normalized, stride, start){ + + // console.log(this.location) + gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); + + } + } + }; + + return attributes; +} + +module.exports = extractAttributes; + +},{"./mapSize":14,"./mapType":15}],12:[function(require,module,exports){ +var mapType = require('./mapType'); +var defaultValue = require('./defaultValue'); + +/** + * Extracts the uniforms + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param program {WebGLProgram} The shader program to get the uniforms from + * @return uniforms {Object} + */ +var extractUniforms = function(gl, program) +{ + var uniforms = {}; + + var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) + + for (var i = 0; i < totalUniforms; i++) + { + var uniformData = gl.getActiveUniform(program, i); + var name = uniformData.name.replace(/\[.*?\]/, ""); + var type = mapType(gl, uniformData.type ); + + uniforms[name] = { + type:type, + size:uniformData.size, + location:gl.getUniformLocation(program, name), + value:defaultValue(type, uniformData.size) + } + }; + + return uniforms; +} + +module.exports = extractUniforms; + +},{"./defaultValue":10,"./mapType":15}],13:[function(require,module,exports){ +/** + * Extracts the attributes + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param uniforms {Array} @mat ? + * @return attributes {Object} + */ +var generateUniformAccessObject = function(gl, uniformData) +{ + // this is the object we will be sending back. + // an object hierachy will be created for structs + var uniforms = {data:{}}; + + uniforms.gl = gl; + + var uniformKeys= Object.keys(uniformData); + + for (var i = 0; i < uniformKeys.length; i++) + { + var fullName = uniformKeys[i] + + var nameTokens = fullName.split('.'); + var name = nameTokens[nameTokens.length - 1]; + + var uniformGroup = getUniformGroup(nameTokens, uniforms); + + var uniform = uniformData[fullName]; + uniformGroup.data[name] = uniform; + + uniformGroup.gl = gl; + + Object.defineProperty(uniformGroup, name, { + get: generateGetter(name), + set: generateSetter(name, uniform) + }) + }; + + return uniforms; +} + +var generateGetter = function(name) +{ + var template = getterTemplate.replace('%%', name); + return new Function(template); +} + +var generateSetter = function(name, uniform) +{ + var template = setterTemplate.replace(/%%/g, name); + var setTemplate + + if(uniform.size === 1) + { + setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; + } + else + { + setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; + } + + if(setTemplate) + { + template += "\nthis.gl." + setTemplate + ";"; + } + + return new Function('value', template); +} + +var getUniformGroup = function(nameTokens, uniform) +{ + var cur = uniform; + + for (var i = 0; i < nameTokens.length - 1; i++) + { + var o = cur[nameTokens[i]] || {data:{}}; + cur[nameTokens[i]] = o; + cur = o; + }; + + return cur +} + +var getterTemplate = [ + 'return this.data.%%.value;', +].join('\n'); + +var setterTemplate = [ + 'this.data.%%.value = value;', + 'var location = this.data.%%.location;' +].join('\n'); + + +var GLSL_TO_SINGLE_SETTERS = { + + 'float': 'uniform1f(location, value)', + + 'vec2': 'uniform2f(location, value[0], value[1])', + 'vec3': 'uniform3f(location, value[0], value[1], value[2])', + 'vec4': 'uniform4f(location, value[0], value[1], value[2], value[3])', + + 'int': 'uniform1i(location, value)', + 'ivec2': 'uniform2i(location, value[0], value[1])', + 'ivec3': 'uniform3i(location, value[0], value[1], value[2])', + 'ivec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', + + 'bool': 'uniform1i(location, value)', + 'bvec2': 'uniform2i(location, value[0], value[1])', + 'bvec3': 'uniform3i(location, value[0], value[1], value[2])', + 'bvec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', + + 'mat2': 'uniformMatrix2fv(location, false, value)', + 'mat3': 'uniformMatrix3fv(location, false, value)', + 'mat4': 'uniformMatrix4fv(location, false, value)', + + 'sampler2D':'uniform1i(location, value)' +} + +var GLSL_TO_ARRAY_SETTERS = { + + 'float': 'uniform1fv(location, value)', + + 'vec2': 'uniform2fv(location, value)', + 'vec3': 'uniform3fv(location, value)', + 'vec4': 'uniform4fv(location, value)', + + 'int': 'uniform1iv(location, value)', + 'ivec2': 'uniform2iv(location, value)', + 'ivec3': 'uniform3iv(location, value)', + 'ivec4': 'uniform4iv(location, value)', + + 'bool': 'uniform1iv(location, value)', + 'bvec2': 'uniform2iv(location, value)', + 'bvec3': 'uniform3iv(location, value)', + 'bvec4': 'uniform4iv(location, value)', + + 'sampler2D':'uniform1iv(location, value)' +} + +module.exports = generateUniformAccessObject; + +},{}],14:[function(require,module,exports){ + + +var mapSize = function(type) +{ + return GLSL_TO_SIZE[type]; +} + + +var GLSL_TO_SIZE = { + 'float': 1, + 'vec2': 2, + 'vec3': 3, + 'vec4': 4, + + 'int': 1, + 'ivec2': 2, + 'ivec3': 3, + 'ivec4': 4, + + 'bool': 1, + 'bvec2': 2, + 'bvec3': 3, + 'bvec4': 4, + + 'mat2': 4, + 'mat3': 9, + 'mat4': 16, + + 'sampler2D': 1 +} + +module.exports = mapSize; + +},{}],15:[function(require,module,exports){ + + +var mapSize = function(gl, type) +{ + if(!GL_TABLE) + { + var typeNames = Object.keys(GL_TO_GLSL_TYPES); + + GL_TABLE = {}; + + for(var i = 0; i < typeNames.length; ++i) + { + var tn = typeNames[i]; + GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn]; + } + } + + return GL_TABLE[type]; +} + +var GL_TABLE = null; + +var GL_TO_GLSL_TYPES = { + 'FLOAT': 'float', + 'FLOAT_VEC2': 'vec2', + 'FLOAT_VEC3': 'vec3', + 'FLOAT_VEC4': 'vec4', + + 'INT': 'int', + 'INT_VEC2': 'ivec2', + 'INT_VEC3': 'ivec3', + 'INT_VEC4': 'ivec4', + + 'BOOL': 'bool', + 'BOOL_VEC2': 'bvec2', + 'BOOL_VEC3': 'bvec3', + 'BOOL_VEC4': 'bvec4', + + 'FLOAT_MAT2': 'mat2', + 'FLOAT_MAT3': 'mat3', + 'FLOAT_MAT4': 'mat4', + + 'SAMPLER_2D': 'sampler2D' +} + +module.exports = mapSize; + +},{}],16:[function(require,module,exports){ +/** + * Bit twiddling hacks for JavaScript. + * + * Author: Mikola Lysenko + * + * Ported from Stanford bit twiddling hack library: + * http://graphics.stanford.edu/~seander/bithacks.html + */ + +"use strict"; "use restrict"; + +//Number of bits in an integer +var INT_BITS = 32; + +//Constants +exports.INT_BITS = INT_BITS; +exports.INT_MAX = 0x7fffffff; +exports.INT_MIN = -1<<(INT_BITS-1); + +//Returns -1, 0, +1 depending on sign of x +exports.sign = function(v) { + return (v > 0) - (v < 0); +} + +//Computes absolute value of integer +exports.abs = function(v) { + var mask = v >> (INT_BITS-1); + return (v ^ mask) - mask; +} + +//Computes minimum of integers x and y +exports.min = function(x, y) { + return y ^ ((x ^ y) & -(x < y)); +} + +//Computes maximum of integers x and y +exports.max = function(x, y) { + return x ^ ((x ^ y) & -(x < y)); +} + +//Checks if a number is a power of two +exports.isPow2 = function(v) { + return !(v & (v-1)) && (!!v); +} + +//Computes log base 2 of v +exports.log2 = function(v) { + var r, shift; + r = (v > 0xFFFF) << 4; v >>>= r; + shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; + shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; + shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; + return r | (v >> 1); +} + +//Computes log base 10 of v +exports.log10 = function(v) { + return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : + (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : + (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; +} + +//Counts number of bits +exports.popCount = function(v) { + v = v - ((v >>> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); + return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; +} + +//Counts number of trailing zeros +function countTrailingZeros(v) { + var c = 32; + v &= -v; + if (v) c--; + if (v & 0x0000FFFF) c -= 16; + if (v & 0x00FF00FF) c -= 8; + if (v & 0x0F0F0F0F) c -= 4; + if (v & 0x33333333) c -= 2; + if (v & 0x55555555) c -= 1; + return c; +} +exports.countTrailingZeros = countTrailingZeros; + +//Rounds to next power of 2 +exports.nextPow2 = function(v) { + v += v === 0; + --v; + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + return v + 1; +} + +//Rounds down to previous power of 2 +exports.prevPow2 = function(v) { + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + return v - (v>>>1); +} + +//Computes parity of word +exports.parity = function(v) { + v ^= v >>> 16; + v ^= v >>> 8; + v ^= v >>> 4; + v &= 0xf; + return (0x6996 >>> v) & 1; +} + +var REVERSE_TABLE = new Array(256); + +(function(tab) { + for(var i=0; i<256; ++i) { + var v = i, r = i, s = 7; + for (v >>>= 1; v; v >>>= 1) { + r <<= 1; + r |= v & 1; + --s; + } + tab[i] = (r << s) & 0xff; + } +})(REVERSE_TABLE); + +//Reverse bits in a 32 bit word +exports.reverse = function(v) { + return (REVERSE_TABLE[ v & 0xff] << 24) | + (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | + (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | + REVERSE_TABLE[(v >>> 24) & 0xff]; +} + +//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes +exports.interleave2 = function(x, y) { + x &= 0xFFFF; + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y &= 0xFFFF; + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +//Extracts the nth interleaved component +exports.deinterleave2 = function(v, n) { + v = (v >>> n) & 0x55555555; + v = (v | (v >>> 1)) & 0x33333333; + v = (v | (v >>> 2)) & 0x0F0F0F0F; + v = (v | (v >>> 4)) & 0x00FF00FF; + v = (v | (v >>> 16)) & 0x000FFFF; + return (v << 16) >> 16; +} + + +//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes +exports.interleave3 = function(x, y, z) { + x &= 0x3FF; + x = (x | (x<<16)) & 4278190335; + x = (x | (x<<8)) & 251719695; + x = (x | (x<<4)) & 3272356035; + x = (x | (x<<2)) & 1227133513; + + y &= 0x3FF; + y = (y | (y<<16)) & 4278190335; + y = (y | (y<<8)) & 251719695; + y = (y | (y<<4)) & 3272356035; + y = (y | (y<<2)) & 1227133513; + x |= (y << 1); + + z &= 0x3FF; + z = (z | (z<<16)) & 4278190335; + z = (z | (z<<8)) & 251719695; + z = (z | (z<<4)) & 3272356035; + z = (z | (z<<2)) & 1227133513; + + return x | (z << 2); +} + +//Extracts nth interleaved component of a 3-tuple +exports.deinterleave3 = function(v, n) { + v = (v >>> n) & 1227133513; + v = (v | (v>>>2)) & 3272356035; + v = (v | (v>>>4)) & 251719695; + v = (v | (v>>>8)) & 4278190335; + v = (v | (v>>>16)) & 0x3FF; + return (v<<22)>>22; +} + +//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) +exports.nextCombination = function(v) { + var t = v | (v - 1); + return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); +} + + +},{}],17:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +}).call(this,require('_process')) +},{"_process":18}],18:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = setTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + clearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + setTimeout(drainQueue, 0); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],19:[function(require,module,exports){ +(function (global){ +/*! https://mths.be/punycode v1.4.0 by @mathias */ +;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.3.2', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + typeof define == 'function' && + typeof define.amd == 'object' && + define.amd + ) { + define('punycode', function() { + return punycode; + }); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { + // in Node.js, io.js, or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { + // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { + // in Rhino or a web browser + root.punycode = punycode; + } + +}(this)); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],20:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +// If obj.hasOwnProperty has been overridden, then calling +// obj.hasOwnProperty(prop) will break. +// See: https://github.com/joyent/node/issues/1707 +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +module.exports = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +},{}],21:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } +}; + +module.exports = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return map(objectKeys(obj), function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (isArray(obj[k])) { + return map(obj[k], function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +function map (xs, f) { + if (xs.map) return xs.map(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + res.push(f(xs[i], i)); + } + return res; +} + +var objectKeys = Object.keys || function (obj) { + var res = []; + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); + } + return res; +}; + +},{}],22:[function(require,module,exports){ +'use strict'; + +exports.decode = exports.parse = require('./decode'); +exports.encode = exports.stringify = require('./encode'); + +},{"./decode":20,"./encode":21}],23:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var punycode = require('punycode'); + +exports.parse = urlParse; +exports.resolve = urlResolve; +exports.resolveObject = urlResolveObject; +exports.format = urlFormat; + +exports.Url = Url; + +function Url() { + this.protocol = null; + this.slashes = null; + this.auth = null; + this.host = null; + this.port = null; + this.hostname = null; + this.hash = null; + this.search = null; + this.query = null; + this.pathname = null; + this.path = null; + this.href = null; +} + +// Reference: RFC 3986, RFC 1808, RFC 2396 + +// define these here so at least they only have to be +// compiled once on the first module load. +var protocolPattern = /^([a-z0-9.+-]+:)/i, + portPattern = /:[0-9]*$/, + + // RFC 2396: characters reserved for delimiting URLs. + // We actually just auto-escape these. + delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], + + // RFC 2396: characters not allowed for various reasons. + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), + + // Allowed by RFCs, but cause of XSS attacks. Always escape these. + autoEscape = ['\''].concat(unwise), + // Characters that are never ever allowed in a hostname. + // Note that any invalid chars are also handled, but these + // are the ones that are *expected* to be seen, so we fast-path + // them. + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), + hostEndingChars = ['/', '?', '#'], + hostnameMaxLen = 255, + hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, + hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, + // protocols that can allow "unsafe" and "unwise" chars. + unsafeProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that never have a hostname. + hostlessProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that always contain a // bit. + slashedProtocol = { + 'http': true, + 'https': true, + 'ftp': true, + 'gopher': true, + 'file': true, + 'http:': true, + 'https:': true, + 'ftp:': true, + 'gopher:': true, + 'file:': true + }, + querystring = require('querystring'); + +function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url && isObject(url) && url instanceof Url) return url; + + var u = new Url; + u.parse(url, parseQueryString, slashesDenoteHost); + return u; +} + +Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + if (!isString(url)) { + throw new TypeError("Parameter 'url' must be a string, not " + typeof url); + } + + var rest = url; + + // trim before proceeding. + // This is to support parse stuff like " http://foo.com \n" + rest = rest.trim(); + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.substr(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var slashes = rest.substr(0, 2) === '//'; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.substr(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:c path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + // find the first instance of any hostEndingChars + var hostEnd = -1; + for (var i = 0; i < hostEndingChars.length; i++) { + var hec = rest.indexOf(hostEndingChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + + // at this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + var auth, atSign; + if (hostEnd === -1) { + // atSign can be anywhere. + atSign = rest.lastIndexOf('@'); + } else { + // atSign must be in auth portion. + // http://a@b/c@d => host:b auth:a path:/c@d + atSign = rest.lastIndexOf('@', hostEnd); + } + + // Now we have a portion which is definitely the auth. + // Pull that off. + if (atSign !== -1) { + auth = rest.slice(0, atSign); + rest = rest.slice(atSign + 1); + this.auth = decodeURIComponent(auth); + } + + // the host is the remaining to the left of the first non-host char + hostEnd = -1; + for (var i = 0; i < nonHostChars.length; i++) { + var hec = rest.indexOf(nonHostChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + // if we still have not hit it, then the entire thing is a host. + if (hostEnd === -1) + hostEnd = rest.length; + + this.host = rest.slice(0, hostEnd); + rest = rest.slice(hostEnd); + + // pull out port. + this.parseHost(); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + this.hostname = this.hostname || ''; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = this.hostname[0] === '[' && + this.hostname[this.hostname.length - 1] === ']'; + + // validate a little. + if (!ipv6Hostname) { + var hostparts = this.hostname.split(/\./); + for (var i = 0, l = hostparts.length; i < l; i++) { + var part = hostparts[i]; + if (!part) continue; + if (!part.match(hostnamePartPattern)) { + var newpart = ''; + for (var j = 0, k = part.length; j < k; j++) { + if (part.charCodeAt(j) > 127) { + // we replace non-ASCII char with a temporary placeholder + // we need this to make sure size of hostname is not + // broken by replacing non-ASCII by nothing + newpart += 'x'; + } else { + newpart += part[j]; + } + } + // we test again with ASCII char only + if (!newpart.match(hostnamePartPattern)) { + var validParts = hostparts.slice(0, i); + var notHost = hostparts.slice(i + 1); + var bit = part.match(hostnamePartStart); + if (bit) { + validParts.push(bit[1]); + notHost.unshift(bit[2]); + } + if (notHost.length) { + rest = '/' + notHost.join('.') + rest; + } + this.hostname = validParts.join('.'); + break; + } + } + } + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a puny coded representation of "domain". + // It only converts the part of the domain name that + // has non ASCII characters. I.e. it dosent matter if + // you call it with a domain that already is in ASCII. + var domainArray = this.hostname.split('.'); + var newOut = []; + for (var i = 0; i < domainArray.length; ++i) { + var s = domainArray[i]; + newOut.push(s.match(/[^A-Za-z0-9_-]/) ? + 'xn--' + punycode.encode(s) : s); + } + this.hostname = newOut.join('.'); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; + this.href += this.host; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + this.hostname = this.hostname.substr(1, this.hostname.length - 2); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + for (var i = 0, l = autoEscape.length; i < l; i++) { + var ae = autoEscape[i]; + var esc = encodeURIComponent(ae); + if (esc === ae) { + esc = escape(ae); + } + rest = rest.split(ae).join(esc); + } + } + + + // chop off from the tail first. + var hash = rest.indexOf('#'); + if (hash !== -1) { + // got a fragment string. + this.hash = rest.substr(hash); + rest = rest.slice(0, hash); + } + var qm = rest.indexOf('?'); + if (qm !== -1) { + this.search = rest.substr(qm); + this.query = rest.substr(qm + 1); + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + rest = rest.slice(0, qm); + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = {}; + } + if (rest) this.pathname = rest; + if (slashedProtocol[lowerProto] && + this.hostname && !this.pathname) { + this.pathname = '/'; + } + + //to support http.request + if (this.pathname || this.search) { + var p = this.pathname || ''; + var s = this.search || ''; + this.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + this.href = this.format(); + return this; +}; + +// format a parsed object into a url string +function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (isString(obj)) obj = urlParse(obj); + if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + return obj.format(); +} + +Url.prototype.format = function() { + var auth = this.auth || ''; + if (auth) { + auth = encodeURIComponent(auth); + auth = auth.replace(/%3A/i, ':'); + auth += '@'; + } + + var protocol = this.protocol || '', + pathname = this.pathname || '', + hash = this.hash || '', + host = false, + query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? + this.hostname : + '[' + this.hostname + ']'); + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query && + isObject(this.query) && + Object.keys(this.query).length) { + query = querystring.stringify(this.query); + } + + var search = this.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.substr(-1) !== ':') protocol += ':'; + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (this.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + if (hash && hash.charAt(0) !== '#') hash = '#' + hash; + if (search && search.charAt(0) !== '?') search = '?' + search; + + pathname = pathname.replace(/[?#]/g, function(match) { + return encodeURIComponent(match); + }); + search = search.replace('#', '%23'); + + return protocol + host + pathname + search + hash; +}; + +function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); +} + +Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); +}; + +function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); +} + +Url.prototype.resolveObject = function(relative) { + if (isString(relative)) { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + Object.keys(this).forEach(function(k) { + result[k] = this[k]; + }, this); + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + Object.keys(relative).forEach(function(k) { + if (k !== 'protocol') + result[k] = relative[k]; + }); + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + Object.keys(relative).forEach(function(k) { + result[k] = relative[k]; + }); + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && !hostlessProtocol[relative.protocol]) { + var relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), + isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ), + mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)), + removeAllDots = mustEndAbs, + srcPath = result.pathname && result.pathname.split('/') || [], + relPath = relative.pathname && relative.pathname.split('/') || [], + psychotic = result.protocol && !slashedProtocol[result.protocol]; + + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + result.host = (relative.host || relative.host === '') ? + relative.host : result.host; + result.hostname = (relative.hostname || relative.hostname === '') ? + relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (!isNullOrUndefined(relative.search)) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host) && (last === '.' || last === '..') || + last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + if (last == '.') { + srcPath.splice(i, 1); + } else if (last === '..') { + srcPath.splice(i, 1); + up++; + } else if (up) { + srcPath.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; +}; + +Url.prototype.parseHost = function() { + var host = this.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + this.port = port.substr(1); + } + host = host.substr(0, host.length - port.length); + } + if (host) this.hostname = host; +}; + +function isString(arg) { + return typeof arg === "string"; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isNull(arg) { + return arg === null; +} +function isNullOrUndefined(arg) { + return arg == null; +} + +},{"punycode":19,"querystring":22}],24:[function(require,module,exports){ +'use strict'; + +module.exports = earcut; + +function earcut(data, holeIndices, dim) { + + dim = dim || 2; + + var hasHoles = holeIndices && holeIndices.length, + outerLen = hasHoles ? holeIndices[0] * dim : data.length, + outerNode = linkedList(data, 0, outerLen, dim, true), + triangles = []; + + if (!outerNode) return triangles; + + var minX, minY, maxX, maxY, x, y, size; + + if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); + + // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox + if (data.length > 80 * dim) { + minX = maxX = data[0]; + minY = maxY = data[1]; + + for (var i = dim; i < outerLen; i += dim) { + x = data[i]; + y = data[i + 1]; + if (x < minX) minX = x; + if (y < minY) minY = y; + if (x > maxX) maxX = x; + if (y > maxY) maxY = y; + } + + // minX, minY and size are later used to transform coords into integers for z-order calculation + size = Math.max(maxX - minX, maxY - minY); + } + + earcutLinked(outerNode, triangles, dim, minX, minY, size); + + return triangles; +} + +// create a circular doubly linked list from polygon points in the specified winding order +function linkedList(data, start, end, dim, clockwise) { + var sum = 0, + i, j, last; + + // calculate original winding order of a polygon ring + for (i = start, j = end - dim; i < end; i += dim) { + sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); + j = i; + } + + // link points into circular doubly-linked list in the specified winding order + if (clockwise === (sum > 0)) { + for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); + } else { + for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); + } + + return last; +} + +// eliminate colinear or duplicate points +function filterPoints(start, end) { + if (!start) return start; + if (!end) end = start; + + var p = start, + again; + do { + again = false; + + if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { + removeNode(p); + p = end = p.prev; + if (p === p.next) return null; + again = true; + + } else { + p = p.next; + } + } while (again || p !== end); + + return end; +} + +// main ear slicing loop which triangulates a polygon (given as a linked list) +function earcutLinked(ear, triangles, dim, minX, minY, size, pass) { + if (!ear) return; + + // interlink polygon nodes in z-order + if (!pass && size) indexCurve(ear, minX, minY, size); + + var stop = ear, + prev, next; + + // iterate through ears, slicing them one by one + while (ear.prev !== ear.next) { + prev = ear.prev; + next = ear.next; + + if (size ? isEarHashed(ear, minX, minY, size) : isEar(ear)) { + // cut off the triangle + triangles.push(prev.i / dim); + triangles.push(ear.i / dim); + triangles.push(next.i / dim); + + removeNode(ear); + + // skipping the next vertice leads to less sliver triangles + ear = next.next; + stop = next.next; + + continue; + } + + ear = next; + + // if we looped through the whole remaining polygon and can't find any more ears + if (ear === stop) { + // try filtering points and slicing again + if (!pass) { + earcutLinked(filterPoints(ear), triangles, dim, minX, minY, size, 1); + + // if this didn't work, try curing all small self-intersections locally + } else if (pass === 1) { + ear = cureLocalIntersections(ear, triangles, dim); + earcutLinked(ear, triangles, dim, minX, minY, size, 2); + + // as a last resort, try splitting the remaining polygon into two + } else if (pass === 2) { + splitEarcut(ear, triangles, dim, minX, minY, size); + } + + break; + } + } +} + +// check whether a polygon node forms a valid ear with adjacent nodes +function isEar(ear) { + var a = ear.prev, + b = ear, + c = ear.next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // now make sure we don't have other points inside the potential ear + var p = ear.next.next; + + while (p !== ear.prev) { + if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.next; + } + + return true; +} + +function isEarHashed(ear, minX, minY, size) { + var a = ear.prev, + b = ear, + c = ear.next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // triangle bbox; min & max are calculated like this for speed + var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x), + minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y), + maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x), + maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y); + + // z-order range for the current triangle bbox; + var minZ = zOrder(minTX, minTY, minX, minY, size), + maxZ = zOrder(maxTX, maxTY, minX, minY, size); + + // first look for points inside the triangle in increasing z-order + var p = ear.nextZ; + + while (p && p.z <= maxZ) { + if (p !== ear.prev && p !== ear.next && + pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.nextZ; + } + + // then look for points in decreasing z-order + p = ear.prevZ; + + while (p && p.z >= minZ) { + if (p !== ear.prev && p !== ear.next && + pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.prevZ; + } + + return true; +} + +// go through all polygon nodes and cure small local self-intersections +function cureLocalIntersections(start, triangles, dim) { + var p = start; + do { + var a = p.prev, + b = p.next.next; + + // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2]) + if (intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) { + + triangles.push(a.i / dim); + triangles.push(p.i / dim); + triangles.push(b.i / dim); + + // remove two nodes involved + removeNode(p); + removeNode(p.next); + + p = start = b; + } + p = p.next; + } while (p !== start); + + return p; +} + +// try splitting polygon into two and triangulate them independently +function splitEarcut(start, triangles, dim, minX, minY, size) { + // look for a valid diagonal that divides the polygon into two + var a = start; + do { + var b = a.next.next; + while (b !== a.prev) { + if (a.i !== b.i && isValidDiagonal(a, b)) { + // split the polygon in two by the diagonal + var c = splitPolygon(a, b); + + // filter colinear points around the cuts + a = filterPoints(a, a.next); + c = filterPoints(c, c.next); + + // run earcut on each half + earcutLinked(a, triangles, dim, minX, minY, size); + earcutLinked(c, triangles, dim, minX, minY, size); + return; + } + b = b.next; + } + a = a.next; + } while (a !== start); +} + +// link every hole into the outer loop, producing a single-ring polygon without holes +function eliminateHoles(data, holeIndices, outerNode, dim) { + var queue = [], + i, len, start, end, list; + + for (i = 0, len = holeIndices.length; i < len; i++) { + start = holeIndices[i] * dim; + end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; + list = linkedList(data, start, end, dim, false); + if (list === list.next) list.steiner = true; + queue.push(getLeftmost(list)); + } + + queue.sort(compareX); + + // process holes from left to right + for (i = 0; i < queue.length; i++) { + eliminateHole(queue[i], outerNode); + outerNode = filterPoints(outerNode, outerNode.next); + } + + return outerNode; +} + +function compareX(a, b) { + return a.x - b.x; +} + +// find a bridge between vertices that connects hole with an outer ring and and link it +function eliminateHole(hole, outerNode) { + outerNode = findHoleBridge(hole, outerNode); + if (outerNode) { + var b = splitPolygon(outerNode, hole); + filterPoints(b, b.next); + } +} + +// David Eberly's algorithm for finding a bridge between hole and outer polygon +function findHoleBridge(hole, outerNode) { + var p = outerNode, + hx = hole.x, + hy = hole.y, + qx = -Infinity, + m; + + // find a segment intersected by a ray from the hole's leftmost point to the left; + // segment's endpoint with lesser x will be potential connection point + do { + if (hy <= p.y && hy >= p.next.y) { + var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); + if (x <= hx && x > qx) { + qx = x; + m = p.x < p.next.x ? p : p.next; + } + } + p = p.next; + } while (p !== outerNode); + + if (!m) return null; + + if (hole.x === m.x) return m.prev; // hole touches outer segment; pick lower endpoint + + // look for points inside the triangle of hole point, segment intersection and endpoint; + // if there are no points found, we have a valid connection; + // otherwise choose the point of the minimum angle with the ray as connection point + + var stop = m, + tanMin = Infinity, + tan; + + p = m.next; + + while (p !== stop) { + if (hx >= p.x && p.x >= m.x && + pointInTriangle(hy < m.y ? hx : qx, hy, m.x, m.y, hy < m.y ? qx : hx, hy, p.x, p.y)) { + + tan = Math.abs(hy - p.y) / (hx - p.x); // tangential + + if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) { + m = p; + tanMin = tan; + } + } + + p = p.next; + } + + return m; +} + +// interlink polygon nodes in z-order +function indexCurve(start, minX, minY, size) { + var p = start; + do { + if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, size); + p.prevZ = p.prev; + p.nextZ = p.next; + p = p.next; + } while (p !== start); + + p.prevZ.nextZ = null; + p.prevZ = null; + + sortLinked(p); +} + +// Simon Tatham's linked list merge sort algorithm +// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html +function sortLinked(list) { + var i, p, q, e, tail, numMerges, pSize, qSize, + inSize = 1; + + do { + p = list; + list = null; + tail = null; + numMerges = 0; + + while (p) { + numMerges++; + q = p; + pSize = 0; + for (i = 0; i < inSize; i++) { + pSize++; + q = q.nextZ; + if (!q) break; + } + + qSize = inSize; + + while (pSize > 0 || (qSize > 0 && q)) { + + if (pSize === 0) { + e = q; + q = q.nextZ; + qSize--; + } else if (qSize === 0 || !q) { + e = p; + p = p.nextZ; + pSize--; + } else if (p.z <= q.z) { + e = p; + p = p.nextZ; + pSize--; + } else { + e = q; + q = q.nextZ; + qSize--; + } + + if (tail) tail.nextZ = e; + else list = e; + + e.prevZ = tail; + tail = e; + } + + p = q; + } + + tail.nextZ = null; + inSize *= 2; + + } while (numMerges > 1); + + return list; +} + +// z-order of a point given coords and size of the data bounding box +function zOrder(x, y, minX, minY, size) { + // coords are transformed into non-negative 15-bit integer range + x = 32767 * (x - minX) / size; + y = 32767 * (y - minY) / size; + + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +// find the leftmost node of a polygon ring +function getLeftmost(start) { + var p = start, + leftmost = start; + do { + if (p.x < leftmost.x) leftmost = p; + p = p.next; + } while (p !== start); + + return leftmost; +} + +// check if a point lies within a convex triangle +function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) { + return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && + (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && + (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; +} + +// check if a diagonal between two polygon nodes is valid (lies in polygon interior) +function isValidDiagonal(a, b) { + return equals(a, b) || a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && + locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b); +} + +// signed area of a triangle +function area(p, q, r) { + return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); +} + +// check if two points are equal +function equals(p1, p2) { + return p1.x === p2.x && p1.y === p2.y; +} + +// check if two segments intersect +function intersects(p1, q1, p2, q2) { + return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && + area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0; +} + +// check if a polygon diagonal intersects any polygon segments +function intersectsPolygon(a, b) { + var p = a; + do { + if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && + intersects(p, p.next, a, b)) return true; + p = p.next; + } while (p !== a); + + return false; +} + +// check if a polygon diagonal is locally inside the polygon +function locallyInside(a, b) { + return area(a.prev, a, a.next) < 0 ? + area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : + area(a, b, a.prev) < 0 || area(a, a.next, b) < 0; +} + +// check if the middle point of a polygon diagonal is inside the polygon +function middleInside(a, b) { + var p = a, + inside = false, + px = (a.x + b.x) / 2, + py = (a.y + b.y) / 2; + do { + if (((p.y > py) !== (p.next.y > py)) && (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) + inside = !inside; + p = p.next; + } while (p !== a); + + return inside; +} + +// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; +// if one belongs to the outer ring and another to a hole, it merges it into a single ring +function splitPolygon(a, b) { + var a2 = new Node(a.i, a.x, a.y), + b2 = new Node(b.i, b.x, b.y), + an = a.next, + bp = b.prev; + + a.next = b; + b.prev = a; + + a2.next = an; + an.prev = a2; + + b2.next = a2; + a2.prev = b2; + + bp.next = b2; + b2.prev = bp; + + return b2; +} + +// create a node and optionally link it with previous one (in a circular doubly linked list) +function insertNode(i, x, y, last) { + var p = new Node(i, x, y); + + if (!last) { + p.prev = p; + p.next = p; + + } else { + p.next = last.next; + p.prev = last; + last.next.prev = p; + last.next = p; + } + return p; +} + +function removeNode(p) { + p.next.prev = p.prev; + p.prev.next = p.next; + + if (p.prevZ) p.prevZ.nextZ = p.nextZ; + if (p.nextZ) p.nextZ.prevZ = p.prevZ; +} + +function Node(i, x, y) { + // vertice index in coordinates array + this.i = i; + + // vertex coordinates + this.x = x; + this.y = y; + + // previous and next vertice nodes in a polygon ring + this.prev = null; + this.next = null; + + // z-order curve value + this.z = null; + + // previous and next nodes in z-order + this.prevZ = null; + this.nextZ = null; + + // indicates whether this is a steiner point + this.steiner = false; +} + +},{}],25:[function(require,module,exports){ +'use strict'; + +// +// We store our EE objects in a plain object whose properties are event names. +// If `Object.create(null)` is not supported we prefix the event names with a +// `~` to make sure that the built-in object properties are not overridden or +// used as an attack vector. +// We also assume that `Object.create(null)` is available when the event name +// is an ES6 Symbol. +// +var prefix = typeof Object.create !== 'function' ? '~' : false; + +/** + * Representation of a single EventEmitter function. + * + * @param {Function} fn Event handler to be called. + * @param {Mixed} context Context for function execution. + * @param {Boolean} once Only emit once + * @api private + */ +function EE(fn, context, once) { + this.fn = fn; + this.context = context; + this.once = once || false; +} + +/** + * Minimal EventEmitter interface that is molded against the Node.js + * EventEmitter interface. + * + * @constructor + * @api public + */ +function EventEmitter() { /* Nothing to set */ } + +/** + * Holds the assigned EventEmitters by name. + * + * @type {Object} + * @private + */ +EventEmitter.prototype._events = undefined; + +/** + * Return a list of assigned event listeners. + * + * @param {String} event The events that should be listed. + * @param {Boolean} exists We only need to know if there are listeners. + * @returns {Array|Boolean} + * @api public + */ +EventEmitter.prototype.listeners = function listeners(event, exists) { + var evt = prefix ? prefix + event : event + , available = this._events && this._events[evt]; + + if (exists) return !!available; + if (!available) return []; + if (available.fn) return [available.fn]; + + for (var i = 0, l = available.length, ee = new Array(l); i < l; i++) { + ee[i] = available[i].fn; + } + + return ee; +}; + +/** + * Emit an event to all registered event listeners. + * + * @param {String} event The name of the event. + * @returns {Boolean} Indication if we've emitted an event. + * @api public + */ +EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { + var evt = prefix ? prefix + event : event; + + if (!this._events || !this._events[evt]) return false; + + var listeners = this._events[evt] + , len = arguments.length + , args + , i; + + if ('function' === typeof listeners.fn) { + if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); + + switch (len) { + case 1: return listeners.fn.call(listeners.context), true; + case 2: return listeners.fn.call(listeners.context, a1), true; + case 3: return listeners.fn.call(listeners.context, a1, a2), true; + case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; + case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; + case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; + } + + for (i = 1, args = new Array(len -1); i < len; i++) { + args[i - 1] = arguments[i]; + } + + listeners.fn.apply(listeners.context, args); + } else { + var length = listeners.length + , j; + + for (i = 0; i < length; i++) { + if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); + + switch (len) { + case 1: listeners[i].fn.call(listeners[i].context); break; + case 2: listeners[i].fn.call(listeners[i].context, a1); break; + case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; + default: + if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { + args[j - 1] = arguments[j]; + } + + listeners[i].fn.apply(listeners[i].context, args); + } + } + } + + return true; +}; + +/** + * Register a new EventListener for the given event. + * + * @param {String} event Name of the event. + * @param {Functon} fn Callback function. + * @param {Mixed} context The context of the function. + * @api public + */ +EventEmitter.prototype.on = function on(event, fn, context) { + var listener = new EE(fn, context || this) + , evt = prefix ? prefix + event : event; + + if (!this._events) this._events = prefix ? {} : Object.create(null); + if (!this._events[evt]) this._events[evt] = listener; + else { + if (!this._events[evt].fn) this._events[evt].push(listener); + else this._events[evt] = [ + this._events[evt], listener + ]; + } + + return this; +}; + +/** + * Add an EventListener that's only called once. + * + * @param {String} event Name of the event. + * @param {Function} fn Callback function. + * @param {Mixed} context The context of the function. + * @api public + */ +EventEmitter.prototype.once = function once(event, fn, context) { + var listener = new EE(fn, context || this, true) + , evt = prefix ? prefix + event : event; + + if (!this._events) this._events = prefix ? {} : Object.create(null); + if (!this._events[evt]) this._events[evt] = listener; + else { + if (!this._events[evt].fn) this._events[evt].push(listener); + else this._events[evt] = [ + this._events[evt], listener + ]; + } + + return this; +}; + +/** + * Remove event listeners. + * + * @param {String} event The event we want to remove. + * @param {Function} fn The listener that we need to find. + * @param {Mixed} context Only remove listeners matching this context. + * @param {Boolean} once Only remove once listeners. + * @api public + */ +EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { + var evt = prefix ? prefix + event : event; + + if (!this._events || !this._events[evt]) return this; + + var listeners = this._events[evt] + , events = []; + + if (fn) { + if (listeners.fn) { + if ( + listeners.fn !== fn + || (once && !listeners.once) + || (context && listeners.context !== context) + ) { + events.push(listeners); + } + } else { + for (var i = 0, length = listeners.length; i < length; i++) { + if ( + listeners[i].fn !== fn + || (once && !listeners[i].once) + || (context && listeners[i].context !== context) + ) { + events.push(listeners[i]); + } + } + } + } + + // + // Reset the array, or remove it completely if we have no more listeners. + // + if (events.length) { + this._events[evt] = events.length === 1 ? events[0] : events; + } else { + delete this._events[evt]; + } + + return this; +}; + +/** + * Remove all listeners or only the listeners for the specified event. + * + * @param {String} event The event want to remove all listeners for. + * @api public + */ +EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { + if (!this._events) return this; + + if (event) delete this._events[prefix ? prefix + event : event]; + else this._events = prefix ? {} : Object.create(null); + + return this; +}; + +// +// Alias methods names because people roll like that. +// +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; +EventEmitter.prototype.addListener = EventEmitter.prototype.on; + +// +// This function doesn't apply anymore. +// +EventEmitter.prototype.setMaxListeners = function setMaxListeners() { + return this; +}; + +// +// Expose the prefix. +// +EventEmitter.prefixed = prefix; + +// +// Expose the module. +// +if ('undefined' !== typeof module) { + module.exports = EventEmitter; +} + +},{}],26:[function(require,module,exports){ +/** + * isMobile.js v0.3.9 + * + * A simple library to detect Apple phones and tablets, + * Android phones and tablets, other mobile devices (like blackberry, mini-opera and windows phone), + * and any kind of seven inch device, via user agent sniffing. + * + * @author: Kai Mallea (kmallea@gmail.com) + * + * @license: http://creativecommons.org/publicdomain/zero/1.0/ + */ +(function (global) { + + var apple_phone = /iPhone/i, + apple_ipod = /iPod/i, + apple_tablet = /iPad/i, + android_phone = /(?=.*\bAndroid\b)(?=.*\bMobile\b)/i, // Match 'Android' AND 'Mobile' + android_tablet = /Android/i, + amazon_phone = /(?=.*\bAndroid\b)(?=.*\bSD4930UR\b)/i, + amazon_tablet = /(?=.*\bAndroid\b)(?=.*\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\b)/i, + windows_phone = /IEMobile/i, + windows_tablet = /(?=.*\bWindows\b)(?=.*\bARM\b)/i, // Match 'Windows' AND 'ARM' + other_blackberry = /BlackBerry/i, + other_blackberry_10 = /BB10/i, + other_opera = /Opera Mini/i, + other_chrome = /(CriOS|Chrome)(?=.*\bMobile\b)/i, + other_firefox = /(?=.*\bFirefox\b)(?=.*\bMobile\b)/i, // Match 'Firefox' AND 'Mobile' + seven_inch = new RegExp( + '(?:' + // Non-capturing group + + 'Nexus 7' + // Nexus 7 + + '|' + // OR + + 'BNTV250' + // B&N Nook Tablet 7 inch + + '|' + // OR + + 'Kindle Fire' + // Kindle Fire + + '|' + // OR + + 'Silk' + // Kindle Fire, Silk Accelerated + + '|' + // OR + + 'GT-P1000' + // Galaxy Tab 7 inch + + ')', // End non-capturing group + + 'i'); // Case-insensitive matching + + var match = function(regex, userAgent) { + return regex.test(userAgent); + }; + + var IsMobileClass = function(userAgent) { + var ua = userAgent || navigator.userAgent; + + // Facebook mobile app's integrated browser adds a bunch of strings that + // match everything. Strip it out if it exists. + var tmp = ua.split('[FBAN'); + if (typeof tmp[1] !== 'undefined') { + ua = tmp[0]; + } + + this.apple = { + phone: match(apple_phone, ua), + ipod: match(apple_ipod, ua), + tablet: !match(apple_phone, ua) && match(apple_tablet, ua), + device: match(apple_phone, ua) || match(apple_ipod, ua) || match(apple_tablet, ua) + }; + this.amazon = { + phone: match(amazon_phone, ua), + tablet: !match(amazon_phone, ua) && match(amazon_tablet, ua), + device: match(amazon_phone, ua) || match(amazon_tablet, ua) + }; + this.android = { + phone: match(amazon_phone, ua) || match(android_phone, ua), + tablet: !match(amazon_phone, ua) && !match(android_phone, ua) && (match(amazon_tablet, ua) || match(android_tablet, ua)), + device: match(amazon_phone, ua) || match(amazon_tablet, ua) || match(android_phone, ua) || match(android_tablet, ua) + }; + this.windows = { + phone: match(windows_phone, ua), + tablet: match(windows_tablet, ua), + device: match(windows_phone, ua) || match(windows_tablet, ua) + }; + this.other = { + blackberry: match(other_blackberry, ua), + blackberry10: match(other_blackberry_10, ua), + opera: match(other_opera, ua), + firefox: match(other_firefox, ua), + chrome: match(other_chrome, ua), + device: match(other_blackberry, ua) || match(other_blackberry_10, ua) || match(other_opera, ua) || match(other_firefox, ua) || match(other_chrome, ua) + }; + this.seven_inch = match(seven_inch, ua); + this.any = this.apple.device || this.android.device || this.windows.device || this.other.device || this.seven_inch; + + // excludes 'other' devices and ipods, targeting touchscreen phones + this.phone = this.apple.phone || this.android.phone || this.windows.phone; + + // excludes 7 inch devices, classifying as phone or tablet is left to the user + this.tablet = this.apple.tablet || this.android.tablet || this.windows.tablet; + + if (typeof window === 'undefined') { + return this; + } + }; + + var instantiate = function() { + var IM = new IsMobileClass(); + IM.Class = IsMobileClass; + return IM; + }; + + if (typeof module !== 'undefined' && module.exports && typeof window === 'undefined') { + //node + module.exports = IsMobileClass; + } else if (typeof module !== 'undefined' && module.exports && typeof window !== 'undefined') { + //browserify + module.exports = instantiate(); + } else if (typeof define === 'function' && define.amd) { + //AMD + define('isMobile', [], global.isMobile = instantiate()); + } else { + global.isMobile = instantiate(); + } + +})(this); + +},{}],27:[function(require,module,exports){ +/* eslint-disable no-unused-vars */ +'use strict'; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; + +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Object.assign cannot be called with null or undefined'); + } + + return Object(val); +} + +module.exports = Object.assign || function (target, source) { + var from; + var to = toObject(target); + var symbols; + + for (var s = 1; s < arguments.length; s++) { + from = Object(arguments[s]); + + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + + if (Object.getOwnPropertySymbols) { + symbols = Object.getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } + } + } + + return to; +}; + +},{}],28:[function(require,module,exports){ (function (process){ /*! * async @@ -1125,4475 +5606,1429 @@ }()); }).call(this,require('_process')) -},{"_process":5}],2:[function(require,module,exports){ -'use strict'; - -// -// We store our EE objects in a plain object whose properties are event names. -// If `Object.create(null)` is not supported we prefix the event names with a -// `~` to make sure that the built-in object properties are not overridden or -// used as an attack vector. -// We also assume that `Object.create(null)` is available when the event name -// is an ES6 Symbol. -// -var prefix = typeof Object.create !== 'function' ? '~' : false; +},{"_process":18}],29:[function(require,module,exports){ +var async = require('async'), + urlParser = require('url'), + Resource = require('./Resource'), + EventEmitter = require('eventemitter3'); /** - * Representation of a single EventEmitter function. - * - * @param {Function} fn Event handler to be called. - * @param {Mixed} context Context for function execution. - * @param {Boolean} once Only emit once - * @api private - */ -function EE(fn, context, once) { - this.fn = fn; - this.context = context; - this.once = once || false; -} - -/** - * Minimal EventEmitter interface that is molded against the Node.js - * EventEmitter interface. - * - * @constructor - * @api public - */ -function EventEmitter() { /* Nothing to set */ } - -/** - * Holds the assigned EventEmitters by name. - * - * @type {Object} - * @private - */ -EventEmitter.prototype._events = undefined; - -/** - * Return a list of assigned event listeners. - * - * @param {String} event The events that should be listed. - * @param {Boolean} exists We only need to know if there are listeners. - * @returns {Array|Boolean} - * @api public - */ -EventEmitter.prototype.listeners = function listeners(event, exists) { - var evt = prefix ? prefix + event : event - , available = this._events && this._events[evt]; - - if (exists) return !!available; - if (!available) return []; - if (available.fn) return [available.fn]; - - for (var i = 0, l = available.length, ee = new Array(l); i < l; i++) { - ee[i] = available[i].fn; - } - - return ee; -}; - -/** - * Emit an event to all registered event listeners. - * - * @param {String} event The name of the event. - * @returns {Boolean} Indication if we've emitted an event. - * @api public - */ -EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { - var evt = prefix ? prefix + event : event; - - if (!this._events || !this._events[evt]) return false; - - var listeners = this._events[evt] - , len = arguments.length - , args - , i; - - if ('function' === typeof listeners.fn) { - if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); - - switch (len) { - case 1: return listeners.fn.call(listeners.context), true; - case 2: return listeners.fn.call(listeners.context, a1), true; - case 3: return listeners.fn.call(listeners.context, a1, a2), true; - case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; - case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; - case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; - } - - for (i = 1, args = new Array(len -1); i < len; i++) { - args[i - 1] = arguments[i]; - } - - listeners.fn.apply(listeners.context, args); - } else { - var length = listeners.length - , j; - - for (i = 0; i < length; i++) { - if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); - - switch (len) { - case 1: listeners[i].fn.call(listeners[i].context); break; - case 2: listeners[i].fn.call(listeners[i].context, a1); break; - case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; - default: - if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { - args[j - 1] = arguments[j]; - } - - listeners[i].fn.apply(listeners[i].context, args); - } - } - } - - return true; -}; - -/** - * Register a new EventListener for the given event. - * - * @param {String} event Name of the event. - * @param {Functon} fn Callback function. - * @param {Mixed} context The context of the function. - * @api public - */ -EventEmitter.prototype.on = function on(event, fn, context) { - var listener = new EE(fn, context || this) - , evt = prefix ? prefix + event : event; - - if (!this._events) this._events = prefix ? {} : Object.create(null); - if (!this._events[evt]) this._events[evt] = listener; - else { - if (!this._events[evt].fn) this._events[evt].push(listener); - else this._events[evt] = [ - this._events[evt], listener - ]; - } - - return this; -}; - -/** - * Add an EventListener that's only called once. - * - * @param {String} event Name of the event. - * @param {Function} fn Callback function. - * @param {Mixed} context The context of the function. - * @api public - */ -EventEmitter.prototype.once = function once(event, fn, context) { - var listener = new EE(fn, context || this, true) - , evt = prefix ? prefix + event : event; - - if (!this._events) this._events = prefix ? {} : Object.create(null); - if (!this._events[evt]) this._events[evt] = listener; - else { - if (!this._events[evt].fn) this._events[evt].push(listener); - else this._events[evt] = [ - this._events[evt], listener - ]; - } - - return this; -}; - -/** - * Remove event listeners. - * - * @param {String} event The event we want to remove. - * @param {Function} fn The listener that we need to find. - * @param {Mixed} context Only remove listeners matching this context. - * @param {Boolean} once Only remove once listeners. - * @api public - */ -EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { - var evt = prefix ? prefix + event : event; - - if (!this._events || !this._events[evt]) return this; - - var listeners = this._events[evt] - , events = []; - - if (fn) { - if (listeners.fn) { - if ( - listeners.fn !== fn - || (once && !listeners.once) - || (context && listeners.context !== context) - ) { - events.push(listeners); - } - } else { - for (var i = 0, length = listeners.length; i < length; i++) { - if ( - listeners[i].fn !== fn - || (once && !listeners[i].once) - || (context && listeners[i].context !== context) - ) { - events.push(listeners[i]); - } - } - } - } - - // - // Reset the array, or remove it completely if we have no more listeners. - // - if (events.length) { - this._events[evt] = events.length === 1 ? events[0] : events; - } else { - delete this._events[evt]; - } - - return this; -}; - -/** - * Remove all listeners or only the listeners for the specified event. - * - * @param {String} event The event want to remove all listeners for. - * @api public - */ -EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { - if (!this._events) return this; - - if (event) delete this._events[prefix ? prefix + event : event]; - else this._events = prefix ? {} : Object.create(null); - - return this; -}; - -// -// Alias methods names because people roll like that. -// -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; -EventEmitter.prototype.addListener = EventEmitter.prototype.on; - -// -// This function doesn't apply anymore. -// -EventEmitter.prototype.setMaxListeners = function setMaxListeners() { - return this; -}; - -// -// Expose the prefix. -// -EventEmitter.prefixed = prefix; - -// -// Expose the module. -// -if ('undefined' !== typeof module) { - module.exports = EventEmitter; -} - -},{}],3:[function(require,module,exports){ -/** - * Bit twiddling hacks for JavaScript. - * - * Author: Mikola Lysenko - * - * Ported from Stanford bit twiddling hack library: - * http://graphics.stanford.edu/~seander/bithacks.html - */ - -"use strict"; "use restrict"; - -//Number of bits in an integer -var INT_BITS = 32; - -//Constants -exports.INT_BITS = INT_BITS; -exports.INT_MAX = 0x7fffffff; -exports.INT_MIN = -1<<(INT_BITS-1); - -//Returns -1, 0, +1 depending on sign of x -exports.sign = function(v) { - return (v > 0) - (v < 0); -} - -//Computes absolute value of integer -exports.abs = function(v) { - var mask = v >> (INT_BITS-1); - return (v ^ mask) - mask; -} - -//Computes minimum of integers x and y -exports.min = function(x, y) { - return y ^ ((x ^ y) & -(x < y)); -} - -//Computes maximum of integers x and y -exports.max = function(x, y) { - return x ^ ((x ^ y) & -(x < y)); -} - -//Checks if a number is a power of two -exports.isPow2 = function(v) { - return !(v & (v-1)) && (!!v); -} - -//Computes log base 2 of v -exports.log2 = function(v) { - var r, shift; - r = (v > 0xFFFF) << 4; v >>>= r; - shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; - return r | (v >> 1); -} - -//Computes log base 10 of v -exports.log10 = function(v) { - return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : - (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : - (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; -} - -//Counts number of bits -exports.popCount = function(v) { - v = v - ((v >>> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); - return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; -} - -//Counts number of trailing zeros -function countTrailingZeros(v) { - var c = 32; - v &= -v; - if (v) c--; - if (v & 0x0000FFFF) c -= 16; - if (v & 0x00FF00FF) c -= 8; - if (v & 0x0F0F0F0F) c -= 4; - if (v & 0x33333333) c -= 2; - if (v & 0x55555555) c -= 1; - return c; -} -exports.countTrailingZeros = countTrailingZeros; - -//Rounds to next power of 2 -exports.nextPow2 = function(v) { - v += v === 0; - --v; - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v + 1; -} - -//Rounds down to previous power of 2 -exports.prevPow2 = function(v) { - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v - (v>>>1); -} - -//Computes parity of word -exports.parity = function(v) { - v ^= v >>> 16; - v ^= v >>> 8; - v ^= v >>> 4; - v &= 0xf; - return (0x6996 >>> v) & 1; -} - -var REVERSE_TABLE = new Array(256); - -(function(tab) { - for(var i=0; i<256; ++i) { - var v = i, r = i, s = 7; - for (v >>>= 1; v; v >>>= 1) { - r <<= 1; - r |= v & 1; - --s; - } - tab[i] = (r << s) & 0xff; - } -})(REVERSE_TABLE); - -//Reverse bits in a 32 bit word -exports.reverse = function(v) { - return (REVERSE_TABLE[ v & 0xff] << 24) | - (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | - (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | - REVERSE_TABLE[(v >>> 24) & 0xff]; -} - -//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes -exports.interleave2 = function(x, y) { - x &= 0xFFFF; - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y &= 0xFFFF; - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -//Extracts the nth interleaved component -exports.deinterleave2 = function(v, n) { - v = (v >>> n) & 0x55555555; - v = (v | (v >>> 1)) & 0x33333333; - v = (v | (v >>> 2)) & 0x0F0F0F0F; - v = (v | (v >>> 4)) & 0x00FF00FF; - v = (v | (v >>> 16)) & 0x000FFFF; - return (v << 16) >> 16; -} - - -//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes -exports.interleave3 = function(x, y, z) { - x &= 0x3FF; - x = (x | (x<<16)) & 4278190335; - x = (x | (x<<8)) & 251719695; - x = (x | (x<<4)) & 3272356035; - x = (x | (x<<2)) & 1227133513; - - y &= 0x3FF; - y = (y | (y<<16)) & 4278190335; - y = (y | (y<<8)) & 251719695; - y = (y | (y<<4)) & 3272356035; - y = (y | (y<<2)) & 1227133513; - x |= (y << 1); - - z &= 0x3FF; - z = (z | (z<<16)) & 4278190335; - z = (z | (z<<8)) & 251719695; - z = (z | (z<<4)) & 3272356035; - z = (z | (z<<2)) & 1227133513; - - return x | (z << 2); -} - -//Extracts nth interleaved component of a 3-tuple -exports.deinterleave3 = function(v, n) { - v = (v >>> n) & 1227133513; - v = (v | (v>>>2)) & 3272356035; - v = (v | (v>>>4)) & 251719695; - v = (v | (v>>>8)) & 4278190335; - v = (v | (v>>>16)) & 0x3FF; - return (v<<22)>>22; -} - -//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) -exports.nextCombination = function(v) { - var t = v | (v - 1); - return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); -} - - -},{}],4:[function(require,module,exports){ -(function (process){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// resolves . and .. elements in a path array with directory names there -// must be no slashes, empty elements, or device names (c:\) in the array -// (so also no leading and trailing slashes - it does not distinguish -// relative and absolute paths) -function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; -} - -// Split a filename into [root, dir, basename, ext], unix version -// 'root' is just a slash, or nothing. -var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; -var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); -}; - -// path.resolve([from ...], to) -// posix version -exports.resolve = function() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : process.cwd(); - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; -}; - -// path.normalize(path) -// posix version -exports.normalize = function(path) { - var isAbsolute = exports.isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isAbsolute).join('/'); - - if (!path && !isAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isAbsolute ? '/' : '') + path; -}; - -// posix version -exports.isAbsolute = function(path) { - return path.charAt(0) === '/'; -}; - -// posix version -exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); -}; - - -// path.relative(from, to) -// posix version -exports.relative = function(from, to) { - from = exports.resolve(from).substr(1); - to = exports.resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); -}; - -exports.sep = '/'; -exports.delimiter = ':'; - -exports.dirname = function(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; -}; - - -exports.basename = function(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; -}; - - -exports.extname = function(path) { - return splitPath(path)[3]; -}; - -function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; -} - -// String.prototype.substr - negative index don't work in IE8 -var substr = 'ab'.substr(-1) === 'b' - ? function (str, start, len) { return str.substr(start, len) } - : function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } -; - -}).call(this,require('_process')) -},{"_process":5}],5:[function(require,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = setTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - clearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - setTimeout(drainQueue, 0); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],6:[function(require,module,exports){ -(function (global){ -/*! https://mths.be/punycode v1.3.2 by @mathias */ -;(function(root) { - - /** Detect free variables */ - var freeExports = typeof exports == 'object' && exports && - !exports.nodeType && exports; - var freeModule = typeof module == 'object' && module && - !module.nodeType && module; - var freeGlobal = typeof global == 'object' && global; - if ( - freeGlobal.global === freeGlobal || - freeGlobal.window === freeGlobal || - freeGlobal.self === freeGlobal - ) { - root = freeGlobal; - } - - /** - * The `punycode` object. - * @name punycode - * @type Object - */ - var punycode, - - /** Highest positive signed 32-bit float value */ - maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 - - /** Bootstring parameters */ - base = 36, - tMin = 1, - tMax = 26, - skew = 38, - damp = 700, - initialBias = 72, - initialN = 128, // 0x80 - delimiter = '-', // '\x2D' - - /** Regular expressions */ - regexPunycode = /^xn--/, - regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars - regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators - - /** Error messages */ - errors = { - 'overflow': 'Overflow: input needs wider integers to process', - 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', - 'invalid-input': 'Invalid input' - }, - - /** Convenience shortcuts */ - baseMinusTMin = base - tMin, - floor = Math.floor, - stringFromCharCode = String.fromCharCode, - - /** Temporary variable */ - key; - - /*--------------------------------------------------------------------------*/ - - /** - * A generic error utility function. - * @private - * @param {String} type The error type. - * @returns {Error} Throws a `RangeError` with the applicable error message. - */ - function error(type) { - throw RangeError(errors[type]); - } - - /** - * A generic `Array#map` utility function. - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function that gets called for every array - * item. - * @returns {Array} A new array of values returned by the callback function. - */ - function map(array, fn) { - var length = array.length; - var result = []; - while (length--) { - result[length] = fn(array[length]); - } - return result; - } - - /** - * A simple `Array#map`-like wrapper to work with domain name strings or email - * addresses. - * @private - * @param {String} domain The domain name or email address. - * @param {Function} callback The function that gets called for every - * character. - * @returns {Array} A new string of characters returned by the callback - * function. - */ - function mapDomain(string, fn) { - var parts = string.split('@'); - var result = ''; - if (parts.length > 1) { - // In email addresses, only the domain name should be punycoded. Leave - // the local part (i.e. everything up to `@`) intact. - result = parts[0] + '@'; - string = parts[1]; - } - // Avoid `split(regex)` for IE8 compatibility. See #17. - string = string.replace(regexSeparators, '\x2E'); - var labels = string.split('.'); - var encoded = map(labels, fn).join('.'); - return result + encoded; - } - - /** - * Creates an array containing the numeric code points of each Unicode - * character in the string. While JavaScript uses UCS-2 internally, - * this function will convert a pair of surrogate halves (each of which - * UCS-2 exposes as separate characters) into a single code point, - * matching UTF-16. - * @see `punycode.ucs2.encode` - * @see - * @memberOf punycode.ucs2 - * @name decode - * @param {String} string The Unicode input string (UCS-2). - * @returns {Array} The new array of code points. - */ - function ucs2decode(string) { - var output = [], - counter = 0, - length = string.length, - value, - extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - /** - * Creates a string based on an array of numeric code points. - * @see `punycode.ucs2.decode` - * @memberOf punycode.ucs2 - * @name encode - * @param {Array} codePoints The array of numeric code points. - * @returns {String} The new Unicode string (UCS-2). - */ - function ucs2encode(array) { - return map(array, function(value) { - var output = ''; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - return output; - }).join(''); - } - - /** - * Converts a basic code point into a digit/integer. - * @see `digitToBasic()` - * @private - * @param {Number} codePoint The basic numeric code point value. - * @returns {Number} The numeric value of a basic code point (for use in - * representing integers) in the range `0` to `base - 1`, or `base` if - * the code point does not represent a value. - */ - function basicToDigit(codePoint) { - if (codePoint - 48 < 10) { - return codePoint - 22; - } - if (codePoint - 65 < 26) { - return codePoint - 65; - } - if (codePoint - 97 < 26) { - return codePoint - 97; - } - return base; - } - - /** - * Converts a digit/integer into a basic code point. - * @see `basicToDigit()` - * @private - * @param {Number} digit The numeric value of a basic code point. - * @returns {Number} The basic code point whose value (when used for - * representing integers) is `digit`, which needs to be in the range - * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is - * used; else, the lowercase form is used. The behavior is undefined - * if `flag` is non-zero and `digit` has no uppercase form. - */ - function digitToBasic(digit, flag) { - // 0..25 map to ASCII a..z or A..Z - // 26..35 map to ASCII 0..9 - return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); - } - - /** - * Bias adaptation function as per section 3.4 of RFC 3492. - * http://tools.ietf.org/html/rfc3492#section-3.4 - * @private - */ - function adapt(delta, numPoints, firstTime) { - var k = 0; - delta = firstTime ? floor(delta / damp) : delta >> 1; - delta += floor(delta / numPoints); - for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { - delta = floor(delta / baseMinusTMin); - } - return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); - } - - /** - * Converts a Punycode string of ASCII-only symbols to a string of Unicode - * symbols. - * @memberOf punycode - * @param {String} input The Punycode string of ASCII-only symbols. - * @returns {String} The resulting string of Unicode symbols. - */ - function decode(input) { - // Don't use UCS-2 - var output = [], - inputLength = input.length, - out, - i = 0, - n = initialN, - bias = initialBias, - basic, - j, - index, - oldi, - w, - k, - digit, - t, - /** Cached calculation results */ - baseMinusT; - - // Handle the basic code points: let `basic` be the number of input code - // points before the last delimiter, or `0` if there is none, then copy - // the first basic code points to the output. - - basic = input.lastIndexOf(delimiter); - if (basic < 0) { - basic = 0; - } - - for (j = 0; j < basic; ++j) { - // if it's not a basic code point - if (input.charCodeAt(j) >= 0x80) { - error('not-basic'); - } - output.push(input.charCodeAt(j)); - } - - // Main decoding loop: start just after the last delimiter if any basic code - // points were copied; start at the beginning otherwise. - - for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { - - // `index` is the index of the next character to be consumed. - // Decode a generalized variable-length integer into `delta`, - // which gets added to `i`. The overflow checking is easier - // if we increase `i` as we go, then subtract off its starting - // value at the end to obtain `delta`. - for (oldi = i, w = 1, k = base; /* no condition */; k += base) { - - if (index >= inputLength) { - error('invalid-input'); - } - - digit = basicToDigit(input.charCodeAt(index++)); - - if (digit >= base || digit > floor((maxInt - i) / w)) { - error('overflow'); - } - - i += digit * w; - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - - if (digit < t) { - break; - } - - baseMinusT = base - t; - if (w > floor(maxInt / baseMinusT)) { - error('overflow'); - } - - w *= baseMinusT; - - } - - out = output.length + 1; - bias = adapt(i - oldi, out, oldi == 0); - - // `i` was supposed to wrap around from `out` to `0`, - // incrementing `n` each time, so we'll fix that now: - if (floor(i / out) > maxInt - n) { - error('overflow'); - } - - n += floor(i / out); - i %= out; - - // Insert `n` at position `i` of the output - output.splice(i++, 0, n); - - } - - return ucs2encode(output); - } - - /** - * Converts a string of Unicode symbols (e.g. a domain name label) to a - * Punycode string of ASCII-only symbols. - * @memberOf punycode - * @param {String} input The string of Unicode symbols. - * @returns {String} The resulting Punycode string of ASCII-only symbols. - */ - function encode(input) { - var n, - delta, - handledCPCount, - basicLength, - bias, - j, - m, - q, - k, - t, - currentValue, - output = [], - /** `inputLength` will hold the number of code points in `input`. */ - inputLength, - /** Cached calculation results */ - handledCPCountPlusOne, - baseMinusT, - qMinusT; - - // Convert the input in UCS-2 to Unicode - input = ucs2decode(input); - - // Cache the length - inputLength = input.length; - - // Initialize the state - n = initialN; - delta = 0; - bias = initialBias; - - // Handle the basic code points - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue < 0x80) { - output.push(stringFromCharCode(currentValue)); - } - } - - handledCPCount = basicLength = output.length; - - // `handledCPCount` is the number of code points that have been handled; - // `basicLength` is the number of basic code points. - - // Finish the basic string - if it is not empty - with a delimiter - if (basicLength) { - output.push(delimiter); - } - - // Main encoding loop: - while (handledCPCount < inputLength) { - - // All non-basic code points < n have been handled already. Find the next - // larger one: - for (m = maxInt, j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue >= n && currentValue < m) { - m = currentValue; - } - } - - // Increase `delta` enough to advance the decoder's state to , - // but guard against overflow - handledCPCountPlusOne = handledCPCount + 1; - if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { - error('overflow'); - } - - delta += (m - n) * handledCPCountPlusOne; - n = m; - - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - - if (currentValue < n && ++delta > maxInt) { - error('overflow'); - } - - if (currentValue == n) { - // Represent delta as a generalized variable-length integer - for (q = delta, k = base; /* no condition */; k += base) { - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - if (q < t) { - break; - } - qMinusT = q - t; - baseMinusT = base - t; - output.push( - stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) - ); - q = floor(qMinusT / baseMinusT); - } - - output.push(stringFromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); - delta = 0; - ++handledCPCount; - } - } - - ++delta; - ++n; - - } - return output.join(''); - } - - /** - * Converts a Punycode string representing a domain name or an email address - * to Unicode. Only the Punycoded parts of the input will be converted, i.e. - * it doesn't matter if you call it on a string that has already been - * converted to Unicode. - * @memberOf punycode - * @param {String} input The Punycoded domain name or email address to - * convert to Unicode. - * @returns {String} The Unicode representation of the given Punycode - * string. - */ - function toUnicode(input) { - return mapDomain(input, function(string) { - return regexPunycode.test(string) - ? decode(string.slice(4).toLowerCase()) - : string; - }); - } - - /** - * Converts a Unicode string representing a domain name or an email address to - * Punycode. Only the non-ASCII parts of the domain name will be converted, - * i.e. it doesn't matter if you call it with a domain that's already in - * ASCII. - * @memberOf punycode - * @param {String} input The domain name or email address to convert, as a - * Unicode string. - * @returns {String} The Punycode representation of the given domain name or - * email address. - */ - function toASCII(input) { - return mapDomain(input, function(string) { - return regexNonASCII.test(string) - ? 'xn--' + encode(string) - : string; - }); - } - - /*--------------------------------------------------------------------------*/ - - /** Define the public API */ - punycode = { - /** - * A string representing the current Punycode.js version number. - * @memberOf punycode - * @type String - */ - 'version': '1.3.2', - /** - * An object of methods to convert from JavaScript's internal character - * representation (UCS-2) to Unicode code points, and back. - * @see - * @memberOf punycode - * @type Object - */ - 'ucs2': { - 'decode': ucs2decode, - 'encode': ucs2encode - }, - 'decode': decode, - 'encode': encode, - 'toASCII': toASCII, - 'toUnicode': toUnicode - }; - - /** Expose `punycode` */ - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - typeof define == 'function' && - typeof define.amd == 'object' && - define.amd - ) { - define('punycode', function() { - return punycode; - }); - } else if (freeExports && freeModule) { - if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+ - freeModule.exports = punycode; - } else { // in Narwhal or RingoJS v0.7.0- - for (key in punycode) { - punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); - } - } - } else { // in Rhino or a web browser - root.punycode = punycode; - } - -}(this)); - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],7:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; - -// If obj.hasOwnProperty has been overridden, then calling -// obj.hasOwnProperty(prop) will break. -// See: https://github.com/joyent/node/issues/1707 -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -module.exports = function(qs, sep, eq, options) { - sep = sep || '&'; - eq = eq || '='; - var obj = {}; - - if (typeof qs !== 'string' || qs.length === 0) { - return obj; - } - - var regexp = /\+/g; - qs = qs.split(sep); - - var maxKeys = 1000; - if (options && typeof options.maxKeys === 'number') { - maxKeys = options.maxKeys; - } - - var len = qs.length; - // maxKeys <= 0 means that we should not limit keys count - if (maxKeys > 0 && len > maxKeys) { - len = maxKeys; - } - - for (var i = 0; i < len; ++i) { - var x = qs[i].replace(regexp, '%20'), - idx = x.indexOf(eq), - kstr, vstr, k, v; - - if (idx >= 0) { - kstr = x.substr(0, idx); - vstr = x.substr(idx + 1); - } else { - kstr = x; - vstr = ''; - } - - k = decodeURIComponent(kstr); - v = decodeURIComponent(vstr); - - if (!hasOwnProperty(obj, k)) { - obj[k] = v; - } else if (isArray(obj[k])) { - obj[k].push(v); - } else { - obj[k] = [obj[k], v]; - } - } - - return obj; -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -},{}],8:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; - -var stringifyPrimitive = function(v) { - switch (typeof v) { - case 'string': - return v; - - case 'boolean': - return v ? 'true' : 'false'; - - case 'number': - return isFinite(v) ? v : ''; - - default: - return ''; - } -}; - -module.exports = function(obj, sep, eq, name) { - sep = sep || '&'; - eq = eq || '='; - if (obj === null) { - obj = undefined; - } - - if (typeof obj === 'object') { - return map(objectKeys(obj), function(k) { - var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; - if (isArray(obj[k])) { - return map(obj[k], function(v) { - return ks + encodeURIComponent(stringifyPrimitive(v)); - }).join(sep); - } else { - return ks + encodeURIComponent(stringifyPrimitive(obj[k])); - } - }).join(sep); - - } - - if (!name) return ''; - return encodeURIComponent(stringifyPrimitive(name)) + eq + - encodeURIComponent(stringifyPrimitive(obj)); -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -function map (xs, f) { - if (xs.map) return xs.map(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - res.push(f(xs[i], i)); - } - return res; -} - -var objectKeys = Object.keys || function (obj) { - var res = []; - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); - } - return res; -}; - -},{}],9:[function(require,module,exports){ -'use strict'; - -exports.decode = exports.parse = require('./decode'); -exports.encode = exports.stringify = require('./encode'); - -},{"./decode":7,"./encode":8}],10:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var punycode = require('punycode'); - -exports.parse = urlParse; -exports.resolve = urlResolve; -exports.resolveObject = urlResolveObject; -exports.format = urlFormat; - -exports.Url = Url; - -function Url() { - this.protocol = null; - this.slashes = null; - this.auth = null; - this.host = null; - this.port = null; - this.hostname = null; - this.hash = null; - this.search = null; - this.query = null; - this.pathname = null; - this.path = null; - this.href = null; -} - -// Reference: RFC 3986, RFC 1808, RFC 2396 - -// define these here so at least they only have to be -// compiled once on the first module load. -var protocolPattern = /^([a-z0-9.+-]+:)/i, - portPattern = /:[0-9]*$/, - - // RFC 2396: characters reserved for delimiting URLs. - // We actually just auto-escape these. - delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], - - // RFC 2396: characters not allowed for various reasons. - unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), - - // Allowed by RFCs, but cause of XSS attacks. Always escape these. - autoEscape = ['\''].concat(unwise), - // Characters that are never ever allowed in a hostname. - // Note that any invalid chars are also handled, but these - // are the ones that are *expected* to be seen, so we fast-path - // them. - nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), - hostEndingChars = ['/', '?', '#'], - hostnameMaxLen = 255, - hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, - hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, - // protocols that can allow "unsafe" and "unwise" chars. - unsafeProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that never have a hostname. - hostlessProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that always contain a // bit. - slashedProtocol = { - 'http': true, - 'https': true, - 'ftp': true, - 'gopher': true, - 'file': true, - 'http:': true, - 'https:': true, - 'ftp:': true, - 'gopher:': true, - 'file:': true - }, - querystring = require('querystring'); - -function urlParse(url, parseQueryString, slashesDenoteHost) { - if (url && isObject(url) && url instanceof Url) return url; - - var u = new Url; - u.parse(url, parseQueryString, slashesDenoteHost); - return u; -} - -Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { - if (!isString(url)) { - throw new TypeError("Parameter 'url' must be a string, not " + typeof url); - } - - var rest = url; - - // trim before proceeding. - // This is to support parse stuff like " http://foo.com \n" - rest = rest.trim(); - - var proto = protocolPattern.exec(rest); - if (proto) { - proto = proto[0]; - var lowerProto = proto.toLowerCase(); - this.protocol = lowerProto; - rest = rest.substr(proto.length); - } - - // figure out if it's got a host - // user@server is *always* interpreted as a hostname, and url - // resolution will treat //foo/bar as host=foo,path=bar because that's - // how the browser resolves relative URLs. - if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { - var slashes = rest.substr(0, 2) === '//'; - if (slashes && !(proto && hostlessProtocol[proto])) { - rest = rest.substr(2); - this.slashes = true; - } - } - - if (!hostlessProtocol[proto] && - (slashes || (proto && !slashedProtocol[proto]))) { - - // there's a hostname. - // the first instance of /, ?, ;, or # ends the host. - // - // If there is an @ in the hostname, then non-host chars *are* allowed - // to the left of the last @ sign, unless some host-ending character - // comes *before* the @-sign. - // URLs are obnoxious. - // - // ex: - // http://a@b@c/ => user:a@b host:c - // http://a@b?@c => user:a host:c path:/?@c - - // v0.12 TODO(isaacs): This is not quite how Chrome does things. - // Review our test case against browsers more comprehensively. - - // find the first instance of any hostEndingChars - var hostEnd = -1; - for (var i = 0; i < hostEndingChars.length; i++) { - var hec = rest.indexOf(hostEndingChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - - // at this point, either we have an explicit point where the - // auth portion cannot go past, or the last @ char is the decider. - var auth, atSign; - if (hostEnd === -1) { - // atSign can be anywhere. - atSign = rest.lastIndexOf('@'); - } else { - // atSign must be in auth portion. - // http://a@b/c@d => host:b auth:a path:/c@d - atSign = rest.lastIndexOf('@', hostEnd); - } - - // Now we have a portion which is definitely the auth. - // Pull that off. - if (atSign !== -1) { - auth = rest.slice(0, atSign); - rest = rest.slice(atSign + 1); - this.auth = decodeURIComponent(auth); - } - - // the host is the remaining to the left of the first non-host char - hostEnd = -1; - for (var i = 0; i < nonHostChars.length; i++) { - var hec = rest.indexOf(nonHostChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - // if we still have not hit it, then the entire thing is a host. - if (hostEnd === -1) - hostEnd = rest.length; - - this.host = rest.slice(0, hostEnd); - rest = rest.slice(hostEnd); - - // pull out port. - this.parseHost(); - - // we've indicated that there is a hostname, - // so even if it's empty, it has to be present. - this.hostname = this.hostname || ''; - - // if hostname begins with [ and ends with ] - // assume that it's an IPv6 address. - var ipv6Hostname = this.hostname[0] === '[' && - this.hostname[this.hostname.length - 1] === ']'; - - // validate a little. - if (!ipv6Hostname) { - var hostparts = this.hostname.split(/\./); - for (var i = 0, l = hostparts.length; i < l; i++) { - var part = hostparts[i]; - if (!part) continue; - if (!part.match(hostnamePartPattern)) { - var newpart = ''; - for (var j = 0, k = part.length; j < k; j++) { - if (part.charCodeAt(j) > 127) { - // we replace non-ASCII char with a temporary placeholder - // we need this to make sure size of hostname is not - // broken by replacing non-ASCII by nothing - newpart += 'x'; - } else { - newpart += part[j]; - } - } - // we test again with ASCII char only - if (!newpart.match(hostnamePartPattern)) { - var validParts = hostparts.slice(0, i); - var notHost = hostparts.slice(i + 1); - var bit = part.match(hostnamePartStart); - if (bit) { - validParts.push(bit[1]); - notHost.unshift(bit[2]); - } - if (notHost.length) { - rest = '/' + notHost.join('.') + rest; - } - this.hostname = validParts.join('.'); - break; - } - } - } - } - - if (this.hostname.length > hostnameMaxLen) { - this.hostname = ''; - } else { - // hostnames are always lower case. - this.hostname = this.hostname.toLowerCase(); - } - - if (!ipv6Hostname) { - // IDNA Support: Returns a puny coded representation of "domain". - // It only converts the part of the domain name that - // has non ASCII characters. I.e. it dosent matter if - // you call it with a domain that already is in ASCII. - var domainArray = this.hostname.split('.'); - var newOut = []; - for (var i = 0; i < domainArray.length; ++i) { - var s = domainArray[i]; - newOut.push(s.match(/[^A-Za-z0-9_-]/) ? - 'xn--' + punycode.encode(s) : s); - } - this.hostname = newOut.join('.'); - } - - var p = this.port ? ':' + this.port : ''; - var h = this.hostname || ''; - this.host = h + p; - this.href += this.host; - - // strip [ and ] from the hostname - // the host field still retains them, though - if (ipv6Hostname) { - this.hostname = this.hostname.substr(1, this.hostname.length - 2); - if (rest[0] !== '/') { - rest = '/' + rest; - } - } - } - - // now rest is set to the post-host stuff. - // chop off any delim chars. - if (!unsafeProtocol[lowerProto]) { - - // First, make 100% sure that any "autoEscape" chars get - // escaped, even if encodeURIComponent doesn't think they - // need to be. - for (var i = 0, l = autoEscape.length; i < l; i++) { - var ae = autoEscape[i]; - var esc = encodeURIComponent(ae); - if (esc === ae) { - esc = escape(ae); - } - rest = rest.split(ae).join(esc); - } - } - - - // chop off from the tail first. - var hash = rest.indexOf('#'); - if (hash !== -1) { - // got a fragment string. - this.hash = rest.substr(hash); - rest = rest.slice(0, hash); - } - var qm = rest.indexOf('?'); - if (qm !== -1) { - this.search = rest.substr(qm); - this.query = rest.substr(qm + 1); - if (parseQueryString) { - this.query = querystring.parse(this.query); - } - rest = rest.slice(0, qm); - } else if (parseQueryString) { - // no query string, but parseQueryString still requested - this.search = ''; - this.query = {}; - } - if (rest) this.pathname = rest; - if (slashedProtocol[lowerProto] && - this.hostname && !this.pathname) { - this.pathname = '/'; - } - - //to support http.request - if (this.pathname || this.search) { - var p = this.pathname || ''; - var s = this.search || ''; - this.path = p + s; - } - - // finally, reconstruct the href based on what has been validated. - this.href = this.format(); - return this; -}; - -// format a parsed object into a url string -function urlFormat(obj) { - // ensure it's an object, and not a string url. - // If it's an obj, this is a no-op. - // this way, you can call url_format() on strings - // to clean up potentially wonky urls. - if (isString(obj)) obj = urlParse(obj); - if (!(obj instanceof Url)) return Url.prototype.format.call(obj); - return obj.format(); -} - -Url.prototype.format = function() { - var auth = this.auth || ''; - if (auth) { - auth = encodeURIComponent(auth); - auth = auth.replace(/%3A/i, ':'); - auth += '@'; - } - - var protocol = this.protocol || '', - pathname = this.pathname || '', - hash = this.hash || '', - host = false, - query = ''; - - if (this.host) { - host = auth + this.host; - } else if (this.hostname) { - host = auth + (this.hostname.indexOf(':') === -1 ? - this.hostname : - '[' + this.hostname + ']'); - if (this.port) { - host += ':' + this.port; - } - } - - if (this.query && - isObject(this.query) && - Object.keys(this.query).length) { - query = querystring.stringify(this.query); - } - - var search = this.search || (query && ('?' + query)) || ''; - - if (protocol && protocol.substr(-1) !== ':') protocol += ':'; - - // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. - // unless they had them to begin with. - if (this.slashes || - (!protocol || slashedProtocol[protocol]) && host !== false) { - host = '//' + (host || ''); - if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; - } else if (!host) { - host = ''; - } - - if (hash && hash.charAt(0) !== '#') hash = '#' + hash; - if (search && search.charAt(0) !== '?') search = '?' + search; - - pathname = pathname.replace(/[?#]/g, function(match) { - return encodeURIComponent(match); - }); - search = search.replace('#', '%23'); - - return protocol + host + pathname + search + hash; -}; - -function urlResolve(source, relative) { - return urlParse(source, false, true).resolve(relative); -} - -Url.prototype.resolve = function(relative) { - return this.resolveObject(urlParse(relative, false, true)).format(); -}; - -function urlResolveObject(source, relative) { - if (!source) return relative; - return urlParse(source, false, true).resolveObject(relative); -} - -Url.prototype.resolveObject = function(relative) { - if (isString(relative)) { - var rel = new Url(); - rel.parse(relative, false, true); - relative = rel; - } - - var result = new Url(); - Object.keys(this).forEach(function(k) { - result[k] = this[k]; - }, this); - - // hash is always overridden, no matter what. - // even href="" will remove it. - result.hash = relative.hash; - - // if the relative url is empty, then there's nothing left to do here. - if (relative.href === '') { - result.href = result.format(); - return result; - } - - // hrefs like //foo/bar always cut to the protocol. - if (relative.slashes && !relative.protocol) { - // take everything except the protocol from relative - Object.keys(relative).forEach(function(k) { - if (k !== 'protocol') - result[k] = relative[k]; - }); - - //urlParse appends trailing / to urls like http://www.example.com - if (slashedProtocol[result.protocol] && - result.hostname && !result.pathname) { - result.path = result.pathname = '/'; - } - - result.href = result.format(); - return result; - } - - if (relative.protocol && relative.protocol !== result.protocol) { - // if it's a known url protocol, then changing - // the protocol does weird things - // first, if it's not file:, then we MUST have a host, - // and if there was a path - // to begin with, then we MUST have a path. - // if it is file:, then the host is dropped, - // because that's known to be hostless. - // anything else is assumed to be absolute. - if (!slashedProtocol[relative.protocol]) { - Object.keys(relative).forEach(function(k) { - result[k] = relative[k]; - }); - result.href = result.format(); - return result; - } - - result.protocol = relative.protocol; - if (!relative.host && !hostlessProtocol[relative.protocol]) { - var relPath = (relative.pathname || '').split('/'); - while (relPath.length && !(relative.host = relPath.shift())); - if (!relative.host) relative.host = ''; - if (!relative.hostname) relative.hostname = ''; - if (relPath[0] !== '') relPath.unshift(''); - if (relPath.length < 2) relPath.unshift(''); - result.pathname = relPath.join('/'); - } else { - result.pathname = relative.pathname; - } - result.search = relative.search; - result.query = relative.query; - result.host = relative.host || ''; - result.auth = relative.auth; - result.hostname = relative.hostname || relative.host; - result.port = relative.port; - // to support http.request - if (result.pathname || result.search) { - var p = result.pathname || ''; - var s = result.search || ''; - result.path = p + s; - } - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; - } - - var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), - isRelAbs = ( - relative.host || - relative.pathname && relative.pathname.charAt(0) === '/' - ), - mustEndAbs = (isRelAbs || isSourceAbs || - (result.host && relative.pathname)), - removeAllDots = mustEndAbs, - srcPath = result.pathname && result.pathname.split('/') || [], - relPath = relative.pathname && relative.pathname.split('/') || [], - psychotic = result.protocol && !slashedProtocol[result.protocol]; - - // if the url is a non-slashed url, then relative - // links like ../.. should be able - // to crawl up to the hostname, as well. This is strange. - // result.protocol has already been set by now. - // Later on, put the first path part into the host field. - if (psychotic) { - result.hostname = ''; - result.port = null; - if (result.host) { - if (srcPath[0] === '') srcPath[0] = result.host; - else srcPath.unshift(result.host); - } - result.host = ''; - if (relative.protocol) { - relative.hostname = null; - relative.port = null; - if (relative.host) { - if (relPath[0] === '') relPath[0] = relative.host; - else relPath.unshift(relative.host); - } - relative.host = null; - } - mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); - } - - if (isRelAbs) { - // it's absolute. - result.host = (relative.host || relative.host === '') ? - relative.host : result.host; - result.hostname = (relative.hostname || relative.hostname === '') ? - relative.hostname : result.hostname; - result.search = relative.search; - result.query = relative.query; - srcPath = relPath; - // fall through to the dot-handling below. - } else if (relPath.length) { - // it's relative - // throw away the existing file, and take the new path instead. - if (!srcPath) srcPath = []; - srcPath.pop(); - srcPath = srcPath.concat(relPath); - result.search = relative.search; - result.query = relative.query; - } else if (!isNullOrUndefined(relative.search)) { - // just pull out the search. - // like href='?foo'. - // Put this after the other two cases because it simplifies the booleans - if (psychotic) { - result.hostname = result.host = srcPath.shift(); - //occationaly the auth can get stuck only in host - //this especialy happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - result.search = relative.search; - result.query = relative.query; - //to support http.request - if (!isNull(result.pathname) || !isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.href = result.format(); - return result; - } - - if (!srcPath.length) { - // no path at all. easy. - // we've already handled the other stuff above. - result.pathname = null; - //to support http.request - if (result.search) { - result.path = '/' + result.search; - } else { - result.path = null; - } - result.href = result.format(); - return result; - } - - // if a url ENDs in . or .., then it must get a trailing slash. - // however, if it ends in anything else non-slashy, - // then it must NOT get a trailing slash. - var last = srcPath.slice(-1)[0]; - var hasTrailingSlash = ( - (result.host || relative.host) && (last === '.' || last === '..') || - last === ''); - - // strip single dots, resolve double dots to parent dir - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = srcPath.length; i >= 0; i--) { - last = srcPath[i]; - if (last == '.') { - srcPath.splice(i, 1); - } else if (last === '..') { - srcPath.splice(i, 1); - up++; - } else if (up) { - srcPath.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (!mustEndAbs && !removeAllDots) { - for (; up--; up) { - srcPath.unshift('..'); - } - } - - if (mustEndAbs && srcPath[0] !== '' && - (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { - srcPath.unshift(''); - } - - if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { - srcPath.push(''); - } - - var isAbsolute = srcPath[0] === '' || - (srcPath[0] && srcPath[0].charAt(0) === '/'); - - // put the host back - if (psychotic) { - result.hostname = result.host = isAbsolute ? '' : - srcPath.length ? srcPath.shift() : ''; - //occationaly the auth can get stuck only in host - //this especialy happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - - mustEndAbs = mustEndAbs || (result.host && srcPath.length); - - if (mustEndAbs && !isAbsolute) { - srcPath.unshift(''); - } - - if (!srcPath.length) { - result.pathname = null; - result.path = null; - } else { - result.pathname = srcPath.join('/'); - } - - //to support request.http - if (!isNull(result.pathname) || !isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.auth = relative.auth || result.auth; - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; -}; - -Url.prototype.parseHost = function() { - var host = this.host; - var port = portPattern.exec(host); - if (port) { - port = port[0]; - if (port !== ':') { - this.port = port.substr(1); - } - host = host.substr(0, host.length - port.length); - } - if (host) this.hostname = host; -}; - -function isString(arg) { - return typeof arg === "string"; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isNull(arg) { - return arg === null; -} -function isNullOrUndefined(arg) { - return arg == null; -} - -},{"punycode":6,"querystring":9}],11:[function(require,module,exports){ -'use strict'; - -module.exports = earcut; - -function earcut(data, holeIndices, dim) { - - dim = dim || 2; - - var hasHoles = holeIndices && holeIndices.length, - outerLen = hasHoles ? holeIndices[0] * dim : data.length, - outerNode = linkedList(data, 0, outerLen, dim, true), - triangles = []; - - if (!outerNode) return triangles; - - var minX, minY, maxX, maxY, x, y, size; - - if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); - - // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox - if (data.length > 80 * dim) { - minX = maxX = data[0]; - minY = maxY = data[1]; - - for (var i = dim; i < outerLen; i += dim) { - x = data[i]; - y = data[i + 1]; - if (x < minX) minX = x; - if (y < minY) minY = y; - if (x > maxX) maxX = x; - if (y > maxY) maxY = y; - } - - // minX, minY and size are later used to transform coords into integers for z-order calculation - size = Math.max(maxX - minX, maxY - minY); - } - - earcutLinked(outerNode, triangles, dim, minX, minY, size); - - return triangles; -} - -// create a circular doubly linked list from polygon points in the specified winding order -function linkedList(data, start, end, dim, clockwise) { - var sum = 0, - i, j, last; - - // calculate original winding order of a polygon ring - for (i = start, j = end - dim; i < end; i += dim) { - sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); - j = i; - } - - // link points into circular doubly-linked list in the specified winding order - if (clockwise === (sum > 0)) { - for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); - } else { - for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); - } - - return last; -} - -// eliminate colinear or duplicate points -function filterPoints(start, end) { - if (!start) return start; - if (!end) end = start; - - var p = start, - again; - do { - again = false; - - if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { - removeNode(p); - p = end = p.prev; - if (p === p.next) return null; - again = true; - - } else { - p = p.next; - } - } while (again || p !== end); - - return end; -} - -// main ear slicing loop which triangulates a polygon (given as a linked list) -function earcutLinked(ear, triangles, dim, minX, minY, size, pass) { - if (!ear) return; - - // interlink polygon nodes in z-order - if (!pass && size) indexCurve(ear, minX, minY, size); - - var stop = ear, - prev, next; - - // iterate through ears, slicing them one by one - while (ear.prev !== ear.next) { - prev = ear.prev; - next = ear.next; - - if (size ? isEarHashed(ear, minX, minY, size) : isEar(ear)) { - // cut off the triangle - triangles.push(prev.i / dim); - triangles.push(ear.i / dim); - triangles.push(next.i / dim); - - removeNode(ear); - - // skipping the next vertice leads to less sliver triangles - ear = next.next; - stop = next.next; - - continue; - } - - ear = next; - - // if we looped through the whole remaining polygon and can't find any more ears - if (ear === stop) { - // try filtering points and slicing again - if (!pass) { - earcutLinked(filterPoints(ear), triangles, dim, minX, minY, size, 1); - - // if this didn't work, try curing all small self-intersections locally - } else if (pass === 1) { - ear = cureLocalIntersections(ear, triangles, dim); - earcutLinked(ear, triangles, dim, minX, minY, size, 2); - - // as a last resort, try splitting the remaining polygon into two - } else if (pass === 2) { - splitEarcut(ear, triangles, dim, minX, minY, size); - } - - break; - } - } -} - -// check whether a polygon node forms a valid ear with adjacent nodes -function isEar(ear) { - var a = ear.prev, - b = ear, - c = ear.next; - - if (area(a, b, c) >= 0) return false; // reflex, can't be an ear - - // now make sure we don't have other points inside the potential ear - var p = ear.next.next; - - while (p !== ear.prev) { - if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && - area(p.prev, p, p.next) >= 0) return false; - p = p.next; - } - - return true; -} - -function isEarHashed(ear, minX, minY, size) { - var a = ear.prev, - b = ear, - c = ear.next; - - if (area(a, b, c) >= 0) return false; // reflex, can't be an ear - - // triangle bbox; min & max are calculated like this for speed - var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x), - minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y), - maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x), - maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y); - - // z-order range for the current triangle bbox; - var minZ = zOrder(minTX, minTY, minX, minY, size), - maxZ = zOrder(maxTX, maxTY, minX, minY, size); - - // first look for points inside the triangle in increasing z-order - var p = ear.nextZ; - - while (p && p.z <= maxZ) { - if (p !== ear.prev && p !== ear.next && - pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && - area(p.prev, p, p.next) >= 0) return false; - p = p.nextZ; - } - - // then look for points in decreasing z-order - p = ear.prevZ; - - while (p && p.z >= minZ) { - if (p !== ear.prev && p !== ear.next && - pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && - area(p.prev, p, p.next) >= 0) return false; - p = p.prevZ; - } - - return true; -} - -// go through all polygon nodes and cure small local self-intersections -function cureLocalIntersections(start, triangles, dim) { - var p = start; - do { - var a = p.prev, - b = p.next.next; - - // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2]) - if (intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) { - - triangles.push(a.i / dim); - triangles.push(p.i / dim); - triangles.push(b.i / dim); - - // remove two nodes involved - removeNode(p); - removeNode(p.next); - - p = start = b; - } - p = p.next; - } while (p !== start); - - return p; -} - -// try splitting polygon into two and triangulate them independently -function splitEarcut(start, triangles, dim, minX, minY, size) { - // look for a valid diagonal that divides the polygon into two - var a = start; - do { - var b = a.next.next; - while (b !== a.prev) { - if (a.i !== b.i && isValidDiagonal(a, b)) { - // split the polygon in two by the diagonal - var c = splitPolygon(a, b); - - // filter colinear points around the cuts - a = filterPoints(a, a.next); - c = filterPoints(c, c.next); - - // run earcut on each half - earcutLinked(a, triangles, dim, minX, minY, size); - earcutLinked(c, triangles, dim, minX, minY, size); - return; - } - b = b.next; - } - a = a.next; - } while (a !== start); -} - -// link every hole into the outer loop, producing a single-ring polygon without holes -function eliminateHoles(data, holeIndices, outerNode, dim) { - var queue = [], - i, len, start, end, list; - - for (i = 0, len = holeIndices.length; i < len; i++) { - start = holeIndices[i] * dim; - end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; - list = linkedList(data, start, end, dim, false); - if (list === list.next) list.steiner = true; - queue.push(getLeftmost(list)); - } - - queue.sort(compareX); - - // process holes from left to right - for (i = 0; i < queue.length; i++) { - eliminateHole(queue[i], outerNode); - outerNode = filterPoints(outerNode, outerNode.next); - } - - return outerNode; -} - -function compareX(a, b) { - return a.x - b.x; -} - -// find a bridge between vertices that connects hole with an outer ring and and link it -function eliminateHole(hole, outerNode) { - outerNode = findHoleBridge(hole, outerNode); - if (outerNode) { - var b = splitPolygon(outerNode, hole); - filterPoints(b, b.next); - } -} - -// David Eberly's algorithm for finding a bridge between hole and outer polygon -function findHoleBridge(hole, outerNode) { - var p = outerNode, - hx = hole.x, - hy = hole.y, - qx = -Infinity, - m; - - // find a segment intersected by a ray from the hole's leftmost point to the left; - // segment's endpoint with lesser x will be potential connection point - do { - if (hy <= p.y && hy >= p.next.y) { - var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); - if (x <= hx && x > qx) { - qx = x; - m = p.x < p.next.x ? p : p.next; - } - } - p = p.next; - } while (p !== outerNode); - - if (!m) return null; - - // look for points inside the triangle of hole point, segment intersection and endpoint; - // if there are no points found, we have a valid connection; - // otherwise choose the point of the minimum angle with the ray as connection point - - var stop = m, - tanMin = Infinity, - tan; - - p = m.next; - - while (p !== stop) { - if (hx >= p.x && p.x >= m.x && - pointInTriangle(hy < m.y ? hx : qx, hy, m.x, m.y, hy < m.y ? qx : hx, hy, p.x, p.y)) { - - tan = Math.abs(hy - p.y) / (hx - p.x); // tangential - - if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) { - m = p; - tanMin = tan; - } - } - - p = p.next; - } - - return m; -} - -// interlink polygon nodes in z-order -function indexCurve(start, minX, minY, size) { - var p = start; - do { - if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, size); - p.prevZ = p.prev; - p.nextZ = p.next; - p = p.next; - } while (p !== start); - - p.prevZ.nextZ = null; - p.prevZ = null; - - sortLinked(p); -} - -// Simon Tatham's linked list merge sort algorithm -// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html -function sortLinked(list) { - var i, p, q, e, tail, numMerges, pSize, qSize, - inSize = 1; - - do { - p = list; - list = null; - tail = null; - numMerges = 0; - - while (p) { - numMerges++; - q = p; - pSize = 0; - for (i = 0; i < inSize; i++) { - pSize++; - q = q.nextZ; - if (!q) break; - } - - qSize = inSize; - - while (pSize > 0 || (qSize > 0 && q)) { - - if (pSize === 0) { - e = q; - q = q.nextZ; - qSize--; - } else if (qSize === 0 || !q) { - e = p; - p = p.nextZ; - pSize--; - } else if (p.z <= q.z) { - e = p; - p = p.nextZ; - pSize--; - } else { - e = q; - q = q.nextZ; - qSize--; - } - - if (tail) tail.nextZ = e; - else list = e; - - e.prevZ = tail; - tail = e; - } - - p = q; - } - - tail.nextZ = null; - inSize *= 2; - - } while (numMerges > 1); - - return list; -} - -// z-order of a point given coords and size of the data bounding box -function zOrder(x, y, minX, minY, size) { - // coords are transformed into non-negative 15-bit integer range - x = 32767 * (x - minX) / size; - y = 32767 * (y - minY) / size; - - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -// find the leftmost node of a polygon ring -function getLeftmost(start) { - var p = start, - leftmost = start; - do { - if (p.x < leftmost.x) leftmost = p; - p = p.next; - } while (p !== start); - - return leftmost; -} - -// check if a point lies within a convex triangle -function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) { - return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && - (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && - (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; -} - -// check if a diagonal between two polygon nodes is valid (lies in polygon interior) -function isValidDiagonal(a, b) { - return equals(a, b) || a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && - locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b); -} - -// signed area of a triangle -function area(p, q, r) { - return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); -} - -// check if two points are equal -function equals(p1, p2) { - return p1.x === p2.x && p1.y === p2.y; -} - -// check if two segments intersect -function intersects(p1, q1, p2, q2) { - return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && - area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0; -} - -// check if a polygon diagonal intersects any polygon segments -function intersectsPolygon(a, b) { - var p = a; - do { - if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && - intersects(p, p.next, a, b)) return true; - p = p.next; - } while (p !== a); - - return false; -} - -// check if a polygon diagonal is locally inside the polygon -function locallyInside(a, b) { - return area(a.prev, a, a.next) < 0 ? - area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : - area(a, b, a.prev) < 0 || area(a, a.next, b) < 0; -} - -// check if the middle point of a polygon diagonal is inside the polygon -function middleInside(a, b) { - var p = a, - inside = false, - px = (a.x + b.x) / 2, - py = (a.y + b.y) / 2; - do { - if (((p.y > py) !== (p.next.y > py)) && (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) - inside = !inside; - p = p.next; - } while (p !== a); - - return inside; -} - -// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; -// if one belongs to the outer ring and another to a hole, it merges it into a single ring -function splitPolygon(a, b) { - var a2 = new Node(a.i, a.x, a.y), - b2 = new Node(b.i, b.x, b.y), - an = a.next, - bp = b.prev; - - a.next = b; - b.prev = a; - - a2.next = an; - an.prev = a2; - - b2.next = a2; - a2.prev = b2; - - bp.next = b2; - b2.prev = bp; - - return b2; -} - -// create a node and optionally link it with previous one (in a circular doubly linked list) -function insertNode(i, x, y, last) { - var p = new Node(i, x, y); - - if (!last) { - p.prev = p; - p.next = p; - - } else { - p.next = last.next; - p.prev = last; - last.next.prev = p; - last.next = p; - } - return p; -} - -function removeNode(p) { - p.next.prev = p.prev; - p.prev.next = p.next; - - if (p.prevZ) p.prevZ.nextZ = p.nextZ; - if (p.nextZ) p.nextZ.prevZ = p.prevZ; -} - -function Node(i, x, y) { - // vertice index in coordinates array - this.i = i; - - // vertex coordinates - this.x = x; - this.y = y; - - // previous and next vertice nodes in a polygon ring - this.prev = null; - this.next = null; - - // z-order curve value - this.z = null; - - // previous and next nodes in z-order - this.prevZ = null; - this.nextZ = null; - - // indicates whether this is a steiner point - this.steiner = false; -} - -},{}],12:[function(require,module,exports){ -arguments[4][2][0].apply(exports,arguments) -},{"dup":2}],13:[function(require,module,exports){ -/** - * isMobile.js v0.4.0 - * - * A simple library to detect Apple phones and tablets, - * Android phones and tablets, other mobile devices (like blackberry, mini-opera and windows phone), - * and any kind of seven inch device, via user agent sniffing. - * - * @author: Kai Mallea (kmallea@gmail.com) - * - * @license: http://creativecommons.org/publicdomain/zero/1.0/ - */ -(function (global) { - - var apple_phone = /iPhone/i, - apple_ipod = /iPod/i, - apple_tablet = /iPad/i, - android_phone = /(?=.*\bAndroid\b)(?=.*\bMobile\b)/i, // Match 'Android' AND 'Mobile' - android_tablet = /Android/i, - amazon_phone = /(?=.*\bAndroid\b)(?=.*\bSD4930UR\b)/i, - amazon_tablet = /(?=.*\bAndroid\b)(?=.*\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\b)/i, - windows_phone = /IEMobile/i, - windows_tablet = /(?=.*\bWindows\b)(?=.*\bARM\b)/i, // Match 'Windows' AND 'ARM' - other_blackberry = /BlackBerry/i, - other_blackberry_10 = /BB10/i, - other_opera = /Opera Mini/i, - other_chrome = /(CriOS|Chrome)(?=.*\bMobile\b)/i, - other_firefox = /(?=.*\bFirefox\b)(?=.*\bMobile\b)/i, // Match 'Firefox' AND 'Mobile' - seven_inch = new RegExp( - '(?:' + // Non-capturing group - - 'Nexus 7' + // Nexus 7 - - '|' + // OR - - 'BNTV250' + // B&N Nook Tablet 7 inch - - '|' + // OR - - 'Kindle Fire' + // Kindle Fire - - '|' + // OR - - 'Silk' + // Kindle Fire, Silk Accelerated - - '|' + // OR - - 'GT-P1000' + // Galaxy Tab 7 inch - - ')', // End non-capturing group - - 'i'); // Case-insensitive matching - - var match = function(regex, userAgent) { - return regex.test(userAgent); - }; - - var IsMobileClass = function(userAgent) { - var ua = userAgent || navigator.userAgent; - - // Facebook mobile app's integrated browser adds a bunch of strings that - // match everything. Strip it out if it exists. - var tmp = ua.split('[FBAN'); - if (typeof tmp[1] !== 'undefined') { - ua = tmp[0]; - } - - // Twitter mobile app's integrated browser on iPad adds a "Twitter for - // iPhone" string. Same probable happens on other tablet platforms. - // This will confuse detection so strip it out if it exists. - tmp = ua.split('Twitter'); - if (typeof tmp[1] !== 'undefined') { - ua = tmp[0]; - } - - this.apple = { - phone: match(apple_phone, ua), - ipod: match(apple_ipod, ua), - tablet: !match(apple_phone, ua) && match(apple_tablet, ua), - device: match(apple_phone, ua) || match(apple_ipod, ua) || match(apple_tablet, ua) - }; - this.amazon = { - phone: match(amazon_phone, ua), - tablet: !match(amazon_phone, ua) && match(amazon_tablet, ua), - device: match(amazon_phone, ua) || match(amazon_tablet, ua) - }; - this.android = { - phone: match(amazon_phone, ua) || match(android_phone, ua), - tablet: !match(amazon_phone, ua) && !match(android_phone, ua) && (match(amazon_tablet, ua) || match(android_tablet, ua)), - device: match(amazon_phone, ua) || match(amazon_tablet, ua) || match(android_phone, ua) || match(android_tablet, ua) - }; - this.windows = { - phone: match(windows_phone, ua), - tablet: match(windows_tablet, ua), - device: match(windows_phone, ua) || match(windows_tablet, ua) - }; - this.other = { - blackberry: match(other_blackberry, ua), - blackberry10: match(other_blackberry_10, ua), - opera: match(other_opera, ua), - firefox: match(other_firefox, ua), - chrome: match(other_chrome, ua), - device: match(other_blackberry, ua) || match(other_blackberry_10, ua) || match(other_opera, ua) || match(other_firefox, ua) || match(other_chrome, ua) - }; - this.seven_inch = match(seven_inch, ua); - this.any = this.apple.device || this.android.device || this.windows.device || this.other.device || this.seven_inch; - - // excludes 'other' devices and ipods, targeting touchscreen phones - this.phone = this.apple.phone || this.android.phone || this.windows.phone; - - // excludes 7 inch devices, classifying as phone or tablet is left to the user - this.tablet = this.apple.tablet || this.android.tablet || this.windows.tablet; - - if (typeof window === 'undefined') { - return this; - } - }; - - var instantiate = function() { - var IM = new IsMobileClass(); - IM.Class = IsMobileClass; - return IM; - }; - - if (typeof module !== 'undefined' && module.exports && typeof window === 'undefined') { - //node - module.exports = IsMobileClass; - } else if (typeof module !== 'undefined' && module.exports && typeof window !== 'undefined') { - //browserify - module.exports = instantiate(); - } else if (typeof define === 'function' && define.amd) { - //AMD - define('isMobile', [], global.isMobile = instantiate()); - } else { - global.isMobile = instantiate(); - } - -})(this); - -},{}],14:[function(require,module,exports){ -/* eslint-disable no-unused-vars */ -'use strict'; -var hasOwnProperty = Object.prototype.hasOwnProperty; -var propIsEnumerable = Object.prototype.propertyIsEnumerable; - -function toObject(val) { - if (val === null || val === undefined) { - throw new TypeError('Object.assign cannot be called with null or undefined'); - } - - return Object(val); -} - -module.exports = Object.assign || function (target, source) { - var from; - var to = toObject(target); - var symbols; - - for (var s = 1; s < arguments.length; s++) { - from = Object(arguments[s]); - - for (var key in from) { - if (hasOwnProperty.call(from, key)) { - to[key] = from[key]; - } - } - - if (Object.getOwnPropertySymbols) { - symbols = Object.getOwnPropertySymbols(from); - for (var i = 0; i < symbols.length; i++) { - if (propIsEnumerable.call(from, symbols[i])) { - to[symbols[i]] = from[symbols[i]]; - } - } - } - } - - return to; -}; - -},{}],15:[function(require,module,exports){ - - -module.exports = { - - createContext: require('./lib/createContext'), - setVertexAttribArrays: require('./lib/setVertexAttribArrays'), - - GLBuffer: require('./lib/GLBuffer'), - GLFramebuffer: require('./lib/GLFramebuffer'), - GLShader: require('./lib/GLShader'), - GLTexture: require('./lib/GLTexture'), - - VertexArrayObject: require('./lib/VertexArrayObject') - -}; -},{"./lib/GLBuffer":16,"./lib/GLFramebuffer":17,"./lib/GLShader":18,"./lib/GLTexture":19,"./lib/VertexArrayObject":20,"./lib/createContext":21,"./lib/setVertexAttribArrays":22}],16:[function(require,module,exports){ -var EMPTY_ARRAY_BUFFER = new ArrayBuffer(0); - -/** - * Helper class to create a webGL buffer + * Manages the state and loading of multiple resources to load. * * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param type {gl.ARRAY_BUFFER | gl.ELEMENT_ARRAY_BUFFER} @mat - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data - * @param drawType {gl.STATIC_DRAW|gl.DYNAMIC_DRAW|gl.STREAM_DRAW} + * @param [baseUrl=''] {string} The base url for all resources loaded by this loader. + * @param [concurrency=10] {number} The number of resources to load concurrently. */ -var Buffer = function(gl, type, data, drawType) -{ +function Loader(baseUrl, concurrency) { + EventEmitter.call(this); - /** - * The current WebGL rendering context + concurrency = concurrency || 10; + + /** + * The base url for all resources loaded by this loader. * - * @member {WebGLRenderingContext} + * @member {string} */ - this.gl = gl; + this.baseUrl = baseUrl || ''; - /** - * The WebGL buffer, created upon instantiation + /** + * The progress percent of the loader going through the queue. * - * @member {WebGLBuffer} + * @member {number} */ - this.buffer = gl.createBuffer(); + this.progress = 0; - /** - * The type of the buffer + /** + * Loading state of the loader, true if it is currently loading resources. * - * @member {gl.ARRAY_BUFFER || gl.ELEMENT_ARRAY_BUFFER} + * @member {boolean} */ - this.type = type || gl.ARRAY_BUFFER; + this.loading = false; - /** - * The draw type of the buffer + /** + * The percentage of total progress that a single resource represents. * - * @member {gl.STATIC_DRAW|gl.DYNAMIC_DRAW|gl.STREAM_DRAW} + * @member {number} */ - this.drawType = drawType || gl.STATIC_DRAW; + this._progressChunk = 0; - /** - * The data in the buffer, as a typed array + /** + * The middleware to run before loading each resource. * - * @member {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} + * @member {function[]} */ - this.data = EMPTY_ARRAY_BUFFER; + this._beforeMiddleware = []; - if(data) - { - this.upload(data); - } + /** + * The middleware to run after loading each resource. + * + * @member {function[]} + */ + this._afterMiddleware = []; + + /** + * The `_loadResource` function bound with this object context. + * + * @private + * @member {function} + */ + this._boundLoadResource = this._loadResource.bind(this); + + /** + * The `_onLoad` function bound with this object context. + * + * @private + * @member {function} + */ + this._boundOnLoad = this._onLoad.bind(this); + + /** + * The resource buffer that fills until `load` is called to start loading resources. + * + * @private + * @member {Resource[]} + */ + this._buffer = []; + + /** + * Used to track load completion. + * + * @private + * @member {number} + */ + this._numToLoad = 0; + + /** + * The resources waiting to be loaded. + * + * @private + * @member {Resource[]} + */ + this._queue = async.queue(this._boundLoadResource, concurrency); + + /** + * All the resources for this loader keyed by name. + * + * @member {object} + */ + this.resources = {}; + + /** + * Emitted once per loaded or errored resource. + * + * @event progress + * @memberof Loader# + */ + + /** + * Emitted once per errored resource. + * + * @event error + * @memberof Loader# + */ + + /** + * Emitted once per loaded resource. + * + * @event load + * @memberof Loader# + */ + + /** + * Emitted when the loader begins to process the queue. + * + * @event start + * @memberof Loader# + */ + + /** + * Emitted when the queued resources all load. + * + * @event complete + * @memberof Loader# + */ } +Loader.prototype = Object.create(EventEmitter.prototype); +Loader.prototype.constructor = Loader; +module.exports = Loader; + /** - * Uploads the buffer to the GPU - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data to upload - * @param offset {Number} if only a subset of the data should be uploaded, this is the amount of data to subtract - * @param dontBind {Boolean} whether to bind the buffer before uploading it - */ -Buffer.prototype.upload = function(data, offset, dontBind) -{ - // todo - needed? - if(!dontBind) this.bind(); - - var gl = this.gl; - - data = data || this.data; - offset = offset || 0; - - if(this.data.byteLength >= data.byteLength) - { - gl.bufferSubData(this.type, offset, data); - } - else - { - gl.bufferData(this.type, data, this.drawType); - } - - this.data = data; -} -/** - * Binds the buffer + * Adds a resource (or multiple resources) to the loader queue. * - */ -Buffer.prototype.bind = function() -{ - var gl = this.gl; - gl.bindBuffer(this.type, this.buffer); -} - -Buffer.createVertexBuffer = function(gl, data, drawType) -{ - return new Buffer(gl, gl.ARRAY_BUFFER, data, drawType); -} - -Buffer.createIndexBuffer = function(gl, data, drawType) -{ - return new Buffer(gl, gl.ELEMENT_ARRAY_BUFFER, data, drawType); -} - -Buffer.create = function(gl, type, data, drawType) -{ - return new Buffer(gl, type, drawType); -} - -/** - * Destroys the buffer + * This function can take a wide variety of different parameters. The only thing that is always + * required the url to load. All the following will work: * - */ -Buffer.prototype.destroy = function(){ - this.gl.deleteBuffer(this.buffer); -} - -module.exports = Buffer; - -},{}],17:[function(require,module,exports){ - -var Texture = require('./GLTexture'); - -/** - * Helper class to create a webGL Framebuffer + * ```js + * loader + * // normal param syntax + * .add('key', 'http://...', function () {}) + * .add('http://...', function () {}) + * .add('http://...') * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer + * // object syntax + * .add({ + * name: 'key2', + * url: 'http://...' + * }, function () {}) + * .add({ + * url: 'http://...' + * }, function () {}) + * .add({ + * name: 'key3', + * url: 'http://...' + * onComplete: function () {} + * }) + * .add({ + * url: 'https://...', + * onComplete: function () {}, + * crossOrigin: true + * }) + * + * // you can also pass an array of objects or urls or both + * .add([ + * { name: 'key4', url: 'http://...', onComplete: function () {} }, + * { url: 'http://...', onComplete: function () {} }, + * 'http://...' + * ]); + * ``` + * + * @alias enqueue + * @param [name] {string} The name of the resource to load, if not passed the url is used. + * @param url {string} The url for this resource, relative to the baseUrl of this loader. + * @param [options] {object} The options for the load. + * @param [options.crossOrigin] {boolean} Is this request cross-origin? Default is to determine automatically. + * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.XHR_LOAD_TYPE} How should this resource be loaded? + * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being + * loaded be interpreted when using XHR? + * @param [callback] {function} Function to call when this specific resource completes loading. + * @return {Loader} */ -var Framebuffer = function(gl, width, height) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; +Loader.prototype.add = Loader.prototype.enqueue = function (name, url, options, cb) { + // special case of an array of objects or urls + if (Array.isArray(name)) { + for (var i = 0; i < name.length; ++i) { + this.add(name[i]); + } - /** - * The frame buffer - * - * @member {WebGLFramebuffer} - */ - this.framebuffer = gl.createFramebuffer(); - - /** - * The stencil buffer - * - * @member {WebGLRenderbuffer} - */ - this.stencil = null; - - /** - * The stencil buffer - * - * @member {GLTexture} - */ - this.texture = null; - - /** - * The width of the drawing area of the buffer - * - * @member {Number} - */ - this.width = width || 100; - /** - * The height of the drawing area of the buffer - * - * @member {Number} - */ - this.height = height || 100; -} - -/** - * Adds a texture to the frame buffer - * @param texture {GLTexture} - */ -Framebuffer.prototype.enableTexture = function(texture) -{ - var gl = this.gl; - - this.texture = texture || new Texture(gl); - - this.texture.bind(); - - //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - this.bind(); - - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); -} - -/** - * Initialises the stencil buffer - * @mat maybe you can come up with a better explaination - */ -Framebuffer.prototype.enableStencil = function() -{ - if(this.stencil)return; - - var gl = this.gl; - - this.stencil = gl.createRenderbuffer(); - - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); - - // TODO.. this is depth AND stencil? - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencil); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width , this.height ); -} - -/** - * Erases the drawing area and fills it with a colour - * @param r {Number} the red value of the clearing colour - * @param g {Number} the green value of the clearing colour - * @param b {Number} the blue value of the clearing colour - * @param a {Number} the alpha value of the clearing colour - */ -Framebuffer.prototype.clear = function( r, g, b, a ) -{ - this.bind(); - - var gl = this.gl; - - gl.clearColor(r, g, b, a); - gl.clear(gl.COLOR_BUFFER_BIT); -} - -/** - * Binds the frame buffer to the WebGL context - */ -Framebuffer.prototype.bind = function() -{ - var gl = this.gl; - - if(this.texture) - { - this.texture.unbind(); - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); -} - -/** - * Unbinds the frame buffer to the WebGL context - */ -Framebuffer.prototype.unbind = function() -{ - var gl = this.gl; - gl.bindFramebuffer(gl.FRAMEBUFFER, null ); -} -/** - * Resizes the drawing area of the buffer to the given width and height - * @param width {Number} the new width - * @param height {Number} the new height - */ -Framebuffer.prototype.resize = function(width, height) -{ - var gl = this.gl; - - this.width = width; - this.height = height; - - if ( this.texture ) - { - this.texture.uploadData(null, width, height); - } - - if ( this.stencil ) - { - // update the stencil buffer width and height - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + return this; } -} -/** - * Destroys this buffer - */ -Framebuffer.prototype.destroy = function() -{ - var gl = this.gl; + // if an object is passed instead of params + if (typeof name === 'object') { + cb = url || name.callback || name.onComplete; + options = name; + url = name.url; + name = name.name || name.key || name.url; + } - //TODO - if(this.texture) - { - this.texture.destroy(); - } + // case where no name is passed shift all args over by one. + if (typeof url !== 'string') { + cb = options; + options = url; + url = name; + } - gl.deleteFramebuffer(this.framebuffer); + // now that we shifted make sure we have a proper url. + if (typeof url !== 'string') { + throw new Error('No url passed to add resource to loader.'); + } - this.gl = null; + // options are optional so people might pass a function and no options + if (typeof options === 'function') { + cb = options; + options = null; + } - this.stencil = null; - this.texture = null; -} + // check if resource already exists. + if (this.resources[name]) { + throw new Error('Resource with name "' + name + '" already exists.'); + } -/** - * Creates a frame buffer with a texture containing the given data - * @mat can you confirm ? :) - * @static - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data - */ -Framebuffer.createRGBA = function(gl, width, height, data) -{ - var texture = Texture.fromData(gl, null, width, height); - texture.enableNearestScaling(); - texture.enableWrapClamp(); + // add base url if this isn't an absolute url + url = this._handleBaseUrl(url); - //now create the framebuffer object and attach the texture to it. - var fbo = new Framebuffer(gl, width, height); - fbo.enableTexture(texture); + // create the store the resource + this.resources[name] = new Resource(name, url, options); - fbo.unbind(); + if (typeof cb === 'function') { + this.resources[name].once('afterMiddleware', cb); + } - return fbo; -} + this._numToLoad++; -/** - * Creates a frame buffer with a texture containing the given data - * @mat not sure what the difference is with the method above ? - * @static - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data - */ -Framebuffer.createFloat32 = function(gl, width, height, data) -{ - // create a new texture.. - var texture = new Texture.fromData(gl, data, width, height); - texture.enableNearestScaling(); - texture.enableWrapClamp(); - - //now create the framebuffer object and attach the texture to it. - var fbo = new Framebuffer(gl, width, height); - fbo.enableTexture(texture) - - fbo.unbind(); - - return fbo; -} - -module.exports = Framebuffer; - -},{"./GLTexture":19}],18:[function(require,module,exports){ - -var compileProgram = require('./shader/compileProgram'), - extractAttributes = require('./shader/extractAttributes'), - extractUniforms = require('./shader/extractUniforms'), - generateUniformAccessObject = require('./shader/generateUniformAccessObject'); - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - */ -var Shader = function(gl, vertexSrc, fragmentSrc) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc); - - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - var uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject( gl, uniformData ); -} -/** - * Uses this shader - */ -Shader.prototype.bind = function() -{ - this.gl.useProgram(this.program); -} - -/** - * Destroys this shader - * TODO - */ -Shader.prototype.destroy = function() -{ - var gl = this.gl; -} - -module.exports = Shader; - -},{"./shader/compileProgram":23,"./shader/extractAttributes":25,"./shader/extractUniforms":26,"./shader/generateUniformAccessObject":27}],19:[function(require,module,exports){ - -/** - * Helper class to create a WebGL Texture - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL context - * @param width {number} the width of the texture - * @param height {number} the height of the texture - * @param format {number} the pixel format of the texture. defaults to gl.RGBA - * @param type {number} the gl type of the texture. defaults to gl.UNSIGNED_BYTE - */ -var Texture = function(gl, width, height, format, type) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - - /** - * The WebGL texture - * - * @member {WebGLTexture} - */ - this.texture = gl.createTexture(); - - /** - * If mipmapping was used for this texture, enable and disable with enableMipmap() - * - * @member {Boolean} - */ - // some settings.. - this.mipmap = false; - - - /** - * Set to true to enable pre-multiplied alpha - * - * @member {Boolean} - */ - this.premultiplyAlpha = false; - - /** - * The width of texture - * - * @member {Number} - */ - this.width = width || 0; - /** - * The height of texture - * - * @member {Number} - */ - this.height = height || 0; - - /** - * The pixel format of the texture. defaults to gl.RGBA - * - * @member {Number} - */ - this.format = format || gl.RGBA; - - /** - * The gl type of the texture. defaults to gl.UNSIGNED_BYTE - * - * @member {Number} - */ - this.type = type || gl.UNSIGNED_BYTE; - - -} - -/** - * Uploads this texture to the GPU - * @param source {HTMLImageElement|ImageData} the source image of the texture - */ -Texture.prototype.upload = function(source) -{ - this.bind(); - - var gl = this.gl; - - this.width = source.width; - this.height = source.height; - - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, source); -} - -var FLOATING_POINT_AVAILABLE = false; - -/** - * Use a data source and uploads this texture to the GPU - * @param data {TypedArray} the data to upload to the texture - * @param width {number} the new width of the texture - * @param height {number} the new height of the texture - */ -Texture.prototype.uploadData = function(data, width, height) -{ - this.bind(); - - var gl = this.gl; - - this.width = width || this.width; - this.height = height || this.height; - - if(data instanceof Float32Array) - { - if(!FLOATING_POINT_AVAILABLE) - { - var ext = gl.getExtension("OES_texture_float"); - - if(ext) - { - FLOATING_POINT_AVAILABLE = true; - } - else - { - throw new Error('floating point textures not available'); - } - } - - this.type = gl.FLOAT; - } - else - { - // TODO support for other types - this.type = gl.UNSIGNED_BYTE; - } - - - - // what type of data? - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, data || null); - -} - -/** - * Binds the texture - * @param location {@mat} - */ -Texture.prototype.bind = function(location) -{ - var gl = this.gl; - - if(location !== undefined) - { - gl.activeTexture(gl.TEXTURE0 + location); - } - - gl.bindTexture(gl.TEXTURE_2D, this.texture); -} - -/** - * Unbinds the texture - */ -Texture.prototype.unbind = function() -{ - var gl = this.gl; - gl.bindTexture(gl.TEXTURE_2D, null); -} - -/** - * @mat - * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation - */ -Texture.prototype.minFilter = function( linear ) -{ - var gl = this.gl; - - this.bind(); - - if(this.mipmap) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST); - } -} - -/** - * @mat - * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation - */ -Texture.prototype.magFilter = function( linear ) -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST); -} - -/** - * Enables mipmapping - */ -Texture.prototype.enableMipmap = function() -{ - var gl = this.gl; - - this.bind(); - - this.mipmap = true; - - gl.generateMipmap(gl.TEXTURE_2D); -} - -/** - * Enables linear filtering - */ -Texture.prototype.enableLinearScaling = function() -{ - this.minFilter(true); - this.magFilter(true); -} - -/** - * Enables nearest neighbour interpolation - */ -Texture.prototype.enableNearestScaling = function() -{ - this.minFilter(false); - this.magFilter(false); -} - -/** - * Enables clamping on the texture so WebGL will not repeat it - */ -Texture.prototype.enableWrapClamp = function() -{ - var gl = this.gl; - - this.bind(); - - 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); -} - -/** - * Enable tiling on the texture - */ -Texture.prototype.enableWrapRepeat = function() -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); -} - -/** - * @mat - */ -Texture.prototype.enableWrapMirrorRepeat = function() -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); -} - - -/** - * Destroys this texture - */ -Texture.prototype.destroy = function() -{ - var gl = this.gl; - //TODO - gl.deleteTexture(this.texture); -} - -/** - * @static - * @param gl {WebGLRenderingContext} The current WebGL context - * @param source {HTMLImageElement|ImageData} the source image of the texture - * @param premultiplyAlpha {Boolean} If we want to use pre-multiplied alpha - */ -Texture.fromSource = function(gl, source, premultiplyAlpha) -{ - var texture = new Texture(gl); - texture.premultiplyAlpha = premultiplyAlpha || false; - texture.upload(source); - - return texture; -} - -/** - * @static - * @param gl {WebGLRenderingContext} The current WebGL context - * @param data {TypedArray} the data to upload to the texture - * @param width {number} the new width of the texture - * @param height {number} the new height of the texture - */ -Texture.fromData = function(gl, data, width, height) -{ - //console.log(data, width, height); - var texture = new Texture(gl); - texture.uploadData(data, width, height); - - return texture; -} - - -module.exports = Texture; - -},{}],20:[function(require,module,exports){ - -// state object// - -/** - * Helper class to work with WebGL VertexArrayObjects (vaos) - * Only works if WebGL extensions are enabled (they usually are) - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL rendering context - */ -function VertexArrayObject(gl) -{ - - this.nativeVaoExtension = ( - gl.getExtension('OES_vertex_array_object') || - gl.getExtension('MOZ_OES_vertex_array_object') || - gl.getExtension('WEBKIT_OES_vertex_array_object') - ); - - if(this.nativeVaoExtension) - { - this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); - } - - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - /** - * An array of attributes ? @mat - * - * @member {Array} - */ - this.attributes = []; - - /** - * @mat - * - * @member {Array} - */ - this.indexBuffer = null; - - /** - * A boolean flag - * - * @member {Boolean} - */ - this.dirty = false; - - -} - -VertexArrayObject.prototype.constructor = VertexArrayObject; -module.exports = VertexArrayObject; - -/** - * Binds the buffer - */ -VertexArrayObject.prototype.bind = function() -{ - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); - - if(this.dirty) - { - this.dirty = false; - this.activate(); - } - } - else - { - this.activate(); - } - - return this; -} - -/** - * Unbinds the buffer - */ -VertexArrayObject.prototype.unbind = function() -{ - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(null); - } - - return this; -} - -/** - * Uses this vao - */ -VertexArrayObject.prototype.activate = function() -{ - var gl = this.gl; - - for (var i = 0; i < this.attributes.length; i++) - { - var attrib = this.attributes[i]; - attrib.buffer.bind(); - - //attrib.attribute.pointer(attrib.type, attrib.normalized, attrib.stride, attrib.start); - gl.vertexAttribPointer(attrib.attribute.location, - attrib.attribute.size, attrib.type || gl.FLOAT, - attrib.normalized || false, - attrib.stride || 0, - attrib.start || 0); - - gl.enableVertexAttribArray(attrib.attribute.location); - }; - - this.indexBuffer.bind(); - - return this; -} - -/** - * - * @param buffer {WebGLBuffer} - * @param attribute {[type]} - * @param type {[type]} - * @param normalized {[type]} - * @param stride {Number} - * @param start {Number} - */ -VertexArrayObject.prototype.addAttribute = function(buffer, attribute, type, normalized, stride, start) -{ - this.attributes.push({ - buffer: buffer, - attribute: attribute, - - location: attribute.location, - type: type || this.gl.FLOAT, - normalized: normalized || false, - stride: stride || 0, - start: start || 0 - }) - - this.dirty = true; - - return this; -} - -/** - * - * @param buffer {WebGLBuffer} - * @param options {Object} - */ -VertexArrayObject.prototype.addIndex = function(buffer, options) -{ - this.indexBuffer = buffer; - - this.dirty = true; + // if already loading add it to the worker queue + if (this._queue.started) { + this._queue.push(this.resources[name]); + this._progressChunk = (100 - this.progress) / (this._queue.length() + this._queue.running()); + } + // otherwise buffer it to be added to the queue later + else { + this._buffer.push(this.resources[name]); + this._progressChunk = 100 / this._buffer.length; + } return this; -} +}; + +Loader.prototype._handleBaseUrl = function (url) { + var parsedUrl = urlParser.parse(url); + + // absolute url, just use it as is. + if (parsedUrl.protocol || parsedUrl.pathname.indexOf('//') === 0) { + return url; + } + + // if baseUrl doesn't end in slash and url doesn't start with slash, then add a slash inbetween + if ( + this.baseUrl.length && + this.baseUrl.lastIndexOf('/') !== this.baseUrl.length - 1 && + url.charAt(0) !== '/' + ) { + return this.baseUrl + '/' + url; + } + else { + return this.baseUrl + url; + } +}; + /** - * Unbinds this vao and disables it + * Sets up a middleware function that will run *before* the + * resource is loaded. + * + * @alias pre + * @param middleware {function} The middleware function to register. + * @return {Loader} */ -VertexArrayObject.prototype.clear = function() -{ - // TODO - should this function unbind after clear? - // for now, no but lets see what happens in the real world! - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); - } +Loader.prototype.before = Loader.prototype.pre = function (fn) { + this._beforeMiddleware.push(fn); - for (var i = 0; i < this.attributes.length; i++) - { - var attrib = this.attributes[i]; - gl.disableVertexAttribArray(attrib.attribute.location); - }; - - this.attributes.length = 0; - this.indexBuffer = null; - - return this; -} + return this; +}; /** - * @mat - * @param type {Number} - * @param size {Number} - * @param start {Number} + * Sets up a middleware function that will run *after* the + * resource is loaded. + * + * @alias use + * @param middleware {function} The middleware function to register. + * @return {Loader} */ -VertexArrayObject.prototype.draw = function(type, size, start) -{ - var gl = this.gl; - gl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0); +Loader.prototype.after = Loader.prototype.use = function (fn) { + this._afterMiddleware.push(fn); - return this; -} - -},{}],21:[function(require,module,exports){ + return this; +}; /** - * Helper class to create a webGL Context + * Resets the queue of the loader to prepare for a new load. + * + * @return {Loader} + */ +Loader.prototype.reset = function () { + // this.baseUrl = baseUrl || ''; + + this.progress = 0; + + this.loading = false; + + this._progressChunk = 0; + + // this._beforeMiddleware.length = 0; + // this._afterMiddleware.length = 0; + + this._buffer.length = 0; + + this._numToLoad = 0; + + this._queue.kill(); + this._queue.started = false; + + this.resources = {}; +}; + +/** + * Starts loading the queued resources. + * + * @fires start + * @param [callback] {function} Optional callback that will be bound to the `complete` event. + * @return {Loader} + */ +Loader.prototype.load = function (cb) { + // register complete callback if they pass one + if (typeof cb === 'function') { + this.once('complete', cb); + } + + // if the queue has already started we are done here + if (this._queue.started) { + return this; + } + + // notify of start + this.emit('start', this); + + // start the internal queue + for (var i = 0; i < this._buffer.length; ++i) { + this._queue.push(this._buffer[i]); + } + + // empty the buffer + this._buffer.length = 0; + + return this; +}; + +/** + * Loads a single resource. + * + * @fires progress + * @private + */ +Loader.prototype._loadResource = function (resource, dequeue) { + var self = this; + + resource._dequeue = dequeue; + + this._runMiddleware(resource, this._beforeMiddleware, function () { + // resource.on('progress', self.emit.bind(self, 'progress')); + + resource.load(self._boundOnLoad); + }); +}; + +/** + * Called once each resource has loaded. + * + * @fires complete + * @private + */ +Loader.prototype._onComplete = function () { + this.emit('complete', this, this.resources); +}; + +/** + * Called each time a resources is loaded. + * + * @fires progress + * @fires error + * @fires load + * @private + */ +Loader.prototype._onLoad = function (resource) { + this.progress += this._progressChunk; + + this.emit('progress', this, resource); + + // run middleware, this *must* happen before dequeue so sub-assets get added properly + this._runMiddleware(resource, this._afterMiddleware, function () { + resource.emit('afterMiddleware', resource); + + this._numToLoad--; + + // do completion check + if (this._numToLoad === 0) { + this.progress = 100; + this._onComplete(); + } + + if (resource.error) { + this.emit('error', resource.error, this, resource); + } + else { + this.emit('load', this, resource); + } + }); + + + + // remove this resource from the async queue + resource._dequeue(); +}; + +/** + * Run middleware functions on a resource. + * + * @private + */ +Loader.prototype._runMiddleware = function (resource, fns, cb) { + var self = this; + + async.eachSeries(fns, function (fn, next) { + fn.call(self, resource, next); + }, cb.bind(this, resource)); +}; + +Loader.LOAD_TYPE = Resource.LOAD_TYPE; +Loader.XHR_READY_STATE = Resource.XHR_READY_STATE; +Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE; + +},{"./Resource":30,"async":28,"eventemitter3":25,"url":23}],30:[function(require,module,exports){ +var EventEmitter = require('eventemitter3'), + _url = require('url'), + // tests is CORS is supported in XHR, if not we need to use XDR + useXdr = !!(window.XDomainRequest && !('withCredentials' in (new XMLHttpRequest()))), + tempAnchor = null; + +/** + * Manages the state and loading of a single resource represented by + * a single URL. * * @class - * @memberof pixi.gl - * @param canvas {HTMLCanvasElement} the canvas element that we will get the context from - * @param options {Object} An options object that gets passed in to the canvas element containing the context attributes, - * see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext for the options available - * @return {WebGLRenderingContext} the WebGL context + * @param name {string} The name of the resource to load. + * @param url {string|string[]} The url for this resource, for audio/video loads you can pass an array of sources. + * @param [options] {object} The options for the load. + * @param [options.crossOrigin] {string|boolean} Is this request cross-origin? Default is to determine automatically. + * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.LOAD_TYPE} How should this resource be loaded? + * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being + * loaded be interpreted when using XHR? + * @param [options.metadata] {object} Extra info for middleware. */ -var createContext = function(canvas, options) -{ - var gl = canvas.getContext('webgl', options) || - canvas.getContext('experimental-webgl', options); +function Resource(name, url, options) { + EventEmitter.call(this); - if (!gl) - { - // fail, not able to get a context - throw new Error('This browser does not support webGL. Try using the canvas renderer'); + options = options || {}; + + if (typeof name !== 'string' || typeof url !== 'string') { + throw new Error('Both name and url are required for constructing a resource.'); } - return gl; + /** + * The name of this resource. + * + * @member {string} + * @readonly + */ + this.name = name; + + /** + * The url used to load this resource. + * + * @member {string} + * @readonly + */ + this.url = url; + + /** + * Stores whether or not this url is a data url. + * + * @member {boolean} + * @readonly + */ + this.isDataUrl = this.url.indexOf('data:') === 0; + + /** + * The data that was loaded by the resource. + * + * @member {any} + */ + this.data = null; + + /** + * Is this request cross-origin? If unset, determined automatically. + * + * @member {string} + */ + this.crossOrigin = options.crossOrigin === true ? 'anonymous' : options.crossOrigin; + + /** + * The method of loading to use for this resource. + * + * @member {Resource.LOAD_TYPE} + */ + this.loadType = options.loadType || this._determineLoadType(); + + /** + * The type used to load the resource via XHR. If unset, determined automatically. + * + * @member {string} + */ + this.xhrType = options.xhrType; + + /** + * Extra info for middleware + * + * @member {object} + */ + this.metadata = options.metadata || {}; + + /** + * The error that occurred while loading (if any). + * + * @member {Error} + * @readonly + */ + this.error = null; + + /** + * The XHR object that was used to load this resource. This is only set + * when `loadType` is `Resource.LOAD_TYPE.XHR`. + * + * @member {XMLHttpRequest} + */ + this.xhr = null; + + /** + * Describes if this resource was loaded as json. Only valid after the resource + * has completely loaded. + * + * @member {boolean} + */ + this.isJson = false; + + /** + * Describes if this resource was loaded as xml. Only valid after the resource + * has completely loaded. + * + * @member {boolean} + */ + this.isXml = false; + + /** + * Describes if this resource was loaded as an image tag. Only valid after the resource + * has completely loaded. + * + * @member {boolean} + */ + this.isImage = false; + + /** + * Describes if this resource was loaded as an audio tag. Only valid after the resource + * has completely loaded. + * + * @member {boolean} + */ + this.isAudio = false; + + /** + * Describes if this resource was loaded as a video tag. Only valid after the resource + * has completely loaded. + * + * @member {boolean} + */ + this.isVideo = false; + + /** + * The `dequeue` method that will be used a storage place for the async queue dequeue method + * used privately by the loader. + * + * @member {function} + * @private + */ + this._dequeue = null; + + /** + * The `complete` function bound to this resource's context. + * + * @member {function} + * @private + */ + this._boundComplete = this.complete.bind(this); + + /** + * The `_onError` function bound to this resource's context. + * + * @member {function} + * @private + */ + this._boundOnError = this._onError.bind(this); + + /** + * The `_onProgress` function bound to this resource's context. + * + * @member {function} + * @private + */ + this._boundOnProgress = this._onProgress.bind(this); + + // xhr callbacks + this._boundXhrOnError = this._xhrOnError.bind(this); + this._boundXhrOnAbort = this._xhrOnAbort.bind(this); + this._boundXhrOnLoad = this._xhrOnLoad.bind(this); + this._boundXdrOnTimeout = this._xdrOnTimeout.bind(this); + + /** + * Emitted when the resource beings to load. + * + * @event start + * @memberof Resource# + */ + + /** + * Emitted each time progress of this resource load updates. + * Not all resources types and loader systems can support this event + * so sometimes it may not be available. If the resource + * is being loaded on a modern browser, using XHR, and the remote server + * properly sets Content-Length headers, then this will be available. + * + * @event progress + * @memberof Resource# + */ + + /** + * Emitted once this resource has loaded, if there was an error it will + * be in the `error` property. + * + * @event complete + * @memberof Resource# + */ } -module.exports = createContext; - -},{}],22:[function(require,module,exports){ -var GL_MAP = {}; +Resource.prototype = Object.create(EventEmitter.prototype); +Resource.prototype.constructor = Resource; +module.exports = Resource; /** - * @mat - * @param gl {WebGLRenderingContext} The current WebGL context - * @param attribs {[type]} + * Marks the resource as complete. + * + * @fires complete */ -var setVertexAttribArrays = function (gl, attribs) -{ - // console.log(gl.id) - var data = GL_MAP[gl.id]; - - if(!data) - { - var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); - data = GL_MAP[gl.id] = {tempAttribState:new Array(maxAttribs) - ,attribState:new Array(maxAttribs)}; - } - - var i, - tempAttribState = data.tempAttribState, - attribState = data.attribState; - - for (i = 0; i < tempAttribState.length; i++) - { - tempAttribState[i] = false; +Resource.prototype.complete = function () { + // TODO: Clean this up in a wrapper or something...gross.... + if (this.data && this.data.removeEventListener) { + this.data.removeEventListener('error', this._boundOnError); + this.data.removeEventListener('load', this._boundComplete); + this.data.removeEventListener('progress', this._boundOnProgress); + this.data.removeEventListener('canplaythrough', this._boundComplete); } - // set the new attribs - for (i in attribs) - { - tempAttribState[attribs[i].location] = true; - } - - for (i = 1; i < attribState.length; i++) - { - if (attribState[i] !== tempAttribState[i]) - { - attribState[i] = tempAttribState[i]; - - if (data.attribState[i]) - { - gl.enableVertexAttribArray(i); - } - else - { - gl.disableVertexAttribArray(i); - } + if (this.xhr) { + if (this.xhr.removeEventListener) { + this.xhr.removeEventListener('error', this._boundXhrOnError); + this.xhr.removeEventListener('abort', this._boundXhrOnAbort); + this.xhr.removeEventListener('progress', this._boundOnProgress); + this.xhr.removeEventListener('load', this._boundXhrOnLoad); } + else { + this.xhr.onerror = null; + this.xhr.ontimeout = null; + this.xhr.onprogress = null; + this.xhr.onload = null; + } + } + + this.emit('complete', this); +}; + +/** + * Kicks off loading of this resource. + * + * @fires start + * @param [callback] {function} Optional callback to call once the resource is loaded. + */ +Resource.prototype.load = function (cb) { + this.emit('start', this); + + // if a callback is set, listen for complete event + if (cb) { + this.once('complete', cb); + } + + // if unset, determine the value + if (this.crossOrigin === false || typeof this.crossOrigin !== 'string') { + this.crossOrigin = this._determineCrossOrigin(this.url); + } + + switch(this.loadType) { + case Resource.LOAD_TYPE.IMAGE: + this._loadImage(); + break; + + case Resource.LOAD_TYPE.AUDIO: + this._loadElement('audio'); + break; + + case Resource.LOAD_TYPE.VIDEO: + this._loadElement('video'); + break; + + case Resource.LOAD_TYPE.XHR: + /* falls through */ + default: + if (useXdr && this.crossOrigin) { + this._loadXdr(); + } + else { + this._loadXhr(); + } + break; } }; -module.exports = setVertexAttribArrays; - -},{}],23:[function(require,module,exports){ - /** + * Loads this resources using an Image object. * - * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @return {WebGLProgram} the shader program + * @private */ -compileProgram = function(gl, vertexSrc, fragmentSrc) -{ - var glVertShader = compileShader(gl, gl.VERTEX_SHADER, vertexSrc); - var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc); +Resource.prototype._loadImage = function () { + this.data = new Image(); - var program = gl.createProgram(); - - gl.attachShader(program, glVertShader); - gl.attachShader(program, glFragShader); - gl.linkProgram(program); - - // if linking fails, then log and cleanup - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) - { - console.error('Pixi.js Error: Could not initialize shader.'); - console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS)); - console.error('gl.getError()', gl.getError()); - - // if there is a program info log, log it - if (gl.getProgramInfoLog(program) !== '') - { - console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program)); - } - - gl.deleteProgram(program); - program = null; + if (this.crossOrigin) { + this.data.crossOrigin = this.crossOrigin; } - // clean up some shaders - gl.deleteShader(glVertShader); - gl.deleteShader(glFragShader); + this.data.src = this.url; - return program; -} + this.isImage = true; -/** - * - * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} - * @param type {Number} the type, can be either VERTEX_SHADER or FRAGMENT_SHADER - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @return {WebGLShader} the shader - */ -var compileShader = function (gl, type, src) -{ - var shader = gl.createShader(type); - - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) - { - console.log(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; + this.data.addEventListener('error', this._boundOnError, false); + this.data.addEventListener('load', this._boundComplete, false); + this.data.addEventListener('progress', this._boundOnProgress, false); }; -module.exports = compileProgram; - -},{}],24:[function(require,module,exports){ - - -var defaultValue = function(type, size) -{ - switch (type) - { - case 'float': - return 0; - - case 'vec2': - return new Float32Array(2 * size); - - case 'vec3': - return new Float32Array(3 * size); - - case 'vec4': - return new Float32Array(4 * size); - - case 'int': - case 'sampler2D': - return 0; - - case 'ivec2': - return new Int32Array(2 * size); - - case 'ivec3': - return new Int32Array(3 * size); - - case 'ivec4': - return new Int32Array(4 * size); - - case 'bool': - return false; - - case 'bvec2': - - return booleanArray( 2 * size); - - case 'bvec3': - return booleanArray(3 * size); - - case 'bvec4': - return booleanArray(4 * size); - - case 'mat2': - return new Float32Array([1, 0 - ,0, 1]); - - case 'mat3': - return new Float32Array([1, 0, 0 - ,0, 1, 0 - ,0, 0, 1]); - - case 'mat4': - return new Float32Array([1, 0, 0, 0 - ,0, 1, 0, 0 - ,0, 0, 1, 0 - ,0, 0, 0, 1]); - } -} - -var booleanArray = function(size) -{ - var array = new Array(size); - - for (var i = 0; i < array.length; i++) - { - array[i] = false; - }; - - return array; -} - -module.exports = defaultValue; - -},{}],25:[function(require,module,exports){ - -var mapType = require('./mapType'); -var mapSize = require('./mapSize'); - /** - * Extracts the attributes - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the attributes from - * @return attributes {Object} + * Loads this resources using an HTMLAudioElement or HTMLVideoElement. + * + * @private */ -var extractAttributes = function(gl, program) -{ - var attributes = {}; +Resource.prototype._loadElement = function (type) { + if (type === 'audio' && typeof Audio !== 'undefined') { + this.data = new Audio(); + } + else { + this.data = document.createElement(type); + } - var totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES) + if (this.data === null) { + this.error = new Error('Unsupported element ' + type); + this.complete(); + return; + } - for (var i = 0; i < totalAttributes; i++) - { - var attribData = gl.getActiveAttrib(program, i); - var type = mapType(gl, attribData.type); - - attributes[attribData.name] = { - type:type, - size:mapSize(type), - location:gl.getAttribLocation(program, attribData.name), - //TODO - make an attribute object - pointer:function(type, normalized, stride, start){ - - // console.log(this.location) - gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); - + // support for CocoonJS Canvas+ runtime, lacks document.createElement('source') + if (navigator.isCocoonJS) { + this.data.src = Array.isArray(this.url) ? this.url[0] : this.url; + } + else { + if (Array.isArray(this.url)) { + for (var i = 0; i < this.url.length; ++i) { + this.data.appendChild(this._createSource(type, this.url[i])); } } - }; - - return attributes; -} - -module.exports = extractAttributes; - -},{"./mapSize":28,"./mapType":29}],26:[function(require,module,exports){ -var mapType = require('./mapType'); -var defaultValue = require('./defaultValue'); - -/** - * Extracts the uniforms - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the uniforms from - * @return uniforms {Object} - */ -var extractUniforms = function(gl, program) -{ - var uniforms = {}; - - var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) - - for (var i = 0; i < totalUniforms; i++) - { - var uniformData = gl.getActiveUniform(program, i); - var name = uniformData.name.replace(/\[.*?\]/, ""); - var type = mapType(gl, uniformData.type ); - - uniforms[name] = { - type:type, - size:uniformData.size, - location:gl.getUniformLocation(program, name), - value:defaultValue(type, uniformData.size) - } - }; - - return uniforms; -} - -module.exports = extractUniforms; - -},{"./defaultValue":24,"./mapType":29}],27:[function(require,module,exports){ -/** - * Extracts the attributes - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param uniforms {Array} @mat ? - * @return attributes {Object} - */ -var generateUniformAccessObject = function(gl, uniformData) -{ - // this is the object we will be sending back. - // an object hierachy will be created for structs - var uniforms = {data:{}}; - - uniforms.gl = gl; - - var uniformKeys= Object.keys(uniformData); - - for (var i = 0; i < uniformKeys.length; i++) - { - var fullName = uniformKeys[i] - - var nameTokens = fullName.split('.'); - var name = nameTokens[nameTokens.length - 1]; - - var uniformGroup = getUniformGroup(nameTokens, uniforms); - - var uniform = uniformData[fullName]; - uniformGroup.data[name] = uniform; - - uniformGroup.gl = gl; - - Object.defineProperty(uniformGroup, name, { - get: generateGetter(name), - set: generateSetter(name, uniform) - }) - }; - - return uniforms; -} - -var generateGetter = function(name) -{ - var template = getterTemplate.replace('%%', name); - return new Function(template); -} - -var generateSetter = function(name, uniform) -{ - var template = setterTemplate.replace(/%%/g, name); - var setTemplate - - if(uniform.size === 1) - { - setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; - } - else - { - setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; - } - - if(setTemplate) - { - template += "\nthis.gl." + setTemplate + ";"; - } - - return new Function('value', template); -} - -var getUniformGroup = function(nameTokens, uniform) -{ - var cur = uniform; - - for (var i = 0; i < nameTokens.length - 1; i++) - { - var o = cur[nameTokens[i]] || {data:{}}; - cur[nameTokens[i]] = o; - cur = o; - }; - - return cur -} - -var getterTemplate = [ - 'return this.data.%%.value;', -].join('\n'); - -var setterTemplate = [ - 'this.data.%%.value = value;', - 'var location = this.data.%%.location;' -].join('\n'); - - -var GLSL_TO_SINGLE_SETTERS = { - - 'float': 'uniform1f(location, value)', - - 'vec2': 'uniform2f(location, value[0], value[1])', - 'vec3': 'uniform3f(location, value[0], value[1], value[2])', - 'vec4': 'uniform4f(location, value[0], value[1], value[2], value[3])', - - 'int': 'uniform1i(location, value)', - 'ivec2': 'uniform2i(location, value[0], value[1])', - 'ivec3': 'uniform3i(location, value[0], value[1], value[2])', - 'ivec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', - - 'bool': 'uniform1i(location, value)', - 'bvec2': 'uniform2i(location, value[0], value[1])', - 'bvec3': 'uniform3i(location, value[0], value[1], value[2])', - 'bvec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', - - 'mat2': 'uniformMatrix2fv(location, false, value)', - 'mat3': 'uniformMatrix3fv(location, false, value)', - 'mat4': 'uniformMatrix4fv(location, false, value)', - - 'sampler2D':'uniform1i(location, value)' -} - -var GLSL_TO_ARRAY_SETTERS = { - - 'float': 'uniform1fv(location, value)', - - 'vec2': 'uniform2fv(location, value)', - 'vec3': 'uniform3fv(location, value)', - 'vec4': 'uniform4fv(location, value)', - - 'int': 'uniform1iv(location, value)', - 'ivec2': 'uniform2iv(location, value)', - 'ivec3': 'uniform3iv(location, value)', - 'ivec4': 'uniform4iv(location, value)', - - 'bool': 'uniform1iv(location, value)', - 'bvec2': 'uniform2iv(location, value)', - 'bvec3': 'uniform3iv(location, value)', - 'bvec4': 'uniform4iv(location, value)', - - 'sampler2D':'uniform1iv(location, value)' -} - -module.exports = generateUniformAccessObject; - -},{}],28:[function(require,module,exports){ - - -var mapSize = function(type) -{ - return GLSL_TO_SIZE[type]; -} - - -var GLSL_TO_SIZE = { - 'float': 1, - 'vec2': 2, - 'vec3': 3, - 'vec4': 4, - - 'int': 1, - 'ivec2': 2, - 'ivec3': 3, - 'ivec4': 4, - - 'bool': 1, - 'bvec2': 2, - 'bvec3': 3, - 'bvec4': 4, - - 'mat2': 4, - 'mat3': 9, - 'mat4': 16, - - 'sampler2D': 1 -} - -module.exports = mapSize; - -},{}],29:[function(require,module,exports){ - - -var mapSize = function(gl, type) -{ - if(!GL_TABLE) - { - var typeNames = Object.keys(GL_TO_GLSL_TYPES); - - GL_TABLE = {}; - - for(var i = 0; i < typeNames.length; ++i) - { - var tn = typeNames[i]; - GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn]; + else { + this.data.appendChild(this._createSource(type, this.url)); } } - return GL_TABLE[type]; + this['is' + type[0].toUpperCase() + type.substring(1)] = true; + + this.data.addEventListener('error', this._boundOnError, false); + this.data.addEventListener('load', this._boundComplete, false); + this.data.addEventListener('progress', this._boundOnProgress, false); + this.data.addEventListener('canplaythrough', this._boundComplete, false); + + this.data.load(); +}; + +/** + * Loads this resources using an XMLHttpRequest. + * + * @private + */ +Resource.prototype._loadXhr = function () { + // if unset, determine the value + if (typeof this.xhrType !== 'string') { + this.xhrType = this._determineXhrType(); + } + + var xhr = this.xhr = new XMLHttpRequest(); + + // set the request type and url + xhr.open('GET', this.url, true); + + // load json as text and parse it ourselves. We do this because some browsers + // *cough* safari *cough* can't deal with it. + if (this.xhrType === Resource.XHR_RESPONSE_TYPE.JSON || this.xhrType === Resource.XHR_RESPONSE_TYPE.DOCUMENT) { + xhr.responseType = Resource.XHR_RESPONSE_TYPE.TEXT; + } + else { + xhr.responseType = this.xhrType; + } + + xhr.addEventListener('error', this._boundXhrOnError, false); + xhr.addEventListener('abort', this._boundXhrOnAbort, false); + xhr.addEventListener('progress', this._boundOnProgress, false); + xhr.addEventListener('load', this._boundXhrOnLoad, false); + + xhr.send(); +}; + +/** + * Loads this resources using an XDomainRequest. This is here because we need to support IE9 (gross). + * + * @private + */ +Resource.prototype._loadXdr = function () { + // if unset, determine the value + if (typeof this.xhrType !== 'string') { + this.xhrType = this._determineXhrType(); + } + + var xdr = this.xhr = new XDomainRequest(); + + // XDomainRequest has a few quirks. Occasionally it will abort requests + // A way to avoid this is to make sure ALL callbacks are set even if not used + // More info here: http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9 + xdr.timeout = 5000; + + xdr.onerror = this._boundXhrOnError; + xdr.ontimeout = this._boundXdrOnTimeout; + xdr.onprogress = this._boundOnProgress; + xdr.onload = this._boundXhrOnLoad; + + xdr.open('GET', this.url, true); + + // Note: The xdr.send() call is wrapped in a timeout to prevent an issue with the interface where some requests are lost + // if multiple XDomainRequests are being sent at the same time. + // Some info here: https://github.com/photonstorm/phaser/issues/1248 + setTimeout(function () { + xdr.send(); + }, 0); +}; + +/** + * Creates a source used in loading via an element. + * + * @param type {string} The element type (video or audio). + * @param url {string} The source URL to load from. + * @param [mime] {string} The mime type of the video + * @private + */ +Resource.prototype._createSource = function (type, url, mime) { + if (!mime) { + mime = type + '/' + url.substr(url.lastIndexOf('.') + 1); + } + + var source = document.createElement('source'); + + source.src = url; + source.type = mime; + + return source; +}; + +/** + * Called if a load errors out. + * + * @param event {Event} The error event from the element that emits it. + * @private + */ +Resource.prototype._onError = function (event) { + this.error = new Error('Failed to load element using ' + event.target.nodeName); + this.complete(); +}; + +/** + * Called if a load progress event fires for xhr/xdr. + * + * @fires progress + * @param event {XMLHttpRequestProgressEvent|Event} + * @private + */ +Resource.prototype._onProgress = function (event) { + if (event && event.lengthComputable) { + this.emit('progress', this, event.loaded / event.total); + } +}; + +/** + * Called if an error event fires for xhr/xdr. + * + * @param event {XMLHttpRequestErrorEvent|Event} + * @private + */ +Resource.prototype._xhrOnError = function () { + this.error = new Error( + reqType(this.xhr) + ' Request failed. ' + + 'Status: ' + this.xhr.status + ', text: "' + this.xhr.statusText + '"' + ); + + this.complete(); +}; + +/** + * Called if an abort event fires for xhr. + * + * @param event {XMLHttpRequestAbortEvent} + * @private + */ +Resource.prototype._xhrOnAbort = function () { + this.error = new Error(reqType(this.xhr) + ' Request was aborted by the user.'); + this.complete(); +}; + +/** + * Called if a timeout event fires for xdr. + * + * @param event {Event} + * @private + */ +Resource.prototype._xdrOnTimeout = function () { + this.error = new Error(reqType(this.xhr) + ' Request timed out.'); + this.complete(); +}; + +/** + * Called when data successfully loads from an xhr/xdr request. + * + * @param event {XMLHttpRequestLoadEvent|Event} + * @private + */ +Resource.prototype._xhrOnLoad = function () { + var xhr = this.xhr, + status = xhr.status !== undefined ? xhr.status : 200; //XDR has no `.status`, assume 200. + + // status can be 0 when using the file:// protocol, also check if a response was found + if (status === 200 || status === 204 || (status === 0 && xhr.responseText.length > 0)) { + // if text, just return it + if (this.xhrType === Resource.XHR_RESPONSE_TYPE.TEXT) { + this.data = xhr.responseText; + } + // if json, parse into json object + else if (this.xhrType === Resource.XHR_RESPONSE_TYPE.JSON) { + try { + this.data = JSON.parse(xhr.responseText); + this.isJson = true; + } catch(e) { + this.error = new Error('Error trying to parse loaded json:', e); + } + } + // if xml, parse into an xml document or div element + else if (this.xhrType === Resource.XHR_RESPONSE_TYPE.DOCUMENT) { + try { + if (window.DOMParser) { + var domparser = new DOMParser(); + this.data = domparser.parseFromString(xhr.responseText, 'text/xml'); + } + else { + var div = document.createElement('div'); + div.innerHTML = xhr.responseText; + this.data = div; + } + this.isXml = true; + } catch (e) { + this.error = new Error('Error trying to parse loaded xml:', e); + } + } + // other types just return the response + else { + this.data = xhr.response || xhr.responseText; + } + } + else { + this.error = new Error('[' + xhr.status + ']' + xhr.statusText + ':' + xhr.responseURL); + } + + this.complete(); +}; + +function reqType(xhr) { + return xhr.toString().replace('object ', ''); } -var GL_TABLE = null; +/** + * Sets the `crossOrigin` property for this resource based on if the url + * for this resource is cross-origin. If crossOrigin was manually set, this + * function does nothing. + * + * @private + * @param url {string} The url to test. + * @param [location=window.location] {object} The location object to test against. + * @return {string} The crossOrigin value to use (or empty string for none). + */ +Resource.prototype._determineCrossOrigin = function (url, loc) { + // data: and javascript: urls are considered same-origin + if (url.indexOf('data:') === 0) { + return ''; + } -var GL_TO_GLSL_TYPES = { - 'FLOAT': 'float', - 'FLOAT_VEC2': 'vec2', - 'FLOAT_VEC3': 'vec3', - 'FLOAT_VEC4': 'vec4', + // default is window.location + loc = loc || window.location; - 'INT': 'int', - 'INT_VEC2': 'ivec2', - 'INT_VEC3': 'ivec3', - 'INT_VEC4': 'ivec4', - - 'BOOL': 'bool', - 'BOOL_VEC2': 'bvec2', - 'BOOL_VEC3': 'bvec3', - 'BOOL_VEC4': 'bvec4', - - 'FLOAT_MAT2': 'mat2', - 'FLOAT_MAT3': 'mat3', - 'FLOAT_MAT4': 'mat4', - - 'SAMPLER_2D': 'sampler2D' + if (!tempAnchor) { + tempAnchor = document.createElement('a'); + } + + // let the browser determine the full href for the url of this resource and then + // parse with the node url lib, we can't use the properties of the anchor element + // because they don't work in IE9 :( + tempAnchor.href = url; + url = _url.parse(tempAnchor.href); + + var samePort = (!url.port && loc.port === '') || (url.port === loc.port); + + // if cross origin + if (url.hostname !== loc.hostname || !samePort || url.protocol !== loc.protocol) { + return 'anonymous'; + } + + return ''; +}; + +/** + * Determines the responseType of an XHR request based on the extension of the + * resource being loaded. + * + * @private + * @return {Resource.XHR_RESPONSE_TYPE} The responseType to use. + */ +Resource.prototype._determineXhrType = function () { + return Resource._xhrTypeMap[this._getExtension()] || Resource.XHR_RESPONSE_TYPE.TEXT; +}; + +Resource.prototype._determineLoadType = function () { + return Resource._loadTypeMap[this._getExtension()] || Resource.LOAD_TYPE.XHR; +}; + +Resource.prototype._getExtension = function () { + var url = this.url, + ext; + + if (this.isDataUrl) { + var slashIndex = url.indexOf('/'); + ext = url.substring(slashIndex + 1, url.indexOf(';', slashIndex)); + } + else { + var queryStart = url.indexOf('?'); + if (queryStart !== -1) { + url = url.substring(0, queryStart); + } + + ext = url.substring(url.lastIndexOf('.') + 1); + } + + return ext; +}; + +/** + * Determines the mime type of an XHR request based on the responseType of + * resource being loaded. + * + * @private + * @return {string} The mime type to use. + */ +Resource.prototype._getMimeFromXhrType = function (type) { + switch(type) { + case Resource.XHR_RESPONSE_TYPE.BUFFER: + return 'application/octet-binary'; + + case Resource.XHR_RESPONSE_TYPE.BLOB: + return 'application/blob'; + + case Resource.XHR_RESPONSE_TYPE.DOCUMENT: + return 'application/xml'; + + case Resource.XHR_RESPONSE_TYPE.JSON: + return 'application/json'; + + case Resource.XHR_RESPONSE_TYPE.DEFAULT: + case Resource.XHR_RESPONSE_TYPE.TEXT: + /* falls through */ + default: + return 'text/plain'; + + } +}; + +/** + * The types of loading a resource can use. + * + * @static + * @constant + * @property {object} LOAD_TYPE + * @property {number} LOAD_TYPE.XHR - Uses XMLHttpRequest to load the resource. + * @property {number} LOAD_TYPE.IMAGE - Uses an `Image` object to load the resource. + * @property {number} LOAD_TYPE.AUDIO - Uses an `Audio` object to load the resource. + * @property {number} LOAD_TYPE.VIDEO - Uses a `Video` object to load the resource. + */ +Resource.LOAD_TYPE = { + XHR: 1, + IMAGE: 2, + AUDIO: 3, + VIDEO: 4 +}; + +/** + * The XHR ready states, used internally. + * + * @static + * @constant + * @property {object} XHR_READY_STATE + * @property {number} XHR_READY_STATE.UNSENT - open()has not been called yet. + * @property {number} XHR_READY_STATE.OPENED - send()has not been called yet. + * @property {number} XHR_READY_STATE.HEADERS_RECEIVED - send() has been called, and headers and status are available. + * @property {number} XHR_READY_STATE.LOADING - Downloading; responseText holds partial data. + * @property {number} XHR_READY_STATE.DONE - The operation is complete. + */ +Resource.XHR_READY_STATE = { + UNSENT: 0, + OPENED: 1, + HEADERS_RECEIVED: 2, + LOADING: 3, + DONE: 4 +}; + +/** + * The XHR ready states, used internally. + * + * @static + * @constant + * @property {object} XHR_RESPONSE_TYPE + * @property {string} XHR_RESPONSE_TYPE.DEFAULT - defaults to text + * @property {string} XHR_RESPONSE_TYPE.BUFFER - ArrayBuffer + * @property {string} XHR_RESPONSE_TYPE.BLOB - Blob + * @property {string} XHR_RESPONSE_TYPE.DOCUMENT - Document + * @property {string} XHR_RESPONSE_TYPE.JSON - Object + * @property {string} XHR_RESPONSE_TYPE.TEXT - String + */ +Resource.XHR_RESPONSE_TYPE = { + DEFAULT: 'text', + BUFFER: 'arraybuffer', + BLOB: 'blob', + DOCUMENT: 'document', + JSON: 'json', + TEXT: 'text' +}; + +Resource._loadTypeMap = { + 'gif': Resource.LOAD_TYPE.IMAGE, + 'png': Resource.LOAD_TYPE.IMAGE, + 'bmp': Resource.LOAD_TYPE.IMAGE, + 'jpg': Resource.LOAD_TYPE.IMAGE, + 'jpeg': Resource.LOAD_TYPE.IMAGE, + 'tif': Resource.LOAD_TYPE.IMAGE, + 'tiff': Resource.LOAD_TYPE.IMAGE, + 'webp': Resource.LOAD_TYPE.IMAGE, + 'tga': Resource.LOAD_TYPE.IMAGE +}; + +Resource._xhrTypeMap = { + // xml + 'xhtml': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'html': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'htm': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'xml': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'tmx': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'tsx': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'svg': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + + // images + 'gif': Resource.XHR_RESPONSE_TYPE.BLOB, + 'png': Resource.XHR_RESPONSE_TYPE.BLOB, + 'bmp': Resource.XHR_RESPONSE_TYPE.BLOB, + 'jpg': Resource.XHR_RESPONSE_TYPE.BLOB, + 'jpeg': Resource.XHR_RESPONSE_TYPE.BLOB, + 'tif': Resource.XHR_RESPONSE_TYPE.BLOB, + 'tiff': Resource.XHR_RESPONSE_TYPE.BLOB, + 'webp': Resource.XHR_RESPONSE_TYPE.BLOB, + 'tga': Resource.XHR_RESPONSE_TYPE.BLOB, + + // json + 'json': Resource.XHR_RESPONSE_TYPE.JSON, + + // text + 'text': Resource.XHR_RESPONSE_TYPE.TEXT, + 'txt': Resource.XHR_RESPONSE_TYPE.TEXT +}; + +/** + * Sets the load type to be used for a specific extension. + * + * @static + * @param extname {string} The extension to set the type for, e.g. "png" or "fnt" + * @param loadType {Resource.LOAD_TYPE} The load type to set it to. + */ +Resource.setExtensionLoadType = function (extname, loadType) { + setExtMap(Resource._loadTypeMap, extname, loadType); +}; + +/** + * Sets the load type to be used for a specific extension. + * + * @static + * @param extname {string} The extension to set the type for, e.g. "png" or "fnt" + * @param xhrType {Resource.XHR_RESPONSE_TYPE} The xhr type to set it to. + */ +Resource.setExtensionXhrType = function (extname, xhrType) { + setExtMap(Resource._xhrTypeMap, extname, xhrType); +}; + +function setExtMap(map, extname, val) { + if (extname && extname.indexOf('.') === 0) { + extname = extname.substring(1); + } + + if (!extname) { + return; + } + + map[extname] = val; } -module.exports = mapSize; +},{"eventemitter3":25,"url":23}],31:[function(require,module,exports){ +module.exports = { -},{}],30:[function(require,module,exports){ + // private property + _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", + + encodeBinary: function (input) { + var output = ""; + var bytebuffer; + var encodedCharIndexes = new Array(4); + var inx = 0; + var jnx = 0; + var paddingBytes = 0; + + while (inx < input.length) { + // Fill byte buffer array + bytebuffer = new Array(3); + for (jnx = 0; jnx < bytebuffer.length; jnx++) { + if (inx < input.length) { + // throw away high-order byte, as documented at: + // https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data + bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff; + } + else { + bytebuffer[jnx] = 0; + } + } + + // Get each encoded character, 6 bits at a time + // index 1: first 6 bits + encodedCharIndexes[0] = bytebuffer[0] >> 2; + // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2) + encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4); + // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3) + encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6); + // index 3: forth 6 bits (6 least significant bits from input byte 3) + encodedCharIndexes[3] = bytebuffer[2] & 0x3f; + + // Determine whether padding happened, and adjust accordingly + paddingBytes = inx - (input.length - 1); + switch (paddingBytes) { + case 2: + // Set last 2 characters to padding char + encodedCharIndexes[3] = 64; + encodedCharIndexes[2] = 64; + break; + + case 1: + // Set last character to padding char + encodedCharIndexes[3] = 64; + break; + + default: + break; // No padding - proceed + } + + // Now we will grab each appropriate character out of our keystring + // based on our index array and append it to the output string + for (jnx = 0; jnx < encodedCharIndexes.length; jnx++) { + output += this._keyStr.charAt(encodedCharIndexes[jnx]); + } + } + return output; + } +}; + +},{}],32:[function(require,module,exports){ +module.exports = require('./Loader'); + +module.exports.Resource = require('./Resource'); + +module.exports.middleware = { + caching: { + memory: require('./middlewares/caching/memory') + }, + parsing: { + blob: require('./middlewares/parsing/blob') + } +}; + +},{"./Loader":29,"./Resource":30,"./middlewares/caching/memory":33,"./middlewares/parsing/blob":34}],33:[function(require,module,exports){ +// a simple in-memory cache for resources +var cache = {}; + +module.exports = function () { + return function (resource, next) { + // if cached, then set data and complete the resource + if (cache[resource.url]) { + resource.data = cache[resource.url]; + resource.complete(); + } + // if not cached, wait for complete and store it in the cache. + else { + resource.once('complete', function () { + cache[this.url] = this.data; + }); + } + + next(); + }; +}; + +},{}],34:[function(require,module,exports){ +var Resource = require('../../Resource'), + b64 = require('../../b64'); + +window.URL = window.URL || window.webkitURL; + +// a middleware for transforming XHR loaded Blobs into more useful objects + +module.exports = function () { + return function (resource, next) { + if (!resource.data) { + return next(); + } + + // if this was an XHR load of a blob + if (resource.xhr && resource.xhrType === Resource.XHR_RESPONSE_TYPE.BLOB) { + // if there is no blob support we probably got a binary string back + if (!window.Blob || typeof resource.data === 'string') { + var type = resource.xhr.getResponseHeader('content-type'); + + // this is an image, convert the binary string into a data url + if (type && type.indexOf('image') === 0) { + resource.data = new Image(); + resource.data.src = 'data:' + type + ';base64,' + b64.encodeBinary(resource.xhr.responseText); + + resource.isImage = true; + + // wait until the image loads and then callback + resource.data.onload = function () { + resource.data.onload = null; + + next(); + }; + } + } + // if content type says this is an image, then we should transform the blob into an Image object + else if (resource.data.type.indexOf('image') === 0) { + var src = URL.createObjectURL(resource.data); + + resource.blob = resource.data; + resource.data = new Image(); + resource.data.src = src; + + resource.isImage = true; + + // cleanup the no longer used blob after the image loads + resource.data.onload = function () { + URL.revokeObjectURL(src); + resource.data.onload = null; + + next(); + }; + } + } + else { + next(); + } + }; +}; + +},{"../../Resource":30,"../../b64":31}],35:[function(require,module,exports){ var core = require('../core'); // add some extra variables to the container.. @@ -6000,7 +7435,7 @@ core.WebGLRenderer.registerPlugin('accessibility', AccessibilityManager); core.CanvasRenderer.registerPlugin('accessibility', AccessibilityManager); -},{"../core":51,"./accessibleTarget":31}],31:[function(require,module,exports){ +},{"../core":56,"./accessibleTarget":36}],36:[function(require,module,exports){ /** * Default property values of accessible objects * used by {@link PIXI.accessibility.AccessibilityManager}. @@ -6046,7 +7481,7 @@ module.exports = accessibleTarget; -},{}],32:[function(require,module,exports){ +},{}],37:[function(require,module,exports){ /** * @file Main export of the PIXI accessibility library * @author Mat Groves @@ -6062,7 +7497,7 @@ AccessibilityManager: require('./AccessibilityManager') }; -},{"./AccessibilityManager":30,"./accessibleTarget":31}],33:[function(require,module,exports){ +},{"./AccessibilityManager":35,"./accessibleTarget":36}],38:[function(require,module,exports){ /** * Constant values used in pixi @@ -6318,9 +7753,9 @@ module.exports = CONST; -},{"./utils/maxRecommendedTextures":100}],34:[function(require,module,exports){ -arguments[4][33][0].apply(exports,arguments) -},{"./utils/maxRecommendedTextures":100,"dup":33}],35:[function(require,module,exports){ +},{"./utils/maxRecommendedTextures":106}],39:[function(require,module,exports){ +arguments[4][38][0].apply(exports,arguments) +},{"./utils/maxRecommendedTextures":106,"dup":38}],40:[function(require,module,exports){ var math = require('../math'), utils = require('../utils'), DisplayObject = require('./DisplayObject'), @@ -6745,9 +8180,11 @@ continue; } - childVisible = true; - childBounds = this.children[i].getBounds(); + if (childBounds === math.Rectangle.EMPTY) { + continue; + } + childVisible = true; minX = minX < childBounds.x ? minX : childBounds.x; minY = minY < childBounds.y ? minY : childBounds.y; @@ -6761,7 +8198,7 @@ if (!childVisible) { - return math.Rectangle.EMPTY; + return this._currentBounds = math.Rectangle.EMPTY; } var bounds = this._bounds; @@ -6947,7 +8384,7 @@ this.children = null; }; -},{"../math":55,"../textures/RenderTexture":92,"../utils":99,"./DisplayObject":36}],36:[function(require,module,exports){ +},{"../math":60,"../textures/RenderTexture":97,"../utils":105,"./DisplayObject":41}],41:[function(require,module,exports){ var math = require('../math'), RenderTexture = require('../textures/RenderTexture'), EventEmitter = require('eventemitter3'), @@ -7063,7 +8500,7 @@ }, set: function (value) { - this.position.x = value; + this.transform.position.x = value; } }, @@ -7080,7 +8517,7 @@ }, set: function (value) { - this.position.y = value; + this.transform.position.y = value; } }, @@ -7446,7 +8883,7 @@ this.filterArea = null; }; -},{"../math":55,"../textures/RenderTexture":92,"./Transform":38,"eventemitter3":12}],37:[function(require,module,exports){ +},{"../math":60,"../textures/RenderTexture":97,"./Transform":43,"eventemitter3":25}],42:[function(require,module,exports){ /** * The Point object represents a location in a two-dimensional coordinate system, where x represents * the horizontal axis and y represents the vertical axis. @@ -7523,7 +8960,7 @@ this.transform._versionLocal++; }; -},{}],38:[function(require,module,exports){ +},{}],43:[function(require,module,exports){ var math = require('../math'), ObservablePoint = require('./ObservablePoint'); @@ -7660,15 +9097,19 @@ module.exports = Transform; -},{"../math":55,"./ObservablePoint":37}],39:[function(require,module,exports){ +},{"../math":60,"./ObservablePoint":42}],44:[function(require,module,exports){ var Container = require('../display/Container'), RenderTexture = require('../textures/RenderTexture'), + Texture = require('../textures/Texture'), GraphicsData = require('./GraphicsData'), Sprite = require('../sprites/Sprite'), math = require('../math'), CONST = require('../const'), bezierCurveTo = require('./utils/bezierCurveTo'), - + CanvasRenderTarget = require('../renderers/canvas/utils/CanvasRenderTarget'), + CanvasRenderer = require('../renderers/canvas/CanvasRenderer'), + canvasRenderer, + tempMatrix = new math.Matrix(), tempPoint = new math.Point(); /** @@ -8672,6 +10113,30 @@ return data; }; +Graphics.prototype.generateCanvasTexture = function(scaleMode, resolution) +{ + resolution = resolution || 1; + + var bounds = this.getLocalBounds(); + + var canvasBuffer = new RenderTexture.create(bounds.width * resolution, bounds.height * resolution); + + if(!canvasRenderer) + { + canvasRenderer = new CanvasRenderer(); + } + + tempMatrix.tx = -bounds.x; + tempMatrix.ty = -bounds.y; + + canvasRenderer.render(this, canvasBuffer, false, tempMatrix); + + var texture = Texture.fromCanvas(canvasBuffer.baseTexture._canvasRenderTarget.canvas, scaleMode); + texture.baseTexture.resolution = resolution; + + return texture; +} + /** * Destroys the Graphics object. */ @@ -8698,7 +10163,7 @@ this._localBounds = null; }; -},{"../const":34,"../display/Container":35,"../math":55,"../sprites/Sprite":83,"../textures/RenderTexture":92,"./GraphicsData":40,"./utils/bezierCurveTo":42}],40:[function(require,module,exports){ +},{"../const":39,"../display/Container":40,"../math":60,"../renderers/canvas/CanvasRenderer":67,"../renderers/canvas/utils/CanvasRenderTarget":69,"../sprites/Sprite":88,"../textures/RenderTexture":97,"../textures/Texture":98,"./GraphicsData":45,"./utils/bezierCurveTo":47}],45:[function(require,module,exports){ /** * A GraphicsData object. * @@ -8791,7 +10256,7 @@ this.shape = null; }; -},{}],41:[function(require,module,exports){ +},{}],46:[function(require,module,exports){ var CanvasRenderer = require('../../renderers/canvas/CanvasRenderer'), CONST = require('../../const'); @@ -9070,7 +10535,7 @@ this.renderer = null; }; -},{"../../const":34,"../../renderers/canvas/CanvasRenderer":62}],42:[function(require,module,exports){ +},{"../../const":39,"../../renderers/canvas/CanvasRenderer":67}],47:[function(require,module,exports){ /** * Calculate the points for a bezier curve and then draws it. @@ -9118,7 +10583,7 @@ module.exports = bezierCurveTo; -},{}],43:[function(require,module,exports){ +},{}],48:[function(require,module,exports){ var utils = require('../../utils'), CONST = require('../../const'), ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), @@ -9339,7 +10804,7 @@ return webGLData; }; -},{"../../const":34,"../../renderers/webgl/WebGLRenderer":68,"../../renderers/webgl/utils/ObjectRenderer":78,"../../utils":99,"./WebGLGraphicsData":44,"./shaders/PrimitiveShader":45,"./utils/buildCircle":46,"./utils/buildPoly":48,"./utils/buildRectangle":49,"./utils/buildRoundedRectangle":50}],44:[function(require,module,exports){ +},{"../../const":39,"../../renderers/webgl/WebGLRenderer":73,"../../renderers/webgl/utils/ObjectRenderer":83,"../../utils":105,"./WebGLGraphicsData":49,"./shaders/PrimitiveShader":50,"./utils/buildCircle":51,"./utils/buildPoly":53,"./utils/buildRectangle":54,"./utils/buildRoundedRectangle":55}],49:[function(require,module,exports){ var glCore = require('pixi-gl-core'); @@ -9464,7 +10929,7 @@ this.glIndices = null; }; -},{"pixi-gl-core":15}],45:[function(require,module,exports){ +},{"pixi-gl-core":1}],50:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; /** @@ -9515,7 +10980,7 @@ module.exports = PrimitiveShader; -},{"pixi-gl-core":15}],46:[function(require,module,exports){ +},{"pixi-gl-core":1}],51:[function(require,module,exports){ var buildLine = require('./buildLine'), CONST = require('../../../const'), utils = require('../../../utils'); @@ -9604,7 +11069,7 @@ module.exports = buildCircle; -},{"../../../const":34,"../../../utils":99,"./buildLine":47}],47:[function(require,module,exports){ +},{"../../../const":39,"../../../utils":105,"./buildLine":52}],52:[function(require,module,exports){ var math = require('../../../math'), utils = require('../../../utils'); @@ -9824,7 +11289,7 @@ }; module.exports = buildLine; -},{"../../../math":55,"../../../utils":99}],48:[function(require,module,exports){ +},{"../../../math":60,"../../../utils":105}],53:[function(require,module,exports){ var buildLine = require('./buildLine'), utils = require('../../../utils'), earcut = require('earcut'); @@ -9904,7 +11369,7 @@ module.exports = buildPoly; -},{"../../../utils":99,"./buildLine":47,"earcut":11}],49:[function(require,module,exports){ +},{"../../../utils":105,"./buildLine":52,"earcut":24}],54:[function(require,module,exports){ var buildLine = require('./buildLine'), utils = require('../../../utils'); @@ -9975,7 +11440,7 @@ }; module.exports = buildRectangle; -},{"../../../utils":99,"./buildLine":47}],50:[function(require,module,exports){ +},{"../../../utils":105,"./buildLine":52}],55:[function(require,module,exports){ var earcut = require('earcut'), // buildLine = require('./buildLine'), utils = require('../../../utils'); @@ -10105,7 +11570,7 @@ module.exports = buildRoundedRectangle; -},{"../../../utils":99,"earcut":11}],51:[function(require,module,exports){ +},{"../../../utils":105,"earcut":24}],56:[function(require,module,exports){ /** * @file Main export of the PIXI core library * @author Mat Groves @@ -10198,7 +11663,7 @@ } }); -},{"./const":34,"./display/Container":35,"./display/DisplayObject":36,"./graphics/Graphics":39,"./graphics/GraphicsData":40,"./graphics/canvas/CanvasGraphicsRenderer":41,"./graphics/webgl/GraphicsRenderer":43,"./math":55,"./renderers/canvas/CanvasRenderer":62,"./renderers/canvas/utils/CanvasRenderTarget":64,"./renderers/webgl/WebGLRenderer":68,"./renderers/webgl/filters/Filter":70,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":73,"./renderers/webgl/managers/WebGLManager":77,"./renderers/webgl/utils/ObjectRenderer":78,"./renderers/webgl/utils/Quad":79,"./renderers/webgl/utils/RenderTarget":80,"./sprites/Sprite":83,"./sprites/canvas/CanvasSpriteRenderer":84,"./sprites/webgl/SpriteRenderer":87,"./text/Text":89,"./textures/BaseRenderTexture":90,"./textures/BaseTexture":91,"./textures/RenderTexture":92,"./textures/Texture":93,"./textures/TextureUvs":94,"./textures/VideoBaseTexture":95,"./ticker":97,"./utils":99,"pixi-gl-core":15}],52:[function(require,module,exports){ +},{"./const":39,"./display/Container":40,"./display/DisplayObject":41,"./graphics/Graphics":44,"./graphics/GraphicsData":45,"./graphics/canvas/CanvasGraphicsRenderer":46,"./graphics/webgl/GraphicsRenderer":48,"./math":60,"./renderers/canvas/CanvasRenderer":67,"./renderers/canvas/utils/CanvasRenderTarget":69,"./renderers/webgl/WebGLRenderer":73,"./renderers/webgl/filters/Filter":75,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":78,"./renderers/webgl/managers/WebGLManager":82,"./renderers/webgl/utils/ObjectRenderer":83,"./renderers/webgl/utils/Quad":84,"./renderers/webgl/utils/RenderTarget":85,"./sprites/Sprite":88,"./sprites/canvas/CanvasSpriteRenderer":89,"./sprites/webgl/SpriteRenderer":92,"./text/Text":94,"./textures/BaseRenderTexture":95,"./textures/BaseTexture":96,"./textures/RenderTexture":97,"./textures/Texture":98,"./textures/TextureUvs":99,"./textures/VideoBaseTexture":100,"./ticker":102,"./utils":105,"pixi-gl-core":1}],57:[function(require,module,exports){ // Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group of order 16 var ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1]; @@ -10362,7 +11827,7 @@ module.exports = GroupD8; -},{"./Matrix":53}],53:[function(require,module,exports){ +},{"./Matrix":58}],58:[function(require,module,exports){ // @todo - ignore the too many parameters warning for now // should either fix it or change the jshint config // jshint -W072 @@ -10803,7 +12268,7 @@ */ Matrix.TEMP_MATRIX = new Matrix(); -},{"./Point":54}],54:[function(require,module,exports){ +},{"./Point":59}],59:[function(require,module,exports){ /** * The Point object represents a location in a two-dimensional coordinate system, where x represents * the horizontal axis and y represents the vertical axis. @@ -10873,7 +12338,7 @@ this.y = y || ( (y !== 0) ? this.x : 0 ) ; }; -},{}],55:[function(require,module,exports){ +},{}],60:[function(require,module,exports){ /** * Math classes and utilities mixed into PIXI namespace. * @@ -10896,7 +12361,7 @@ RoundedRectangle: require('./shapes/RoundedRectangle') }; -},{"./GroupD8":52,"./Matrix":53,"./Point":54,"./shapes/Circle":56,"./shapes/Ellipse":57,"./shapes/Polygon":58,"./shapes/Rectangle":59,"./shapes/RoundedRectangle":60}],56:[function(require,module,exports){ +},{"./GroupD8":57,"./Matrix":58,"./Point":59,"./shapes/Circle":61,"./shapes/Ellipse":62,"./shapes/Polygon":63,"./shapes/Rectangle":64,"./shapes/RoundedRectangle":65}],61:[function(require,module,exports){ var Rectangle = require('./Rectangle'), CONST = require('../../const'); @@ -10984,7 +12449,7 @@ return new Rectangle(this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2); }; -},{"../../const":34,"./Rectangle":59}],57:[function(require,module,exports){ +},{"../../const":39,"./Rectangle":64}],62:[function(require,module,exports){ var Rectangle = require('./Rectangle'), CONST = require('../../const'); @@ -11079,7 +12544,7 @@ return new Rectangle(this.x - this.width, this.y - this.height, this.width, this.height); }; -},{"../../const":34,"./Rectangle":59}],58:[function(require,module,exports){ +},{"../../const":39,"./Rectangle":64}],63:[function(require,module,exports){ var Point = require('../Point'), CONST = require('../../const'); @@ -11182,7 +12647,7 @@ return inside; }; -},{"../../const":34,"../Point":54}],59:[function(require,module,exports){ +},{"../../const":39,"../Point":59}],64:[function(require,module,exports){ var CONST = require('../../const'); /** @@ -11336,7 +12801,19 @@ } }; -},{"../../const":34}],60:[function(require,module,exports){ +Rectangle.prototype.enlarge = function (rect) { + if (rect === Rectangle.EMPTY) return; + var x1 = Math.min(this.x, rect.x); + var x2 = Math.max(this.x + this.width, rect.x + rect.width); + var y1 = Math.min(this.y, rect.y); + var y2 = Math.max(this.y + this.height, rect.y + rect.height); + this.x = x1; + this.width = x2 - x1; + this.y = y1; + this.height = y2 - y1; +}; + +},{"../../const":39}],65:[function(require,module,exports){ var CONST = require('../../const'); /** @@ -11428,7 +12905,7 @@ return false; }; -},{"../../const":34}],61:[function(require,module,exports){ +},{"../../const":39}],66:[function(require,module,exports){ var utils = require('../utils'), math = require('../math'), CONST = require('../const'), @@ -11718,7 +13195,7 @@ this._lastObjectRendered = null; }; -},{"../const":34,"../display/Container":35,"../math":55,"../textures/RenderTexture":92,"../utils":99,"eventemitter3":12}],62:[function(require,module,exports){ +},{"../const":39,"../display/Container":40,"../math":60,"../textures/RenderTexture":97,"../utils":105,"eventemitter3":25}],67:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), CanvasMaskManager = require('./utils/CanvasMaskManager'), CanvasRenderTarget = require('./utils/CanvasRenderTarget'), @@ -11840,9 +13317,10 @@ if(renderTexture) { renderTexture = renderTexture.baseTexture || renderTexture; - + if(!renderTexture._canvasRenderTarget) { + renderTexture._canvasRenderTarget = new CanvasRenderTarget(renderTexture.width, renderTexture.height, renderTexture.resolution); renderTexture.source = renderTexture._canvasRenderTarget.canvas; renderTexture.valid = true; @@ -11972,7 +13450,7 @@ }; -},{"../../const":34,"../../utils":99,"../SystemRenderer":61,"./utils/CanvasMaskManager":63,"./utils/CanvasRenderTarget":64,"./utils/mapCanvasBlendModesToPixi":66}],63:[function(require,module,exports){ +},{"../../const":39,"../../utils":105,"../SystemRenderer":66,"./utils/CanvasMaskManager":68,"./utils/CanvasRenderTarget":69,"./utils/mapCanvasBlendModesToPixi":71}],68:[function(require,module,exports){ var CONST = require('../../../const'); /** * A set of functions used to handle masking. @@ -12135,7 +13613,7 @@ CanvasMaskManager.prototype.destroy = function () {}; -},{"../../../const":34}],64:[function(require,module,exports){ +},{"../../../const":39}],69:[function(require,module,exports){ var CONST = require('../../../const'); /** @@ -12239,7 +13717,7 @@ this.canvas = null; }; -},{"../../../const":34}],65:[function(require,module,exports){ +},{"../../../const":39}],70:[function(require,module,exports){ /** * Checks whether the Canvas BlendModes are supported by the current browser @@ -12278,7 +13756,7 @@ module.exports = canUseNewCanvasBlendModes; -},{}],66:[function(require,module,exports){ +},{}],71:[function(require,module,exports){ var CONST = require('../../../Const'), canUseNewCanvasBlendModes = require('./canUseNewCanvasBlendModes'); @@ -12338,7 +13816,7 @@ module.exports = mapWebGLBlendModesToPixi; -},{"../../../Const":33,"./canUseNewCanvasBlendModes":65}],67:[function(require,module,exports){ +},{"../../../Const":38,"./canUseNewCanvasBlendModes":70}],72:[function(require,module,exports){ var GLTexture = require('pixi-gl-core').GLTexture, CONST = require('../../const'), RenderTarget = require('./utils/RenderTarget'), @@ -12544,7 +14022,7 @@ module.exports = TextureManager; -},{"../../const":34,"../../utils":99,"./utils/RenderTarget":80,"pixi-gl-core":15}],68:[function(require,module,exports){ +},{"../../const":39,"../../utils":105,"./utils/RenderTarget":85,"pixi-gl-core":1}],73:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), MaskManager = require('./managers/MaskManager'), StencilManager = require('./managers/StencilManager'), @@ -13087,7 +14565,7 @@ // this = null; }; -},{"../../const":34,"../../utils":99,"../SystemRenderer":61,"./TextureManager":67,"./WebGLState":69,"./managers/FilterManager":74,"./managers/MaskManager":75,"./managers/StencilManager":76,"./utils/ObjectRenderer":78,"./utils/RenderTarget":80,"./utils/mapWebGLDrawModesToPixi":82,"pixi-gl-core":15}],69:[function(require,module,exports){ +},{"../../const":39,"../../utils":105,"../SystemRenderer":66,"./TextureManager":72,"./WebGLState":74,"./managers/FilterManager":79,"./managers/MaskManager":80,"./managers/StencilManager":81,"./utils/ObjectRenderer":83,"./utils/RenderTarget":85,"./utils/mapWebGLDrawModesToPixi":87,"pixi-gl-core":1}],74:[function(require,module,exports){ var mapWebGLBlendModesToPixi = require('./utils/mapWebGLBlendModesToPixi'); @@ -13357,7 +14835,7 @@ module.exports = WebGLState; -},{"./utils/mapWebGLBlendModesToPixi":81}],70:[function(require,module,exports){ +},{"./utils/mapWebGLBlendModesToPixi":86}],75:[function(require,module,exports){ var extractUniformsFromSrc = require('./extractUniformsFromSrc'); // var math = require('../../../math'); /** @@ -13485,7 +14963,7 @@ '}' ].join('\n'); -},{"./extractUniformsFromSrc":71}],71:[function(require,module,exports){ +},{"./extractUniformsFromSrc":76}],76:[function(require,module,exports){ var defaultValue = require('pixi-gl-core/lib/shader/defaultValue'); var mapSize = require('pixi-gl-core/lib/shader/mapSize'); @@ -13548,7 +15026,7 @@ module.exports = extractUniformsFromSrc; -},{"pixi-gl-core/lib/shader/defaultValue":24,"pixi-gl-core/lib/shader/mapSize":28}],72:[function(require,module,exports){ +},{"pixi-gl-core/lib/shader/defaultValue":10,"pixi-gl-core/lib/shader/mapSize":14}],77:[function(require,module,exports){ var math = require('../../../math'); /* @@ -13657,7 +15135,7 @@ calculateSpriteMatrix:calculateSpriteMatrix }; -},{"../../../math":55}],73:[function(require,module,exports){ +},{"../../../math":60}],78:[function(require,module,exports){ var Filter = require('../Filter'), math = require('../../../../math'); @@ -13676,8 +15154,8 @@ var maskMatrix = new math.Matrix(); Filter.call(this, - "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nuniform mat3 otherMatrix;\n\nvarying vec2 vMaskCoord;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n\n{\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n\n}\n\n", - "precision lowp float;\n#define GLSLIFY 1\n\nvarying vec2 vMaskCoord;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nuniform float alpha;\n\nuniform sampler2D mask;\n\nvoid main(void)\n\n{\n\n // check clip! this will stop the mask bleeding out from the edges\r\n vec2 text = abs( vMaskCoord - 0.5 );\n\n text = step(0.5, text);\n\n float clip = 1.0 - max(text.y, text.x);\n\n vec4 original = texture2D(uSampler, vTextureCoord);\n\n vec4 masky = texture2D(mask, vMaskCoord);\n\n original *= (masky.r * masky.a * alpha * clip);\n\n gl_FragColor = original;\n\n}\n\n" + "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nuniform mat3 otherMatrix;\n\nvarying vec2 vMaskCoord;\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n}\n", + "precision lowp float;\n#define GLSLIFY 1\n\nvarying vec2 vMaskCoord;\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float alpha;\nuniform sampler2D mask;\n\nvoid main(void)\n{\n // check clip! this will stop the mask bleeding out from the edges\n vec2 text = abs( vMaskCoord - 0.5 );\n text = step(0.5, text);\n float clip = 1.0 - max(text.y, text.x);\n vec4 original = texture2D(uSampler, vTextureCoord);\n vec4 masky = texture2D(mask, vMaskCoord);\n original *= (masky.r * masky.a * alpha * clip);\n gl_FragColor = original;\n}\n" ); sprite.renderable = false; @@ -13708,7 +15186,7 @@ filterManager.applyFilter(this, input, output); }; -},{"../../../../math":55,"../Filter":70}],74:[function(require,module,exports){ +},{"../../../../math":60,"../Filter":75}],79:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'), RenderTarget = require('../utils/RenderTarget'), @@ -14052,7 +15530,7 @@ FilterManager.pool[key].push(renderTarget); }; -},{"../../../math":55,"../filters/filterTransforms":72,"../utils/Quad":79,"../utils/RenderTarget":80,"./WebGLManager":77,"bit-twiddle":3,"pixi-gl-core":15}],75:[function(require,module,exports){ +},{"../../../math":60,"../filters/filterTransforms":77,"../utils/Quad":84,"../utils/RenderTarget":85,"./WebGLManager":82,"bit-twiddle":16,"pixi-gl-core":1}],80:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'), AlphaMaskFilter = require('../filters/spriteMask/SpriteMaskFilter'); @@ -14231,7 +15709,7 @@ gl.disable(gl.SCISSOR_TEST); }; -},{"../filters/spriteMask/SpriteMaskFilter":73,"./WebGLManager":77}],76:[function(require,module,exports){ +},{"../filters/spriteMask/SpriteMaskFilter":78,"./WebGLManager":82}],81:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'); /** @@ -14347,7 +15825,7 @@ this.stencilMaskStack.stencilStack = null; }; -},{"./WebGLManager":77}],77:[function(require,module,exports){ +},{"./WebGLManager":82}],82:[function(require,module,exports){ /** * @class * @memberof PIXI @@ -14388,7 +15866,7 @@ this.renderer = null; }; -},{}],78:[function(require,module,exports){ +},{}],83:[function(require,module,exports){ var WebGLManager = require('../managers/WebGLManager'); /** @@ -14446,7 +15924,7 @@ // render the object }; -},{"../managers/WebGLManager":77}],79:[function(require,module,exports){ +},{"../managers/WebGLManager":82}],84:[function(require,module,exports){ var glCore = require('pixi-gl-core'), createIndicesForQuads = require('../../../utils/createIndicesForQuads'); @@ -14618,7 +16096,7 @@ module.exports = Quad; -},{"../../../utils/createIndicesForQuads":98,"pixi-gl-core":15}],80:[function(require,module,exports){ +},{"../../../utils/createIndicesForQuads":103,"pixi-gl-core":1}],85:[function(require,module,exports){ var math = require('../../../math'), CONST = require('../../../const'), GLTexture = require('pixi-gl-core').GLTexture, @@ -14945,7 +16423,7 @@ this.texture = null; }; -},{"../../../const":34,"../../../math":55,"pixi-gl-core":15}],81:[function(require,module,exports){ +},{"../../../const":39,"../../../math":60,"pixi-gl-core":1}],86:[function(require,module,exports){ var CONST = require('../../../const'); /** @@ -14982,7 +16460,7 @@ module.exports = mapWebGLBlendModesToPixi; -},{"../../../const":34}],82:[function(require,module,exports){ +},{"../../../const":39}],87:[function(require,module,exports){ var CONST = require('../../../const'); /** @@ -15006,7 +16484,7 @@ module.exports = mapWebGLDrawModesToPixi; -},{"../../../const":34}],83:[function(require,module,exports){ +},{"../../../const":39}],88:[function(require,module,exports){ var math = require('../math'), Texture = require('../textures/Texture'), Container = require('../display/Container'), @@ -15486,7 +16964,7 @@ return new Sprite(Texture.fromImage(imageId, crossorigin, scaleMode)); }; -},{"../const":34,"../display/Container":35,"../math":55,"../textures/Texture":93,"../utils":99}],84:[function(require,module,exports){ +},{"../const":39,"../display/Container":40,"../math":60,"../textures/Texture":98,"../utils":105}],89:[function(require,module,exports){ var CanvasRenderer = require('../../renderers/canvas/CanvasRenderer'), CONST = require('../../const'), math = require('../../math'), @@ -15652,7 +17130,7 @@ this.renderer = null; }; -},{"../../const":34,"../../math":55,"../../renderers/canvas/CanvasRenderer":62,"./CanvasTinter":85}],85:[function(require,module,exports){ +},{"../../const":39,"../../math":60,"../../renderers/canvas/CanvasRenderer":67,"./CanvasTinter":90}],90:[function(require,module,exports){ var utils = require('../../utils'), canUseNewCanvasBlendModes = require('../../renderers/canvas/utils/canUseNewCanvasBlendModes'); /** @@ -15885,7 +17363,7 @@ */ CanvasTinter.tintMethod = CanvasTinter.canUseMultiply ? CanvasTinter.tintWithMultiply : CanvasTinter.tintWithPerPixel; -},{"../../renderers/canvas/utils/canUseNewCanvasBlendModes":65,"../../utils":99}],86:[function(require,module,exports){ +},{"../../renderers/canvas/utils/canUseNewCanvasBlendModes":70,"../../utils":105}],91:[function(require,module,exports){ var Buffer = function(size) @@ -15916,7 +17394,7 @@ this.uvs = null; this.colors = null; }; -},{}],87:[function(require,module,exports){ +},{}],92:[function(require,module,exports){ var ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), createIndicesForQuads = require('../../utils/createIndicesForQuads'), @@ -16000,7 +17478,7 @@ this.vertexBuffers = []; this.vaos = []; - this.vaoMax = 10 + this.vaoMax = 20; this.vertexCount = 0; } @@ -16270,7 +17748,7 @@ }; -},{"../../const":34,"../../renderers/webgl/WebGLRenderer":68,"../../renderers/webgl/utils/ObjectRenderer":78,"../../utils/createIndicesForQuads":98,"./BatchBuffer":86,"./generateMultiTextureShader":88,"bit-twiddle":3,"pixi-gl-core":15}],88:[function(require,module,exports){ +},{"../../const":39,"../../renderers/webgl/WebGLRenderer":73,"../../renderers/webgl/utils/ObjectRenderer":83,"../../utils/createIndicesForQuads":103,"./BatchBuffer":91,"./generateMultiTextureShader":93,"bit-twiddle":16,"pixi-gl-core":1}],93:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; var fragTemplate = [ @@ -16290,7 +17768,7 @@ function generateMultiTextureShader(gl, maxTextures) { - var vertexSrc = "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nattribute vec4 aColor;\n\nattribute float aTextureId;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvarying vec4 vColor;\n\nvarying float vTextureId;\n\nvoid main(void){\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n vTextureId = aTextureId;\n\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n\n}"; + var vertexSrc = "precision lowp float;\n#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\nattribute float aTextureId;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying float vTextureId;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vTextureId = aTextureId;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}"; var fragmentSrc = fragTemplate; fragmentSrc = fragmentSrc.replace(/\%count\%/gi, maxTextures); @@ -16344,7 +17822,7 @@ module.exports = generateMultiTextureShader; -},{"pixi-gl-core":15}],89:[function(require,module,exports){ +},{"pixi-gl-core":1}],94:[function(require,module,exports){ var Sprite = require('../sprites/Sprite'), Texture = require('../textures/Texture'), math = require('../math'), @@ -16965,7 +18443,7 @@ this._texture.destroy(destroyBaseTexture === undefined ? true : destroyBaseTexture); }; -},{"../const":34,"../math":55,"../sprites/Sprite":83,"../textures/Texture":93,"../utils":99}],90:[function(require,module,exports){ +},{"../const":39,"../math":60,"../sprites/Sprite":88,"../textures/Texture":98,"../utils":105}],95:[function(require,module,exports){ var BaseTexture = require('./BaseTexture'), math = require('../math'), CONST = require('../const'), @@ -17033,7 +18511,6 @@ * * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} */ - this.renderer = renderer; /** * @member {boolean} @@ -17243,10 +18720,11 @@ return this.getPixels(tempRect); }; -},{"../const":34,"../math":55,"./BaseTexture":91}],91:[function(require,module,exports){ +},{"../const":39,"../math":60,"./BaseTexture":96}],96:[function(require,module,exports){ var utils = require('../utils'), CONST = require('../const'), EventEmitter = require('eventemitter3'), + determineCrossOrigin = require('../utils/determineCrossOrigin'), bitTwiddle = require('bit-twiddle'); /** @@ -17637,19 +19115,16 @@ { var baseTexture = utils.BaseTextureCache[imageUrl]; - if (crossorigin === undefined && imageUrl.indexOf('data:') !== 0) - { - crossorigin = true; - } - if (!baseTexture) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 var image = new Image();//document.createElement('img'); - if (crossorigin) + + + if (crossorigin === undefined && imageUrl.indexOf('data:') !== 0) { - image.crossOrigin = ''; + image.crossOrigin = determineCrossOrigin(imageUrl); } baseTexture = new BaseTexture(image, scaleMode); @@ -17692,7 +19167,7 @@ return baseTexture; }; -},{"../const":34,"../utils":99,"bit-twiddle":3,"eventemitter3":12}],92:[function(require,module,exports){ +},{"../const":39,"../utils":105,"../utils/determineCrossOrigin":104,"bit-twiddle":16,"eventemitter3":25}],97:[function(require,module,exports){ var BaseRenderTexture = require('./BaseRenderTexture'), Texture = require('./Texture'); @@ -17803,7 +19278,7 @@ return new RenderTexture(new BaseRenderTexture(width, height, scaleMode, resolution)); }; -},{"./BaseRenderTexture":90,"./Texture":93}],93:[function(require,module,exports){ +},{"./BaseRenderTexture":95,"./Texture":98}],98:[function(require,module,exports){ var BaseTexture = require('./BaseTexture'), VideoBaseTexture = require('./VideoBaseTexture'), TextureUvs = require('./TextureUvs'), @@ -18298,7 +19773,7 @@ */ Texture.EMPTY = new Texture(new BaseTexture()); -},{"../math":55,"../utils":99,"./BaseTexture":91,"./TextureUvs":94,"./VideoBaseTexture":95,"eventemitter3":12}],94:[function(require,module,exports){ +},{"../math":60,"../utils":105,"./BaseTexture":96,"./TextureUvs":99,"./VideoBaseTexture":100,"eventemitter3":25}],99:[function(require,module,exports){ /** * A standard object to store the Uvs of a texture @@ -18388,7 +19863,7 @@ this.uvs_uint32[3] = (((this.y3 * 65535) & 0xFFFF) << 16) | ((this.x3 * 65535) & 0xFFFF); }; -},{"../math/GroupD8":52}],95:[function(require,module,exports){ +},{"../math/GroupD8":57}],100:[function(require,module,exports){ var BaseTexture = require('./BaseTexture'), utils = require('../utils'); @@ -18625,7 +20100,7 @@ return source; } -},{"../utils":99,"./BaseTexture":91}],96:[function(require,module,exports){ +},{"../utils":105,"./BaseTexture":96}],101:[function(require,module,exports){ var CONST = require('../const'), EventEmitter = require('eventemitter3'), // Internal event used by composed emitter @@ -18980,7 +20455,7 @@ module.exports = Ticker; -},{"../const":34,"eventemitter3":12}],97:[function(require,module,exports){ +},{"../const":39,"eventemitter3":25}],102:[function(require,module,exports){ var Ticker = require('./Ticker'); /** @@ -19036,7 +20511,7 @@ Ticker: Ticker }; -},{"./Ticker":96}],98:[function(require,module,exports){ +},{"./Ticker":101}],103:[function(require,module,exports){ /** * Generic Mask Stack data structure * @class @@ -19067,7 +20542,51 @@ module.exports = createIndicesForQuads; -},{}],99:[function(require,module,exports){ +},{}],104:[function(require,module,exports){ +var tempAnchor; +var _url = require('url'); + +/** + * Sets the `crossOrigin` property for this resource based on if the url + * for this resource is cross-origin. If crossOrigin was manually set, this + * function does nothing. + * Nipped from the resource loader! + * @private + * @param url {string} The url to test. + * @param [location=window.location] {object} The location object to test against. + * @return {string} The crossOrigin value to use (or empty string for none). + */ +var determineCrossOrigin = function (url, loc) { + // data: and javascript: urls are considered same-origin + if (url.indexOf('data:') === 0) { + return ''; + } + + // default is window.location + loc = loc || window.location; + + if (!tempAnchor) { + tempAnchor = document.createElement('a'); + } + + // let the browser determine the full href for the url of this resource and then + // parse with the node url lib, we can't use the properties of the anchor element + // because they don't work in IE9 :( + tempAnchor.href = url; + url = _url.parse(tempAnchor.href); + + var samePort = (!url.port && loc.port === '') || (url.port === loc.port); + + // if cross origin + if (url.hostname !== loc.hostname || !samePort || url.protocol !== loc.protocol) { + return 'anonymous'; + } + + return ''; +}; + +module.exports = determineCrossOrigin; +},{"url":23}],105:[function(require,module,exports){ var CONST = require('../const'); /** @@ -19270,7 +20789,7 @@ BaseTextureCache: {} }; -},{"../const":34,"./pluginTarget":101,"eventemitter3":12}],100:[function(require,module,exports){ +},{"../const":39,"./pluginTarget":107,"eventemitter3":25}],106:[function(require,module,exports){ var Device = require('ismobilejs'); @@ -19291,7 +20810,7 @@ } module.exports = maxRecommendedTextures; -},{"ismobilejs":13}],101:[function(require,module,exports){ +},{"ismobilejs":26}],107:[function(require,module,exports){ /** * Mixins functionality to make an object have "plugins". * @@ -19361,7 +20880,7 @@ } }; -},{}],102:[function(require,module,exports){ +},{}],108:[function(require,module,exports){ /*global console */ var core = require('./core'), mesh = require('./mesh'), @@ -19597,6 +21116,14 @@ console.warn('generateTexture has moved to the renderer, please use renderer.generateTexture(displayObject)'); }; + +core.Graphics.prototype.generateTexture = function(scaleMode, resolution) +{ + console.warn('graphics generate texture has moved to the renderer. Or to render a graphics to a texture using canvas please use generateCanvasTexture'); + + return this.generateCanvasTexture(scaleMode, resolution) +} + core.RenderTexture.prototype.render = function() { //displayObject, matrix, clear, updateTransform @@ -19616,6 +21143,8 @@ console.warn('setTexture is now deprecated, please use the texture property, e.g : sprite.texture = texture;'); }; + + /** * @method * @name PIXI.extras.BitmapText#setText @@ -19724,7 +21253,7 @@ return core.utils.uid(); }; -},{"./core":51,"./extras":109,"./filters":121,"./mesh":136}],103:[function(require,module,exports){ +},{"./core":56,"./extras":115,"./filters":127,"./mesh":142}],109:[function(require,module,exports){ var core = require('../core'); /** @@ -20112,7 +21641,7 @@ BitmapText.fonts = {}; -},{"../core":51}],104:[function(require,module,exports){ +},{"../core":56}],110:[function(require,module,exports){ var core = require('../core'); /** @@ -20432,7 +21961,7 @@ return new MovieClip(textures); }; -},{"../core":51}],105:[function(require,module,exports){ +},{"../core":56}],111:[function(require,module,exports){ var core = require('../core'), // a sprite use dfor rendering textures.. tempPoint = new core.Point(), @@ -20864,7 +22393,7 @@ return new TilingSprite(core.Texture.fromImage(imageId, crossorigin, scaleMode),width,height); }; -},{"../core":51,"../core/sprites/canvas/CanvasTinter":85,"./webgl/TilingShader":110}],106:[function(require,module,exports){ +},{"../core":56,"../core/sprites/canvas/CanvasTinter":90,"./webgl/TilingShader":116}],112:[function(require,module,exports){ var core = require('../core'), DisplayObject = core.DisplayObject, _tempMatrix = new core.Matrix(); @@ -21140,7 +22669,7 @@ this._originalDestroy(); }; -},{"../core":51}],107:[function(require,module,exports){ +},{"../core":56}],113:[function(require,module,exports){ var core = require('../core'); /** @@ -21170,7 +22699,7 @@ return null; }; -},{"../core":51}],108:[function(require,module,exports){ +},{"../core":56}],114:[function(require,module,exports){ var core = require('../core'); /** @@ -21200,7 +22729,7 @@ return point; }; -},{"../core":51}],109:[function(require,module,exports){ +},{"../core":56}],115:[function(require,module,exports){ /** * @file Main export of the PIXI extras library * @author Mat Groves @@ -21221,7 +22750,7 @@ BitmapText: require('./BitmapText') }; -},{"./BitmapText":103,"./MovieClip":104,"./TilingSprite":105,"./cacheAsBitmap":106,"./getChildByName":107,"./getGlobalPosition":108}],110:[function(require,module,exports){ +},{"./BitmapText":109,"./MovieClip":110,"./TilingSprite":111,"./cacheAsBitmap":112,"./getChildByName":113,"./getGlobalPosition":114}],116:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; @@ -21235,8 +22764,8 @@ { Shader.call(this, gl, - "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\n\nuniform mat3 translationMatrix;\n\nuniform vec4 uFrame;\n\nuniform vec4 uTransform;\n\nvarying vec2 vTextureCoord;\n\nvarying vec4 vColor;\n\nvoid main(void)\n\n{\n\n gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n \n\n vec2 coord = aTextureCoord;\n\n coord -= uTransform.xy;\n\n coord /= uTransform.zw;\n\n vTextureCoord = coord;\n\n \n\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n\n}", - "precision lowp float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nvarying vec4 vColor;\n\nuniform sampler2D uSampler;\n\nuniform vec4 uFrame;\n\nuniform vec2 uPixelSize;\n\nvoid main(void)\n\n{\n\n vec2 coord = mod(vTextureCoord, uFrame.zw);\n\n coord = clamp(coord, uPixelSize, uFrame.zw - uPixelSize);\n\n coord += uFrame.xy;\n\n gl_FragColor = texture2D(uSampler, coord) ;\n\n}" + "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\nuniform mat3 translationMatrix;\n\nuniform vec4 uFrame;\nuniform vec4 uTransform;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n \n vec2 coord = aTextureCoord;\n coord -= uTransform.xy;\n coord /= uTransform.zw;\n vTextureCoord = coord;\n \n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}", + "precision lowp float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform sampler2D uSampler;\nuniform vec4 uFrame;\nuniform vec2 uPixelSize;\n\nvoid main(void)\n{\n\n vec2 coord = mod(vTextureCoord, uFrame.zw);\n coord = clamp(coord, uPixelSize, uFrame.zw - uPixelSize);\n coord += uFrame.xy;\n\n gl_FragColor = texture2D(uSampler, coord) ;\n}" ); } @@ -21245,7 +22774,7 @@ module.exports = TilingShader; -},{"pixi-gl-core":15}],111:[function(require,module,exports){ +},{"pixi-gl-core":1}],117:[function(require,module,exports){ var core = require('../../core'), BlurXFilter = require('./BlurXFilter'), BlurYFilter = require('./BlurYFilter'); @@ -21361,7 +22890,7 @@ } }); -},{"../../core":51,"./BlurXFilter":112,"./BlurYFilter":113}],112:[function(require,module,exports){ +},{"../../core":56,"./BlurXFilter":118,"./BlurYFilter":119}],118:[function(require,module,exports){ var core = require('../../core'); var generateBlurVertSource = require('./generateBlurVertSource'); var generateBlurFragSource = require('./generateBlurFragSource'); @@ -21469,7 +22998,7 @@ } }); -},{"../../core":51,"./generateBlurFragSource":114,"./generateBlurVertSource":115,"./getMaxBlurKernelSize":116}],113:[function(require,module,exports){ +},{"../../core":56,"./generateBlurFragSource":120,"./generateBlurVertSource":121,"./getMaxBlurKernelSize":122}],119:[function(require,module,exports){ var core = require('../../core'); var generateBlurVertSource = require('./generateBlurVertSource'); var generateBlurFragSource = require('./generateBlurFragSource'); @@ -21567,7 +23096,7 @@ } }); -},{"../../core":51,"./generateBlurFragSource":114,"./generateBlurVertSource":115,"./getMaxBlurKernelSize":116}],114:[function(require,module,exports){ +},{"../../core":56,"./generateBlurFragSource":120,"./generateBlurVertSource":121,"./getMaxBlurKernelSize":122}],120:[function(require,module,exports){ var GAUSSIAN_VALUES = { 5:[0.153388, 0.221461, 0.250301], 7:[0.071303, 0.131514, 0.189879, 0.214607], @@ -21632,7 +23161,7 @@ module.exports = generateFragBlurSource; -},{}],115:[function(require,module,exports){ +},{}],121:[function(require,module,exports){ var vertTemplate = [ 'attribute vec2 aVertexPosition;', @@ -21698,7 +23227,7 @@ module.exports = generateVertBlurSource; -},{}],116:[function(require,module,exports){ +},{}],122:[function(require,module,exports){ var getMaxKernelSize = function(gl) @@ -21716,7 +23245,7 @@ module.exports = getMaxKernelSize; -},{}],117:[function(require,module,exports){ +},{}],123:[function(require,module,exports){ var core = require('../../core'); // @see https://github.com/substack/brfs/issues/25 @@ -21740,9 +23269,9 @@ { core.Filter.call(this, // vertex shader - "precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n}", + "precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nuniform float m[20];\n\nvoid main(void)\n\n{\n\n vec4 c = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.r = (m[0] * c.r);\n\n gl_FragColor.r += (m[1] * c.g);\n\n gl_FragColor.r += (m[2] * c.b);\n\n gl_FragColor.r += (m[3] * c.a);\n\n gl_FragColor.r += m[4];\n\n gl_FragColor.g = (m[5] * c.r);\n\n gl_FragColor.g += (m[6] * c.g);\n\n gl_FragColor.g += (m[7] * c.b);\n\n gl_FragColor.g += (m[8] * c.a);\n\n gl_FragColor.g += m[9];\n\n gl_FragColor.b = (m[10] * c.r);\n\n gl_FragColor.b += (m[11] * c.g);\n\n gl_FragColor.b += (m[12] * c.b);\n\n gl_FragColor.b += (m[13] * c.a);\n\n gl_FragColor.b += m[14];\n\n gl_FragColor.a = (m[15] * c.r);\n\n gl_FragColor.a += (m[16] * c.g);\n\n gl_FragColor.a += (m[17] * c.b);\n\n gl_FragColor.a += (m[18] * c.a);\n\n gl_FragColor.a += m[19];\n\n// gl_FragColor = vec4(m[0]);\r\n}\n\n" + "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\nuniform sampler2D uSampler;\nuniform float m[20];\n\nvoid main(void)\n{\n\n vec4 c = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.r = (m[0] * c.r);\n gl_FragColor.r += (m[1] * c.g);\n gl_FragColor.r += (m[2] * c.b);\n gl_FragColor.r += (m[3] * c.a);\n gl_FragColor.r += m[4];\n\n gl_FragColor.g = (m[5] * c.r);\n gl_FragColor.g += (m[6] * c.g);\n gl_FragColor.g += (m[7] * c.b);\n gl_FragColor.g += (m[8] * c.a);\n gl_FragColor.g += m[9];\n\n gl_FragColor.b = (m[10] * c.r);\n gl_FragColor.b += (m[11] * c.g);\n gl_FragColor.b += (m[12] * c.b);\n gl_FragColor.b += (m[13] * c.a);\n gl_FragColor.b += m[14];\n\n gl_FragColor.a = (m[15] * c.r);\n gl_FragColor.a += (m[16] * c.g);\n gl_FragColor.a += (m[17] * c.b);\n gl_FragColor.a += (m[18] * c.a);\n gl_FragColor.a += m[19];\n\n// gl_FragColor = vec4(m[0]);\n}\n" ); this.uniforms.m = [ @@ -22250,7 +23779,7 @@ } }); -},{"../../core":51}],118:[function(require,module,exports){ +},{"../../core":56}],124:[function(require,module,exports){ var core = require('../../core'); @@ -22271,9 +23800,9 @@ core.Filter.call(this, // vertex shader - "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\n\nuniform mat3 otherMatrix;\n\nvarying vec2 vMapCoord;\n\nvarying vec2 vTextureCoord;\n\nvarying vec4 vColor;\n\nvoid main(void)\n\n{\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n vMapCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n\n}\n\n", + "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\nuniform mat3 otherMatrix;\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vMapCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}\n", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vMapCoord;\n\nvarying vec2 vTextureCoord;\n\nvarying vec4 vColor;\n\nuniform vec2 scale;\n\nuniform sampler2D uSampler;\n\nuniform sampler2D mapSampler;\n\nvoid main(void)\n\n{\n\n vec4 map = texture2D(mapSampler, vMapCoord);\n\n map -= 0.5;\n\n map.xy *= scale;\n\n gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y));\n\n}\n\n" + "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform vec2 scale;\n\nuniform sampler2D uSampler;\nuniform sampler2D mapSampler;\n\nvoid main(void)\n{\n vec4 map = texture2D(mapSampler, vMapCoord);\n\n map -= 0.5;\n map.xy *= scale;\n\n gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y));\n}\n" ); @@ -22301,8 +23830,10 @@ var ratio = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); this.uniforms.otherMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = 0.01//this.scale.x * ratio; + this.uniforms.scale.y = 0.01//this.scale.y * ratio; + + // console.log( this.scale) // draw the filter... filterManager.applyFilter(this, input, output); @@ -22329,7 +23860,7 @@ } }); -},{"../../core":51}],119:[function(require,module,exports){ +},{"../../core":56}],125:[function(require,module,exports){ var core = require('../../core'); @@ -22345,9 +23876,9 @@ core.Filter.call(this, // vertex shader - "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n\n{\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n}\n\n", + "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}\n\n", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform float exposure;\n\nuniform float decay;\n\nuniform float density;\n\nuniform float weight;\n\nuniform vec2 lightPositionOnScreen;\n\nuniform sampler2D uSampler;\n\nconst int NUM_SAMPLES = 100;\n\nvoid main()\n\n{\n\n vec2 deltaTextCoord = vec2( vTextureCoord - lightPositionOnScreen.xy );\n\n vec2 textCoo = vTextureCoord;\n\n deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * density;\n\n float illuminationDecay = 1.0;\n\n \n\n for(int i=0; i < NUM_SAMPLES ; i++)\n\n {\n\n textCoo -= deltaTextCoord;\n\n vec4 sample = texture2D(uSampler, textCoo );\n\n sample *= illuminationDecay * weight;\n\n gl_FragColor += sample;\n\n illuminationDecay *= decay;\n\n }\n\n \n\n gl_FragColor *= exposure;\n\n}" + "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\nuniform float exposure;\nuniform float decay;\nuniform float density;\nuniform float weight;\nuniform vec2 lightPositionOnScreen;\nuniform sampler2D uSampler;\n\nconst int NUM_SAMPLES = 100;\n\nvoid main()\n{\n vec2 deltaTextCoord = vec2( vTextureCoord - lightPositionOnScreen.xy );\n vec2 textCoo = vTextureCoord;\n deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * density;\n float illuminationDecay = 1.0;\n \n for(int i=0; i < NUM_SAMPLES ; i++)\n {\n textCoo -= deltaTextCoord;\n vec4 sample = texture2D(uSampler, textCoo );\n\n sample *= illuminationDecay * weight;\n\n gl_FragColor += sample;\n\n illuminationDecay *= decay;\n }\n \n gl_FragColor *= exposure;\n}" ); this.uniforms.exposure = 0.0034; @@ -22422,7 +23953,7 @@ } }); -},{"../../core":51}],120:[function(require,module,exports){ +},{"../../core":56}],126:[function(require,module,exports){ var core = require('../../core'); // @see https://github.com/substack/brfs/issues/25 @@ -22438,9 +23969,9 @@ { core.Filter.call(this, // vertex shader - "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n}", + "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nuniform float gray;\n\nvoid main(void)\n\n{\n\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);\n\n}\n\n" + "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float gray;\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);\n}\n" ); this.uniforms.gray = 1; @@ -22471,7 +24002,7 @@ } }); -},{"../../core":51}],121:[function(require,module,exports){ +},{"../../core":56}],127:[function(require,module,exports){ /** * @file Main export of the PIXI filters library * @author Mat Groves @@ -22512,7 +24043,7 @@ GodrayFilter: require('./godray/GodrayFilter') }; -},{"./blur/BlurFilter":111,"./blur/BlurXFilter":112,"./blur/BlurYFilter":113,"./colormatrix/ColorMatrixFilter":117,"./displacement/DisplacementFilter":118,"./godray/GodrayFilter":119,"./gray/GrayFilter":120,"./twist/TwistFilter":122}],122:[function(require,module,exports){ +},{"./blur/BlurFilter":117,"./blur/BlurXFilter":118,"./blur/BlurYFilter":119,"./colormatrix/ColorMatrixFilter":123,"./displacement/DisplacementFilter":124,"./godray/GodrayFilter":125,"./gray/GrayFilter":126,"./twist/TwistFilter":128}],128:[function(require,module,exports){ var core = require('../../core'); @@ -22528,9 +24059,9 @@ core.Filter.call(this, // vertex shader - "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n\n{\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n}\n\n", + "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}\n\n", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nuniform float radius;\n\nuniform float angle;\n\nuniform vec2 offset;\n\nuniform vec4 filterArea;\n\nvec2 mapCoord( vec2 coord )\n\n{\n\n coord *= filterArea.xy;\n\n coord += filterArea.zw;\n\n return coord;\n\n}\n\nvec2 unmapCoord( vec2 coord )\n\n{\n\n coord -= filterArea.zw;\n\n coord /= filterArea.xy;\n\n return coord;\n\n}\n\nvec2 twist(vec2 coord)\n\n{\n\n coord -= offset;\n\n float dist = length(coord);\n\n if (dist < radius)\n\n {\n\n float ratioDist = (radius - dist) / radius;\n\n float angleMod = ratioDist * ratioDist * angle;\n\n float s = sin(angleMod);\n\n float c = cos(angleMod);\n\n coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);\n\n }\n\n coord += offset;\n\n return coord;\n\n}\n\nvoid main(void)\n\n{\n\n vec2 coord = mapCoord(vTextureCoord);\n\n coord = twist(coord);\n\n coord = unmapCoord(coord);\n\n gl_FragColor = texture2D(uSampler, coord );\n\n}\n\n" + "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float radius;\nuniform float angle;\nuniform vec2 offset;\nuniform vec4 filterArea;\n\nvec2 mapCoord( vec2 coord )\n{\n coord *= filterArea.xy;\n coord += filterArea.zw;\n\n return coord;\n}\n\nvec2 unmapCoord( vec2 coord )\n{\n coord -= filterArea.zw;\n coord /= filterArea.xy;\n\n return coord;\n}\n\nvec2 twist(vec2 coord)\n{\n coord -= offset;\n\n float dist = length(coord);\n\n if (dist < radius)\n {\n float ratioDist = (radius - dist) / radius;\n float angleMod = ratioDist * ratioDist * angle;\n float s = sin(angleMod);\n float c = cos(angleMod);\n coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);\n }\n\n coord += offset;\n\n return coord;\n}\n\nvoid main(void)\n{\n\n vec2 coord = mapCoord(vTextureCoord);\n\n coord = twist(coord);\n\n coord = unmapCoord(coord);\n\n gl_FragColor = texture2D(uSampler, coord );\n\n}\n" ); this.uniforms.radius = 400; @@ -22610,7 +24141,7 @@ } }); -},{"../../core":51}],123:[function(require,module,exports){ +},{"../../core":56}],129:[function(require,module,exports){ (function (global){ // run the polyfills require('./polyfill'); @@ -22643,7 +24174,7 @@ global.PIXI = core; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./accessibility":32,"./core":51,"./deprecation":102,"./extras":109,"./filters":121,"./interaction":126,"./loaders":129,"./mesh":136,"./particles":139,"./polyfill":145}],124:[function(require,module,exports){ +},{"./accessibility":37,"./core":56,"./deprecation":108,"./extras":115,"./filters":127,"./interaction":132,"./loaders":135,"./mesh":142,"./particles":145,"./polyfill":151}],130:[function(require,module,exports){ var core = require('../core'); /** @@ -22692,7 +24223,7 @@ return displayObject.worldTransform.applyInverse(globalPos || this.global, point); }; -},{"../core":51}],125:[function(require,module,exports){ +},{"../core":56}],131:[function(require,module,exports){ var core = require('../core'), InteractionData = require('./InteractionData'); @@ -23612,7 +25143,7 @@ core.WebGLRenderer.registerPlugin('interaction', InteractionManager); core.CanvasRenderer.registerPlugin('interaction', InteractionManager); -},{"../core":51,"./InteractionData":124,"./interactiveTarget":127}],126:[function(require,module,exports){ +},{"../core":56,"./InteractionData":130,"./interactiveTarget":133}],132:[function(require,module,exports){ /** * @file Main export of the PIXI interactions library * @author Mat Groves @@ -23629,7 +25160,7 @@ interactiveTarget: require('./interactiveTarget') }; -},{"./InteractionData":124,"./InteractionManager":125,"./interactiveTarget":127}],127:[function(require,module,exports){ +},{"./InteractionData":130,"./InteractionManager":131,"./interactiveTarget":133}],133:[function(require,module,exports){ /** * Default property values of interactive objects * used by {@link PIXI.interaction.InteractionManager}. @@ -23678,7 +25209,7 @@ module.exports = interactiveTarget; -},{}],128:[function(require,module,exports){ +},{}],134:[function(require,module,exports){ var Resource = require('resource-loader').Resource, core = require('../core'), extras = require('../extras'), @@ -23802,7 +25333,7 @@ }; }; -},{"../core":51,"../extras":109,"path":4,"resource-loader":150}],129:[function(require,module,exports){ +},{"../core":56,"../extras":115,"path":17,"resource-loader":32}],135:[function(require,module,exports){ /** * @file Main export of the PIXI loaders library * @author Mat Groves @@ -23823,7 +25354,7 @@ Resource: require('resource-loader').Resource }; -},{"./bitmapFontParser":128,"./loader":130,"./spritesheetParser":131,"./textureParser":132,"resource-loader":150}],130:[function(require,module,exports){ +},{"./bitmapFontParser":134,"./loader":136,"./spritesheetParser":137,"./textureParser":138,"resource-loader":32}],136:[function(require,module,exports){ var ResourceLoader = require('resource-loader'), textureParser = require('./textureParser'), spritesheetParser = require('./spritesheetParser'), @@ -23885,7 +25416,7 @@ Resource.setExtensionXhrType('fnt', Resource.XHR_RESPONSE_TYPE.DOCUMENT); -},{"./bitmapFontParser":128,"./spritesheetParser":131,"./textureParser":132,"resource-loader":150}],131:[function(require,module,exports){ +},{"./bitmapFontParser":134,"./spritesheetParser":137,"./textureParser":138,"resource-loader":32}],137:[function(require,module,exports){ var Resource = require('resource-loader').Resource, path = require('path'), core = require('../core'); @@ -23957,7 +25488,7 @@ }; }; -},{"../core":51,"path":4,"resource-loader":150}],132:[function(require,module,exports){ +},{"../core":56,"path":17,"resource-loader":32}],138:[function(require,module,exports){ var core = require('../core'); module.exports = function () @@ -23979,7 +25510,7 @@ }; }; -},{"../core":51}],133:[function(require,module,exports){ +},{"../core":56}],139:[function(require,module,exports){ var core = require('../core'), glCore = require('pixi-gl-core'), Shader = require('./webgl/MeshShader'), @@ -24504,7 +26035,7 @@ TRIANGLES: 1 }; -},{"../core":51,"./webgl/MeshShader":137,"pixi-gl-core":15}],134:[function(require,module,exports){ +},{"../core":56,"./webgl/MeshShader":143,"pixi-gl-core":1}],140:[function(require,module,exports){ var Mesh = require('./Mesh'); /** @@ -24630,7 +26161,7 @@ } }; -},{"./Mesh":133}],135:[function(require,module,exports){ +},{"./Mesh":139}],141:[function(require,module,exports){ var Mesh = require('./Mesh'); var core = require('../core'); @@ -24843,7 +26374,7 @@ this.containerUpdateTransform(); }; -},{"../core":51,"./Mesh":133}],136:[function(require,module,exports){ +},{"../core":56,"./Mesh":139}],142:[function(require,module,exports){ /** * @file Main export of the PIXI extras library * @author Mat Groves @@ -24861,7 +26392,7 @@ MeshShader: require('./webgl/MeshShader') }; -},{"./Mesh":133,"./Plane":134,"./Rope":135,"./webgl/MeshShader":137}],137:[function(require,module,exports){ +},{"./Mesh":139,"./Plane":140,"./Rope":141,"./webgl/MeshShader":143}],143:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; /** @@ -24911,7 +26442,7 @@ module.exports = MeshShader; -},{"pixi-gl-core":15}],138:[function(require,module,exports){ +},{"pixi-gl-core":1}],144:[function(require,module,exports){ var core = require('../core'); /** @@ -25244,7 +26775,7 @@ this._buffers = null; }; -},{"../core":51}],139:[function(require,module,exports){ +},{"../core":56}],145:[function(require,module,exports){ /** * @file Main export of the PIXI extras library * @author Mat Groves @@ -25260,7 +26791,7 @@ ParticleRenderer: require('./webgl/ParticleRenderer') }; -},{"./ParticleContainer":138,"./webgl/ParticleRenderer":141}],140:[function(require,module,exports){ +},{"./ParticleContainer":144,"./webgl/ParticleRenderer":147}],146:[function(require,module,exports){ var glCore = require('pixi-gl-core'), createIndicesForQuads = require('../../core/utils/createIndicesForQuads'); @@ -25481,7 +27012,7 @@ this.staticBuffer.destroy(); }; -},{"../../core/utils/createIndicesForQuads":98,"pixi-gl-core":15}],141:[function(require,module,exports){ +},{"../../core/utils/createIndicesForQuads":103,"pixi-gl-core":1}],147:[function(require,module,exports){ var core = require('../../core'), ParticleShader = require('./ParticleShader'), ParticleBuffer = require('./ParticleBuffer'); @@ -25912,7 +27443,7 @@ this.tempMatrix = null; }; -},{"../../core":51,"./ParticleBuffer":140,"./ParticleShader":142}],142:[function(require,module,exports){ +},{"../../core":56,"./ParticleBuffer":146,"./ParticleShader":148}],148:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; /** @@ -25980,7 +27511,7 @@ module.exports = ParticleShader; -},{"pixi-gl-core":15}],143:[function(require,module,exports){ +},{"pixi-gl-core":1}],149:[function(require,module,exports){ // References: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign @@ -25996,7 +27527,7 @@ }; } -},{}],144:[function(require,module,exports){ +},{}],150:[function(require,module,exports){ // References: // https://github.com/sindresorhus/object-assign // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign @@ -26006,7 +27537,7 @@ Object.assign = require('object-assign'); } -},{"object-assign":14}],145:[function(require,module,exports){ +},{"object-assign":27}],151:[function(require,module,exports){ require('./Object.assign'); require('./requestAnimationFrame'); require('./Math.sign'); @@ -26024,7 +27555,7 @@ window.Uint16Array = Array; } -},{"./Math.sign":143,"./Object.assign":144,"./requestAnimationFrame":146}],146:[function(require,module,exports){ +},{"./Math.sign":149,"./Object.assign":150,"./requestAnimationFrame":152}],152:[function(require,module,exports){ (function (global){ // References: // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ @@ -26094,1436 +27625,6 @@ } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],147:[function(require,module,exports){ -var async = require('async'), - urlParser = require('url'), - Resource = require('./Resource'), - EventEmitter = require('eventemitter3'); - -/** - * Manages the state and loading of multiple resources to load. - * - * @class - * @param [baseUrl=''] {string} The base url for all resources loaded by this loader. - * @param [concurrency=10] {number} The number of resources to load concurrently. - */ -function Loader(baseUrl, concurrency) { - EventEmitter.call(this); - - concurrency = concurrency || 10; - - /** - * The base url for all resources loaded by this loader. - * - * @member {string} - */ - this.baseUrl = baseUrl || ''; - - /** - * The progress percent of the loader going through the queue. - * - * @member {number} - */ - this.progress = 0; - - /** - * Loading state of the loader, true if it is currently loading resources. - * - * @member {boolean} - */ - this.loading = false; - - /** - * The percentage of total progress that a single resource represents. - * - * @member {number} - */ - this._progressChunk = 0; - - /** - * The middleware to run before loading each resource. - * - * @member {function[]} - */ - this._beforeMiddleware = []; - - /** - * The middleware to run after loading each resource. - * - * @member {function[]} - */ - this._afterMiddleware = []; - - /** - * The `_loadResource` function bound with this object context. - * - * @private - * @member {function} - */ - this._boundLoadResource = this._loadResource.bind(this); - - /** - * The `_onLoad` function bound with this object context. - * - * @private - * @member {function} - */ - this._boundOnLoad = this._onLoad.bind(this); - - /** - * The resource buffer that fills until `load` is called to start loading resources. - * - * @private - * @member {Resource[]} - */ - this._buffer = []; - - /** - * Used to track load completion. - * - * @private - * @member {number} - */ - this._numToLoad = 0; - - /** - * The resources waiting to be loaded. - * - * @private - * @member {Resource[]} - */ - this._queue = async.queue(this._boundLoadResource, concurrency); - - /** - * All the resources for this loader keyed by name. - * - * @member {object} - */ - this.resources = {}; - - /** - * Emitted once per loaded or errored resource. - * - * @event progress - * @memberof Loader# - */ - - /** - * Emitted once per errored resource. - * - * @event error - * @memberof Loader# - */ - - /** - * Emitted once per loaded resource. - * - * @event load - * @memberof Loader# - */ - - /** - * Emitted when the loader begins to process the queue. - * - * @event start - * @memberof Loader# - */ - - /** - * Emitted when the queued resources all load. - * - * @event complete - * @memberof Loader# - */ -} - -Loader.prototype = Object.create(EventEmitter.prototype); -Loader.prototype.constructor = Loader; -module.exports = Loader; - -/** - * Adds a resource (or multiple resources) to the loader queue. - * - * This function can take a wide variety of different parameters. The only thing that is always - * required the url to load. All the following will work: - * - * ```js - * loader - * // normal param syntax - * .add('key', 'http://...', function () {}) - * .add('http://...', function () {}) - * .add('http://...') - * - * // object syntax - * .add({ - * name: 'key2', - * url: 'http://...' - * }, function () {}) - * .add({ - * url: 'http://...' - * }, function () {}) - * .add({ - * name: 'key3', - * url: 'http://...' - * onComplete: function () {} - * }) - * .add({ - * url: 'https://...', - * onComplete: function () {}, - * crossOrigin: true - * }) - * - * // you can also pass an array of objects or urls or both - * .add([ - * { name: 'key4', url: 'http://...', onComplete: function () {} }, - * { url: 'http://...', onComplete: function () {} }, - * 'http://...' - * ]); - * ``` - * - * @alias enqueue - * @param [name] {string} The name of the resource to load, if not passed the url is used. - * @param url {string} The url for this resource, relative to the baseUrl of this loader. - * @param [options] {object} The options for the load. - * @param [options.crossOrigin] {boolean} Is this request cross-origin? Default is to determine automatically. - * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.XHR_LOAD_TYPE} How should this resource be loaded? - * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being - * loaded be interpreted when using XHR? - * @param [callback] {function} Function to call when this specific resource completes loading. - * @return {Loader} - */ -Loader.prototype.add = Loader.prototype.enqueue = function (name, url, options, cb) { - // special case of an array of objects or urls - if (Array.isArray(name)) { - for (var i = 0; i < name.length; ++i) { - this.add(name[i]); - } - - return this; - } - - // if an object is passed instead of params - if (typeof name === 'object') { - cb = url || name.callback || name.onComplete; - options = name; - url = name.url; - name = name.name || name.key || name.url; - } - - // case where no name is passed shift all args over by one. - if (typeof url !== 'string') { - cb = options; - options = url; - url = name; - } - - // now that we shifted make sure we have a proper url. - if (typeof url !== 'string') { - throw new Error('No url passed to add resource to loader.'); - } - - // options are optional so people might pass a function and no options - if (typeof options === 'function') { - cb = options; - options = null; - } - - // check if resource already exists. - if (this.resources[name]) { - throw new Error('Resource with name "' + name + '" already exists.'); - } - - // add base url if this isn't an absolute url - url = this._handleBaseUrl(url); - - // create the store the resource - this.resources[name] = new Resource(name, url, options); - - if (typeof cb === 'function') { - this.resources[name].once('afterMiddleware', cb); - } - - this._numToLoad++; - - // if already loading add it to the worker queue - if (this._queue.started) { - this._queue.push(this.resources[name]); - this._progressChunk = (100 - this.progress) / (this._queue.length() + this._queue.running()); - } - // otherwise buffer it to be added to the queue later - else { - this._buffer.push(this.resources[name]); - this._progressChunk = 100 / this._buffer.length; - } - - return this; -}; - -Loader.prototype._handleBaseUrl = function (url) { - var parsedUrl = urlParser.parse(url); - - // absolute url, just use it as is. - if (parsedUrl.protocol || parsedUrl.pathname.indexOf('//') === 0) { - return url; - } - - // if baseUrl doesn't end in slash and url doesn't start with slash, then add a slash inbetween - if ( - this.baseUrl.length && - this.baseUrl.lastIndexOf('/') !== this.baseUrl.length - 1 && - url.charAt(0) !== '/' - ) { - return this.baseUrl + '/' + url; - } - else { - return this.baseUrl + url; - } -}; - - -/** - * Sets up a middleware function that will run *before* the - * resource is loaded. - * - * @alias pre - * @param middleware {function} The middleware function to register. - * @return {Loader} - */ -Loader.prototype.before = Loader.prototype.pre = function (fn) { - this._beforeMiddleware.push(fn); - - return this; -}; - -/** - * Sets up a middleware function that will run *after* the - * resource is loaded. - * - * @alias use - * @param middleware {function} The middleware function to register. - * @return {Loader} - */ -Loader.prototype.after = Loader.prototype.use = function (fn) { - this._afterMiddleware.push(fn); - - return this; -}; - -/** - * Resets the queue of the loader to prepare for a new load. - * - * @return {Loader} - */ -Loader.prototype.reset = function () { - // this.baseUrl = baseUrl || ''; - - this.progress = 0; - - this.loading = false; - - this._progressChunk = 0; - - // this._beforeMiddleware.length = 0; - // this._afterMiddleware.length = 0; - - this._buffer.length = 0; - - this._numToLoad = 0; - - this._queue.kill(); - this._queue.started = false; - - this.resources = {}; -}; - -/** - * Starts loading the queued resources. - * - * @fires start - * @param [callback] {function} Optional callback that will be bound to the `complete` event. - * @return {Loader} - */ -Loader.prototype.load = function (cb) { - // register complete callback if they pass one - if (typeof cb === 'function') { - this.once('complete', cb); - } - - // if the queue has already started we are done here - if (this._queue.started) { - return this; - } - - // notify of start - this.emit('start', this); - - // start the internal queue - for (var i = 0; i < this._buffer.length; ++i) { - this._queue.push(this._buffer[i]); - } - - // empty the buffer - this._buffer.length = 0; - - return this; -}; - -/** - * Loads a single resource. - * - * @fires progress - * @private - */ -Loader.prototype._loadResource = function (resource, dequeue) { - var self = this; - - resource._dequeue = dequeue; - - this._runMiddleware(resource, this._beforeMiddleware, function () { - // resource.on('progress', self.emit.bind(self, 'progress')); - - resource.load(self._boundOnLoad); - }); -}; - -/** - * Called once each resource has loaded. - * - * @fires complete - * @private - */ -Loader.prototype._onComplete = function () { - this.emit('complete', this, this.resources); -}; - -/** - * Called each time a resources is loaded. - * - * @fires progress - * @fires error - * @fires load - * @private - */ -Loader.prototype._onLoad = function (resource) { - this.progress += this._progressChunk; - - this.emit('progress', this, resource); - - // run middleware, this *must* happen before dequeue so sub-assets get added properly - this._runMiddleware(resource, this._afterMiddleware, function () { - resource.emit('afterMiddleware', resource); - - this._numToLoad--; - - // do completion check - if (this._numToLoad === 0) { - this.progress = 100; - this._onComplete(); - } - - if (resource.error) { - this.emit('error', resource.error, this, resource); - } - else { - this.emit('load', this, resource); - } - }); - - - - // remove this resource from the async queue - resource._dequeue(); -}; - -/** - * Run middleware functions on a resource. - * - * @private - */ -Loader.prototype._runMiddleware = function (resource, fns, cb) { - var self = this; - - async.eachSeries(fns, function (fn, next) { - fn.call(self, resource, next); - }, cb.bind(this, resource)); -}; - -Loader.LOAD_TYPE = Resource.LOAD_TYPE; -Loader.XHR_READY_STATE = Resource.XHR_READY_STATE; -Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE; - -},{"./Resource":148,"async":1,"eventemitter3":2,"url":10}],148:[function(require,module,exports){ -var EventEmitter = require('eventemitter3'), - _url = require('url'), - // tests is CORS is supported in XHR, if not we need to use XDR - useXdr = !!(window.XDomainRequest && !('withCredentials' in (new XMLHttpRequest()))), - tempAnchor = null; - -/** - * Manages the state and loading of a single resource represented by - * a single URL. - * - * @class - * @param name {string} The name of the resource to load. - * @param url {string|string[]} The url for this resource, for audio/video loads you can pass an array of sources. - * @param [options] {object} The options for the load. - * @param [options.crossOrigin] {string|boolean} Is this request cross-origin? Default is to determine automatically. - * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.LOAD_TYPE} How should this resource be loaded? - * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being - * loaded be interpreted when using XHR? - * @param [options.metadata] {object} Extra info for middleware. - */ -function Resource(name, url, options) { - EventEmitter.call(this); - - options = options || {}; - - if (typeof name !== 'string' || typeof url !== 'string') { - throw new Error('Both name and url are required for constructing a resource.'); - } - - /** - * The name of this resource. - * - * @member {string} - * @readonly - */ - this.name = name; - - /** - * The url used to load this resource. - * - * @member {string} - * @readonly - */ - this.url = url; - - /** - * Stores whether or not this url is a data url. - * - * @member {boolean} - * @readonly - */ - this.isDataUrl = this.url.indexOf('data:') === 0; - - /** - * The data that was loaded by the resource. - * - * @member {any} - */ - this.data = null; - - /** - * Is this request cross-origin? If unset, determined automatically. - * - * @member {string} - */ - this.crossOrigin = options.crossOrigin === true ? 'anonymous' : options.crossOrigin; - - /** - * The method of loading to use for this resource. - * - * @member {Resource.LOAD_TYPE} - */ - this.loadType = options.loadType || this._determineLoadType(); - - /** - * The type used to load the resource via XHR. If unset, determined automatically. - * - * @member {string} - */ - this.xhrType = options.xhrType; - - /** - * Extra info for middleware - * - * @member {object} - */ - this.metadata = options.metadata || {}; - - /** - * The error that occurred while loading (if any). - * - * @member {Error} - * @readonly - */ - this.error = null; - - /** - * The XHR object that was used to load this resource. This is only set - * when `loadType` is `Resource.LOAD_TYPE.XHR`. - * - * @member {XMLHttpRequest} - */ - this.xhr = null; - - /** - * Describes if this resource was loaded as json. Only valid after the resource - * has completely loaded. - * - * @member {boolean} - */ - this.isJson = false; - - /** - * Describes if this resource was loaded as xml. Only valid after the resource - * has completely loaded. - * - * @member {boolean} - */ - this.isXml = false; - - /** - * Describes if this resource was loaded as an image tag. Only valid after the resource - * has completely loaded. - * - * @member {boolean} - */ - this.isImage = false; - - /** - * Describes if this resource was loaded as an audio tag. Only valid after the resource - * has completely loaded. - * - * @member {boolean} - */ - this.isAudio = false; - - /** - * Describes if this resource was loaded as a video tag. Only valid after the resource - * has completely loaded. - * - * @member {boolean} - */ - this.isVideo = false; - - /** - * The `dequeue` method that will be used a storage place for the async queue dequeue method - * used privately by the loader. - * - * @member {function} - * @private - */ - this._dequeue = null; - - /** - * The `complete` function bound to this resource's context. - * - * @member {function} - * @private - */ - this._boundComplete = this.complete.bind(this); - - /** - * The `_onError` function bound to this resource's context. - * - * @member {function} - * @private - */ - this._boundOnError = this._onError.bind(this); - - /** - * The `_onProgress` function bound to this resource's context. - * - * @member {function} - * @private - */ - this._boundOnProgress = this._onProgress.bind(this); - - // xhr callbacks - this._boundXhrOnError = this._xhrOnError.bind(this); - this._boundXhrOnAbort = this._xhrOnAbort.bind(this); - this._boundXhrOnLoad = this._xhrOnLoad.bind(this); - this._boundXdrOnTimeout = this._xdrOnTimeout.bind(this); - - /** - * Emitted when the resource beings to load. - * - * @event start - * @memberof Resource# - */ - - /** - * Emitted each time progress of this resource load updates. - * Not all resources types and loader systems can support this event - * so sometimes it may not be available. If the resource - * is being loaded on a modern browser, using XHR, and the remote server - * properly sets Content-Length headers, then this will be available. - * - * @event progress - * @memberof Resource# - */ - - /** - * Emitted once this resource has loaded, if there was an error it will - * be in the `error` property. - * - * @event complete - * @memberof Resource# - */ -} - -Resource.prototype = Object.create(EventEmitter.prototype); -Resource.prototype.constructor = Resource; -module.exports = Resource; - -/** - * Marks the resource as complete. - * - * @fires complete - */ -Resource.prototype.complete = function () { - // TODO: Clean this up in a wrapper or something...gross.... - if (this.data && this.data.removeEventListener) { - this.data.removeEventListener('error', this._boundOnError); - this.data.removeEventListener('load', this._boundComplete); - this.data.removeEventListener('progress', this._boundOnProgress); - this.data.removeEventListener('canplaythrough', this._boundComplete); - } - - if (this.xhr) { - if (this.xhr.removeEventListener) { - this.xhr.removeEventListener('error', this._boundXhrOnError); - this.xhr.removeEventListener('abort', this._boundXhrOnAbort); - this.xhr.removeEventListener('progress', this._boundOnProgress); - this.xhr.removeEventListener('load', this._boundXhrOnLoad); - } - else { - this.xhr.onerror = null; - this.xhr.ontimeout = null; - this.xhr.onprogress = null; - this.xhr.onload = null; - } - } - - this.emit('complete', this); -}; - -/** - * Kicks off loading of this resource. - * - * @fires start - * @param [callback] {function} Optional callback to call once the resource is loaded. - */ -Resource.prototype.load = function (cb) { - this.emit('start', this); - - // if a callback is set, listen for complete event - if (cb) { - this.once('complete', cb); - } - - // if unset, determine the value - if (this.crossOrigin === false || typeof this.crossOrigin !== 'string') { - this.crossOrigin = this._determineCrossOrigin(this.url); - } - - switch(this.loadType) { - case Resource.LOAD_TYPE.IMAGE: - this._loadImage(); - break; - - case Resource.LOAD_TYPE.AUDIO: - this._loadElement('audio'); - break; - - case Resource.LOAD_TYPE.VIDEO: - this._loadElement('video'); - break; - - case Resource.LOAD_TYPE.XHR: - /* falls through */ - default: - if (useXdr && this.crossOrigin) { - this._loadXdr(); - } - else { - this._loadXhr(); - } - break; - } -}; - -/** - * Loads this resources using an Image object. - * - * @private - */ -Resource.prototype._loadImage = function () { - if (!this.data) { - this.prepareImage(); - } - this.data.src = this.url; -}; - -/** - * Prepares image for loading, but does not set src yet - */ -Resource.prototype.prepareImage = function () { - this.data = new Image(); - - if (this.crossOrigin) { - this.data.crossOrigin = this.crossOrigin; - } - - this.isImage = true; - - this.data.addEventListener('error', this._boundOnError, false); - this.data.addEventListener('load', this._boundComplete, false); - this.data.addEventListener('progress', this._boundOnProgress, false); -}; - -/** - * Loads this resources using an HTMLAudioElement or HTMLVideoElement. - * - * @private - */ -Resource.prototype._loadElement = function (type) { - if (type === 'audio' && typeof Audio !== 'undefined') { - this.data = new Audio(); - } - else { - this.data = document.createElement(type); - } - - if (this.data === null) { - this.error = new Error('Unsupported element ' + type); - this.complete(); - return; - } - - // support for CocoonJS Canvas+ runtime, lacks document.createElement('source') - if (navigator.isCocoonJS) { - this.data.src = Array.isArray(this.url) ? this.url[0] : this.url; - } - else { - if (Array.isArray(this.url)) { - for (var i = 0; i < this.url.length; ++i) { - this.data.appendChild(this._createSource(type, this.url[i])); - } - } - else { - this.data.appendChild(this._createSource(type, this.url)); - } - } - - this['is' + type[0].toUpperCase() + type.substring(1)] = true; - - this.data.addEventListener('error', this._boundOnError, false); - this.data.addEventListener('load', this._boundComplete, false); - this.data.addEventListener('progress', this._boundOnProgress, false); - this.data.addEventListener('canplaythrough', this._boundComplete, false); - - this.data.load(); -}; - -/** - * Loads this resources using an XMLHttpRequest. - * - * @private - */ -Resource.prototype._loadXhr = function () { - // if unset, determine the value - if (typeof this.xhrType !== 'string') { - this.xhrType = this._determineXhrType(); - } - - var xhr = this.xhr = new XMLHttpRequest(); - - // set the request type and url - xhr.open('GET', this.url, true); - - // load json as text and parse it ourselves. We do this because some browsers - // *cough* safari *cough* can't deal with it. - if (this.xhrType === Resource.XHR_RESPONSE_TYPE.JSON || this.xhrType === Resource.XHR_RESPONSE_TYPE.DOCUMENT) { - xhr.responseType = Resource.XHR_RESPONSE_TYPE.TEXT; - } - else { - xhr.responseType = this.xhrType; - } - - xhr.addEventListener('error', this._boundXhrOnError, false); - xhr.addEventListener('abort', this._boundXhrOnAbort, false); - xhr.addEventListener('progress', this._boundOnProgress, false); - xhr.addEventListener('load', this._boundXhrOnLoad, false); - - xhr.send(); -}; - -/** - * Loads this resources using an XDomainRequest. This is here because we need to support IE9 (gross). - * - * @private - */ -Resource.prototype._loadXdr = function () { - // if unset, determine the value - if (typeof this.xhrType !== 'string') { - this.xhrType = this._determineXhrType(); - } - - var xdr = this.xhr = new XDomainRequest(); - - // XDomainRequest has a few quirks. Occasionally it will abort requests - // A way to avoid this is to make sure ALL callbacks are set even if not used - // More info here: http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9 - xdr.timeout = 5000; - - xdr.onerror = this._boundXhrOnError; - xdr.ontimeout = this._boundXdrOnTimeout; - xdr.onprogress = this._boundOnProgress; - xdr.onload = this._boundXhrOnLoad; - - xdr.open('GET', this.url, true); - - // Note: The xdr.send() call is wrapped in a timeout to prevent an issue with the interface where some requests are lost - // if multiple XDomainRequests are being sent at the same time. - // Some info here: https://github.com/photonstorm/phaser/issues/1248 - setTimeout(function () { - xdr.send(); - }, 0); -}; - -/** - * Creates a source used in loading via an element. - * - * @param type {string} The element type (video or audio). - * @param url {string} The source URL to load from. - * @param [mime] {string} The mime type of the video - * @private - */ -Resource.prototype._createSource = function (type, url, mime) { - if (!mime) { - mime = type + '/' + url.substr(url.lastIndexOf('.') + 1); - } - - var source = document.createElement('source'); - - source.src = url; - source.type = mime; - - return source; -}; - -/** - * Called if a load errors out. - * - * @param event {Event} The error event from the element that emits it. - * @private - */ -Resource.prototype._onError = function (event) { - this.error = new Error('Failed to load element using ' + event.target.nodeName); - this.complete(); -}; - -/** - * Called if a load progress event fires for xhr/xdr. - * - * @fires progress - * @param event {XMLHttpRequestProgressEvent|Event} - * @private - */ -Resource.prototype._onProgress = function (event) { - if (event && event.lengthComputable) { - this.emit('progress', this, event.loaded / event.total); - } -}; - -/** - * Called if an error event fires for xhr/xdr. - * - * @param event {XMLHttpRequestErrorEvent|Event} - * @private - */ -Resource.prototype._xhrOnError = function () { - this.error = new Error( - reqType(this.xhr) + ' Request failed. ' + - 'Status: ' + this.xhr.status + ', text: "' + this.xhr.statusText + '"' - ); - - this.complete(); -}; - -/** - * Called if an abort event fires for xhr. - * - * @param event {XMLHttpRequestAbortEvent} - * @private - */ -Resource.prototype._xhrOnAbort = function () { - this.error = new Error(reqType(this.xhr) + ' Request was aborted by the user.'); - this.complete(); -}; - -/** - * Called if a timeout event fires for xdr. - * - * @param event {Event} - * @private - */ -Resource.prototype._xdrOnTimeout = function () { - this.error = new Error(reqType(this.xhr) + ' Request timed out.'); - this.complete(); -}; - -/** - * Called when data successfully loads from an xhr/xdr request. - * - * @param event {XMLHttpRequestLoadEvent|Event} - * @private - */ -Resource.prototype._xhrOnLoad = function () { - var xhr = this.xhr, - status = xhr.status !== undefined ? xhr.status : 200; //XDR has no `.status`, assume 200. - - // status can be 0 when using the file:// protocol, also check if a response was found - if (status === 200 || status === 204 || (status === 0 && xhr.responseText.length > 0)) { - // if text, just return it - if (this.xhrType === Resource.XHR_RESPONSE_TYPE.TEXT) { - this.data = xhr.responseText; - } - // if json, parse into json object - else if (this.xhrType === Resource.XHR_RESPONSE_TYPE.JSON) { - try { - this.data = JSON.parse(xhr.responseText); - this.isJson = true; - } catch(e) { - this.error = new Error('Error trying to parse loaded json:', e); - } - } - // if xml, parse into an xml document or div element - else if (this.xhrType === Resource.XHR_RESPONSE_TYPE.DOCUMENT) { - try { - if (window.DOMParser) { - var domparser = new DOMParser(); - this.data = domparser.parseFromString(xhr.responseText, 'text/xml'); - } - else { - var div = document.createElement('div'); - div.innerHTML = xhr.responseText; - this.data = div; - } - this.isXml = true; - } catch (e) { - this.error = new Error('Error trying to parse loaded xml:', e); - } - } - // other types just return the response - else { - this.data = xhr.response || xhr.responseText; - } - } - else { - this.error = new Error('[' + xhr.status + ']' + xhr.statusText + ':' + xhr.responseURL); - } - - this.complete(); -}; - -function reqType(xhr) { - return xhr.toString().replace('object ', ''); -} - -/** - * Sets the `crossOrigin` property for this resource based on if the url - * for this resource is cross-origin. If crossOrigin was manually set, this - * function does nothing. - * - * @private - * @param url {string} The url to test. - * @param [location=window.location] {object} The location object to test against. - * @return {string} The crossOrigin value to use (or empty string for none). - */ -Resource.prototype._determineCrossOrigin = function (url, loc) { - // data: and javascript: urls are considered same-origin - if (url.indexOf('data:') === 0) { - return ''; - } - - // default is window.location - loc = loc || window.location; - - if (!tempAnchor) { - tempAnchor = document.createElement('a'); - } - - // let the browser determine the full href for the url of this resource and then - // parse with the node url lib, we can't use the properties of the anchor element - // because they don't work in IE9 :( - tempAnchor.href = url; - url = _url.parse(tempAnchor.href); - - var samePort = (!url.port && loc.port === '') || (url.port === loc.port); - - // if cross origin - if (url.hostname !== loc.hostname || !samePort || url.protocol !== loc.protocol) { - return 'anonymous'; - } - - return ''; -}; - -/** - * Determines the responseType of an XHR request based on the extension of the - * resource being loaded. - * - * @private - * @return {Resource.XHR_RESPONSE_TYPE} The responseType to use. - */ -Resource.prototype._determineXhrType = function () { - return Resource._xhrTypeMap[this._getExtension()] || Resource.XHR_RESPONSE_TYPE.TEXT; -}; - -Resource.prototype._determineLoadType = function () { - return Resource._loadTypeMap[this._getExtension()] || Resource.LOAD_TYPE.XHR; -}; - -Resource.prototype._getExtension = function () { - var url = this.url, - ext; - - if (this.isDataUrl) { - var slashIndex = url.indexOf('/'); - ext = url.substring(slashIndex + 1, url.indexOf(';', slashIndex)); - } - else { - var queryStart = url.indexOf('?'); - if (queryStart !== -1) { - url = url.substring(0, queryStart); - } - - ext = url.substring(url.lastIndexOf('.') + 1); - } - - return ext; -}; - -/** - * Determines the mime type of an XHR request based on the responseType of - * resource being loaded. - * - * @private - * @return {string} The mime type to use. - */ -Resource.prototype._getMimeFromXhrType = function (type) { - switch(type) { - case Resource.XHR_RESPONSE_TYPE.BUFFER: - return 'application/octet-binary'; - - case Resource.XHR_RESPONSE_TYPE.BLOB: - return 'application/blob'; - - case Resource.XHR_RESPONSE_TYPE.DOCUMENT: - return 'application/xml'; - - case Resource.XHR_RESPONSE_TYPE.JSON: - return 'application/json'; - - case Resource.XHR_RESPONSE_TYPE.DEFAULT: - case Resource.XHR_RESPONSE_TYPE.TEXT: - /* falls through */ - default: - return 'text/plain'; - - } -}; - -/** - * The types of loading a resource can use. - * - * @static - * @constant - * @property {object} LOAD_TYPE - * @property {number} LOAD_TYPE.XHR - Uses XMLHttpRequest to load the resource. - * @property {number} LOAD_TYPE.IMAGE - Uses an `Image` object to load the resource. - * @property {number} LOAD_TYPE.AUDIO - Uses an `Audio` object to load the resource. - * @property {number} LOAD_TYPE.VIDEO - Uses a `Video` object to load the resource. - */ -Resource.LOAD_TYPE = { - XHR: 1, - IMAGE: 2, - AUDIO: 3, - VIDEO: 4 -}; - -/** - * The XHR ready states, used internally. - * - * @static - * @constant - * @property {object} XHR_READY_STATE - * @property {number} XHR_READY_STATE.UNSENT - open()has not been called yet. - * @property {number} XHR_READY_STATE.OPENED - send()has not been called yet. - * @property {number} XHR_READY_STATE.HEADERS_RECEIVED - send() has been called, and headers and status are available. - * @property {number} XHR_READY_STATE.LOADING - Downloading; responseText holds partial data. - * @property {number} XHR_READY_STATE.DONE - The operation is complete. - */ -Resource.XHR_READY_STATE = { - UNSENT: 0, - OPENED: 1, - HEADERS_RECEIVED: 2, - LOADING: 3, - DONE: 4 -}; - -/** - * The XHR ready states, used internally. - * - * @static - * @constant - * @property {object} XHR_RESPONSE_TYPE - * @property {string} XHR_RESPONSE_TYPE.DEFAULT - defaults to text - * @property {string} XHR_RESPONSE_TYPE.BUFFER - ArrayBuffer - * @property {string} XHR_RESPONSE_TYPE.BLOB - Blob - * @property {string} XHR_RESPONSE_TYPE.DOCUMENT - Document - * @property {string} XHR_RESPONSE_TYPE.JSON - Object - * @property {string} XHR_RESPONSE_TYPE.TEXT - String - */ -Resource.XHR_RESPONSE_TYPE = { - DEFAULT: 'text', - BUFFER: 'arraybuffer', - BLOB: 'blob', - DOCUMENT: 'document', - JSON: 'json', - TEXT: 'text' -}; - -Resource._loadTypeMap = { - 'gif': Resource.LOAD_TYPE.IMAGE, - 'png': Resource.LOAD_TYPE.IMAGE, - 'bmp': Resource.LOAD_TYPE.IMAGE, - 'jpg': Resource.LOAD_TYPE.IMAGE, - 'jpeg': Resource.LOAD_TYPE.IMAGE, - 'tif': Resource.LOAD_TYPE.IMAGE, - 'tiff': Resource.LOAD_TYPE.IMAGE, - 'webp': Resource.LOAD_TYPE.IMAGE, - 'tga': Resource.LOAD_TYPE.IMAGE -}; - -Resource._xhrTypeMap = { - // xml - 'xhtml': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'html': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'htm': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'xml': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'tmx': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'tsx': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'svg': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - - // images - 'gif': Resource.XHR_RESPONSE_TYPE.BLOB, - 'png': Resource.XHR_RESPONSE_TYPE.BLOB, - 'bmp': Resource.XHR_RESPONSE_TYPE.BLOB, - 'jpg': Resource.XHR_RESPONSE_TYPE.BLOB, - 'jpeg': Resource.XHR_RESPONSE_TYPE.BLOB, - 'tif': Resource.XHR_RESPONSE_TYPE.BLOB, - 'tiff': Resource.XHR_RESPONSE_TYPE.BLOB, - 'webp': Resource.XHR_RESPONSE_TYPE.BLOB, - 'tga': Resource.XHR_RESPONSE_TYPE.BLOB, - - // json - 'json': Resource.XHR_RESPONSE_TYPE.JSON, - - // text - 'text': Resource.XHR_RESPONSE_TYPE.TEXT, - 'txt': Resource.XHR_RESPONSE_TYPE.TEXT -}; - -/** - * Sets the load type to be used for a specific extension. - * - * @static - * @param extname {string} The extension to set the type for, e.g. "png" or "fnt" - * @param loadType {Resource.LOAD_TYPE} The load type to set it to. - */ -Resource.setExtensionLoadType = function (extname, loadType) { - setExtMap(Resource._loadTypeMap, extname, loadType); -}; - -/** - * Sets the load type to be used for a specific extension. - * - * @static - * @param extname {string} The extension to set the type for, e.g. "png" or "fnt" - * @param xhrType {Resource.XHR_RESPONSE_TYPE} The xhr type to set it to. - */ -Resource.setExtensionXhrType = function (extname, xhrType) { - setExtMap(Resource._xhrTypeMap, extname, xhrType); -}; - -function setExtMap(map, extname, val) { - if (extname && extname.indexOf('.') === 0) { - extname = extname.substring(1); - } - - if (!extname) { - return; - } - - map[extname] = val; -} - -},{"eventemitter3":2,"url":10}],149:[function(require,module,exports){ -module.exports = { - - // private property - _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", - - encodeBinary: function (input) { - var output = ""; - var bytebuffer; - var encodedCharIndexes = new Array(4); - var inx = 0; - var jnx = 0; - var paddingBytes = 0; - - while (inx < input.length) { - // Fill byte buffer array - bytebuffer = new Array(3); - for (jnx = 0; jnx < bytebuffer.length; jnx++) { - if (inx < input.length) { - // throw away high-order byte, as documented at: - // https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data - bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff; - } - else { - bytebuffer[jnx] = 0; - } - } - - // Get each encoded character, 6 bits at a time - // index 1: first 6 bits - encodedCharIndexes[0] = bytebuffer[0] >> 2; - // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2) - encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4); - // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3) - encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6); - // index 3: forth 6 bits (6 least significant bits from input byte 3) - encodedCharIndexes[3] = bytebuffer[2] & 0x3f; - - // Determine whether padding happened, and adjust accordingly - paddingBytes = inx - (input.length - 1); - switch (paddingBytes) { - case 2: - // Set last 2 characters to padding char - encodedCharIndexes[3] = 64; - encodedCharIndexes[2] = 64; - break; - - case 1: - // Set last character to padding char - encodedCharIndexes[3] = 64; - break; - - default: - break; // No padding - proceed - } - - // Now we will grab each appropriate character out of our keystring - // based on our index array and append it to the output string - for (jnx = 0; jnx < encodedCharIndexes.length; jnx++) { - output += this._keyStr.charAt(encodedCharIndexes[jnx]); - } - } - return output; - } -}; - -},{}],150:[function(require,module,exports){ -module.exports = require('./Loader'); - -module.exports.Resource = require('./Resource'); - -module.exports.middleware = { - caching: { - memory: require('./middlewares/caching/memory') - }, - parsing: { - blob: require('./middlewares/parsing/blob') - } -}; - -},{"./Loader":147,"./Resource":148,"./middlewares/caching/memory":151,"./middlewares/parsing/blob":152}],151:[function(require,module,exports){ -// a simple in-memory cache for resources -var cache = {}; - -module.exports = function () { - return function (resource, next) { - // if cached, then set data and complete the resource - if (cache[resource.url]) { - resource.data = cache[resource.url]; - resource.complete(); - } - // if not cached, wait for complete and store it in the cache. - else { - resource.once('complete', function () { - cache[this.url] = this.data; - }); - } - - next(); - }; -}; - -},{}],152:[function(require,module,exports){ -var Resource = require('../../Resource'), - b64 = require('../../b64'); - -window.URL = window.URL || window.webkitURL; - -// a middleware for transforming XHR loaded Blobs into more useful objects - -module.exports = function () { - return function (resource, next) { - if (!resource.data) { - return next(); - } - - // if this was an XHR load of a blob - if (resource.xhr && resource.xhrType === Resource.XHR_RESPONSE_TYPE.BLOB) { - // if there is no blob support we probably got a binary string back - if (!window.Blob || typeof resource.data === 'string') { - var type = resource.xhr.getResponseHeader('content-type'); - - // this is an image, convert the binary string into a data url - if (type && type.indexOf('image') === 0) { - resource.data = new Image(); - resource.data.src = 'data:' + type + ';base64,' + b64.encodeBinary(resource.xhr.responseText); - - resource.isImage = true; - - // wait until the image loads and then callback - resource.data.onload = function () { - resource.data.onload = null; - - next(); - }; - } - } - // if content type says this is an image, then we should transform the blob into an Image object - else if (resource.data.type.indexOf('image') === 0) { - var src = URL.createObjectURL(resource.data); - - resource.blob = resource.data; - resource.data = new Image(); - resource.data.src = src; - - resource.isImage = true; - - // cleanup the no longer used blob after the image loads - resource.data.onload = function () { - URL.revokeObjectURL(src); - resource.data.onload = null; - - next(); - }; - } - } - else { - next(); - } - }; -}; - -},{"../../Resource":148,"../../b64":149}]},{},[123])(123) +},{}]},{},[129])(129) }); //# sourceMappingURL=pixi.js.map diff --git a/bin/pixi.js b/bin/pixi.js index 7bb4fa7..49a3d63 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -1,4 +1,4485 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.PIXI = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= data.byteLength) + { + gl.bufferSubData(this.type, offset, data); + } + else + { + gl.bufferData(this.type, data, this.drawType); + } + + this.data = data; +} +/** + * Binds the buffer + * + */ +Buffer.prototype.bind = function() +{ + var gl = this.gl; + gl.bindBuffer(this.type, this.buffer); +} + +Buffer.createVertexBuffer = function(gl, data, drawType) +{ + return new Buffer(gl, gl.ARRAY_BUFFER, data, drawType); +} + +Buffer.createIndexBuffer = function(gl, data, drawType) +{ + return new Buffer(gl, gl.ELEMENT_ARRAY_BUFFER, data, drawType); +} + +Buffer.create = function(gl, type, data, drawType) +{ + return new Buffer(gl, type, drawType); +} + +/** + * Destroys the buffer + * + */ +Buffer.prototype.destroy = function(){ + this.gl.deleteBuffer(this.buffer); +} + +module.exports = Buffer; + +},{}],3:[function(require,module,exports){ + +var Texture = require('./GLTexture'); + +/** + * Helper class to create a webGL Framebuffer + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + */ +var Framebuffer = function(gl, width, height) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * The frame buffer + * + * @member {WebGLFramebuffer} + */ + this.framebuffer = gl.createFramebuffer(); + + /** + * The stencil buffer + * + * @member {WebGLRenderbuffer} + */ + this.stencil = null; + + /** + * The stencil buffer + * + * @member {GLTexture} + */ + this.texture = null; + + /** + * The width of the drawing area of the buffer + * + * @member {Number} + */ + this.width = width || 100; + /** + * The height of the drawing area of the buffer + * + * @member {Number} + */ + this.height = height || 100; +} + +/** + * Adds a texture to the frame buffer + * @param texture {GLTexture} + */ +Framebuffer.prototype.enableTexture = function(texture) +{ + var gl = this.gl; + + this.texture = texture || new Texture(gl); + + this.texture.bind(); + + //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + + this.bind(); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); +} + +/** + * Initialises the stencil buffer + * @mat maybe you can come up with a better explaination + */ +Framebuffer.prototype.enableStencil = function() +{ + if(this.stencil)return; + + var gl = this.gl; + + this.stencil = gl.createRenderbuffer(); + + gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); + + // TODO.. this is depth AND stencil? + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width , this.height ); +} + +/** + * Erases the drawing area and fills it with a colour + * @param r {Number} the red value of the clearing colour + * @param g {Number} the green value of the clearing colour + * @param b {Number} the blue value of the clearing colour + * @param a {Number} the alpha value of the clearing colour + */ +Framebuffer.prototype.clear = function( r, g, b, a ) +{ + this.bind(); + + var gl = this.gl; + + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT); +} + +/** + * Binds the frame buffer to the WebGL context + */ +Framebuffer.prototype.bind = function() +{ + var gl = this.gl; + + if(this.texture) + { + this.texture.unbind(); + } + + gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); +} + +/** + * Unbinds the frame buffer to the WebGL context + */ +Framebuffer.prototype.unbind = function() +{ + var gl = this.gl; + gl.bindFramebuffer(gl.FRAMEBUFFER, null ); +} +/** + * Resizes the drawing area of the buffer to the given width and height + * @param width {Number} the new width + * @param height {Number} the new height + */ +Framebuffer.prototype.resize = function(width, height) +{ + var gl = this.gl; + + this.width = width; + this.height = height; + + if ( this.texture ) + { + this.texture.uploadData(null, width, height); + } + + if ( this.stencil ) + { + // update the stencil buffer width and height + gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + } +} + +/** + * Destroys this buffer + */ +Framebuffer.prototype.destroy = function() +{ + var gl = this.gl; + + //TODO + if(this.texture) + { + this.texture.destroy(); + } + + gl.deleteFramebuffer(this.framebuffer); + + this.gl = null; + + this.stencil = null; + this.texture = null; +} + +/** + * Creates a frame buffer with a texture containing the given data + * @mat can you confirm ? :) + * @static + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data + */ +Framebuffer.createRGBA = function(gl, width, height, data) +{ + var texture = Texture.fromData(gl, null, width, height); + texture.enableNearestScaling(); + texture.enableWrapClamp(); + + //now create the framebuffer object and attach the texture to it. + var fbo = new Framebuffer(gl, width, height); + fbo.enableTexture(texture); + + fbo.unbind(); + + return fbo; +} + +/** + * Creates a frame buffer with a texture containing the given data + * @mat not sure what the difference is with the method above ? + * @static + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param width {Number} the width of the drawing area of the frame buffer + * @param height {Number} the height of the drawing area of the frame buffer + * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data + */ +Framebuffer.createFloat32 = function(gl, width, height, data) +{ + // create a new texture.. + var texture = new Texture.fromData(gl, data, width, height); + texture.enableNearestScaling(); + texture.enableWrapClamp(); + + //now create the framebuffer object and attach the texture to it. + var fbo = new Framebuffer(gl, width, height); + fbo.enableTexture(texture) + + fbo.unbind(); + + return fbo; +} + +module.exports = Framebuffer; + +},{"./GLTexture":5}],4:[function(require,module,exports){ + +var compileProgram = require('./shader/compileProgram'), + extractAttributes = require('./shader/extractAttributes'), + extractUniforms = require('./shader/extractUniforms'), + generateUniformAccessObject = require('./shader/generateUniformAccessObject'); + +/** + * Helper class to create a webGL Shader + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. + */ +var Shader = function(gl, vertexSrc, fragmentSrc) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * The shader program + * + * @member {WebGLProgram} + */ + // First compile the program.. + this.program = compileProgram(gl, vertexSrc, fragmentSrc); + + + /** + * The attributes of the shader as an object containing the following properties + * { + * type, + * size, + * location, + * pointer + * } + * @member {Object} + */ + // next extract the attributes + this.attributes = extractAttributes(gl, this.program); + + var uniformData = extractUniforms(gl, this.program); + + /** + * The uniforms of the shader as an object containing the following properties + * { + * gl, + * data + * } + * @member {Object} + */ + this.uniforms = generateUniformAccessObject( gl, uniformData ); +} +/** + * Uses this shader + */ +Shader.prototype.bind = function() +{ + this.gl.useProgram(this.program); +} + +/** + * Destroys this shader + * TODO + */ +Shader.prototype.destroy = function() +{ + var gl = this.gl; +} + +module.exports = Shader; + +},{"./shader/compileProgram":9,"./shader/extractAttributes":11,"./shader/extractUniforms":12,"./shader/generateUniformAccessObject":13}],5:[function(require,module,exports){ + +/** + * Helper class to create a WebGL Texture + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL context + * @param width {number} the width of the texture + * @param height {number} the height of the texture + * @param format {number} the pixel format of the texture. defaults to gl.RGBA + * @param type {number} the gl type of the texture. defaults to gl.UNSIGNED_BYTE + */ +var Texture = function(gl, width, height, format, type) +{ + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + + /** + * The WebGL texture + * + * @member {WebGLTexture} + */ + this.texture = gl.createTexture(); + + /** + * If mipmapping was used for this texture, enable and disable with enableMipmap() + * + * @member {Boolean} + */ + // some settings.. + this.mipmap = false; + + + /** + * Set to true to enable pre-multiplied alpha + * + * @member {Boolean} + */ + this.premultiplyAlpha = false; + + /** + * The width of texture + * + * @member {Number} + */ + this.width = width || 0; + /** + * The height of texture + * + * @member {Number} + */ + this.height = height || 0; + + /** + * The pixel format of the texture. defaults to gl.RGBA + * + * @member {Number} + */ + this.format = format || gl.RGBA; + + /** + * The gl type of the texture. defaults to gl.UNSIGNED_BYTE + * + * @member {Number} + */ + this.type = type || gl.UNSIGNED_BYTE; + + +} + +/** + * Uploads this texture to the GPU + * @param source {HTMLImageElement|ImageData} the source image of the texture + */ +Texture.prototype.upload = function(source) +{ + this.bind(); + + var gl = this.gl; + + this.width = source.width; + this.height = source.height; + + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); + gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, source); +} + +var FLOATING_POINT_AVAILABLE = false; + +/** + * Use a data source and uploads this texture to the GPU + * @param data {TypedArray} the data to upload to the texture + * @param width {number} the new width of the texture + * @param height {number} the new height of the texture + */ +Texture.prototype.uploadData = function(data, width, height) +{ + this.bind(); + + var gl = this.gl; + + this.width = width || this.width; + this.height = height || this.height; + + if(data instanceof Float32Array) + { + if(!FLOATING_POINT_AVAILABLE) + { + var ext = gl.getExtension("OES_texture_float"); + + if(ext) + { + FLOATING_POINT_AVAILABLE = true; + } + else + { + throw new Error('floating point textures not available'); + } + } + + this.type = gl.FLOAT; + } + else + { + // TODO support for other types + this.type = gl.UNSIGNED_BYTE; + } + + + + // what type of data? + gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); + gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, data || null); + +} + +/** + * Binds the texture + * @param location {@mat} + */ +Texture.prototype.bind = function(location) +{ + var gl = this.gl; + + if(location !== undefined) + { + gl.activeTexture(gl.TEXTURE0 + location); + } + + gl.bindTexture(gl.TEXTURE_2D, this.texture); +} + +/** + * Unbinds the texture + */ +Texture.prototype.unbind = function() +{ + var gl = this.gl; + gl.bindTexture(gl.TEXTURE_2D, null); +} + +/** + * @mat + * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation + */ +Texture.prototype.minFilter = function( linear ) +{ + var gl = this.gl; + + this.bind(); + + if(this.mipmap) + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); + } + else + { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST); + } +} + +/** + * @mat + * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation + */ +Texture.prototype.magFilter = function( linear ) +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST); +} + +/** + * Enables mipmapping + */ +Texture.prototype.enableMipmap = function() +{ + var gl = this.gl; + + this.bind(); + + this.mipmap = true; + + gl.generateMipmap(gl.TEXTURE_2D); +} + +/** + * Enables linear filtering + */ +Texture.prototype.enableLinearScaling = function() +{ + this.minFilter(true); + this.magFilter(true); +} + +/** + * Enables nearest neighbour interpolation + */ +Texture.prototype.enableNearestScaling = function() +{ + this.minFilter(false); + this.magFilter(false); +} + +/** + * Enables clamping on the texture so WebGL will not repeat it + */ +Texture.prototype.enableWrapClamp = function() +{ + var gl = this.gl; + + this.bind(); + + 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); +} + +/** + * Enable tiling on the texture + */ +Texture.prototype.enableWrapRepeat = function() +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); +} + +/** + * @mat + */ +Texture.prototype.enableWrapMirrorRepeat = function() +{ + var gl = this.gl; + + this.bind(); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); +} + + +/** + * Destroys this texture + */ +Texture.prototype.destroy = function() +{ + var gl = this.gl; + //TODO + gl.deleteTexture(this.texture); +} + +/** + * @static + * @param gl {WebGLRenderingContext} The current WebGL context + * @param source {HTMLImageElement|ImageData} the source image of the texture + * @param premultiplyAlpha {Boolean} If we want to use pre-multiplied alpha + */ +Texture.fromSource = function(gl, source, premultiplyAlpha) +{ + var texture = new Texture(gl); + texture.premultiplyAlpha = premultiplyAlpha || false; + texture.upload(source); + + return texture; +} + +/** + * @static + * @param gl {WebGLRenderingContext} The current WebGL context + * @param data {TypedArray} the data to upload to the texture + * @param width {number} the new width of the texture + * @param height {number} the new height of the texture + */ +Texture.fromData = function(gl, data, width, height) +{ + //console.log(data, width, height); + var texture = new Texture(gl); + texture.uploadData(data, width, height); + + return texture; +} + + +module.exports = Texture; + +},{}],6:[function(require,module,exports){ + +// state object// +var setVertexAttribArrays = require( './setVertexAttribArrays' ); + +/** + * Helper class to work with WebGL VertexArrayObjects (vaos) + * Only works if WebGL extensions are enabled (they usually are) + * + * @class + * @memberof pixi.gl + * @param gl {WebGLRenderingContext} The current WebGL rendering context + */ +function VertexArrayObject(gl, state) +{ + + this.nativeVaoExtension = ( + gl.getExtension('OES_vertex_array_object') || + gl.getExtension('MOZ_OES_vertex_array_object') || + gl.getExtension('WEBKIT_OES_vertex_array_object') + ); + + this.nativeState = state; + + if(this.nativeVaoExtension) + { + this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); + + var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + + // VAO - overwrite the state.. + this.nativeState = {tempAttribState:new Array(maxAttribs) + ,attribState:new Array(maxAttribs)}; + } + + /** + * The current WebGL rendering context + * + * @member {WebGLRenderingContext} + */ + this.gl = gl; + + /** + * An array of attributes ? @mat + * + * @member {Array} + */ + this.attributes = []; + + /** + * @mat + * + * @member {Array} + */ + this.indexBuffer = null; + + /** + * A boolean flag + * + * @member {Boolean} + */ + this.dirty = false; +} + +VertexArrayObject.prototype.constructor = VertexArrayObject; +module.exports = VertexArrayObject; + + +/** + * Binds the buffer + */ +VertexArrayObject.prototype.bind = function() +{ + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + + if(this.dirty) + { + this.dirty = false; + this.activate(); + } + } + else + { + + this.activate(); + } + + return this; +} + +/** + * Unbinds the buffer + */ +VertexArrayObject.prototype.unbind = function() +{ + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + return this; +} + +/** + * Uses this vao + */ +VertexArrayObject.prototype.activate = function() +{ + + var gl = this.gl; + var lastBuffer = null; + + for (var i = 0; i < this.attributes.length; i++) + { + var attrib = this.attributes[i]; + + if(lastBuffer !== attrib.buffer) + { + attrib.buffer.bind(); + lastBuffer = attrib.buffer; + } + + //attrib.attribute.pointer(attrib.type, attrib.normalized, attrib.stride, attrib.start); + gl.vertexAttribPointer(attrib.attribute.location, + attrib.attribute.size, attrib.type || gl.FLOAT, + attrib.normalized || false, + attrib.stride || 0, + attrib.start || 0); + + + }; + + setVertexAttribArrays(gl, this.attributes, this.nativeState); + + this.indexBuffer.bind(); + + return this; +} + +/** + * + * @param buffer {WebGLBuffer} + * @param attribute {[type]} + * @param type {[type]} + * @param normalized {[type]} + * @param stride {Number} + * @param start {Number} + */ +VertexArrayObject.prototype.addAttribute = function(buffer, attribute, type, normalized, stride, start) +{ + this.attributes.push({ + buffer: buffer, + attribute: attribute, + + location: attribute.location, + type: type || this.gl.FLOAT, + normalized: normalized || false, + stride: stride || 0, + start: start || 0 + }) + + this.dirty = true; + + return this; +} + +/** + * + * @param buffer {WebGLBuffer} + * @param options {Object} + */ +VertexArrayObject.prototype.addIndex = function(buffer, options) +{ + this.indexBuffer = buffer; + + this.dirty = true; + + return this; +} + +/** + * Unbinds this vao and disables it + */ +VertexArrayObject.prototype.clear = function() +{ + var gl = this.gl; + + // TODO - should this function unbind after clear? + // for now, no but lets see what happens in the real world! + if(this.nativeVao) + { + this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); + } + + this.attributes.length = 0; + this.indexBuffer = null; + + return this; +} + +/** + * @mat + * @param type {Number} + * @param size {Number} + * @param start {Number} + */ +VertexArrayObject.prototype.draw = function(type, size, start) +{ + var gl = this.gl; + gl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0); + + return this; +} + +},{"./setVertexAttribArrays":8}],7:[function(require,module,exports){ + +/** + * Helper class to create a webGL Context + * + * @class + * @memberof pixi.gl + * @param canvas {HTMLCanvasElement} the canvas element that we will get the context from + * @param options {Object} An options object that gets passed in to the canvas element containing the context attributes, + * see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext for the options available + * @return {WebGLRenderingContext} the WebGL context + */ +var createContext = function(canvas, options) +{ + var gl = canvas.getContext('webgl', options) || + canvas.getContext('experimental-webgl', options); + + if (!gl) + { + // fail, not able to get a context + throw new Error('This browser does not support webGL. Try using the canvas renderer'); + } + + return gl; +} + +module.exports = createContext; + +},{}],8:[function(require,module,exports){ +var GL_MAP = {}; + +/** + * @mat + * @param gl {WebGLRenderingContext} The current WebGL context + * @param attribs {[type]} + */ +var setVertexAttribArrays = function (gl, attribs, state) +{ + + if(state) + { + + var i, + tempAttribState = state.tempAttribState, + attribState = state.attribState; + + for (i = 0; i < tempAttribState.length; i++) + { + tempAttribState[i] = false; + } + + // set the new attribs + for (i in attribs) + { + tempAttribState[attribs[i].attribute.location] = true; + } + + for (i = 0; i < attribState.length; i++) + { + if (attribState[i] !== tempAttribState[i]) + { + attribState[i] = tempAttribState[i]; + + if (state.attribState[i]) + { + gl.enableVertexAttribArray(i); + } + else + { + gl.disableVertexAttribArray(i); + } + } + } + + } + else + { + for (var i = 0; i < attribs.length; i++) + { + var attrib = attribs[i]; + gl.enableVertexAttribArray(attrib.attribute.location); + } + } +}; + +module.exports = setVertexAttribArrays; + +},{}],9:[function(require,module,exports){ + +/** + * + * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. + * @return {WebGLProgram} the shader program + */ +compileProgram = function(gl, vertexSrc, fragmentSrc) +{ + var glVertShader = compileShader(gl, gl.VERTEX_SHADER, vertexSrc); + var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc); + + var program = gl.createProgram(); + + gl.attachShader(program, glVertShader); + gl.attachShader(program, glFragShader); + gl.linkProgram(program); + + // if linking fails, then log and cleanup + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) + { + console.error('Pixi.js Error: Could not initialize shader.'); + console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS)); + console.error('gl.getError()', gl.getError()); + + // if there is a program info log, log it + if (gl.getProgramInfoLog(program) !== '') + { + console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program)); + } + + gl.deleteProgram(program); + program = null; + } + + // clean up some shaders + gl.deleteShader(glVertShader); + gl.deleteShader(glFragShader); + + return program; +} + +/** + * + * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} + * @param type {Number} the type, can be either VERTEX_SHADER or FRAGMENT_SHADER + * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. + * @return {WebGLShader} the shader + */ +var compileShader = function (gl, type, src) +{ + var shader = gl.createShader(type); + + gl.shaderSource(shader, src); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) + { + console.log(gl.getShaderInfoLog(shader)); + return null; + } + + return shader; +}; + +module.exports = compileProgram; + +},{}],10:[function(require,module,exports){ + + +var defaultValue = function(type, size) +{ + switch (type) + { + case 'float': + return 0; + + case 'vec2': + return new Float32Array(2 * size); + + case 'vec3': + return new Float32Array(3 * size); + + case 'vec4': + return new Float32Array(4 * size); + + case 'int': + case 'sampler2D': + return 0; + + case 'ivec2': + return new Int32Array(2 * size); + + case 'ivec3': + return new Int32Array(3 * size); + + case 'ivec4': + return new Int32Array(4 * size); + + case 'bool': + return false; + + case 'bvec2': + + return booleanArray( 2 * size); + + case 'bvec3': + return booleanArray(3 * size); + + case 'bvec4': + return booleanArray(4 * size); + + case 'mat2': + return new Float32Array([1, 0 + ,0, 1]); + + case 'mat3': + return new Float32Array([1, 0, 0 + ,0, 1, 0 + ,0, 0, 1]); + + case 'mat4': + return new Float32Array([1, 0, 0, 0 + ,0, 1, 0, 0 + ,0, 0, 1, 0 + ,0, 0, 0, 1]); + } +} + +var booleanArray = function(size) +{ + var array = new Array(size); + + for (var i = 0; i < array.length; i++) + { + array[i] = false; + }; + + return array; +} + +module.exports = defaultValue; + +},{}],11:[function(require,module,exports){ + +var mapType = require('./mapType'); +var mapSize = require('./mapSize'); + +/** + * Extracts the attributes + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param program {WebGLProgram} The shader program to get the attributes from + * @return attributes {Object} + */ +var extractAttributes = function(gl, program) +{ + var attributes = {}; + + var totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES) + + for (var i = 0; i < totalAttributes; i++) + { + var attribData = gl.getActiveAttrib(program, i); + var type = mapType(gl, attribData.type); + + attributes[attribData.name] = { + type:type, + size:mapSize(type), + location:gl.getAttribLocation(program, attribData.name), + //TODO - make an attribute object + pointer:function(type, normalized, stride, start){ + + // console.log(this.location) + gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); + + } + } + }; + + return attributes; +} + +module.exports = extractAttributes; + +},{"./mapSize":14,"./mapType":15}],12:[function(require,module,exports){ +var mapType = require('./mapType'); +var defaultValue = require('./defaultValue'); + +/** + * Extracts the uniforms + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param program {WebGLProgram} The shader program to get the uniforms from + * @return uniforms {Object} + */ +var extractUniforms = function(gl, program) +{ + var uniforms = {}; + + var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) + + for (var i = 0; i < totalUniforms; i++) + { + var uniformData = gl.getActiveUniform(program, i); + var name = uniformData.name.replace(/\[.*?\]/, ""); + var type = mapType(gl, uniformData.type ); + + uniforms[name] = { + type:type, + size:uniformData.size, + location:gl.getUniformLocation(program, name), + value:defaultValue(type, uniformData.size) + } + }; + + return uniforms; +} + +module.exports = extractUniforms; + +},{"./defaultValue":10,"./mapType":15}],13:[function(require,module,exports){ +/** + * Extracts the attributes + * @param gl {WebGLRenderingContext} The current WebGL rendering context + * @param uniforms {Array} @mat ? + * @return attributes {Object} + */ +var generateUniformAccessObject = function(gl, uniformData) +{ + // this is the object we will be sending back. + // an object hierachy will be created for structs + var uniforms = {data:{}}; + + uniforms.gl = gl; + + var uniformKeys= Object.keys(uniformData); + + for (var i = 0; i < uniformKeys.length; i++) + { + var fullName = uniformKeys[i] + + var nameTokens = fullName.split('.'); + var name = nameTokens[nameTokens.length - 1]; + + var uniformGroup = getUniformGroup(nameTokens, uniforms); + + var uniform = uniformData[fullName]; + uniformGroup.data[name] = uniform; + + uniformGroup.gl = gl; + + Object.defineProperty(uniformGroup, name, { + get: generateGetter(name), + set: generateSetter(name, uniform) + }) + }; + + return uniforms; +} + +var generateGetter = function(name) +{ + var template = getterTemplate.replace('%%', name); + return new Function(template); +} + +var generateSetter = function(name, uniform) +{ + var template = setterTemplate.replace(/%%/g, name); + var setTemplate + + if(uniform.size === 1) + { + setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; + } + else + { + setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; + } + + if(setTemplate) + { + template += "\nthis.gl." + setTemplate + ";"; + } + + return new Function('value', template); +} + +var getUniformGroup = function(nameTokens, uniform) +{ + var cur = uniform; + + for (var i = 0; i < nameTokens.length - 1; i++) + { + var o = cur[nameTokens[i]] || {data:{}}; + cur[nameTokens[i]] = o; + cur = o; + }; + + return cur +} + +var getterTemplate = [ + 'return this.data.%%.value;', +].join('\n'); + +var setterTemplate = [ + 'this.data.%%.value = value;', + 'var location = this.data.%%.location;' +].join('\n'); + + +var GLSL_TO_SINGLE_SETTERS = { + + 'float': 'uniform1f(location, value)', + + 'vec2': 'uniform2f(location, value[0], value[1])', + 'vec3': 'uniform3f(location, value[0], value[1], value[2])', + 'vec4': 'uniform4f(location, value[0], value[1], value[2], value[3])', + + 'int': 'uniform1i(location, value)', + 'ivec2': 'uniform2i(location, value[0], value[1])', + 'ivec3': 'uniform3i(location, value[0], value[1], value[2])', + 'ivec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', + + 'bool': 'uniform1i(location, value)', + 'bvec2': 'uniform2i(location, value[0], value[1])', + 'bvec3': 'uniform3i(location, value[0], value[1], value[2])', + 'bvec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', + + 'mat2': 'uniformMatrix2fv(location, false, value)', + 'mat3': 'uniformMatrix3fv(location, false, value)', + 'mat4': 'uniformMatrix4fv(location, false, value)', + + 'sampler2D':'uniform1i(location, value)' +} + +var GLSL_TO_ARRAY_SETTERS = { + + 'float': 'uniform1fv(location, value)', + + 'vec2': 'uniform2fv(location, value)', + 'vec3': 'uniform3fv(location, value)', + 'vec4': 'uniform4fv(location, value)', + + 'int': 'uniform1iv(location, value)', + 'ivec2': 'uniform2iv(location, value)', + 'ivec3': 'uniform3iv(location, value)', + 'ivec4': 'uniform4iv(location, value)', + + 'bool': 'uniform1iv(location, value)', + 'bvec2': 'uniform2iv(location, value)', + 'bvec3': 'uniform3iv(location, value)', + 'bvec4': 'uniform4iv(location, value)', + + 'sampler2D':'uniform1iv(location, value)' +} + +module.exports = generateUniformAccessObject; + +},{}],14:[function(require,module,exports){ + + +var mapSize = function(type) +{ + return GLSL_TO_SIZE[type]; +} + + +var GLSL_TO_SIZE = { + 'float': 1, + 'vec2': 2, + 'vec3': 3, + 'vec4': 4, + + 'int': 1, + 'ivec2': 2, + 'ivec3': 3, + 'ivec4': 4, + + 'bool': 1, + 'bvec2': 2, + 'bvec3': 3, + 'bvec4': 4, + + 'mat2': 4, + 'mat3': 9, + 'mat4': 16, + + 'sampler2D': 1 +} + +module.exports = mapSize; + +},{}],15:[function(require,module,exports){ + + +var mapSize = function(gl, type) +{ + if(!GL_TABLE) + { + var typeNames = Object.keys(GL_TO_GLSL_TYPES); + + GL_TABLE = {}; + + for(var i = 0; i < typeNames.length; ++i) + { + var tn = typeNames[i]; + GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn]; + } + } + + return GL_TABLE[type]; +} + +var GL_TABLE = null; + +var GL_TO_GLSL_TYPES = { + 'FLOAT': 'float', + 'FLOAT_VEC2': 'vec2', + 'FLOAT_VEC3': 'vec3', + 'FLOAT_VEC4': 'vec4', + + 'INT': 'int', + 'INT_VEC2': 'ivec2', + 'INT_VEC3': 'ivec3', + 'INT_VEC4': 'ivec4', + + 'BOOL': 'bool', + 'BOOL_VEC2': 'bvec2', + 'BOOL_VEC3': 'bvec3', + 'BOOL_VEC4': 'bvec4', + + 'FLOAT_MAT2': 'mat2', + 'FLOAT_MAT3': 'mat3', + 'FLOAT_MAT4': 'mat4', + + 'SAMPLER_2D': 'sampler2D' +} + +module.exports = mapSize; + +},{}],16:[function(require,module,exports){ +/** + * Bit twiddling hacks for JavaScript. + * + * Author: Mikola Lysenko + * + * Ported from Stanford bit twiddling hack library: + * http://graphics.stanford.edu/~seander/bithacks.html + */ + +"use strict"; "use restrict"; + +//Number of bits in an integer +var INT_BITS = 32; + +//Constants +exports.INT_BITS = INT_BITS; +exports.INT_MAX = 0x7fffffff; +exports.INT_MIN = -1<<(INT_BITS-1); + +//Returns -1, 0, +1 depending on sign of x +exports.sign = function(v) { + return (v > 0) - (v < 0); +} + +//Computes absolute value of integer +exports.abs = function(v) { + var mask = v >> (INT_BITS-1); + return (v ^ mask) - mask; +} + +//Computes minimum of integers x and y +exports.min = function(x, y) { + return y ^ ((x ^ y) & -(x < y)); +} + +//Computes maximum of integers x and y +exports.max = function(x, y) { + return x ^ ((x ^ y) & -(x < y)); +} + +//Checks if a number is a power of two +exports.isPow2 = function(v) { + return !(v & (v-1)) && (!!v); +} + +//Computes log base 2 of v +exports.log2 = function(v) { + var r, shift; + r = (v > 0xFFFF) << 4; v >>>= r; + shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; + shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; + shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; + return r | (v >> 1); +} + +//Computes log base 10 of v +exports.log10 = function(v) { + return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : + (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : + (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; +} + +//Counts number of bits +exports.popCount = function(v) { + v = v - ((v >>> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); + return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; +} + +//Counts number of trailing zeros +function countTrailingZeros(v) { + var c = 32; + v &= -v; + if (v) c--; + if (v & 0x0000FFFF) c -= 16; + if (v & 0x00FF00FF) c -= 8; + if (v & 0x0F0F0F0F) c -= 4; + if (v & 0x33333333) c -= 2; + if (v & 0x55555555) c -= 1; + return c; +} +exports.countTrailingZeros = countTrailingZeros; + +//Rounds to next power of 2 +exports.nextPow2 = function(v) { + v += v === 0; + --v; + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + return v + 1; +} + +//Rounds down to previous power of 2 +exports.prevPow2 = function(v) { + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + return v - (v>>>1); +} + +//Computes parity of word +exports.parity = function(v) { + v ^= v >>> 16; + v ^= v >>> 8; + v ^= v >>> 4; + v &= 0xf; + return (0x6996 >>> v) & 1; +} + +var REVERSE_TABLE = new Array(256); + +(function(tab) { + for(var i=0; i<256; ++i) { + var v = i, r = i, s = 7; + for (v >>>= 1; v; v >>>= 1) { + r <<= 1; + r |= v & 1; + --s; + } + tab[i] = (r << s) & 0xff; + } +})(REVERSE_TABLE); + +//Reverse bits in a 32 bit word +exports.reverse = function(v) { + return (REVERSE_TABLE[ v & 0xff] << 24) | + (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | + (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | + REVERSE_TABLE[(v >>> 24) & 0xff]; +} + +//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes +exports.interleave2 = function(x, y) { + x &= 0xFFFF; + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y &= 0xFFFF; + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +//Extracts the nth interleaved component +exports.deinterleave2 = function(v, n) { + v = (v >>> n) & 0x55555555; + v = (v | (v >>> 1)) & 0x33333333; + v = (v | (v >>> 2)) & 0x0F0F0F0F; + v = (v | (v >>> 4)) & 0x00FF00FF; + v = (v | (v >>> 16)) & 0x000FFFF; + return (v << 16) >> 16; +} + + +//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes +exports.interleave3 = function(x, y, z) { + x &= 0x3FF; + x = (x | (x<<16)) & 4278190335; + x = (x | (x<<8)) & 251719695; + x = (x | (x<<4)) & 3272356035; + x = (x | (x<<2)) & 1227133513; + + y &= 0x3FF; + y = (y | (y<<16)) & 4278190335; + y = (y | (y<<8)) & 251719695; + y = (y | (y<<4)) & 3272356035; + y = (y | (y<<2)) & 1227133513; + x |= (y << 1); + + z &= 0x3FF; + z = (z | (z<<16)) & 4278190335; + z = (z | (z<<8)) & 251719695; + z = (z | (z<<4)) & 3272356035; + z = (z | (z<<2)) & 1227133513; + + return x | (z << 2); +} + +//Extracts nth interleaved component of a 3-tuple +exports.deinterleave3 = function(v, n) { + v = (v >>> n) & 1227133513; + v = (v | (v>>>2)) & 3272356035; + v = (v | (v>>>4)) & 251719695; + v = (v | (v>>>8)) & 4278190335; + v = (v | (v>>>16)) & 0x3FF; + return (v<<22)>>22; +} + +//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) +exports.nextCombination = function(v) { + var t = v | (v - 1); + return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); +} + + +},{}],17:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} + +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; + +}).call(this,require('_process')) +},{"_process":18}],18:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = setTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + clearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + setTimeout(drainQueue, 0); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],19:[function(require,module,exports){ +(function (global){ +/*! https://mths.be/punycode v1.4.0 by @mathias */ +;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.3.2', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + typeof define == 'function' && + typeof define.amd == 'object' && + define.amd + ) { + define('punycode', function() { + return punycode; + }); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { + // in Node.js, io.js, or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { + // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { + // in Rhino or a web browser + root.punycode = punycode; + } + +}(this)); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],20:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +// If obj.hasOwnProperty has been overridden, then calling +// obj.hasOwnProperty(prop) will break. +// See: https://github.com/joyent/node/issues/1707 +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +module.exports = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +},{}],21:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } +}; + +module.exports = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return map(objectKeys(obj), function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (isArray(obj[k])) { + return map(obj[k], function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +function map (xs, f) { + if (xs.map) return xs.map(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + res.push(f(xs[i], i)); + } + return res; +} + +var objectKeys = Object.keys || function (obj) { + var res = []; + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); + } + return res; +}; + +},{}],22:[function(require,module,exports){ +'use strict'; + +exports.decode = exports.parse = require('./decode'); +exports.encode = exports.stringify = require('./encode'); + +},{"./decode":20,"./encode":21}],23:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var punycode = require('punycode'); + +exports.parse = urlParse; +exports.resolve = urlResolve; +exports.resolveObject = urlResolveObject; +exports.format = urlFormat; + +exports.Url = Url; + +function Url() { + this.protocol = null; + this.slashes = null; + this.auth = null; + this.host = null; + this.port = null; + this.hostname = null; + this.hash = null; + this.search = null; + this.query = null; + this.pathname = null; + this.path = null; + this.href = null; +} + +// Reference: RFC 3986, RFC 1808, RFC 2396 + +// define these here so at least they only have to be +// compiled once on the first module load. +var protocolPattern = /^([a-z0-9.+-]+:)/i, + portPattern = /:[0-9]*$/, + + // RFC 2396: characters reserved for delimiting URLs. + // We actually just auto-escape these. + delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], + + // RFC 2396: characters not allowed for various reasons. + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), + + // Allowed by RFCs, but cause of XSS attacks. Always escape these. + autoEscape = ['\''].concat(unwise), + // Characters that are never ever allowed in a hostname. + // Note that any invalid chars are also handled, but these + // are the ones that are *expected* to be seen, so we fast-path + // them. + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), + hostEndingChars = ['/', '?', '#'], + hostnameMaxLen = 255, + hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, + hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, + // protocols that can allow "unsafe" and "unwise" chars. + unsafeProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that never have a hostname. + hostlessProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that always contain a // bit. + slashedProtocol = { + 'http': true, + 'https': true, + 'ftp': true, + 'gopher': true, + 'file': true, + 'http:': true, + 'https:': true, + 'ftp:': true, + 'gopher:': true, + 'file:': true + }, + querystring = require('querystring'); + +function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url && isObject(url) && url instanceof Url) return url; + + var u = new Url; + u.parse(url, parseQueryString, slashesDenoteHost); + return u; +} + +Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + if (!isString(url)) { + throw new TypeError("Parameter 'url' must be a string, not " + typeof url); + } + + var rest = url; + + // trim before proceeding. + // This is to support parse stuff like " http://foo.com \n" + rest = rest.trim(); + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.substr(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var slashes = rest.substr(0, 2) === '//'; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.substr(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:c path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + // find the first instance of any hostEndingChars + var hostEnd = -1; + for (var i = 0; i < hostEndingChars.length; i++) { + var hec = rest.indexOf(hostEndingChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + + // at this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + var auth, atSign; + if (hostEnd === -1) { + // atSign can be anywhere. + atSign = rest.lastIndexOf('@'); + } else { + // atSign must be in auth portion. + // http://a@b/c@d => host:b auth:a path:/c@d + atSign = rest.lastIndexOf('@', hostEnd); + } + + // Now we have a portion which is definitely the auth. + // Pull that off. + if (atSign !== -1) { + auth = rest.slice(0, atSign); + rest = rest.slice(atSign + 1); + this.auth = decodeURIComponent(auth); + } + + // the host is the remaining to the left of the first non-host char + hostEnd = -1; + for (var i = 0; i < nonHostChars.length; i++) { + var hec = rest.indexOf(nonHostChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + // if we still have not hit it, then the entire thing is a host. + if (hostEnd === -1) + hostEnd = rest.length; + + this.host = rest.slice(0, hostEnd); + rest = rest.slice(hostEnd); + + // pull out port. + this.parseHost(); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + this.hostname = this.hostname || ''; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = this.hostname[0] === '[' && + this.hostname[this.hostname.length - 1] === ']'; + + // validate a little. + if (!ipv6Hostname) { + var hostparts = this.hostname.split(/\./); + for (var i = 0, l = hostparts.length; i < l; i++) { + var part = hostparts[i]; + if (!part) continue; + if (!part.match(hostnamePartPattern)) { + var newpart = ''; + for (var j = 0, k = part.length; j < k; j++) { + if (part.charCodeAt(j) > 127) { + // we replace non-ASCII char with a temporary placeholder + // we need this to make sure size of hostname is not + // broken by replacing non-ASCII by nothing + newpart += 'x'; + } else { + newpart += part[j]; + } + } + // we test again with ASCII char only + if (!newpart.match(hostnamePartPattern)) { + var validParts = hostparts.slice(0, i); + var notHost = hostparts.slice(i + 1); + var bit = part.match(hostnamePartStart); + if (bit) { + validParts.push(bit[1]); + notHost.unshift(bit[2]); + } + if (notHost.length) { + rest = '/' + notHost.join('.') + rest; + } + this.hostname = validParts.join('.'); + break; + } + } + } + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a puny coded representation of "domain". + // It only converts the part of the domain name that + // has non ASCII characters. I.e. it dosent matter if + // you call it with a domain that already is in ASCII. + var domainArray = this.hostname.split('.'); + var newOut = []; + for (var i = 0; i < domainArray.length; ++i) { + var s = domainArray[i]; + newOut.push(s.match(/[^A-Za-z0-9_-]/) ? + 'xn--' + punycode.encode(s) : s); + } + this.hostname = newOut.join('.'); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; + this.href += this.host; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + this.hostname = this.hostname.substr(1, this.hostname.length - 2); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + for (var i = 0, l = autoEscape.length; i < l; i++) { + var ae = autoEscape[i]; + var esc = encodeURIComponent(ae); + if (esc === ae) { + esc = escape(ae); + } + rest = rest.split(ae).join(esc); + } + } + + + // chop off from the tail first. + var hash = rest.indexOf('#'); + if (hash !== -1) { + // got a fragment string. + this.hash = rest.substr(hash); + rest = rest.slice(0, hash); + } + var qm = rest.indexOf('?'); + if (qm !== -1) { + this.search = rest.substr(qm); + this.query = rest.substr(qm + 1); + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + rest = rest.slice(0, qm); + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = {}; + } + if (rest) this.pathname = rest; + if (slashedProtocol[lowerProto] && + this.hostname && !this.pathname) { + this.pathname = '/'; + } + + //to support http.request + if (this.pathname || this.search) { + var p = this.pathname || ''; + var s = this.search || ''; + this.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + this.href = this.format(); + return this; +}; + +// format a parsed object into a url string +function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (isString(obj)) obj = urlParse(obj); + if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + return obj.format(); +} + +Url.prototype.format = function() { + var auth = this.auth || ''; + if (auth) { + auth = encodeURIComponent(auth); + auth = auth.replace(/%3A/i, ':'); + auth += '@'; + } + + var protocol = this.protocol || '', + pathname = this.pathname || '', + hash = this.hash || '', + host = false, + query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? + this.hostname : + '[' + this.hostname + ']'); + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query && + isObject(this.query) && + Object.keys(this.query).length) { + query = querystring.stringify(this.query); + } + + var search = this.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.substr(-1) !== ':') protocol += ':'; + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (this.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + if (hash && hash.charAt(0) !== '#') hash = '#' + hash; + if (search && search.charAt(0) !== '?') search = '?' + search; + + pathname = pathname.replace(/[?#]/g, function(match) { + return encodeURIComponent(match); + }); + search = search.replace('#', '%23'); + + return protocol + host + pathname + search + hash; +}; + +function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); +} + +Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); +}; + +function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); +} + +Url.prototype.resolveObject = function(relative) { + if (isString(relative)) { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + Object.keys(this).forEach(function(k) { + result[k] = this[k]; + }, this); + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + Object.keys(relative).forEach(function(k) { + if (k !== 'protocol') + result[k] = relative[k]; + }); + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + Object.keys(relative).forEach(function(k) { + result[k] = relative[k]; + }); + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && !hostlessProtocol[relative.protocol]) { + var relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), + isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ), + mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)), + removeAllDots = mustEndAbs, + srcPath = result.pathname && result.pathname.split('/') || [], + relPath = relative.pathname && relative.pathname.split('/') || [], + psychotic = result.protocol && !slashedProtocol[result.protocol]; + + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + result.host = (relative.host || relative.host === '') ? + relative.host : result.host; + result.hostname = (relative.hostname || relative.hostname === '') ? + relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (!isNullOrUndefined(relative.search)) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host) && (last === '.' || last === '..') || + last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + if (last == '.') { + srcPath.splice(i, 1); + } else if (last === '..') { + srcPath.splice(i, 1); + up++; + } else if (up) { + srcPath.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occationaly the auth can get stuck only in host + //this especialy happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; +}; + +Url.prototype.parseHost = function() { + var host = this.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + this.port = port.substr(1); + } + host = host.substr(0, host.length - port.length); + } + if (host) this.hostname = host; +}; + +function isString(arg) { + return typeof arg === "string"; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isNull(arg) { + return arg === null; +} +function isNullOrUndefined(arg) { + return arg == null; +} + +},{"punycode":19,"querystring":22}],24:[function(require,module,exports){ +'use strict'; + +module.exports = earcut; + +function earcut(data, holeIndices, dim) { + + dim = dim || 2; + + var hasHoles = holeIndices && holeIndices.length, + outerLen = hasHoles ? holeIndices[0] * dim : data.length, + outerNode = linkedList(data, 0, outerLen, dim, true), + triangles = []; + + if (!outerNode) return triangles; + + var minX, minY, maxX, maxY, x, y, size; + + if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); + + // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox + if (data.length > 80 * dim) { + minX = maxX = data[0]; + minY = maxY = data[1]; + + for (var i = dim; i < outerLen; i += dim) { + x = data[i]; + y = data[i + 1]; + if (x < minX) minX = x; + if (y < minY) minY = y; + if (x > maxX) maxX = x; + if (y > maxY) maxY = y; + } + + // minX, minY and size are later used to transform coords into integers for z-order calculation + size = Math.max(maxX - minX, maxY - minY); + } + + earcutLinked(outerNode, triangles, dim, minX, minY, size); + + return triangles; +} + +// create a circular doubly linked list from polygon points in the specified winding order +function linkedList(data, start, end, dim, clockwise) { + var sum = 0, + i, j, last; + + // calculate original winding order of a polygon ring + for (i = start, j = end - dim; i < end; i += dim) { + sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); + j = i; + } + + // link points into circular doubly-linked list in the specified winding order + if (clockwise === (sum > 0)) { + for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); + } else { + for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); + } + + return last; +} + +// eliminate colinear or duplicate points +function filterPoints(start, end) { + if (!start) return start; + if (!end) end = start; + + var p = start, + again; + do { + again = false; + + if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { + removeNode(p); + p = end = p.prev; + if (p === p.next) return null; + again = true; + + } else { + p = p.next; + } + } while (again || p !== end); + + return end; +} + +// main ear slicing loop which triangulates a polygon (given as a linked list) +function earcutLinked(ear, triangles, dim, minX, minY, size, pass) { + if (!ear) return; + + // interlink polygon nodes in z-order + if (!pass && size) indexCurve(ear, minX, minY, size); + + var stop = ear, + prev, next; + + // iterate through ears, slicing them one by one + while (ear.prev !== ear.next) { + prev = ear.prev; + next = ear.next; + + if (size ? isEarHashed(ear, minX, minY, size) : isEar(ear)) { + // cut off the triangle + triangles.push(prev.i / dim); + triangles.push(ear.i / dim); + triangles.push(next.i / dim); + + removeNode(ear); + + // skipping the next vertice leads to less sliver triangles + ear = next.next; + stop = next.next; + + continue; + } + + ear = next; + + // if we looped through the whole remaining polygon and can't find any more ears + if (ear === stop) { + // try filtering points and slicing again + if (!pass) { + earcutLinked(filterPoints(ear), triangles, dim, minX, minY, size, 1); + + // if this didn't work, try curing all small self-intersections locally + } else if (pass === 1) { + ear = cureLocalIntersections(ear, triangles, dim); + earcutLinked(ear, triangles, dim, minX, minY, size, 2); + + // as a last resort, try splitting the remaining polygon into two + } else if (pass === 2) { + splitEarcut(ear, triangles, dim, minX, minY, size); + } + + break; + } + } +} + +// check whether a polygon node forms a valid ear with adjacent nodes +function isEar(ear) { + var a = ear.prev, + b = ear, + c = ear.next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // now make sure we don't have other points inside the potential ear + var p = ear.next.next; + + while (p !== ear.prev) { + if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.next; + } + + return true; +} + +function isEarHashed(ear, minX, minY, size) { + var a = ear.prev, + b = ear, + c = ear.next; + + if (area(a, b, c) >= 0) return false; // reflex, can't be an ear + + // triangle bbox; min & max are calculated like this for speed + var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x), + minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y), + maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x), + maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y); + + // z-order range for the current triangle bbox; + var minZ = zOrder(minTX, minTY, minX, minY, size), + maxZ = zOrder(maxTX, maxTY, minX, minY, size); + + // first look for points inside the triangle in increasing z-order + var p = ear.nextZ; + + while (p && p.z <= maxZ) { + if (p !== ear.prev && p !== ear.next && + pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.nextZ; + } + + // then look for points in decreasing z-order + p = ear.prevZ; + + while (p && p.z >= minZ) { + if (p !== ear.prev && p !== ear.next && + pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && + area(p.prev, p, p.next) >= 0) return false; + p = p.prevZ; + } + + return true; +} + +// go through all polygon nodes and cure small local self-intersections +function cureLocalIntersections(start, triangles, dim) { + var p = start; + do { + var a = p.prev, + b = p.next.next; + + // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2]) + if (intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) { + + triangles.push(a.i / dim); + triangles.push(p.i / dim); + triangles.push(b.i / dim); + + // remove two nodes involved + removeNode(p); + removeNode(p.next); + + p = start = b; + } + p = p.next; + } while (p !== start); + + return p; +} + +// try splitting polygon into two and triangulate them independently +function splitEarcut(start, triangles, dim, minX, minY, size) { + // look for a valid diagonal that divides the polygon into two + var a = start; + do { + var b = a.next.next; + while (b !== a.prev) { + if (a.i !== b.i && isValidDiagonal(a, b)) { + // split the polygon in two by the diagonal + var c = splitPolygon(a, b); + + // filter colinear points around the cuts + a = filterPoints(a, a.next); + c = filterPoints(c, c.next); + + // run earcut on each half + earcutLinked(a, triangles, dim, minX, minY, size); + earcutLinked(c, triangles, dim, minX, minY, size); + return; + } + b = b.next; + } + a = a.next; + } while (a !== start); +} + +// link every hole into the outer loop, producing a single-ring polygon without holes +function eliminateHoles(data, holeIndices, outerNode, dim) { + var queue = [], + i, len, start, end, list; + + for (i = 0, len = holeIndices.length; i < len; i++) { + start = holeIndices[i] * dim; + end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; + list = linkedList(data, start, end, dim, false); + if (list === list.next) list.steiner = true; + queue.push(getLeftmost(list)); + } + + queue.sort(compareX); + + // process holes from left to right + for (i = 0; i < queue.length; i++) { + eliminateHole(queue[i], outerNode); + outerNode = filterPoints(outerNode, outerNode.next); + } + + return outerNode; +} + +function compareX(a, b) { + return a.x - b.x; +} + +// find a bridge between vertices that connects hole with an outer ring and and link it +function eliminateHole(hole, outerNode) { + outerNode = findHoleBridge(hole, outerNode); + if (outerNode) { + var b = splitPolygon(outerNode, hole); + filterPoints(b, b.next); + } +} + +// David Eberly's algorithm for finding a bridge between hole and outer polygon +function findHoleBridge(hole, outerNode) { + var p = outerNode, + hx = hole.x, + hy = hole.y, + qx = -Infinity, + m; + + // find a segment intersected by a ray from the hole's leftmost point to the left; + // segment's endpoint with lesser x will be potential connection point + do { + if (hy <= p.y && hy >= p.next.y) { + var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); + if (x <= hx && x > qx) { + qx = x; + m = p.x < p.next.x ? p : p.next; + } + } + p = p.next; + } while (p !== outerNode); + + if (!m) return null; + + if (hole.x === m.x) return m.prev; // hole touches outer segment; pick lower endpoint + + // look for points inside the triangle of hole point, segment intersection and endpoint; + // if there are no points found, we have a valid connection; + // otherwise choose the point of the minimum angle with the ray as connection point + + var stop = m, + tanMin = Infinity, + tan; + + p = m.next; + + while (p !== stop) { + if (hx >= p.x && p.x >= m.x && + pointInTriangle(hy < m.y ? hx : qx, hy, m.x, m.y, hy < m.y ? qx : hx, hy, p.x, p.y)) { + + tan = Math.abs(hy - p.y) / (hx - p.x); // tangential + + if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) { + m = p; + tanMin = tan; + } + } + + p = p.next; + } + + return m; +} + +// interlink polygon nodes in z-order +function indexCurve(start, minX, minY, size) { + var p = start; + do { + if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, size); + p.prevZ = p.prev; + p.nextZ = p.next; + p = p.next; + } while (p !== start); + + p.prevZ.nextZ = null; + p.prevZ = null; + + sortLinked(p); +} + +// Simon Tatham's linked list merge sort algorithm +// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html +function sortLinked(list) { + var i, p, q, e, tail, numMerges, pSize, qSize, + inSize = 1; + + do { + p = list; + list = null; + tail = null; + numMerges = 0; + + while (p) { + numMerges++; + q = p; + pSize = 0; + for (i = 0; i < inSize; i++) { + pSize++; + q = q.nextZ; + if (!q) break; + } + + qSize = inSize; + + while (pSize > 0 || (qSize > 0 && q)) { + + if (pSize === 0) { + e = q; + q = q.nextZ; + qSize--; + } else if (qSize === 0 || !q) { + e = p; + p = p.nextZ; + pSize--; + } else if (p.z <= q.z) { + e = p; + p = p.nextZ; + pSize--; + } else { + e = q; + q = q.nextZ; + qSize--; + } + + if (tail) tail.nextZ = e; + else list = e; + + e.prevZ = tail; + tail = e; + } + + p = q; + } + + tail.nextZ = null; + inSize *= 2; + + } while (numMerges > 1); + + return list; +} + +// z-order of a point given coords and size of the data bounding box +function zOrder(x, y, minX, minY, size) { + // coords are transformed into non-negative 15-bit integer range + x = 32767 * (x - minX) / size; + y = 32767 * (y - minY) / size; + + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +// find the leftmost node of a polygon ring +function getLeftmost(start) { + var p = start, + leftmost = start; + do { + if (p.x < leftmost.x) leftmost = p; + p = p.next; + } while (p !== start); + + return leftmost; +} + +// check if a point lies within a convex triangle +function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) { + return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && + (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && + (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; +} + +// check if a diagonal between two polygon nodes is valid (lies in polygon interior) +function isValidDiagonal(a, b) { + return equals(a, b) || a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && + locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b); +} + +// signed area of a triangle +function area(p, q, r) { + return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); +} + +// check if two points are equal +function equals(p1, p2) { + return p1.x === p2.x && p1.y === p2.y; +} + +// check if two segments intersect +function intersects(p1, q1, p2, q2) { + return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && + area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0; +} + +// check if a polygon diagonal intersects any polygon segments +function intersectsPolygon(a, b) { + var p = a; + do { + if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && + intersects(p, p.next, a, b)) return true; + p = p.next; + } while (p !== a); + + return false; +} + +// check if a polygon diagonal is locally inside the polygon +function locallyInside(a, b) { + return area(a.prev, a, a.next) < 0 ? + area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : + area(a, b, a.prev) < 0 || area(a, a.next, b) < 0; +} + +// check if the middle point of a polygon diagonal is inside the polygon +function middleInside(a, b) { + var p = a, + inside = false, + px = (a.x + b.x) / 2, + py = (a.y + b.y) / 2; + do { + if (((p.y > py) !== (p.next.y > py)) && (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) + inside = !inside; + p = p.next; + } while (p !== a); + + return inside; +} + +// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; +// if one belongs to the outer ring and another to a hole, it merges it into a single ring +function splitPolygon(a, b) { + var a2 = new Node(a.i, a.x, a.y), + b2 = new Node(b.i, b.x, b.y), + an = a.next, + bp = b.prev; + + a.next = b; + b.prev = a; + + a2.next = an; + an.prev = a2; + + b2.next = a2; + a2.prev = b2; + + bp.next = b2; + b2.prev = bp; + + return b2; +} + +// create a node and optionally link it with previous one (in a circular doubly linked list) +function insertNode(i, x, y, last) { + var p = new Node(i, x, y); + + if (!last) { + p.prev = p; + p.next = p; + + } else { + p.next = last.next; + p.prev = last; + last.next.prev = p; + last.next = p; + } + return p; +} + +function removeNode(p) { + p.next.prev = p.prev; + p.prev.next = p.next; + + if (p.prevZ) p.prevZ.nextZ = p.nextZ; + if (p.nextZ) p.nextZ.prevZ = p.prevZ; +} + +function Node(i, x, y) { + // vertice index in coordinates array + this.i = i; + + // vertex coordinates + this.x = x; + this.y = y; + + // previous and next vertice nodes in a polygon ring + this.prev = null; + this.next = null; + + // z-order curve value + this.z = null; + + // previous and next nodes in z-order + this.prevZ = null; + this.nextZ = null; + + // indicates whether this is a steiner point + this.steiner = false; +} + +},{}],25:[function(require,module,exports){ +'use strict'; + +// +// We store our EE objects in a plain object whose properties are event names. +// If `Object.create(null)` is not supported we prefix the event names with a +// `~` to make sure that the built-in object properties are not overridden or +// used as an attack vector. +// We also assume that `Object.create(null)` is available when the event name +// is an ES6 Symbol. +// +var prefix = typeof Object.create !== 'function' ? '~' : false; + +/** + * Representation of a single EventEmitter function. + * + * @param {Function} fn Event handler to be called. + * @param {Mixed} context Context for function execution. + * @param {Boolean} once Only emit once + * @api private + */ +function EE(fn, context, once) { + this.fn = fn; + this.context = context; + this.once = once || false; +} + +/** + * Minimal EventEmitter interface that is molded against the Node.js + * EventEmitter interface. + * + * @constructor + * @api public + */ +function EventEmitter() { /* Nothing to set */ } + +/** + * Holds the assigned EventEmitters by name. + * + * @type {Object} + * @private + */ +EventEmitter.prototype._events = undefined; + +/** + * Return a list of assigned event listeners. + * + * @param {String} event The events that should be listed. + * @param {Boolean} exists We only need to know if there are listeners. + * @returns {Array|Boolean} + * @api public + */ +EventEmitter.prototype.listeners = function listeners(event, exists) { + var evt = prefix ? prefix + event : event + , available = this._events && this._events[evt]; + + if (exists) return !!available; + if (!available) return []; + if (available.fn) return [available.fn]; + + for (var i = 0, l = available.length, ee = new Array(l); i < l; i++) { + ee[i] = available[i].fn; + } + + return ee; +}; + +/** + * Emit an event to all registered event listeners. + * + * @param {String} event The name of the event. + * @returns {Boolean} Indication if we've emitted an event. + * @api public + */ +EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { + var evt = prefix ? prefix + event : event; + + if (!this._events || !this._events[evt]) return false; + + var listeners = this._events[evt] + , len = arguments.length + , args + , i; + + if ('function' === typeof listeners.fn) { + if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); + + switch (len) { + case 1: return listeners.fn.call(listeners.context), true; + case 2: return listeners.fn.call(listeners.context, a1), true; + case 3: return listeners.fn.call(listeners.context, a1, a2), true; + case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; + case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; + case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; + } + + for (i = 1, args = new Array(len -1); i < len; i++) { + args[i - 1] = arguments[i]; + } + + listeners.fn.apply(listeners.context, args); + } else { + var length = listeners.length + , j; + + for (i = 0; i < length; i++) { + if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); + + switch (len) { + case 1: listeners[i].fn.call(listeners[i].context); break; + case 2: listeners[i].fn.call(listeners[i].context, a1); break; + case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; + default: + if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { + args[j - 1] = arguments[j]; + } + + listeners[i].fn.apply(listeners[i].context, args); + } + } + } + + return true; +}; + +/** + * Register a new EventListener for the given event. + * + * @param {String} event Name of the event. + * @param {Functon} fn Callback function. + * @param {Mixed} context The context of the function. + * @api public + */ +EventEmitter.prototype.on = function on(event, fn, context) { + var listener = new EE(fn, context || this) + , evt = prefix ? prefix + event : event; + + if (!this._events) this._events = prefix ? {} : Object.create(null); + if (!this._events[evt]) this._events[evt] = listener; + else { + if (!this._events[evt].fn) this._events[evt].push(listener); + else this._events[evt] = [ + this._events[evt], listener + ]; + } + + return this; +}; + +/** + * Add an EventListener that's only called once. + * + * @param {String} event Name of the event. + * @param {Function} fn Callback function. + * @param {Mixed} context The context of the function. + * @api public + */ +EventEmitter.prototype.once = function once(event, fn, context) { + var listener = new EE(fn, context || this, true) + , evt = prefix ? prefix + event : event; + + if (!this._events) this._events = prefix ? {} : Object.create(null); + if (!this._events[evt]) this._events[evt] = listener; + else { + if (!this._events[evt].fn) this._events[evt].push(listener); + else this._events[evt] = [ + this._events[evt], listener + ]; + } + + return this; +}; + +/** + * Remove event listeners. + * + * @param {String} event The event we want to remove. + * @param {Function} fn The listener that we need to find. + * @param {Mixed} context Only remove listeners matching this context. + * @param {Boolean} once Only remove once listeners. + * @api public + */ +EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { + var evt = prefix ? prefix + event : event; + + if (!this._events || !this._events[evt]) return this; + + var listeners = this._events[evt] + , events = []; + + if (fn) { + if (listeners.fn) { + if ( + listeners.fn !== fn + || (once && !listeners.once) + || (context && listeners.context !== context) + ) { + events.push(listeners); + } + } else { + for (var i = 0, length = listeners.length; i < length; i++) { + if ( + listeners[i].fn !== fn + || (once && !listeners[i].once) + || (context && listeners[i].context !== context) + ) { + events.push(listeners[i]); + } + } + } + } + + // + // Reset the array, or remove it completely if we have no more listeners. + // + if (events.length) { + this._events[evt] = events.length === 1 ? events[0] : events; + } else { + delete this._events[evt]; + } + + return this; +}; + +/** + * Remove all listeners or only the listeners for the specified event. + * + * @param {String} event The event want to remove all listeners for. + * @api public + */ +EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { + if (!this._events) return this; + + if (event) delete this._events[prefix ? prefix + event : event]; + else this._events = prefix ? {} : Object.create(null); + + return this; +}; + +// +// Alias methods names because people roll like that. +// +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; +EventEmitter.prototype.addListener = EventEmitter.prototype.on; + +// +// This function doesn't apply anymore. +// +EventEmitter.prototype.setMaxListeners = function setMaxListeners() { + return this; +}; + +// +// Expose the prefix. +// +EventEmitter.prefixed = prefix; + +// +// Expose the module. +// +if ('undefined' !== typeof module) { + module.exports = EventEmitter; +} + +},{}],26:[function(require,module,exports){ +/** + * isMobile.js v0.3.9 + * + * A simple library to detect Apple phones and tablets, + * Android phones and tablets, other mobile devices (like blackberry, mini-opera and windows phone), + * and any kind of seven inch device, via user agent sniffing. + * + * @author: Kai Mallea (kmallea@gmail.com) + * + * @license: http://creativecommons.org/publicdomain/zero/1.0/ + */ +(function (global) { + + var apple_phone = /iPhone/i, + apple_ipod = /iPod/i, + apple_tablet = /iPad/i, + android_phone = /(?=.*\bAndroid\b)(?=.*\bMobile\b)/i, // Match 'Android' AND 'Mobile' + android_tablet = /Android/i, + amazon_phone = /(?=.*\bAndroid\b)(?=.*\bSD4930UR\b)/i, + amazon_tablet = /(?=.*\bAndroid\b)(?=.*\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\b)/i, + windows_phone = /IEMobile/i, + windows_tablet = /(?=.*\bWindows\b)(?=.*\bARM\b)/i, // Match 'Windows' AND 'ARM' + other_blackberry = /BlackBerry/i, + other_blackberry_10 = /BB10/i, + other_opera = /Opera Mini/i, + other_chrome = /(CriOS|Chrome)(?=.*\bMobile\b)/i, + other_firefox = /(?=.*\bFirefox\b)(?=.*\bMobile\b)/i, // Match 'Firefox' AND 'Mobile' + seven_inch = new RegExp( + '(?:' + // Non-capturing group + + 'Nexus 7' + // Nexus 7 + + '|' + // OR + + 'BNTV250' + // B&N Nook Tablet 7 inch + + '|' + // OR + + 'Kindle Fire' + // Kindle Fire + + '|' + // OR + + 'Silk' + // Kindle Fire, Silk Accelerated + + '|' + // OR + + 'GT-P1000' + // Galaxy Tab 7 inch + + ')', // End non-capturing group + + 'i'); // Case-insensitive matching + + var match = function(regex, userAgent) { + return regex.test(userAgent); + }; + + var IsMobileClass = function(userAgent) { + var ua = userAgent || navigator.userAgent; + + // Facebook mobile app's integrated browser adds a bunch of strings that + // match everything. Strip it out if it exists. + var tmp = ua.split('[FBAN'); + if (typeof tmp[1] !== 'undefined') { + ua = tmp[0]; + } + + this.apple = { + phone: match(apple_phone, ua), + ipod: match(apple_ipod, ua), + tablet: !match(apple_phone, ua) && match(apple_tablet, ua), + device: match(apple_phone, ua) || match(apple_ipod, ua) || match(apple_tablet, ua) + }; + this.amazon = { + phone: match(amazon_phone, ua), + tablet: !match(amazon_phone, ua) && match(amazon_tablet, ua), + device: match(amazon_phone, ua) || match(amazon_tablet, ua) + }; + this.android = { + phone: match(amazon_phone, ua) || match(android_phone, ua), + tablet: !match(amazon_phone, ua) && !match(android_phone, ua) && (match(amazon_tablet, ua) || match(android_tablet, ua)), + device: match(amazon_phone, ua) || match(amazon_tablet, ua) || match(android_phone, ua) || match(android_tablet, ua) + }; + this.windows = { + phone: match(windows_phone, ua), + tablet: match(windows_tablet, ua), + device: match(windows_phone, ua) || match(windows_tablet, ua) + }; + this.other = { + blackberry: match(other_blackberry, ua), + blackberry10: match(other_blackberry_10, ua), + opera: match(other_opera, ua), + firefox: match(other_firefox, ua), + chrome: match(other_chrome, ua), + device: match(other_blackberry, ua) || match(other_blackberry_10, ua) || match(other_opera, ua) || match(other_firefox, ua) || match(other_chrome, ua) + }; + this.seven_inch = match(seven_inch, ua); + this.any = this.apple.device || this.android.device || this.windows.device || this.other.device || this.seven_inch; + + // excludes 'other' devices and ipods, targeting touchscreen phones + this.phone = this.apple.phone || this.android.phone || this.windows.phone; + + // excludes 7 inch devices, classifying as phone or tablet is left to the user + this.tablet = this.apple.tablet || this.android.tablet || this.windows.tablet; + + if (typeof window === 'undefined') { + return this; + } + }; + + var instantiate = function() { + var IM = new IsMobileClass(); + IM.Class = IsMobileClass; + return IM; + }; + + if (typeof module !== 'undefined' && module.exports && typeof window === 'undefined') { + //node + module.exports = IsMobileClass; + } else if (typeof module !== 'undefined' && module.exports && typeof window !== 'undefined') { + //browserify + module.exports = instantiate(); + } else if (typeof define === 'function' && define.amd) { + //AMD + define('isMobile', [], global.isMobile = instantiate()); + } else { + global.isMobile = instantiate(); + } + +})(this); + +},{}],27:[function(require,module,exports){ +/* eslint-disable no-unused-vars */ +'use strict'; +var hasOwnProperty = Object.prototype.hasOwnProperty; +var propIsEnumerable = Object.prototype.propertyIsEnumerable; + +function toObject(val) { + if (val === null || val === undefined) { + throw new TypeError('Object.assign cannot be called with null or undefined'); + } + + return Object(val); +} + +module.exports = Object.assign || function (target, source) { + var from; + var to = toObject(target); + var symbols; + + for (var s = 1; s < arguments.length; s++) { + from = Object(arguments[s]); + + for (var key in from) { + if (hasOwnProperty.call(from, key)) { + to[key] = from[key]; + } + } + + if (Object.getOwnPropertySymbols) { + symbols = Object.getOwnPropertySymbols(from); + for (var i = 0; i < symbols.length; i++) { + if (propIsEnumerable.call(from, symbols[i])) { + to[symbols[i]] = from[symbols[i]]; + } + } + } + } + + return to; +}; + +},{}],28:[function(require,module,exports){ (function (process){ /*! * async @@ -1125,4475 +5606,1429 @@ }()); }).call(this,require('_process')) -},{"_process":5}],2:[function(require,module,exports){ -'use strict'; - -// -// We store our EE objects in a plain object whose properties are event names. -// If `Object.create(null)` is not supported we prefix the event names with a -// `~` to make sure that the built-in object properties are not overridden or -// used as an attack vector. -// We also assume that `Object.create(null)` is available when the event name -// is an ES6 Symbol. -// -var prefix = typeof Object.create !== 'function' ? '~' : false; +},{"_process":18}],29:[function(require,module,exports){ +var async = require('async'), + urlParser = require('url'), + Resource = require('./Resource'), + EventEmitter = require('eventemitter3'); /** - * Representation of a single EventEmitter function. - * - * @param {Function} fn Event handler to be called. - * @param {Mixed} context Context for function execution. - * @param {Boolean} once Only emit once - * @api private - */ -function EE(fn, context, once) { - this.fn = fn; - this.context = context; - this.once = once || false; -} - -/** - * Minimal EventEmitter interface that is molded against the Node.js - * EventEmitter interface. - * - * @constructor - * @api public - */ -function EventEmitter() { /* Nothing to set */ } - -/** - * Holds the assigned EventEmitters by name. - * - * @type {Object} - * @private - */ -EventEmitter.prototype._events = undefined; - -/** - * Return a list of assigned event listeners. - * - * @param {String} event The events that should be listed. - * @param {Boolean} exists We only need to know if there are listeners. - * @returns {Array|Boolean} - * @api public - */ -EventEmitter.prototype.listeners = function listeners(event, exists) { - var evt = prefix ? prefix + event : event - , available = this._events && this._events[evt]; - - if (exists) return !!available; - if (!available) return []; - if (available.fn) return [available.fn]; - - for (var i = 0, l = available.length, ee = new Array(l); i < l; i++) { - ee[i] = available[i].fn; - } - - return ee; -}; - -/** - * Emit an event to all registered event listeners. - * - * @param {String} event The name of the event. - * @returns {Boolean} Indication if we've emitted an event. - * @api public - */ -EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { - var evt = prefix ? prefix + event : event; - - if (!this._events || !this._events[evt]) return false; - - var listeners = this._events[evt] - , len = arguments.length - , args - , i; - - if ('function' === typeof listeners.fn) { - if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); - - switch (len) { - case 1: return listeners.fn.call(listeners.context), true; - case 2: return listeners.fn.call(listeners.context, a1), true; - case 3: return listeners.fn.call(listeners.context, a1, a2), true; - case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; - case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; - case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; - } - - for (i = 1, args = new Array(len -1); i < len; i++) { - args[i - 1] = arguments[i]; - } - - listeners.fn.apply(listeners.context, args); - } else { - var length = listeners.length - , j; - - for (i = 0; i < length; i++) { - if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); - - switch (len) { - case 1: listeners[i].fn.call(listeners[i].context); break; - case 2: listeners[i].fn.call(listeners[i].context, a1); break; - case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; - default: - if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { - args[j - 1] = arguments[j]; - } - - listeners[i].fn.apply(listeners[i].context, args); - } - } - } - - return true; -}; - -/** - * Register a new EventListener for the given event. - * - * @param {String} event Name of the event. - * @param {Functon} fn Callback function. - * @param {Mixed} context The context of the function. - * @api public - */ -EventEmitter.prototype.on = function on(event, fn, context) { - var listener = new EE(fn, context || this) - , evt = prefix ? prefix + event : event; - - if (!this._events) this._events = prefix ? {} : Object.create(null); - if (!this._events[evt]) this._events[evt] = listener; - else { - if (!this._events[evt].fn) this._events[evt].push(listener); - else this._events[evt] = [ - this._events[evt], listener - ]; - } - - return this; -}; - -/** - * Add an EventListener that's only called once. - * - * @param {String} event Name of the event. - * @param {Function} fn Callback function. - * @param {Mixed} context The context of the function. - * @api public - */ -EventEmitter.prototype.once = function once(event, fn, context) { - var listener = new EE(fn, context || this, true) - , evt = prefix ? prefix + event : event; - - if (!this._events) this._events = prefix ? {} : Object.create(null); - if (!this._events[evt]) this._events[evt] = listener; - else { - if (!this._events[evt].fn) this._events[evt].push(listener); - else this._events[evt] = [ - this._events[evt], listener - ]; - } - - return this; -}; - -/** - * Remove event listeners. - * - * @param {String} event The event we want to remove. - * @param {Function} fn The listener that we need to find. - * @param {Mixed} context Only remove listeners matching this context. - * @param {Boolean} once Only remove once listeners. - * @api public - */ -EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { - var evt = prefix ? prefix + event : event; - - if (!this._events || !this._events[evt]) return this; - - var listeners = this._events[evt] - , events = []; - - if (fn) { - if (listeners.fn) { - if ( - listeners.fn !== fn - || (once && !listeners.once) - || (context && listeners.context !== context) - ) { - events.push(listeners); - } - } else { - for (var i = 0, length = listeners.length; i < length; i++) { - if ( - listeners[i].fn !== fn - || (once && !listeners[i].once) - || (context && listeners[i].context !== context) - ) { - events.push(listeners[i]); - } - } - } - } - - // - // Reset the array, or remove it completely if we have no more listeners. - // - if (events.length) { - this._events[evt] = events.length === 1 ? events[0] : events; - } else { - delete this._events[evt]; - } - - return this; -}; - -/** - * Remove all listeners or only the listeners for the specified event. - * - * @param {String} event The event want to remove all listeners for. - * @api public - */ -EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { - if (!this._events) return this; - - if (event) delete this._events[prefix ? prefix + event : event]; - else this._events = prefix ? {} : Object.create(null); - - return this; -}; - -// -// Alias methods names because people roll like that. -// -EventEmitter.prototype.off = EventEmitter.prototype.removeListener; -EventEmitter.prototype.addListener = EventEmitter.prototype.on; - -// -// This function doesn't apply anymore. -// -EventEmitter.prototype.setMaxListeners = function setMaxListeners() { - return this; -}; - -// -// Expose the prefix. -// -EventEmitter.prefixed = prefix; - -// -// Expose the module. -// -if ('undefined' !== typeof module) { - module.exports = EventEmitter; -} - -},{}],3:[function(require,module,exports){ -/** - * Bit twiddling hacks for JavaScript. - * - * Author: Mikola Lysenko - * - * Ported from Stanford bit twiddling hack library: - * http://graphics.stanford.edu/~seander/bithacks.html - */ - -"use strict"; "use restrict"; - -//Number of bits in an integer -var INT_BITS = 32; - -//Constants -exports.INT_BITS = INT_BITS; -exports.INT_MAX = 0x7fffffff; -exports.INT_MIN = -1<<(INT_BITS-1); - -//Returns -1, 0, +1 depending on sign of x -exports.sign = function(v) { - return (v > 0) - (v < 0); -} - -//Computes absolute value of integer -exports.abs = function(v) { - var mask = v >> (INT_BITS-1); - return (v ^ mask) - mask; -} - -//Computes minimum of integers x and y -exports.min = function(x, y) { - return y ^ ((x ^ y) & -(x < y)); -} - -//Computes maximum of integers x and y -exports.max = function(x, y) { - return x ^ ((x ^ y) & -(x < y)); -} - -//Checks if a number is a power of two -exports.isPow2 = function(v) { - return !(v & (v-1)) && (!!v); -} - -//Computes log base 2 of v -exports.log2 = function(v) { - var r, shift; - r = (v > 0xFFFF) << 4; v >>>= r; - shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; - return r | (v >> 1); -} - -//Computes log base 10 of v -exports.log10 = function(v) { - return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : - (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : - (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; -} - -//Counts number of bits -exports.popCount = function(v) { - v = v - ((v >>> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); - return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; -} - -//Counts number of trailing zeros -function countTrailingZeros(v) { - var c = 32; - v &= -v; - if (v) c--; - if (v & 0x0000FFFF) c -= 16; - if (v & 0x00FF00FF) c -= 8; - if (v & 0x0F0F0F0F) c -= 4; - if (v & 0x33333333) c -= 2; - if (v & 0x55555555) c -= 1; - return c; -} -exports.countTrailingZeros = countTrailingZeros; - -//Rounds to next power of 2 -exports.nextPow2 = function(v) { - v += v === 0; - --v; - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v + 1; -} - -//Rounds down to previous power of 2 -exports.prevPow2 = function(v) { - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v - (v>>>1); -} - -//Computes parity of word -exports.parity = function(v) { - v ^= v >>> 16; - v ^= v >>> 8; - v ^= v >>> 4; - v &= 0xf; - return (0x6996 >>> v) & 1; -} - -var REVERSE_TABLE = new Array(256); - -(function(tab) { - for(var i=0; i<256; ++i) { - var v = i, r = i, s = 7; - for (v >>>= 1; v; v >>>= 1) { - r <<= 1; - r |= v & 1; - --s; - } - tab[i] = (r << s) & 0xff; - } -})(REVERSE_TABLE); - -//Reverse bits in a 32 bit word -exports.reverse = function(v) { - return (REVERSE_TABLE[ v & 0xff] << 24) | - (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | - (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | - REVERSE_TABLE[(v >>> 24) & 0xff]; -} - -//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes -exports.interleave2 = function(x, y) { - x &= 0xFFFF; - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y &= 0xFFFF; - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -//Extracts the nth interleaved component -exports.deinterleave2 = function(v, n) { - v = (v >>> n) & 0x55555555; - v = (v | (v >>> 1)) & 0x33333333; - v = (v | (v >>> 2)) & 0x0F0F0F0F; - v = (v | (v >>> 4)) & 0x00FF00FF; - v = (v | (v >>> 16)) & 0x000FFFF; - return (v << 16) >> 16; -} - - -//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes -exports.interleave3 = function(x, y, z) { - x &= 0x3FF; - x = (x | (x<<16)) & 4278190335; - x = (x | (x<<8)) & 251719695; - x = (x | (x<<4)) & 3272356035; - x = (x | (x<<2)) & 1227133513; - - y &= 0x3FF; - y = (y | (y<<16)) & 4278190335; - y = (y | (y<<8)) & 251719695; - y = (y | (y<<4)) & 3272356035; - y = (y | (y<<2)) & 1227133513; - x |= (y << 1); - - z &= 0x3FF; - z = (z | (z<<16)) & 4278190335; - z = (z | (z<<8)) & 251719695; - z = (z | (z<<4)) & 3272356035; - z = (z | (z<<2)) & 1227133513; - - return x | (z << 2); -} - -//Extracts nth interleaved component of a 3-tuple -exports.deinterleave3 = function(v, n) { - v = (v >>> n) & 1227133513; - v = (v | (v>>>2)) & 3272356035; - v = (v | (v>>>4)) & 251719695; - v = (v | (v>>>8)) & 4278190335; - v = (v | (v>>>16)) & 0x3FF; - return (v<<22)>>22; -} - -//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) -exports.nextCombination = function(v) { - var t = v | (v - 1); - return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); -} - - -},{}],4:[function(require,module,exports){ -(function (process){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// resolves . and .. elements in a path array with directory names there -// must be no slashes, empty elements, or device names (c:\) in the array -// (so also no leading and trailing slashes - it does not distinguish -// relative and absolute paths) -function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; -} - -// Split a filename into [root, dir, basename, ext], unix version -// 'root' is just a slash, or nothing. -var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; -var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); -}; - -// path.resolve([from ...], to) -// posix version -exports.resolve = function() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : process.cwd(); - - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; -}; - -// path.normalize(path) -// posix version -exports.normalize = function(path) { - var isAbsolute = exports.isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; - - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isAbsolute).join('/'); - - if (!path && !isAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } - - return (isAbsolute ? '/' : '') + path; -}; - -// posix version -exports.isAbsolute = function(path) { - return path.charAt(0) === '/'; -}; - -// posix version -exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); -}; - - -// path.relative(from, to) -// posix version -exports.relative = function(from, to) { - from = exports.resolve(from).substr(1); - to = exports.resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); -}; - -exports.sep = '/'; -exports.delimiter = ':'; - -exports.dirname = function(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } - - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } - - return root + dir; -}; - - -exports.basename = function(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; -}; - - -exports.extname = function(path) { - return splitPath(path)[3]; -}; - -function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; -} - -// String.prototype.substr - negative index don't work in IE8 -var substr = 'ab'.substr(-1) === 'b' - ? function (str, start, len) { return str.substr(start, len) } - : function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } -; - -}).call(this,require('_process')) -},{"_process":5}],5:[function(require,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; - -function cleanUpNextTick() { - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} - -function drainQueue() { - if (draining) { - return; - } - var timeout = setTimeout(cleanUpNextTick); - draining = true; - - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); - } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - clearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - setTimeout(drainQueue, 0); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],6:[function(require,module,exports){ -(function (global){ -/*! https://mths.be/punycode v1.3.2 by @mathias */ -;(function(root) { - - /** Detect free variables */ - var freeExports = typeof exports == 'object' && exports && - !exports.nodeType && exports; - var freeModule = typeof module == 'object' && module && - !module.nodeType && module; - var freeGlobal = typeof global == 'object' && global; - if ( - freeGlobal.global === freeGlobal || - freeGlobal.window === freeGlobal || - freeGlobal.self === freeGlobal - ) { - root = freeGlobal; - } - - /** - * The `punycode` object. - * @name punycode - * @type Object - */ - var punycode, - - /** Highest positive signed 32-bit float value */ - maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 - - /** Bootstring parameters */ - base = 36, - tMin = 1, - tMax = 26, - skew = 38, - damp = 700, - initialBias = 72, - initialN = 128, // 0x80 - delimiter = '-', // '\x2D' - - /** Regular expressions */ - regexPunycode = /^xn--/, - regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars - regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators - - /** Error messages */ - errors = { - 'overflow': 'Overflow: input needs wider integers to process', - 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', - 'invalid-input': 'Invalid input' - }, - - /** Convenience shortcuts */ - baseMinusTMin = base - tMin, - floor = Math.floor, - stringFromCharCode = String.fromCharCode, - - /** Temporary variable */ - key; - - /*--------------------------------------------------------------------------*/ - - /** - * A generic error utility function. - * @private - * @param {String} type The error type. - * @returns {Error} Throws a `RangeError` with the applicable error message. - */ - function error(type) { - throw RangeError(errors[type]); - } - - /** - * A generic `Array#map` utility function. - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function that gets called for every array - * item. - * @returns {Array} A new array of values returned by the callback function. - */ - function map(array, fn) { - var length = array.length; - var result = []; - while (length--) { - result[length] = fn(array[length]); - } - return result; - } - - /** - * A simple `Array#map`-like wrapper to work with domain name strings or email - * addresses. - * @private - * @param {String} domain The domain name or email address. - * @param {Function} callback The function that gets called for every - * character. - * @returns {Array} A new string of characters returned by the callback - * function. - */ - function mapDomain(string, fn) { - var parts = string.split('@'); - var result = ''; - if (parts.length > 1) { - // In email addresses, only the domain name should be punycoded. Leave - // the local part (i.e. everything up to `@`) intact. - result = parts[0] + '@'; - string = parts[1]; - } - // Avoid `split(regex)` for IE8 compatibility. See #17. - string = string.replace(regexSeparators, '\x2E'); - var labels = string.split('.'); - var encoded = map(labels, fn).join('.'); - return result + encoded; - } - - /** - * Creates an array containing the numeric code points of each Unicode - * character in the string. While JavaScript uses UCS-2 internally, - * this function will convert a pair of surrogate halves (each of which - * UCS-2 exposes as separate characters) into a single code point, - * matching UTF-16. - * @see `punycode.ucs2.encode` - * @see - * @memberOf punycode.ucs2 - * @name decode - * @param {String} string The Unicode input string (UCS-2). - * @returns {Array} The new array of code points. - */ - function ucs2decode(string) { - var output = [], - counter = 0, - length = string.length, - value, - extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - /** - * Creates a string based on an array of numeric code points. - * @see `punycode.ucs2.decode` - * @memberOf punycode.ucs2 - * @name encode - * @param {Array} codePoints The array of numeric code points. - * @returns {String} The new Unicode string (UCS-2). - */ - function ucs2encode(array) { - return map(array, function(value) { - var output = ''; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - return output; - }).join(''); - } - - /** - * Converts a basic code point into a digit/integer. - * @see `digitToBasic()` - * @private - * @param {Number} codePoint The basic numeric code point value. - * @returns {Number} The numeric value of a basic code point (for use in - * representing integers) in the range `0` to `base - 1`, or `base` if - * the code point does not represent a value. - */ - function basicToDigit(codePoint) { - if (codePoint - 48 < 10) { - return codePoint - 22; - } - if (codePoint - 65 < 26) { - return codePoint - 65; - } - if (codePoint - 97 < 26) { - return codePoint - 97; - } - return base; - } - - /** - * Converts a digit/integer into a basic code point. - * @see `basicToDigit()` - * @private - * @param {Number} digit The numeric value of a basic code point. - * @returns {Number} The basic code point whose value (when used for - * representing integers) is `digit`, which needs to be in the range - * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is - * used; else, the lowercase form is used. The behavior is undefined - * if `flag` is non-zero and `digit` has no uppercase form. - */ - function digitToBasic(digit, flag) { - // 0..25 map to ASCII a..z or A..Z - // 26..35 map to ASCII 0..9 - return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); - } - - /** - * Bias adaptation function as per section 3.4 of RFC 3492. - * http://tools.ietf.org/html/rfc3492#section-3.4 - * @private - */ - function adapt(delta, numPoints, firstTime) { - var k = 0; - delta = firstTime ? floor(delta / damp) : delta >> 1; - delta += floor(delta / numPoints); - for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { - delta = floor(delta / baseMinusTMin); - } - return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); - } - - /** - * Converts a Punycode string of ASCII-only symbols to a string of Unicode - * symbols. - * @memberOf punycode - * @param {String} input The Punycode string of ASCII-only symbols. - * @returns {String} The resulting string of Unicode symbols. - */ - function decode(input) { - // Don't use UCS-2 - var output = [], - inputLength = input.length, - out, - i = 0, - n = initialN, - bias = initialBias, - basic, - j, - index, - oldi, - w, - k, - digit, - t, - /** Cached calculation results */ - baseMinusT; - - // Handle the basic code points: let `basic` be the number of input code - // points before the last delimiter, or `0` if there is none, then copy - // the first basic code points to the output. - - basic = input.lastIndexOf(delimiter); - if (basic < 0) { - basic = 0; - } - - for (j = 0; j < basic; ++j) { - // if it's not a basic code point - if (input.charCodeAt(j) >= 0x80) { - error('not-basic'); - } - output.push(input.charCodeAt(j)); - } - - // Main decoding loop: start just after the last delimiter if any basic code - // points were copied; start at the beginning otherwise. - - for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { - - // `index` is the index of the next character to be consumed. - // Decode a generalized variable-length integer into `delta`, - // which gets added to `i`. The overflow checking is easier - // if we increase `i` as we go, then subtract off its starting - // value at the end to obtain `delta`. - for (oldi = i, w = 1, k = base; /* no condition */; k += base) { - - if (index >= inputLength) { - error('invalid-input'); - } - - digit = basicToDigit(input.charCodeAt(index++)); - - if (digit >= base || digit > floor((maxInt - i) / w)) { - error('overflow'); - } - - i += digit * w; - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - - if (digit < t) { - break; - } - - baseMinusT = base - t; - if (w > floor(maxInt / baseMinusT)) { - error('overflow'); - } - - w *= baseMinusT; - - } - - out = output.length + 1; - bias = adapt(i - oldi, out, oldi == 0); - - // `i` was supposed to wrap around from `out` to `0`, - // incrementing `n` each time, so we'll fix that now: - if (floor(i / out) > maxInt - n) { - error('overflow'); - } - - n += floor(i / out); - i %= out; - - // Insert `n` at position `i` of the output - output.splice(i++, 0, n); - - } - - return ucs2encode(output); - } - - /** - * Converts a string of Unicode symbols (e.g. a domain name label) to a - * Punycode string of ASCII-only symbols. - * @memberOf punycode - * @param {String} input The string of Unicode symbols. - * @returns {String} The resulting Punycode string of ASCII-only symbols. - */ - function encode(input) { - var n, - delta, - handledCPCount, - basicLength, - bias, - j, - m, - q, - k, - t, - currentValue, - output = [], - /** `inputLength` will hold the number of code points in `input`. */ - inputLength, - /** Cached calculation results */ - handledCPCountPlusOne, - baseMinusT, - qMinusT; - - // Convert the input in UCS-2 to Unicode - input = ucs2decode(input); - - // Cache the length - inputLength = input.length; - - // Initialize the state - n = initialN; - delta = 0; - bias = initialBias; - - // Handle the basic code points - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue < 0x80) { - output.push(stringFromCharCode(currentValue)); - } - } - - handledCPCount = basicLength = output.length; - - // `handledCPCount` is the number of code points that have been handled; - // `basicLength` is the number of basic code points. - - // Finish the basic string - if it is not empty - with a delimiter - if (basicLength) { - output.push(delimiter); - } - - // Main encoding loop: - while (handledCPCount < inputLength) { - - // All non-basic code points < n have been handled already. Find the next - // larger one: - for (m = maxInt, j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue >= n && currentValue < m) { - m = currentValue; - } - } - - // Increase `delta` enough to advance the decoder's state to , - // but guard against overflow - handledCPCountPlusOne = handledCPCount + 1; - if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { - error('overflow'); - } - - delta += (m - n) * handledCPCountPlusOne; - n = m; - - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - - if (currentValue < n && ++delta > maxInt) { - error('overflow'); - } - - if (currentValue == n) { - // Represent delta as a generalized variable-length integer - for (q = delta, k = base; /* no condition */; k += base) { - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - if (q < t) { - break; - } - qMinusT = q - t; - baseMinusT = base - t; - output.push( - stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) - ); - q = floor(qMinusT / baseMinusT); - } - - output.push(stringFromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); - delta = 0; - ++handledCPCount; - } - } - - ++delta; - ++n; - - } - return output.join(''); - } - - /** - * Converts a Punycode string representing a domain name or an email address - * to Unicode. Only the Punycoded parts of the input will be converted, i.e. - * it doesn't matter if you call it on a string that has already been - * converted to Unicode. - * @memberOf punycode - * @param {String} input The Punycoded domain name or email address to - * convert to Unicode. - * @returns {String} The Unicode representation of the given Punycode - * string. - */ - function toUnicode(input) { - return mapDomain(input, function(string) { - return regexPunycode.test(string) - ? decode(string.slice(4).toLowerCase()) - : string; - }); - } - - /** - * Converts a Unicode string representing a domain name or an email address to - * Punycode. Only the non-ASCII parts of the domain name will be converted, - * i.e. it doesn't matter if you call it with a domain that's already in - * ASCII. - * @memberOf punycode - * @param {String} input The domain name or email address to convert, as a - * Unicode string. - * @returns {String} The Punycode representation of the given domain name or - * email address. - */ - function toASCII(input) { - return mapDomain(input, function(string) { - return regexNonASCII.test(string) - ? 'xn--' + encode(string) - : string; - }); - } - - /*--------------------------------------------------------------------------*/ - - /** Define the public API */ - punycode = { - /** - * A string representing the current Punycode.js version number. - * @memberOf punycode - * @type String - */ - 'version': '1.3.2', - /** - * An object of methods to convert from JavaScript's internal character - * representation (UCS-2) to Unicode code points, and back. - * @see - * @memberOf punycode - * @type Object - */ - 'ucs2': { - 'decode': ucs2decode, - 'encode': ucs2encode - }, - 'decode': decode, - 'encode': encode, - 'toASCII': toASCII, - 'toUnicode': toUnicode - }; - - /** Expose `punycode` */ - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - typeof define == 'function' && - typeof define.amd == 'object' && - define.amd - ) { - define('punycode', function() { - return punycode; - }); - } else if (freeExports && freeModule) { - if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+ - freeModule.exports = punycode; - } else { // in Narwhal or RingoJS v0.7.0- - for (key in punycode) { - punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); - } - } - } else { // in Rhino or a web browser - root.punycode = punycode; - } - -}(this)); - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],7:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; - -// If obj.hasOwnProperty has been overridden, then calling -// obj.hasOwnProperty(prop) will break. -// See: https://github.com/joyent/node/issues/1707 -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -module.exports = function(qs, sep, eq, options) { - sep = sep || '&'; - eq = eq || '='; - var obj = {}; - - if (typeof qs !== 'string' || qs.length === 0) { - return obj; - } - - var regexp = /\+/g; - qs = qs.split(sep); - - var maxKeys = 1000; - if (options && typeof options.maxKeys === 'number') { - maxKeys = options.maxKeys; - } - - var len = qs.length; - // maxKeys <= 0 means that we should not limit keys count - if (maxKeys > 0 && len > maxKeys) { - len = maxKeys; - } - - for (var i = 0; i < len; ++i) { - var x = qs[i].replace(regexp, '%20'), - idx = x.indexOf(eq), - kstr, vstr, k, v; - - if (idx >= 0) { - kstr = x.substr(0, idx); - vstr = x.substr(idx + 1); - } else { - kstr = x; - vstr = ''; - } - - k = decodeURIComponent(kstr); - v = decodeURIComponent(vstr); - - if (!hasOwnProperty(obj, k)) { - obj[k] = v; - } else if (isArray(obj[k])) { - obj[k].push(v); - } else { - obj[k] = [obj[k], v]; - } - } - - return obj; -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -},{}],8:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -'use strict'; - -var stringifyPrimitive = function(v) { - switch (typeof v) { - case 'string': - return v; - - case 'boolean': - return v ? 'true' : 'false'; - - case 'number': - return isFinite(v) ? v : ''; - - default: - return ''; - } -}; - -module.exports = function(obj, sep, eq, name) { - sep = sep || '&'; - eq = eq || '='; - if (obj === null) { - obj = undefined; - } - - if (typeof obj === 'object') { - return map(objectKeys(obj), function(k) { - var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; - if (isArray(obj[k])) { - return map(obj[k], function(v) { - return ks + encodeURIComponent(stringifyPrimitive(v)); - }).join(sep); - } else { - return ks + encodeURIComponent(stringifyPrimitive(obj[k])); - } - }).join(sep); - - } - - if (!name) return ''; - return encodeURIComponent(stringifyPrimitive(name)) + eq + - encodeURIComponent(stringifyPrimitive(obj)); -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -function map (xs, f) { - if (xs.map) return xs.map(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - res.push(f(xs[i], i)); - } - return res; -} - -var objectKeys = Object.keys || function (obj) { - var res = []; - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); - } - return res; -}; - -},{}],9:[function(require,module,exports){ -'use strict'; - -exports.decode = exports.parse = require('./decode'); -exports.encode = exports.stringify = require('./encode'); - -},{"./decode":7,"./encode":8}],10:[function(require,module,exports){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var punycode = require('punycode'); - -exports.parse = urlParse; -exports.resolve = urlResolve; -exports.resolveObject = urlResolveObject; -exports.format = urlFormat; - -exports.Url = Url; - -function Url() { - this.protocol = null; - this.slashes = null; - this.auth = null; - this.host = null; - this.port = null; - this.hostname = null; - this.hash = null; - this.search = null; - this.query = null; - this.pathname = null; - this.path = null; - this.href = null; -} - -// Reference: RFC 3986, RFC 1808, RFC 2396 - -// define these here so at least they only have to be -// compiled once on the first module load. -var protocolPattern = /^([a-z0-9.+-]+:)/i, - portPattern = /:[0-9]*$/, - - // RFC 2396: characters reserved for delimiting URLs. - // We actually just auto-escape these. - delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], - - // RFC 2396: characters not allowed for various reasons. - unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), - - // Allowed by RFCs, but cause of XSS attacks. Always escape these. - autoEscape = ['\''].concat(unwise), - // Characters that are never ever allowed in a hostname. - // Note that any invalid chars are also handled, but these - // are the ones that are *expected* to be seen, so we fast-path - // them. - nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), - hostEndingChars = ['/', '?', '#'], - hostnameMaxLen = 255, - hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, - hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, - // protocols that can allow "unsafe" and "unwise" chars. - unsafeProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that never have a hostname. - hostlessProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that always contain a // bit. - slashedProtocol = { - 'http': true, - 'https': true, - 'ftp': true, - 'gopher': true, - 'file': true, - 'http:': true, - 'https:': true, - 'ftp:': true, - 'gopher:': true, - 'file:': true - }, - querystring = require('querystring'); - -function urlParse(url, parseQueryString, slashesDenoteHost) { - if (url && isObject(url) && url instanceof Url) return url; - - var u = new Url; - u.parse(url, parseQueryString, slashesDenoteHost); - return u; -} - -Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { - if (!isString(url)) { - throw new TypeError("Parameter 'url' must be a string, not " + typeof url); - } - - var rest = url; - - // trim before proceeding. - // This is to support parse stuff like " http://foo.com \n" - rest = rest.trim(); - - var proto = protocolPattern.exec(rest); - if (proto) { - proto = proto[0]; - var lowerProto = proto.toLowerCase(); - this.protocol = lowerProto; - rest = rest.substr(proto.length); - } - - // figure out if it's got a host - // user@server is *always* interpreted as a hostname, and url - // resolution will treat //foo/bar as host=foo,path=bar because that's - // how the browser resolves relative URLs. - if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { - var slashes = rest.substr(0, 2) === '//'; - if (slashes && !(proto && hostlessProtocol[proto])) { - rest = rest.substr(2); - this.slashes = true; - } - } - - if (!hostlessProtocol[proto] && - (slashes || (proto && !slashedProtocol[proto]))) { - - // there's a hostname. - // the first instance of /, ?, ;, or # ends the host. - // - // If there is an @ in the hostname, then non-host chars *are* allowed - // to the left of the last @ sign, unless some host-ending character - // comes *before* the @-sign. - // URLs are obnoxious. - // - // ex: - // http://a@b@c/ => user:a@b host:c - // http://a@b?@c => user:a host:c path:/?@c - - // v0.12 TODO(isaacs): This is not quite how Chrome does things. - // Review our test case against browsers more comprehensively. - - // find the first instance of any hostEndingChars - var hostEnd = -1; - for (var i = 0; i < hostEndingChars.length; i++) { - var hec = rest.indexOf(hostEndingChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - - // at this point, either we have an explicit point where the - // auth portion cannot go past, or the last @ char is the decider. - var auth, atSign; - if (hostEnd === -1) { - // atSign can be anywhere. - atSign = rest.lastIndexOf('@'); - } else { - // atSign must be in auth portion. - // http://a@b/c@d => host:b auth:a path:/c@d - atSign = rest.lastIndexOf('@', hostEnd); - } - - // Now we have a portion which is definitely the auth. - // Pull that off. - if (atSign !== -1) { - auth = rest.slice(0, atSign); - rest = rest.slice(atSign + 1); - this.auth = decodeURIComponent(auth); - } - - // the host is the remaining to the left of the first non-host char - hostEnd = -1; - for (var i = 0; i < nonHostChars.length; i++) { - var hec = rest.indexOf(nonHostChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - // if we still have not hit it, then the entire thing is a host. - if (hostEnd === -1) - hostEnd = rest.length; - - this.host = rest.slice(0, hostEnd); - rest = rest.slice(hostEnd); - - // pull out port. - this.parseHost(); - - // we've indicated that there is a hostname, - // so even if it's empty, it has to be present. - this.hostname = this.hostname || ''; - - // if hostname begins with [ and ends with ] - // assume that it's an IPv6 address. - var ipv6Hostname = this.hostname[0] === '[' && - this.hostname[this.hostname.length - 1] === ']'; - - // validate a little. - if (!ipv6Hostname) { - var hostparts = this.hostname.split(/\./); - for (var i = 0, l = hostparts.length; i < l; i++) { - var part = hostparts[i]; - if (!part) continue; - if (!part.match(hostnamePartPattern)) { - var newpart = ''; - for (var j = 0, k = part.length; j < k; j++) { - if (part.charCodeAt(j) > 127) { - // we replace non-ASCII char with a temporary placeholder - // we need this to make sure size of hostname is not - // broken by replacing non-ASCII by nothing - newpart += 'x'; - } else { - newpart += part[j]; - } - } - // we test again with ASCII char only - if (!newpart.match(hostnamePartPattern)) { - var validParts = hostparts.slice(0, i); - var notHost = hostparts.slice(i + 1); - var bit = part.match(hostnamePartStart); - if (bit) { - validParts.push(bit[1]); - notHost.unshift(bit[2]); - } - if (notHost.length) { - rest = '/' + notHost.join('.') + rest; - } - this.hostname = validParts.join('.'); - break; - } - } - } - } - - if (this.hostname.length > hostnameMaxLen) { - this.hostname = ''; - } else { - // hostnames are always lower case. - this.hostname = this.hostname.toLowerCase(); - } - - if (!ipv6Hostname) { - // IDNA Support: Returns a puny coded representation of "domain". - // It only converts the part of the domain name that - // has non ASCII characters. I.e. it dosent matter if - // you call it with a domain that already is in ASCII. - var domainArray = this.hostname.split('.'); - var newOut = []; - for (var i = 0; i < domainArray.length; ++i) { - var s = domainArray[i]; - newOut.push(s.match(/[^A-Za-z0-9_-]/) ? - 'xn--' + punycode.encode(s) : s); - } - this.hostname = newOut.join('.'); - } - - var p = this.port ? ':' + this.port : ''; - var h = this.hostname || ''; - this.host = h + p; - this.href += this.host; - - // strip [ and ] from the hostname - // the host field still retains them, though - if (ipv6Hostname) { - this.hostname = this.hostname.substr(1, this.hostname.length - 2); - if (rest[0] !== '/') { - rest = '/' + rest; - } - } - } - - // now rest is set to the post-host stuff. - // chop off any delim chars. - if (!unsafeProtocol[lowerProto]) { - - // First, make 100% sure that any "autoEscape" chars get - // escaped, even if encodeURIComponent doesn't think they - // need to be. - for (var i = 0, l = autoEscape.length; i < l; i++) { - var ae = autoEscape[i]; - var esc = encodeURIComponent(ae); - if (esc === ae) { - esc = escape(ae); - } - rest = rest.split(ae).join(esc); - } - } - - - // chop off from the tail first. - var hash = rest.indexOf('#'); - if (hash !== -1) { - // got a fragment string. - this.hash = rest.substr(hash); - rest = rest.slice(0, hash); - } - var qm = rest.indexOf('?'); - if (qm !== -1) { - this.search = rest.substr(qm); - this.query = rest.substr(qm + 1); - if (parseQueryString) { - this.query = querystring.parse(this.query); - } - rest = rest.slice(0, qm); - } else if (parseQueryString) { - // no query string, but parseQueryString still requested - this.search = ''; - this.query = {}; - } - if (rest) this.pathname = rest; - if (slashedProtocol[lowerProto] && - this.hostname && !this.pathname) { - this.pathname = '/'; - } - - //to support http.request - if (this.pathname || this.search) { - var p = this.pathname || ''; - var s = this.search || ''; - this.path = p + s; - } - - // finally, reconstruct the href based on what has been validated. - this.href = this.format(); - return this; -}; - -// format a parsed object into a url string -function urlFormat(obj) { - // ensure it's an object, and not a string url. - // If it's an obj, this is a no-op. - // this way, you can call url_format() on strings - // to clean up potentially wonky urls. - if (isString(obj)) obj = urlParse(obj); - if (!(obj instanceof Url)) return Url.prototype.format.call(obj); - return obj.format(); -} - -Url.prototype.format = function() { - var auth = this.auth || ''; - if (auth) { - auth = encodeURIComponent(auth); - auth = auth.replace(/%3A/i, ':'); - auth += '@'; - } - - var protocol = this.protocol || '', - pathname = this.pathname || '', - hash = this.hash || '', - host = false, - query = ''; - - if (this.host) { - host = auth + this.host; - } else if (this.hostname) { - host = auth + (this.hostname.indexOf(':') === -1 ? - this.hostname : - '[' + this.hostname + ']'); - if (this.port) { - host += ':' + this.port; - } - } - - if (this.query && - isObject(this.query) && - Object.keys(this.query).length) { - query = querystring.stringify(this.query); - } - - var search = this.search || (query && ('?' + query)) || ''; - - if (protocol && protocol.substr(-1) !== ':') protocol += ':'; - - // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. - // unless they had them to begin with. - if (this.slashes || - (!protocol || slashedProtocol[protocol]) && host !== false) { - host = '//' + (host || ''); - if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; - } else if (!host) { - host = ''; - } - - if (hash && hash.charAt(0) !== '#') hash = '#' + hash; - if (search && search.charAt(0) !== '?') search = '?' + search; - - pathname = pathname.replace(/[?#]/g, function(match) { - return encodeURIComponent(match); - }); - search = search.replace('#', '%23'); - - return protocol + host + pathname + search + hash; -}; - -function urlResolve(source, relative) { - return urlParse(source, false, true).resolve(relative); -} - -Url.prototype.resolve = function(relative) { - return this.resolveObject(urlParse(relative, false, true)).format(); -}; - -function urlResolveObject(source, relative) { - if (!source) return relative; - return urlParse(source, false, true).resolveObject(relative); -} - -Url.prototype.resolveObject = function(relative) { - if (isString(relative)) { - var rel = new Url(); - rel.parse(relative, false, true); - relative = rel; - } - - var result = new Url(); - Object.keys(this).forEach(function(k) { - result[k] = this[k]; - }, this); - - // hash is always overridden, no matter what. - // even href="" will remove it. - result.hash = relative.hash; - - // if the relative url is empty, then there's nothing left to do here. - if (relative.href === '') { - result.href = result.format(); - return result; - } - - // hrefs like //foo/bar always cut to the protocol. - if (relative.slashes && !relative.protocol) { - // take everything except the protocol from relative - Object.keys(relative).forEach(function(k) { - if (k !== 'protocol') - result[k] = relative[k]; - }); - - //urlParse appends trailing / to urls like http://www.example.com - if (slashedProtocol[result.protocol] && - result.hostname && !result.pathname) { - result.path = result.pathname = '/'; - } - - result.href = result.format(); - return result; - } - - if (relative.protocol && relative.protocol !== result.protocol) { - // if it's a known url protocol, then changing - // the protocol does weird things - // first, if it's not file:, then we MUST have a host, - // and if there was a path - // to begin with, then we MUST have a path. - // if it is file:, then the host is dropped, - // because that's known to be hostless. - // anything else is assumed to be absolute. - if (!slashedProtocol[relative.protocol]) { - Object.keys(relative).forEach(function(k) { - result[k] = relative[k]; - }); - result.href = result.format(); - return result; - } - - result.protocol = relative.protocol; - if (!relative.host && !hostlessProtocol[relative.protocol]) { - var relPath = (relative.pathname || '').split('/'); - while (relPath.length && !(relative.host = relPath.shift())); - if (!relative.host) relative.host = ''; - if (!relative.hostname) relative.hostname = ''; - if (relPath[0] !== '') relPath.unshift(''); - if (relPath.length < 2) relPath.unshift(''); - result.pathname = relPath.join('/'); - } else { - result.pathname = relative.pathname; - } - result.search = relative.search; - result.query = relative.query; - result.host = relative.host || ''; - result.auth = relative.auth; - result.hostname = relative.hostname || relative.host; - result.port = relative.port; - // to support http.request - if (result.pathname || result.search) { - var p = result.pathname || ''; - var s = result.search || ''; - result.path = p + s; - } - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; - } - - var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), - isRelAbs = ( - relative.host || - relative.pathname && relative.pathname.charAt(0) === '/' - ), - mustEndAbs = (isRelAbs || isSourceAbs || - (result.host && relative.pathname)), - removeAllDots = mustEndAbs, - srcPath = result.pathname && result.pathname.split('/') || [], - relPath = relative.pathname && relative.pathname.split('/') || [], - psychotic = result.protocol && !slashedProtocol[result.protocol]; - - // if the url is a non-slashed url, then relative - // links like ../.. should be able - // to crawl up to the hostname, as well. This is strange. - // result.protocol has already been set by now. - // Later on, put the first path part into the host field. - if (psychotic) { - result.hostname = ''; - result.port = null; - if (result.host) { - if (srcPath[0] === '') srcPath[0] = result.host; - else srcPath.unshift(result.host); - } - result.host = ''; - if (relative.protocol) { - relative.hostname = null; - relative.port = null; - if (relative.host) { - if (relPath[0] === '') relPath[0] = relative.host; - else relPath.unshift(relative.host); - } - relative.host = null; - } - mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); - } - - if (isRelAbs) { - // it's absolute. - result.host = (relative.host || relative.host === '') ? - relative.host : result.host; - result.hostname = (relative.hostname || relative.hostname === '') ? - relative.hostname : result.hostname; - result.search = relative.search; - result.query = relative.query; - srcPath = relPath; - // fall through to the dot-handling below. - } else if (relPath.length) { - // it's relative - // throw away the existing file, and take the new path instead. - if (!srcPath) srcPath = []; - srcPath.pop(); - srcPath = srcPath.concat(relPath); - result.search = relative.search; - result.query = relative.query; - } else if (!isNullOrUndefined(relative.search)) { - // just pull out the search. - // like href='?foo'. - // Put this after the other two cases because it simplifies the booleans - if (psychotic) { - result.hostname = result.host = srcPath.shift(); - //occationaly the auth can get stuck only in host - //this especialy happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - result.search = relative.search; - result.query = relative.query; - //to support http.request - if (!isNull(result.pathname) || !isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.href = result.format(); - return result; - } - - if (!srcPath.length) { - // no path at all. easy. - // we've already handled the other stuff above. - result.pathname = null; - //to support http.request - if (result.search) { - result.path = '/' + result.search; - } else { - result.path = null; - } - result.href = result.format(); - return result; - } - - // if a url ENDs in . or .., then it must get a trailing slash. - // however, if it ends in anything else non-slashy, - // then it must NOT get a trailing slash. - var last = srcPath.slice(-1)[0]; - var hasTrailingSlash = ( - (result.host || relative.host) && (last === '.' || last === '..') || - last === ''); - - // strip single dots, resolve double dots to parent dir - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = srcPath.length; i >= 0; i--) { - last = srcPath[i]; - if (last == '.') { - srcPath.splice(i, 1); - } else if (last === '..') { - srcPath.splice(i, 1); - up++; - } else if (up) { - srcPath.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (!mustEndAbs && !removeAllDots) { - for (; up--; up) { - srcPath.unshift('..'); - } - } - - if (mustEndAbs && srcPath[0] !== '' && - (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { - srcPath.unshift(''); - } - - if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { - srcPath.push(''); - } - - var isAbsolute = srcPath[0] === '' || - (srcPath[0] && srcPath[0].charAt(0) === '/'); - - // put the host back - if (psychotic) { - result.hostname = result.host = isAbsolute ? '' : - srcPath.length ? srcPath.shift() : ''; - //occationaly the auth can get stuck only in host - //this especialy happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - - mustEndAbs = mustEndAbs || (result.host && srcPath.length); - - if (mustEndAbs && !isAbsolute) { - srcPath.unshift(''); - } - - if (!srcPath.length) { - result.pathname = null; - result.path = null; - } else { - result.pathname = srcPath.join('/'); - } - - //to support request.http - if (!isNull(result.pathname) || !isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.auth = relative.auth || result.auth; - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; -}; - -Url.prototype.parseHost = function() { - var host = this.host; - var port = portPattern.exec(host); - if (port) { - port = port[0]; - if (port !== ':') { - this.port = port.substr(1); - } - host = host.substr(0, host.length - port.length); - } - if (host) this.hostname = host; -}; - -function isString(arg) { - return typeof arg === "string"; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isNull(arg) { - return arg === null; -} -function isNullOrUndefined(arg) { - return arg == null; -} - -},{"punycode":6,"querystring":9}],11:[function(require,module,exports){ -'use strict'; - -module.exports = earcut; - -function earcut(data, holeIndices, dim) { - - dim = dim || 2; - - var hasHoles = holeIndices && holeIndices.length, - outerLen = hasHoles ? holeIndices[0] * dim : data.length, - outerNode = linkedList(data, 0, outerLen, dim, true), - triangles = []; - - if (!outerNode) return triangles; - - var minX, minY, maxX, maxY, x, y, size; - - if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim); - - // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox - if (data.length > 80 * dim) { - minX = maxX = data[0]; - minY = maxY = data[1]; - - for (var i = dim; i < outerLen; i += dim) { - x = data[i]; - y = data[i + 1]; - if (x < minX) minX = x; - if (y < minY) minY = y; - if (x > maxX) maxX = x; - if (y > maxY) maxY = y; - } - - // minX, minY and size are later used to transform coords into integers for z-order calculation - size = Math.max(maxX - minX, maxY - minY); - } - - earcutLinked(outerNode, triangles, dim, minX, minY, size); - - return triangles; -} - -// create a circular doubly linked list from polygon points in the specified winding order -function linkedList(data, start, end, dim, clockwise) { - var sum = 0, - i, j, last; - - // calculate original winding order of a polygon ring - for (i = start, j = end - dim; i < end; i += dim) { - sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]); - j = i; - } - - // link points into circular doubly-linked list in the specified winding order - if (clockwise === (sum > 0)) { - for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last); - } else { - for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last); - } - - return last; -} - -// eliminate colinear or duplicate points -function filterPoints(start, end) { - if (!start) return start; - if (!end) end = start; - - var p = start, - again; - do { - again = false; - - if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) { - removeNode(p); - p = end = p.prev; - if (p === p.next) return null; - again = true; - - } else { - p = p.next; - } - } while (again || p !== end); - - return end; -} - -// main ear slicing loop which triangulates a polygon (given as a linked list) -function earcutLinked(ear, triangles, dim, minX, minY, size, pass) { - if (!ear) return; - - // interlink polygon nodes in z-order - if (!pass && size) indexCurve(ear, minX, minY, size); - - var stop = ear, - prev, next; - - // iterate through ears, slicing them one by one - while (ear.prev !== ear.next) { - prev = ear.prev; - next = ear.next; - - if (size ? isEarHashed(ear, minX, minY, size) : isEar(ear)) { - // cut off the triangle - triangles.push(prev.i / dim); - triangles.push(ear.i / dim); - triangles.push(next.i / dim); - - removeNode(ear); - - // skipping the next vertice leads to less sliver triangles - ear = next.next; - stop = next.next; - - continue; - } - - ear = next; - - // if we looped through the whole remaining polygon and can't find any more ears - if (ear === stop) { - // try filtering points and slicing again - if (!pass) { - earcutLinked(filterPoints(ear), triangles, dim, minX, minY, size, 1); - - // if this didn't work, try curing all small self-intersections locally - } else if (pass === 1) { - ear = cureLocalIntersections(ear, triangles, dim); - earcutLinked(ear, triangles, dim, minX, minY, size, 2); - - // as a last resort, try splitting the remaining polygon into two - } else if (pass === 2) { - splitEarcut(ear, triangles, dim, minX, minY, size); - } - - break; - } - } -} - -// check whether a polygon node forms a valid ear with adjacent nodes -function isEar(ear) { - var a = ear.prev, - b = ear, - c = ear.next; - - if (area(a, b, c) >= 0) return false; // reflex, can't be an ear - - // now make sure we don't have other points inside the potential ear - var p = ear.next.next; - - while (p !== ear.prev) { - if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && - area(p.prev, p, p.next) >= 0) return false; - p = p.next; - } - - return true; -} - -function isEarHashed(ear, minX, minY, size) { - var a = ear.prev, - b = ear, - c = ear.next; - - if (area(a, b, c) >= 0) return false; // reflex, can't be an ear - - // triangle bbox; min & max are calculated like this for speed - var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x), - minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y), - maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x), - maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y); - - // z-order range for the current triangle bbox; - var minZ = zOrder(minTX, minTY, minX, minY, size), - maxZ = zOrder(maxTX, maxTY, minX, minY, size); - - // first look for points inside the triangle in increasing z-order - var p = ear.nextZ; - - while (p && p.z <= maxZ) { - if (p !== ear.prev && p !== ear.next && - pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && - area(p.prev, p, p.next) >= 0) return false; - p = p.nextZ; - } - - // then look for points in decreasing z-order - p = ear.prevZ; - - while (p && p.z >= minZ) { - if (p !== ear.prev && p !== ear.next && - pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) && - area(p.prev, p, p.next) >= 0) return false; - p = p.prevZ; - } - - return true; -} - -// go through all polygon nodes and cure small local self-intersections -function cureLocalIntersections(start, triangles, dim) { - var p = start; - do { - var a = p.prev, - b = p.next.next; - - // a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2]) - if (intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) { - - triangles.push(a.i / dim); - triangles.push(p.i / dim); - triangles.push(b.i / dim); - - // remove two nodes involved - removeNode(p); - removeNode(p.next); - - p = start = b; - } - p = p.next; - } while (p !== start); - - return p; -} - -// try splitting polygon into two and triangulate them independently -function splitEarcut(start, triangles, dim, minX, minY, size) { - // look for a valid diagonal that divides the polygon into two - var a = start; - do { - var b = a.next.next; - while (b !== a.prev) { - if (a.i !== b.i && isValidDiagonal(a, b)) { - // split the polygon in two by the diagonal - var c = splitPolygon(a, b); - - // filter colinear points around the cuts - a = filterPoints(a, a.next); - c = filterPoints(c, c.next); - - // run earcut on each half - earcutLinked(a, triangles, dim, minX, minY, size); - earcutLinked(c, triangles, dim, minX, minY, size); - return; - } - b = b.next; - } - a = a.next; - } while (a !== start); -} - -// link every hole into the outer loop, producing a single-ring polygon without holes -function eliminateHoles(data, holeIndices, outerNode, dim) { - var queue = [], - i, len, start, end, list; - - for (i = 0, len = holeIndices.length; i < len; i++) { - start = holeIndices[i] * dim; - end = i < len - 1 ? holeIndices[i + 1] * dim : data.length; - list = linkedList(data, start, end, dim, false); - if (list === list.next) list.steiner = true; - queue.push(getLeftmost(list)); - } - - queue.sort(compareX); - - // process holes from left to right - for (i = 0; i < queue.length; i++) { - eliminateHole(queue[i], outerNode); - outerNode = filterPoints(outerNode, outerNode.next); - } - - return outerNode; -} - -function compareX(a, b) { - return a.x - b.x; -} - -// find a bridge between vertices that connects hole with an outer ring and and link it -function eliminateHole(hole, outerNode) { - outerNode = findHoleBridge(hole, outerNode); - if (outerNode) { - var b = splitPolygon(outerNode, hole); - filterPoints(b, b.next); - } -} - -// David Eberly's algorithm for finding a bridge between hole and outer polygon -function findHoleBridge(hole, outerNode) { - var p = outerNode, - hx = hole.x, - hy = hole.y, - qx = -Infinity, - m; - - // find a segment intersected by a ray from the hole's leftmost point to the left; - // segment's endpoint with lesser x will be potential connection point - do { - if (hy <= p.y && hy >= p.next.y) { - var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y); - if (x <= hx && x > qx) { - qx = x; - m = p.x < p.next.x ? p : p.next; - } - } - p = p.next; - } while (p !== outerNode); - - if (!m) return null; - - // look for points inside the triangle of hole point, segment intersection and endpoint; - // if there are no points found, we have a valid connection; - // otherwise choose the point of the minimum angle with the ray as connection point - - var stop = m, - tanMin = Infinity, - tan; - - p = m.next; - - while (p !== stop) { - if (hx >= p.x && p.x >= m.x && - pointInTriangle(hy < m.y ? hx : qx, hy, m.x, m.y, hy < m.y ? qx : hx, hy, p.x, p.y)) { - - tan = Math.abs(hy - p.y) / (hx - p.x); // tangential - - if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && locallyInside(p, hole)) { - m = p; - tanMin = tan; - } - } - - p = p.next; - } - - return m; -} - -// interlink polygon nodes in z-order -function indexCurve(start, minX, minY, size) { - var p = start; - do { - if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, size); - p.prevZ = p.prev; - p.nextZ = p.next; - p = p.next; - } while (p !== start); - - p.prevZ.nextZ = null; - p.prevZ = null; - - sortLinked(p); -} - -// Simon Tatham's linked list merge sort algorithm -// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html -function sortLinked(list) { - var i, p, q, e, tail, numMerges, pSize, qSize, - inSize = 1; - - do { - p = list; - list = null; - tail = null; - numMerges = 0; - - while (p) { - numMerges++; - q = p; - pSize = 0; - for (i = 0; i < inSize; i++) { - pSize++; - q = q.nextZ; - if (!q) break; - } - - qSize = inSize; - - while (pSize > 0 || (qSize > 0 && q)) { - - if (pSize === 0) { - e = q; - q = q.nextZ; - qSize--; - } else if (qSize === 0 || !q) { - e = p; - p = p.nextZ; - pSize--; - } else if (p.z <= q.z) { - e = p; - p = p.nextZ; - pSize--; - } else { - e = q; - q = q.nextZ; - qSize--; - } - - if (tail) tail.nextZ = e; - else list = e; - - e.prevZ = tail; - tail = e; - } - - p = q; - } - - tail.nextZ = null; - inSize *= 2; - - } while (numMerges > 1); - - return list; -} - -// z-order of a point given coords and size of the data bounding box -function zOrder(x, y, minX, minY, size) { - // coords are transformed into non-negative 15-bit integer range - x = 32767 * (x - minX) / size; - y = 32767 * (y - minY) / size; - - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -// find the leftmost node of a polygon ring -function getLeftmost(start) { - var p = start, - leftmost = start; - do { - if (p.x < leftmost.x) leftmost = p; - p = p.next; - } while (p !== start); - - return leftmost; -} - -// check if a point lies within a convex triangle -function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) { - return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 && - (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 && - (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0; -} - -// check if a diagonal between two polygon nodes is valid (lies in polygon interior) -function isValidDiagonal(a, b) { - return equals(a, b) || a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && - locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b); -} - -// signed area of a triangle -function area(p, q, r) { - return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); -} - -// check if two points are equal -function equals(p1, p2) { - return p1.x === p2.x && p1.y === p2.y; -} - -// check if two segments intersect -function intersects(p1, q1, p2, q2) { - return area(p1, q1, p2) > 0 !== area(p1, q1, q2) > 0 && - area(p2, q2, p1) > 0 !== area(p2, q2, q1) > 0; -} - -// check if a polygon diagonal intersects any polygon segments -function intersectsPolygon(a, b) { - var p = a; - do { - if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && - intersects(p, p.next, a, b)) return true; - p = p.next; - } while (p !== a); - - return false; -} - -// check if a polygon diagonal is locally inside the polygon -function locallyInside(a, b) { - return area(a.prev, a, a.next) < 0 ? - area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : - area(a, b, a.prev) < 0 || area(a, a.next, b) < 0; -} - -// check if the middle point of a polygon diagonal is inside the polygon -function middleInside(a, b) { - var p = a, - inside = false, - px = (a.x + b.x) / 2, - py = (a.y + b.y) / 2; - do { - if (((p.y > py) !== (p.next.y > py)) && (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x)) - inside = !inside; - p = p.next; - } while (p !== a); - - return inside; -} - -// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; -// if one belongs to the outer ring and another to a hole, it merges it into a single ring -function splitPolygon(a, b) { - var a2 = new Node(a.i, a.x, a.y), - b2 = new Node(b.i, b.x, b.y), - an = a.next, - bp = b.prev; - - a.next = b; - b.prev = a; - - a2.next = an; - an.prev = a2; - - b2.next = a2; - a2.prev = b2; - - bp.next = b2; - b2.prev = bp; - - return b2; -} - -// create a node and optionally link it with previous one (in a circular doubly linked list) -function insertNode(i, x, y, last) { - var p = new Node(i, x, y); - - if (!last) { - p.prev = p; - p.next = p; - - } else { - p.next = last.next; - p.prev = last; - last.next.prev = p; - last.next = p; - } - return p; -} - -function removeNode(p) { - p.next.prev = p.prev; - p.prev.next = p.next; - - if (p.prevZ) p.prevZ.nextZ = p.nextZ; - if (p.nextZ) p.nextZ.prevZ = p.prevZ; -} - -function Node(i, x, y) { - // vertice index in coordinates array - this.i = i; - - // vertex coordinates - this.x = x; - this.y = y; - - // previous and next vertice nodes in a polygon ring - this.prev = null; - this.next = null; - - // z-order curve value - this.z = null; - - // previous and next nodes in z-order - this.prevZ = null; - this.nextZ = null; - - // indicates whether this is a steiner point - this.steiner = false; -} - -},{}],12:[function(require,module,exports){ -arguments[4][2][0].apply(exports,arguments) -},{"dup":2}],13:[function(require,module,exports){ -/** - * isMobile.js v0.4.0 - * - * A simple library to detect Apple phones and tablets, - * Android phones and tablets, other mobile devices (like blackberry, mini-opera and windows phone), - * and any kind of seven inch device, via user agent sniffing. - * - * @author: Kai Mallea (kmallea@gmail.com) - * - * @license: http://creativecommons.org/publicdomain/zero/1.0/ - */ -(function (global) { - - var apple_phone = /iPhone/i, - apple_ipod = /iPod/i, - apple_tablet = /iPad/i, - android_phone = /(?=.*\bAndroid\b)(?=.*\bMobile\b)/i, // Match 'Android' AND 'Mobile' - android_tablet = /Android/i, - amazon_phone = /(?=.*\bAndroid\b)(?=.*\bSD4930UR\b)/i, - amazon_tablet = /(?=.*\bAndroid\b)(?=.*\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\b)/i, - windows_phone = /IEMobile/i, - windows_tablet = /(?=.*\bWindows\b)(?=.*\bARM\b)/i, // Match 'Windows' AND 'ARM' - other_blackberry = /BlackBerry/i, - other_blackberry_10 = /BB10/i, - other_opera = /Opera Mini/i, - other_chrome = /(CriOS|Chrome)(?=.*\bMobile\b)/i, - other_firefox = /(?=.*\bFirefox\b)(?=.*\bMobile\b)/i, // Match 'Firefox' AND 'Mobile' - seven_inch = new RegExp( - '(?:' + // Non-capturing group - - 'Nexus 7' + // Nexus 7 - - '|' + // OR - - 'BNTV250' + // B&N Nook Tablet 7 inch - - '|' + // OR - - 'Kindle Fire' + // Kindle Fire - - '|' + // OR - - 'Silk' + // Kindle Fire, Silk Accelerated - - '|' + // OR - - 'GT-P1000' + // Galaxy Tab 7 inch - - ')', // End non-capturing group - - 'i'); // Case-insensitive matching - - var match = function(regex, userAgent) { - return regex.test(userAgent); - }; - - var IsMobileClass = function(userAgent) { - var ua = userAgent || navigator.userAgent; - - // Facebook mobile app's integrated browser adds a bunch of strings that - // match everything. Strip it out if it exists. - var tmp = ua.split('[FBAN'); - if (typeof tmp[1] !== 'undefined') { - ua = tmp[0]; - } - - // Twitter mobile app's integrated browser on iPad adds a "Twitter for - // iPhone" string. Same probable happens on other tablet platforms. - // This will confuse detection so strip it out if it exists. - tmp = ua.split('Twitter'); - if (typeof tmp[1] !== 'undefined') { - ua = tmp[0]; - } - - this.apple = { - phone: match(apple_phone, ua), - ipod: match(apple_ipod, ua), - tablet: !match(apple_phone, ua) && match(apple_tablet, ua), - device: match(apple_phone, ua) || match(apple_ipod, ua) || match(apple_tablet, ua) - }; - this.amazon = { - phone: match(amazon_phone, ua), - tablet: !match(amazon_phone, ua) && match(amazon_tablet, ua), - device: match(amazon_phone, ua) || match(amazon_tablet, ua) - }; - this.android = { - phone: match(amazon_phone, ua) || match(android_phone, ua), - tablet: !match(amazon_phone, ua) && !match(android_phone, ua) && (match(amazon_tablet, ua) || match(android_tablet, ua)), - device: match(amazon_phone, ua) || match(amazon_tablet, ua) || match(android_phone, ua) || match(android_tablet, ua) - }; - this.windows = { - phone: match(windows_phone, ua), - tablet: match(windows_tablet, ua), - device: match(windows_phone, ua) || match(windows_tablet, ua) - }; - this.other = { - blackberry: match(other_blackberry, ua), - blackberry10: match(other_blackberry_10, ua), - opera: match(other_opera, ua), - firefox: match(other_firefox, ua), - chrome: match(other_chrome, ua), - device: match(other_blackberry, ua) || match(other_blackberry_10, ua) || match(other_opera, ua) || match(other_firefox, ua) || match(other_chrome, ua) - }; - this.seven_inch = match(seven_inch, ua); - this.any = this.apple.device || this.android.device || this.windows.device || this.other.device || this.seven_inch; - - // excludes 'other' devices and ipods, targeting touchscreen phones - this.phone = this.apple.phone || this.android.phone || this.windows.phone; - - // excludes 7 inch devices, classifying as phone or tablet is left to the user - this.tablet = this.apple.tablet || this.android.tablet || this.windows.tablet; - - if (typeof window === 'undefined') { - return this; - } - }; - - var instantiate = function() { - var IM = new IsMobileClass(); - IM.Class = IsMobileClass; - return IM; - }; - - if (typeof module !== 'undefined' && module.exports && typeof window === 'undefined') { - //node - module.exports = IsMobileClass; - } else if (typeof module !== 'undefined' && module.exports && typeof window !== 'undefined') { - //browserify - module.exports = instantiate(); - } else if (typeof define === 'function' && define.amd) { - //AMD - define('isMobile', [], global.isMobile = instantiate()); - } else { - global.isMobile = instantiate(); - } - -})(this); - -},{}],14:[function(require,module,exports){ -/* eslint-disable no-unused-vars */ -'use strict'; -var hasOwnProperty = Object.prototype.hasOwnProperty; -var propIsEnumerable = Object.prototype.propertyIsEnumerable; - -function toObject(val) { - if (val === null || val === undefined) { - throw new TypeError('Object.assign cannot be called with null or undefined'); - } - - return Object(val); -} - -module.exports = Object.assign || function (target, source) { - var from; - var to = toObject(target); - var symbols; - - for (var s = 1; s < arguments.length; s++) { - from = Object(arguments[s]); - - for (var key in from) { - if (hasOwnProperty.call(from, key)) { - to[key] = from[key]; - } - } - - if (Object.getOwnPropertySymbols) { - symbols = Object.getOwnPropertySymbols(from); - for (var i = 0; i < symbols.length; i++) { - if (propIsEnumerable.call(from, symbols[i])) { - to[symbols[i]] = from[symbols[i]]; - } - } - } - } - - return to; -}; - -},{}],15:[function(require,module,exports){ - - -module.exports = { - - createContext: require('./lib/createContext'), - setVertexAttribArrays: require('./lib/setVertexAttribArrays'), - - GLBuffer: require('./lib/GLBuffer'), - GLFramebuffer: require('./lib/GLFramebuffer'), - GLShader: require('./lib/GLShader'), - GLTexture: require('./lib/GLTexture'), - - VertexArrayObject: require('./lib/VertexArrayObject') - -}; -},{"./lib/GLBuffer":16,"./lib/GLFramebuffer":17,"./lib/GLShader":18,"./lib/GLTexture":19,"./lib/VertexArrayObject":20,"./lib/createContext":21,"./lib/setVertexAttribArrays":22}],16:[function(require,module,exports){ -var EMPTY_ARRAY_BUFFER = new ArrayBuffer(0); - -/** - * Helper class to create a webGL buffer + * Manages the state and loading of multiple resources to load. * * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param type {gl.ARRAY_BUFFER | gl.ELEMENT_ARRAY_BUFFER} @mat - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data - * @param drawType {gl.STATIC_DRAW|gl.DYNAMIC_DRAW|gl.STREAM_DRAW} + * @param [baseUrl=''] {string} The base url for all resources loaded by this loader. + * @param [concurrency=10] {number} The number of resources to load concurrently. */ -var Buffer = function(gl, type, data, drawType) -{ +function Loader(baseUrl, concurrency) { + EventEmitter.call(this); - /** - * The current WebGL rendering context + concurrency = concurrency || 10; + + /** + * The base url for all resources loaded by this loader. * - * @member {WebGLRenderingContext} + * @member {string} */ - this.gl = gl; + this.baseUrl = baseUrl || ''; - /** - * The WebGL buffer, created upon instantiation + /** + * The progress percent of the loader going through the queue. * - * @member {WebGLBuffer} + * @member {number} */ - this.buffer = gl.createBuffer(); + this.progress = 0; - /** - * The type of the buffer + /** + * Loading state of the loader, true if it is currently loading resources. * - * @member {gl.ARRAY_BUFFER || gl.ELEMENT_ARRAY_BUFFER} + * @member {boolean} */ - this.type = type || gl.ARRAY_BUFFER; + this.loading = false; - /** - * The draw type of the buffer + /** + * The percentage of total progress that a single resource represents. * - * @member {gl.STATIC_DRAW|gl.DYNAMIC_DRAW|gl.STREAM_DRAW} + * @member {number} */ - this.drawType = drawType || gl.STATIC_DRAW; + this._progressChunk = 0; - /** - * The data in the buffer, as a typed array + /** + * The middleware to run before loading each resource. * - * @member {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} + * @member {function[]} */ - this.data = EMPTY_ARRAY_BUFFER; + this._beforeMiddleware = []; - if(data) - { - this.upload(data); - } + /** + * The middleware to run after loading each resource. + * + * @member {function[]} + */ + this._afterMiddleware = []; + + /** + * The `_loadResource` function bound with this object context. + * + * @private + * @member {function} + */ + this._boundLoadResource = this._loadResource.bind(this); + + /** + * The `_onLoad` function bound with this object context. + * + * @private + * @member {function} + */ + this._boundOnLoad = this._onLoad.bind(this); + + /** + * The resource buffer that fills until `load` is called to start loading resources. + * + * @private + * @member {Resource[]} + */ + this._buffer = []; + + /** + * Used to track load completion. + * + * @private + * @member {number} + */ + this._numToLoad = 0; + + /** + * The resources waiting to be loaded. + * + * @private + * @member {Resource[]} + */ + this._queue = async.queue(this._boundLoadResource, concurrency); + + /** + * All the resources for this loader keyed by name. + * + * @member {object} + */ + this.resources = {}; + + /** + * Emitted once per loaded or errored resource. + * + * @event progress + * @memberof Loader# + */ + + /** + * Emitted once per errored resource. + * + * @event error + * @memberof Loader# + */ + + /** + * Emitted once per loaded resource. + * + * @event load + * @memberof Loader# + */ + + /** + * Emitted when the loader begins to process the queue. + * + * @event start + * @memberof Loader# + */ + + /** + * Emitted when the queued resources all load. + * + * @event complete + * @memberof Loader# + */ } +Loader.prototype = Object.create(EventEmitter.prototype); +Loader.prototype.constructor = Loader; +module.exports = Loader; + /** - * Uploads the buffer to the GPU - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data to upload - * @param offset {Number} if only a subset of the data should be uploaded, this is the amount of data to subtract - * @param dontBind {Boolean} whether to bind the buffer before uploading it - */ -Buffer.prototype.upload = function(data, offset, dontBind) -{ - // todo - needed? - if(!dontBind) this.bind(); - - var gl = this.gl; - - data = data || this.data; - offset = offset || 0; - - if(this.data.byteLength >= data.byteLength) - { - gl.bufferSubData(this.type, offset, data); - } - else - { - gl.bufferData(this.type, data, this.drawType); - } - - this.data = data; -} -/** - * Binds the buffer + * Adds a resource (or multiple resources) to the loader queue. * - */ -Buffer.prototype.bind = function() -{ - var gl = this.gl; - gl.bindBuffer(this.type, this.buffer); -} - -Buffer.createVertexBuffer = function(gl, data, drawType) -{ - return new Buffer(gl, gl.ARRAY_BUFFER, data, drawType); -} - -Buffer.createIndexBuffer = function(gl, data, drawType) -{ - return new Buffer(gl, gl.ELEMENT_ARRAY_BUFFER, data, drawType); -} - -Buffer.create = function(gl, type, data, drawType) -{ - return new Buffer(gl, type, drawType); -} - -/** - * Destroys the buffer + * This function can take a wide variety of different parameters. The only thing that is always + * required the url to load. All the following will work: * - */ -Buffer.prototype.destroy = function(){ - this.gl.deleteBuffer(this.buffer); -} - -module.exports = Buffer; - -},{}],17:[function(require,module,exports){ - -var Texture = require('./GLTexture'); - -/** - * Helper class to create a webGL Framebuffer + * ```js + * loader + * // normal param syntax + * .add('key', 'http://...', function () {}) + * .add('http://...', function () {}) + * .add('http://...') * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer + * // object syntax + * .add({ + * name: 'key2', + * url: 'http://...' + * }, function () {}) + * .add({ + * url: 'http://...' + * }, function () {}) + * .add({ + * name: 'key3', + * url: 'http://...' + * onComplete: function () {} + * }) + * .add({ + * url: 'https://...', + * onComplete: function () {}, + * crossOrigin: true + * }) + * + * // you can also pass an array of objects or urls or both + * .add([ + * { name: 'key4', url: 'http://...', onComplete: function () {} }, + * { url: 'http://...', onComplete: function () {} }, + * 'http://...' + * ]); + * ``` + * + * @alias enqueue + * @param [name] {string} The name of the resource to load, if not passed the url is used. + * @param url {string} The url for this resource, relative to the baseUrl of this loader. + * @param [options] {object} The options for the load. + * @param [options.crossOrigin] {boolean} Is this request cross-origin? Default is to determine automatically. + * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.XHR_LOAD_TYPE} How should this resource be loaded? + * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being + * loaded be interpreted when using XHR? + * @param [callback] {function} Function to call when this specific resource completes loading. + * @return {Loader} */ -var Framebuffer = function(gl, width, height) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; +Loader.prototype.add = Loader.prototype.enqueue = function (name, url, options, cb) { + // special case of an array of objects or urls + if (Array.isArray(name)) { + for (var i = 0; i < name.length; ++i) { + this.add(name[i]); + } - /** - * The frame buffer - * - * @member {WebGLFramebuffer} - */ - this.framebuffer = gl.createFramebuffer(); - - /** - * The stencil buffer - * - * @member {WebGLRenderbuffer} - */ - this.stencil = null; - - /** - * The stencil buffer - * - * @member {GLTexture} - */ - this.texture = null; - - /** - * The width of the drawing area of the buffer - * - * @member {Number} - */ - this.width = width || 100; - /** - * The height of the drawing area of the buffer - * - * @member {Number} - */ - this.height = height || 100; -} - -/** - * Adds a texture to the frame buffer - * @param texture {GLTexture} - */ -Framebuffer.prototype.enableTexture = function(texture) -{ - var gl = this.gl; - - this.texture = texture || new Texture(gl); - - this.texture.bind(); - - //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); - - this.bind(); - - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture.texture, 0); -} - -/** - * Initialises the stencil buffer - * @mat maybe you can come up with a better explaination - */ -Framebuffer.prototype.enableStencil = function() -{ - if(this.stencil)return; - - var gl = this.gl; - - this.stencil = gl.createRenderbuffer(); - - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); - - // TODO.. this is depth AND stencil? - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.stencil); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, this.width , this.height ); -} - -/** - * Erases the drawing area and fills it with a colour - * @param r {Number} the red value of the clearing colour - * @param g {Number} the green value of the clearing colour - * @param b {Number} the blue value of the clearing colour - * @param a {Number} the alpha value of the clearing colour - */ -Framebuffer.prototype.clear = function( r, g, b, a ) -{ - this.bind(); - - var gl = this.gl; - - gl.clearColor(r, g, b, a); - gl.clear(gl.COLOR_BUFFER_BIT); -} - -/** - * Binds the frame buffer to the WebGL context - */ -Framebuffer.prototype.bind = function() -{ - var gl = this.gl; - - if(this.texture) - { - this.texture.unbind(); - } - - gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer ); -} - -/** - * Unbinds the frame buffer to the WebGL context - */ -Framebuffer.prototype.unbind = function() -{ - var gl = this.gl; - gl.bindFramebuffer(gl.FRAMEBUFFER, null ); -} -/** - * Resizes the drawing area of the buffer to the given width and height - * @param width {Number} the new width - * @param height {Number} the new height - */ -Framebuffer.prototype.resize = function(width, height) -{ - var gl = this.gl; - - this.width = width; - this.height = height; - - if ( this.texture ) - { - this.texture.uploadData(null, width, height); - } - - if ( this.stencil ) - { - // update the stencil buffer width and height - gl.bindRenderbuffer(gl.RENDERBUFFER, this.stencil); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); + return this; } -} -/** - * Destroys this buffer - */ -Framebuffer.prototype.destroy = function() -{ - var gl = this.gl; + // if an object is passed instead of params + if (typeof name === 'object') { + cb = url || name.callback || name.onComplete; + options = name; + url = name.url; + name = name.name || name.key || name.url; + } - //TODO - if(this.texture) - { - this.texture.destroy(); - } + // case where no name is passed shift all args over by one. + if (typeof url !== 'string') { + cb = options; + options = url; + url = name; + } - gl.deleteFramebuffer(this.framebuffer); + // now that we shifted make sure we have a proper url. + if (typeof url !== 'string') { + throw new Error('No url passed to add resource to loader.'); + } - this.gl = null; + // options are optional so people might pass a function and no options + if (typeof options === 'function') { + cb = options; + options = null; + } - this.stencil = null; - this.texture = null; -} + // check if resource already exists. + if (this.resources[name]) { + throw new Error('Resource with name "' + name + '" already exists.'); + } -/** - * Creates a frame buffer with a texture containing the given data - * @mat can you confirm ? :) - * @static - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data - */ -Framebuffer.createRGBA = function(gl, width, height, data) -{ - var texture = Texture.fromData(gl, null, width, height); - texture.enableNearestScaling(); - texture.enableWrapClamp(); + // add base url if this isn't an absolute url + url = this._handleBaseUrl(url); - //now create the framebuffer object and attach the texture to it. - var fbo = new Framebuffer(gl, width, height); - fbo.enableTexture(texture); + // create the store the resource + this.resources[name] = new Resource(name, url, options); - fbo.unbind(); + if (typeof cb === 'function') { + this.resources[name].once('afterMiddleware', cb); + } - return fbo; -} + this._numToLoad++; -/** - * Creates a frame buffer with a texture containing the given data - * @mat not sure what the difference is with the method above ? - * @static - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param width {Number} the width of the drawing area of the frame buffer - * @param height {Number} the height of the drawing area of the frame buffer - * @param data {ArrayBuffer| SharedArrayBuffer|ArrayBufferView} an array of data - */ -Framebuffer.createFloat32 = function(gl, width, height, data) -{ - // create a new texture.. - var texture = new Texture.fromData(gl, data, width, height); - texture.enableNearestScaling(); - texture.enableWrapClamp(); - - //now create the framebuffer object and attach the texture to it. - var fbo = new Framebuffer(gl, width, height); - fbo.enableTexture(texture) - - fbo.unbind(); - - return fbo; -} - -module.exports = Framebuffer; - -},{"./GLTexture":19}],18:[function(require,module,exports){ - -var compileProgram = require('./shader/compileProgram'), - extractAttributes = require('./shader/extractAttributes'), - extractUniforms = require('./shader/extractUniforms'), - generateUniformAccessObject = require('./shader/generateUniformAccessObject'); - -/** - * Helper class to create a webGL Shader - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - */ -var Shader = function(gl, vertexSrc, fragmentSrc) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - /** - * The shader program - * - * @member {WebGLProgram} - */ - // First compile the program.. - this.program = compileProgram(gl, vertexSrc, fragmentSrc); - - - /** - * The attributes of the shader as an object containing the following properties - * { - * type, - * size, - * location, - * pointer - * } - * @member {Object} - */ - // next extract the attributes - this.attributes = extractAttributes(gl, this.program); - - var uniformData = extractUniforms(gl, this.program); - - /** - * The uniforms of the shader as an object containing the following properties - * { - * gl, - * data - * } - * @member {Object} - */ - this.uniforms = generateUniformAccessObject( gl, uniformData ); -} -/** - * Uses this shader - */ -Shader.prototype.bind = function() -{ - this.gl.useProgram(this.program); -} - -/** - * Destroys this shader - * TODO - */ -Shader.prototype.destroy = function() -{ - var gl = this.gl; -} - -module.exports = Shader; - -},{"./shader/compileProgram":23,"./shader/extractAttributes":25,"./shader/extractUniforms":26,"./shader/generateUniformAccessObject":27}],19:[function(require,module,exports){ - -/** - * Helper class to create a WebGL Texture - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL context - * @param width {number} the width of the texture - * @param height {number} the height of the texture - * @param format {number} the pixel format of the texture. defaults to gl.RGBA - * @param type {number} the gl type of the texture. defaults to gl.UNSIGNED_BYTE - */ -var Texture = function(gl, width, height, format, type) -{ - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - - /** - * The WebGL texture - * - * @member {WebGLTexture} - */ - this.texture = gl.createTexture(); - - /** - * If mipmapping was used for this texture, enable and disable with enableMipmap() - * - * @member {Boolean} - */ - // some settings.. - this.mipmap = false; - - - /** - * Set to true to enable pre-multiplied alpha - * - * @member {Boolean} - */ - this.premultiplyAlpha = false; - - /** - * The width of texture - * - * @member {Number} - */ - this.width = width || 0; - /** - * The height of texture - * - * @member {Number} - */ - this.height = height || 0; - - /** - * The pixel format of the texture. defaults to gl.RGBA - * - * @member {Number} - */ - this.format = format || gl.RGBA; - - /** - * The gl type of the texture. defaults to gl.UNSIGNED_BYTE - * - * @member {Number} - */ - this.type = type || gl.UNSIGNED_BYTE; - - -} - -/** - * Uploads this texture to the GPU - * @param source {HTMLImageElement|ImageData} the source image of the texture - */ -Texture.prototype.upload = function(source) -{ - this.bind(); - - var gl = this.gl; - - this.width = source.width; - this.height = source.height; - - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, source); -} - -var FLOATING_POINT_AVAILABLE = false; - -/** - * Use a data source and uploads this texture to the GPU - * @param data {TypedArray} the data to upload to the texture - * @param width {number} the new width of the texture - * @param height {number} the new height of the texture - */ -Texture.prototype.uploadData = function(data, width, height) -{ - this.bind(); - - var gl = this.gl; - - this.width = width || this.width; - this.height = height || this.height; - - if(data instanceof Float32Array) - { - if(!FLOATING_POINT_AVAILABLE) - { - var ext = gl.getExtension("OES_texture_float"); - - if(ext) - { - FLOATING_POINT_AVAILABLE = true; - } - else - { - throw new Error('floating point textures not available'); - } - } - - this.type = gl.FLOAT; - } - else - { - // TODO support for other types - this.type = gl.UNSIGNED_BYTE; - } - - - - // what type of data? - gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this.premultiplyAlpha); - gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.width, this.height, 0, this.format, this.type, data || null); - -} - -/** - * Binds the texture - * @param location {@mat} - */ -Texture.prototype.bind = function(location) -{ - var gl = this.gl; - - if(location !== undefined) - { - gl.activeTexture(gl.TEXTURE0 + location); - } - - gl.bindTexture(gl.TEXTURE_2D, this.texture); -} - -/** - * Unbinds the texture - */ -Texture.prototype.unbind = function() -{ - var gl = this.gl; - gl.bindTexture(gl.TEXTURE_2D, null); -} - -/** - * @mat - * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation - */ -Texture.prototype.minFilter = function( linear ) -{ - var gl = this.gl; - - this.bind(); - - if(this.mipmap) - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR_MIPMAP_LINEAR : gl.NEAREST_MIPMAP_NEAREST); - } - else - { - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linear ? gl.LINEAR : gl.NEAREST); - } -} - -/** - * @mat - * @param linear {Boolean} if we want to use linear filtering or nearest neighbour interpolation - */ -Texture.prototype.magFilter = function( linear ) -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linear ? gl.LINEAR : gl.NEAREST); -} - -/** - * Enables mipmapping - */ -Texture.prototype.enableMipmap = function() -{ - var gl = this.gl; - - this.bind(); - - this.mipmap = true; - - gl.generateMipmap(gl.TEXTURE_2D); -} - -/** - * Enables linear filtering - */ -Texture.prototype.enableLinearScaling = function() -{ - this.minFilter(true); - this.magFilter(true); -} - -/** - * Enables nearest neighbour interpolation - */ -Texture.prototype.enableNearestScaling = function() -{ - this.minFilter(false); - this.magFilter(false); -} - -/** - * Enables clamping on the texture so WebGL will not repeat it - */ -Texture.prototype.enableWrapClamp = function() -{ - var gl = this.gl; - - this.bind(); - - 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); -} - -/** - * Enable tiling on the texture - */ -Texture.prototype.enableWrapRepeat = function() -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); -} - -/** - * @mat - */ -Texture.prototype.enableWrapMirrorRepeat = function() -{ - var gl = this.gl; - - this.bind(); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.MIRRORED_REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.MIRRORED_REPEAT); -} - - -/** - * Destroys this texture - */ -Texture.prototype.destroy = function() -{ - var gl = this.gl; - //TODO - gl.deleteTexture(this.texture); -} - -/** - * @static - * @param gl {WebGLRenderingContext} The current WebGL context - * @param source {HTMLImageElement|ImageData} the source image of the texture - * @param premultiplyAlpha {Boolean} If we want to use pre-multiplied alpha - */ -Texture.fromSource = function(gl, source, premultiplyAlpha) -{ - var texture = new Texture(gl); - texture.premultiplyAlpha = premultiplyAlpha || false; - texture.upload(source); - - return texture; -} - -/** - * @static - * @param gl {WebGLRenderingContext} The current WebGL context - * @param data {TypedArray} the data to upload to the texture - * @param width {number} the new width of the texture - * @param height {number} the new height of the texture - */ -Texture.fromData = function(gl, data, width, height) -{ - //console.log(data, width, height); - var texture = new Texture(gl); - texture.uploadData(data, width, height); - - return texture; -} - - -module.exports = Texture; - -},{}],20:[function(require,module,exports){ - -// state object// - -/** - * Helper class to work with WebGL VertexArrayObjects (vaos) - * Only works if WebGL extensions are enabled (they usually are) - * - * @class - * @memberof pixi.gl - * @param gl {WebGLRenderingContext} The current WebGL rendering context - */ -function VertexArrayObject(gl) -{ - - this.nativeVaoExtension = ( - gl.getExtension('OES_vertex_array_object') || - gl.getExtension('MOZ_OES_vertex_array_object') || - gl.getExtension('WEBKIT_OES_vertex_array_object') - ); - - if(this.nativeVaoExtension) - { - this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); - } - - /** - * The current WebGL rendering context - * - * @member {WebGLRenderingContext} - */ - this.gl = gl; - - /** - * An array of attributes ? @mat - * - * @member {Array} - */ - this.attributes = []; - - /** - * @mat - * - * @member {Array} - */ - this.indexBuffer = null; - - /** - * A boolean flag - * - * @member {Boolean} - */ - this.dirty = false; - - -} - -VertexArrayObject.prototype.constructor = VertexArrayObject; -module.exports = VertexArrayObject; - -/** - * Binds the buffer - */ -VertexArrayObject.prototype.bind = function() -{ - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); - - if(this.dirty) - { - this.dirty = false; - this.activate(); - } - } - else - { - this.activate(); - } - - return this; -} - -/** - * Unbinds the buffer - */ -VertexArrayObject.prototype.unbind = function() -{ - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(null); - } - - return this; -} - -/** - * Uses this vao - */ -VertexArrayObject.prototype.activate = function() -{ - var gl = this.gl; - - for (var i = 0; i < this.attributes.length; i++) - { - var attrib = this.attributes[i]; - attrib.buffer.bind(); - - //attrib.attribute.pointer(attrib.type, attrib.normalized, attrib.stride, attrib.start); - gl.vertexAttribPointer(attrib.attribute.location, - attrib.attribute.size, attrib.type || gl.FLOAT, - attrib.normalized || false, - attrib.stride || 0, - attrib.start || 0); - - gl.enableVertexAttribArray(attrib.attribute.location); - }; - - this.indexBuffer.bind(); - - return this; -} - -/** - * - * @param buffer {WebGLBuffer} - * @param attribute {[type]} - * @param type {[type]} - * @param normalized {[type]} - * @param stride {Number} - * @param start {Number} - */ -VertexArrayObject.prototype.addAttribute = function(buffer, attribute, type, normalized, stride, start) -{ - this.attributes.push({ - buffer: buffer, - attribute: attribute, - - location: attribute.location, - type: type || this.gl.FLOAT, - normalized: normalized || false, - stride: stride || 0, - start: start || 0 - }) - - this.dirty = true; - - return this; -} - -/** - * - * @param buffer {WebGLBuffer} - * @param options {Object} - */ -VertexArrayObject.prototype.addIndex = function(buffer, options) -{ - this.indexBuffer = buffer; - - this.dirty = true; + // if already loading add it to the worker queue + if (this._queue.started) { + this._queue.push(this.resources[name]); + this._progressChunk = (100 - this.progress) / (this._queue.length() + this._queue.running()); + } + // otherwise buffer it to be added to the queue later + else { + this._buffer.push(this.resources[name]); + this._progressChunk = 100 / this._buffer.length; + } return this; -} +}; + +Loader.prototype._handleBaseUrl = function (url) { + var parsedUrl = urlParser.parse(url); + + // absolute url, just use it as is. + if (parsedUrl.protocol || parsedUrl.pathname.indexOf('//') === 0) { + return url; + } + + // if baseUrl doesn't end in slash and url doesn't start with slash, then add a slash inbetween + if ( + this.baseUrl.length && + this.baseUrl.lastIndexOf('/') !== this.baseUrl.length - 1 && + url.charAt(0) !== '/' + ) { + return this.baseUrl + '/' + url; + } + else { + return this.baseUrl + url; + } +}; + /** - * Unbinds this vao and disables it + * Sets up a middleware function that will run *before* the + * resource is loaded. + * + * @alias pre + * @param middleware {function} The middleware function to register. + * @return {Loader} */ -VertexArrayObject.prototype.clear = function() -{ - // TODO - should this function unbind after clear? - // for now, no but lets see what happens in the real world! - if(this.nativeVao) - { - this.nativeVaoExtension.bindVertexArrayOES(this.nativeVao); - } +Loader.prototype.before = Loader.prototype.pre = function (fn) { + this._beforeMiddleware.push(fn); - for (var i = 0; i < this.attributes.length; i++) - { - var attrib = this.attributes[i]; - gl.disableVertexAttribArray(attrib.attribute.location); - }; - - this.attributes.length = 0; - this.indexBuffer = null; - - return this; -} + return this; +}; /** - * @mat - * @param type {Number} - * @param size {Number} - * @param start {Number} + * Sets up a middleware function that will run *after* the + * resource is loaded. + * + * @alias use + * @param middleware {function} The middleware function to register. + * @return {Loader} */ -VertexArrayObject.prototype.draw = function(type, size, start) -{ - var gl = this.gl; - gl.drawElements(type, size, gl.UNSIGNED_SHORT, start || 0); +Loader.prototype.after = Loader.prototype.use = function (fn) { + this._afterMiddleware.push(fn); - return this; -} - -},{}],21:[function(require,module,exports){ + return this; +}; /** - * Helper class to create a webGL Context + * Resets the queue of the loader to prepare for a new load. + * + * @return {Loader} + */ +Loader.prototype.reset = function () { + // this.baseUrl = baseUrl || ''; + + this.progress = 0; + + this.loading = false; + + this._progressChunk = 0; + + // this._beforeMiddleware.length = 0; + // this._afterMiddleware.length = 0; + + this._buffer.length = 0; + + this._numToLoad = 0; + + this._queue.kill(); + this._queue.started = false; + + this.resources = {}; +}; + +/** + * Starts loading the queued resources. + * + * @fires start + * @param [callback] {function} Optional callback that will be bound to the `complete` event. + * @return {Loader} + */ +Loader.prototype.load = function (cb) { + // register complete callback if they pass one + if (typeof cb === 'function') { + this.once('complete', cb); + } + + // if the queue has already started we are done here + if (this._queue.started) { + return this; + } + + // notify of start + this.emit('start', this); + + // start the internal queue + for (var i = 0; i < this._buffer.length; ++i) { + this._queue.push(this._buffer[i]); + } + + // empty the buffer + this._buffer.length = 0; + + return this; +}; + +/** + * Loads a single resource. + * + * @fires progress + * @private + */ +Loader.prototype._loadResource = function (resource, dequeue) { + var self = this; + + resource._dequeue = dequeue; + + this._runMiddleware(resource, this._beforeMiddleware, function () { + // resource.on('progress', self.emit.bind(self, 'progress')); + + resource.load(self._boundOnLoad); + }); +}; + +/** + * Called once each resource has loaded. + * + * @fires complete + * @private + */ +Loader.prototype._onComplete = function () { + this.emit('complete', this, this.resources); +}; + +/** + * Called each time a resources is loaded. + * + * @fires progress + * @fires error + * @fires load + * @private + */ +Loader.prototype._onLoad = function (resource) { + this.progress += this._progressChunk; + + this.emit('progress', this, resource); + + // run middleware, this *must* happen before dequeue so sub-assets get added properly + this._runMiddleware(resource, this._afterMiddleware, function () { + resource.emit('afterMiddleware', resource); + + this._numToLoad--; + + // do completion check + if (this._numToLoad === 0) { + this.progress = 100; + this._onComplete(); + } + + if (resource.error) { + this.emit('error', resource.error, this, resource); + } + else { + this.emit('load', this, resource); + } + }); + + + + // remove this resource from the async queue + resource._dequeue(); +}; + +/** + * Run middleware functions on a resource. + * + * @private + */ +Loader.prototype._runMiddleware = function (resource, fns, cb) { + var self = this; + + async.eachSeries(fns, function (fn, next) { + fn.call(self, resource, next); + }, cb.bind(this, resource)); +}; + +Loader.LOAD_TYPE = Resource.LOAD_TYPE; +Loader.XHR_READY_STATE = Resource.XHR_READY_STATE; +Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE; + +},{"./Resource":30,"async":28,"eventemitter3":25,"url":23}],30:[function(require,module,exports){ +var EventEmitter = require('eventemitter3'), + _url = require('url'), + // tests is CORS is supported in XHR, if not we need to use XDR + useXdr = !!(window.XDomainRequest && !('withCredentials' in (new XMLHttpRequest()))), + tempAnchor = null; + +/** + * Manages the state and loading of a single resource represented by + * a single URL. * * @class - * @memberof pixi.gl - * @param canvas {HTMLCanvasElement} the canvas element that we will get the context from - * @param options {Object} An options object that gets passed in to the canvas element containing the context attributes, - * see https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement/getContext for the options available - * @return {WebGLRenderingContext} the WebGL context + * @param name {string} The name of the resource to load. + * @param url {string|string[]} The url for this resource, for audio/video loads you can pass an array of sources. + * @param [options] {object} The options for the load. + * @param [options.crossOrigin] {string|boolean} Is this request cross-origin? Default is to determine automatically. + * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.LOAD_TYPE} How should this resource be loaded? + * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being + * loaded be interpreted when using XHR? + * @param [options.metadata] {object} Extra info for middleware. */ -var createContext = function(canvas, options) -{ - var gl = canvas.getContext('webgl', options) || - canvas.getContext('experimental-webgl', options); +function Resource(name, url, options) { + EventEmitter.call(this); - if (!gl) - { - // fail, not able to get a context - throw new Error('This browser does not support webGL. Try using the canvas renderer'); + options = options || {}; + + if (typeof name !== 'string' || typeof url !== 'string') { + throw new Error('Both name and url are required for constructing a resource.'); } - return gl; + /** + * The name of this resource. + * + * @member {string} + * @readonly + */ + this.name = name; + + /** + * The url used to load this resource. + * + * @member {string} + * @readonly + */ + this.url = url; + + /** + * Stores whether or not this url is a data url. + * + * @member {boolean} + * @readonly + */ + this.isDataUrl = this.url.indexOf('data:') === 0; + + /** + * The data that was loaded by the resource. + * + * @member {any} + */ + this.data = null; + + /** + * Is this request cross-origin? If unset, determined automatically. + * + * @member {string} + */ + this.crossOrigin = options.crossOrigin === true ? 'anonymous' : options.crossOrigin; + + /** + * The method of loading to use for this resource. + * + * @member {Resource.LOAD_TYPE} + */ + this.loadType = options.loadType || this._determineLoadType(); + + /** + * The type used to load the resource via XHR. If unset, determined automatically. + * + * @member {string} + */ + this.xhrType = options.xhrType; + + /** + * Extra info for middleware + * + * @member {object} + */ + this.metadata = options.metadata || {}; + + /** + * The error that occurred while loading (if any). + * + * @member {Error} + * @readonly + */ + this.error = null; + + /** + * The XHR object that was used to load this resource. This is only set + * when `loadType` is `Resource.LOAD_TYPE.XHR`. + * + * @member {XMLHttpRequest} + */ + this.xhr = null; + + /** + * Describes if this resource was loaded as json. Only valid after the resource + * has completely loaded. + * + * @member {boolean} + */ + this.isJson = false; + + /** + * Describes if this resource was loaded as xml. Only valid after the resource + * has completely loaded. + * + * @member {boolean} + */ + this.isXml = false; + + /** + * Describes if this resource was loaded as an image tag. Only valid after the resource + * has completely loaded. + * + * @member {boolean} + */ + this.isImage = false; + + /** + * Describes if this resource was loaded as an audio tag. Only valid after the resource + * has completely loaded. + * + * @member {boolean} + */ + this.isAudio = false; + + /** + * Describes if this resource was loaded as a video tag. Only valid after the resource + * has completely loaded. + * + * @member {boolean} + */ + this.isVideo = false; + + /** + * The `dequeue` method that will be used a storage place for the async queue dequeue method + * used privately by the loader. + * + * @member {function} + * @private + */ + this._dequeue = null; + + /** + * The `complete` function bound to this resource's context. + * + * @member {function} + * @private + */ + this._boundComplete = this.complete.bind(this); + + /** + * The `_onError` function bound to this resource's context. + * + * @member {function} + * @private + */ + this._boundOnError = this._onError.bind(this); + + /** + * The `_onProgress` function bound to this resource's context. + * + * @member {function} + * @private + */ + this._boundOnProgress = this._onProgress.bind(this); + + // xhr callbacks + this._boundXhrOnError = this._xhrOnError.bind(this); + this._boundXhrOnAbort = this._xhrOnAbort.bind(this); + this._boundXhrOnLoad = this._xhrOnLoad.bind(this); + this._boundXdrOnTimeout = this._xdrOnTimeout.bind(this); + + /** + * Emitted when the resource beings to load. + * + * @event start + * @memberof Resource# + */ + + /** + * Emitted each time progress of this resource load updates. + * Not all resources types and loader systems can support this event + * so sometimes it may not be available. If the resource + * is being loaded on a modern browser, using XHR, and the remote server + * properly sets Content-Length headers, then this will be available. + * + * @event progress + * @memberof Resource# + */ + + /** + * Emitted once this resource has loaded, if there was an error it will + * be in the `error` property. + * + * @event complete + * @memberof Resource# + */ } -module.exports = createContext; - -},{}],22:[function(require,module,exports){ -var GL_MAP = {}; +Resource.prototype = Object.create(EventEmitter.prototype); +Resource.prototype.constructor = Resource; +module.exports = Resource; /** - * @mat - * @param gl {WebGLRenderingContext} The current WebGL context - * @param attribs {[type]} + * Marks the resource as complete. + * + * @fires complete */ -var setVertexAttribArrays = function (gl, attribs) -{ - // console.log(gl.id) - var data = GL_MAP[gl.id]; - - if(!data) - { - var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); - data = GL_MAP[gl.id] = {tempAttribState:new Array(maxAttribs) - ,attribState:new Array(maxAttribs)}; - } - - var i, - tempAttribState = data.tempAttribState, - attribState = data.attribState; - - for (i = 0; i < tempAttribState.length; i++) - { - tempAttribState[i] = false; +Resource.prototype.complete = function () { + // TODO: Clean this up in a wrapper or something...gross.... + if (this.data && this.data.removeEventListener) { + this.data.removeEventListener('error', this._boundOnError); + this.data.removeEventListener('load', this._boundComplete); + this.data.removeEventListener('progress', this._boundOnProgress); + this.data.removeEventListener('canplaythrough', this._boundComplete); } - // set the new attribs - for (i in attribs) - { - tempAttribState[attribs[i].location] = true; - } - - for (i = 1; i < attribState.length; i++) - { - if (attribState[i] !== tempAttribState[i]) - { - attribState[i] = tempAttribState[i]; - - if (data.attribState[i]) - { - gl.enableVertexAttribArray(i); - } - else - { - gl.disableVertexAttribArray(i); - } + if (this.xhr) { + if (this.xhr.removeEventListener) { + this.xhr.removeEventListener('error', this._boundXhrOnError); + this.xhr.removeEventListener('abort', this._boundXhrOnAbort); + this.xhr.removeEventListener('progress', this._boundOnProgress); + this.xhr.removeEventListener('load', this._boundXhrOnLoad); } + else { + this.xhr.onerror = null; + this.xhr.ontimeout = null; + this.xhr.onprogress = null; + this.xhr.onload = null; + } + } + + this.emit('complete', this); +}; + +/** + * Kicks off loading of this resource. + * + * @fires start + * @param [callback] {function} Optional callback to call once the resource is loaded. + */ +Resource.prototype.load = function (cb) { + this.emit('start', this); + + // if a callback is set, listen for complete event + if (cb) { + this.once('complete', cb); + } + + // if unset, determine the value + if (this.crossOrigin === false || typeof this.crossOrigin !== 'string') { + this.crossOrigin = this._determineCrossOrigin(this.url); + } + + switch(this.loadType) { + case Resource.LOAD_TYPE.IMAGE: + this._loadImage(); + break; + + case Resource.LOAD_TYPE.AUDIO: + this._loadElement('audio'); + break; + + case Resource.LOAD_TYPE.VIDEO: + this._loadElement('video'); + break; + + case Resource.LOAD_TYPE.XHR: + /* falls through */ + default: + if (useXdr && this.crossOrigin) { + this._loadXdr(); + } + else { + this._loadXhr(); + } + break; } }; -module.exports = setVertexAttribArrays; - -},{}],23:[function(require,module,exports){ - /** + * Loads this resources using an Image object. * - * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @param fragmentSrc {string|string[]} The fragment shader source as an array of strings. - * @return {WebGLProgram} the shader program + * @private */ -compileProgram = function(gl, vertexSrc, fragmentSrc) -{ - var glVertShader = compileShader(gl, gl.VERTEX_SHADER, vertexSrc); - var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc); +Resource.prototype._loadImage = function () { + this.data = new Image(); - var program = gl.createProgram(); - - gl.attachShader(program, glVertShader); - gl.attachShader(program, glFragShader); - gl.linkProgram(program); - - // if linking fails, then log and cleanup - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) - { - console.error('Pixi.js Error: Could not initialize shader.'); - console.error('gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS)); - console.error('gl.getError()', gl.getError()); - - // if there is a program info log, log it - if (gl.getProgramInfoLog(program) !== '') - { - console.warn('Pixi.js Warning: gl.getProgramInfoLog()', gl.getProgramInfoLog(program)); - } - - gl.deleteProgram(program); - program = null; + if (this.crossOrigin) { + this.data.crossOrigin = this.crossOrigin; } - // clean up some shaders - gl.deleteShader(glVertShader); - gl.deleteShader(glFragShader); + this.data.src = this.url; - return program; -} + this.isImage = true; -/** - * - * @param gl {WebGLRenderingContext} The current WebGL context {WebGLProgram} - * @param type {Number} the type, can be either VERTEX_SHADER or FRAGMENT_SHADER - * @param vertexSrc {string|string[]} The vertex shader source as an array of strings. - * @return {WebGLShader} the shader - */ -var compileShader = function (gl, type, src) -{ - var shader = gl.createShader(type); - - gl.shaderSource(shader, src); - gl.compileShader(shader); - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) - { - console.log(gl.getShaderInfoLog(shader)); - return null; - } - - return shader; + this.data.addEventListener('error', this._boundOnError, false); + this.data.addEventListener('load', this._boundComplete, false); + this.data.addEventListener('progress', this._boundOnProgress, false); }; -module.exports = compileProgram; - -},{}],24:[function(require,module,exports){ - - -var defaultValue = function(type, size) -{ - switch (type) - { - case 'float': - return 0; - - case 'vec2': - return new Float32Array(2 * size); - - case 'vec3': - return new Float32Array(3 * size); - - case 'vec4': - return new Float32Array(4 * size); - - case 'int': - case 'sampler2D': - return 0; - - case 'ivec2': - return new Int32Array(2 * size); - - case 'ivec3': - return new Int32Array(3 * size); - - case 'ivec4': - return new Int32Array(4 * size); - - case 'bool': - return false; - - case 'bvec2': - - return booleanArray( 2 * size); - - case 'bvec3': - return booleanArray(3 * size); - - case 'bvec4': - return booleanArray(4 * size); - - case 'mat2': - return new Float32Array([1, 0 - ,0, 1]); - - case 'mat3': - return new Float32Array([1, 0, 0 - ,0, 1, 0 - ,0, 0, 1]); - - case 'mat4': - return new Float32Array([1, 0, 0, 0 - ,0, 1, 0, 0 - ,0, 0, 1, 0 - ,0, 0, 0, 1]); - } -} - -var booleanArray = function(size) -{ - var array = new Array(size); - - for (var i = 0; i < array.length; i++) - { - array[i] = false; - }; - - return array; -} - -module.exports = defaultValue; - -},{}],25:[function(require,module,exports){ - -var mapType = require('./mapType'); -var mapSize = require('./mapSize'); - /** - * Extracts the attributes - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the attributes from - * @return attributes {Object} + * Loads this resources using an HTMLAudioElement or HTMLVideoElement. + * + * @private */ -var extractAttributes = function(gl, program) -{ - var attributes = {}; +Resource.prototype._loadElement = function (type) { + if (type === 'audio' && typeof Audio !== 'undefined') { + this.data = new Audio(); + } + else { + this.data = document.createElement(type); + } - var totalAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES) + if (this.data === null) { + this.error = new Error('Unsupported element ' + type); + this.complete(); + return; + } - for (var i = 0; i < totalAttributes; i++) - { - var attribData = gl.getActiveAttrib(program, i); - var type = mapType(gl, attribData.type); - - attributes[attribData.name] = { - type:type, - size:mapSize(type), - location:gl.getAttribLocation(program, attribData.name), - //TODO - make an attribute object - pointer:function(type, normalized, stride, start){ - - // console.log(this.location) - gl.vertexAttribPointer(this.location,this.size, type || gl.FLOAT, normalized || false, stride || 0, start || 0); - + // support for CocoonJS Canvas+ runtime, lacks document.createElement('source') + if (navigator.isCocoonJS) { + this.data.src = Array.isArray(this.url) ? this.url[0] : this.url; + } + else { + if (Array.isArray(this.url)) { + for (var i = 0; i < this.url.length; ++i) { + this.data.appendChild(this._createSource(type, this.url[i])); } } - }; - - return attributes; -} - -module.exports = extractAttributes; - -},{"./mapSize":28,"./mapType":29}],26:[function(require,module,exports){ -var mapType = require('./mapType'); -var defaultValue = require('./defaultValue'); - -/** - * Extracts the uniforms - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param program {WebGLProgram} The shader program to get the uniforms from - * @return uniforms {Object} - */ -var extractUniforms = function(gl, program) -{ - var uniforms = {}; - - var totalUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) - - for (var i = 0; i < totalUniforms; i++) - { - var uniformData = gl.getActiveUniform(program, i); - var name = uniformData.name.replace(/\[.*?\]/, ""); - var type = mapType(gl, uniformData.type ); - - uniforms[name] = { - type:type, - size:uniformData.size, - location:gl.getUniformLocation(program, name), - value:defaultValue(type, uniformData.size) - } - }; - - return uniforms; -} - -module.exports = extractUniforms; - -},{"./defaultValue":24,"./mapType":29}],27:[function(require,module,exports){ -/** - * Extracts the attributes - * @param gl {WebGLRenderingContext} The current WebGL rendering context - * @param uniforms {Array} @mat ? - * @return attributes {Object} - */ -var generateUniformAccessObject = function(gl, uniformData) -{ - // this is the object we will be sending back. - // an object hierachy will be created for structs - var uniforms = {data:{}}; - - uniforms.gl = gl; - - var uniformKeys= Object.keys(uniformData); - - for (var i = 0; i < uniformKeys.length; i++) - { - var fullName = uniformKeys[i] - - var nameTokens = fullName.split('.'); - var name = nameTokens[nameTokens.length - 1]; - - var uniformGroup = getUniformGroup(nameTokens, uniforms); - - var uniform = uniformData[fullName]; - uniformGroup.data[name] = uniform; - - uniformGroup.gl = gl; - - Object.defineProperty(uniformGroup, name, { - get: generateGetter(name), - set: generateSetter(name, uniform) - }) - }; - - return uniforms; -} - -var generateGetter = function(name) -{ - var template = getterTemplate.replace('%%', name); - return new Function(template); -} - -var generateSetter = function(name, uniform) -{ - var template = setterTemplate.replace(/%%/g, name); - var setTemplate - - if(uniform.size === 1) - { - setTemplate = GLSL_TO_SINGLE_SETTERS[uniform.type]; - } - else - { - setTemplate = GLSL_TO_ARRAY_SETTERS[uniform.type]; - } - - if(setTemplate) - { - template += "\nthis.gl." + setTemplate + ";"; - } - - return new Function('value', template); -} - -var getUniformGroup = function(nameTokens, uniform) -{ - var cur = uniform; - - for (var i = 0; i < nameTokens.length - 1; i++) - { - var o = cur[nameTokens[i]] || {data:{}}; - cur[nameTokens[i]] = o; - cur = o; - }; - - return cur -} - -var getterTemplate = [ - 'return this.data.%%.value;', -].join('\n'); - -var setterTemplate = [ - 'this.data.%%.value = value;', - 'var location = this.data.%%.location;' -].join('\n'); - - -var GLSL_TO_SINGLE_SETTERS = { - - 'float': 'uniform1f(location, value)', - - 'vec2': 'uniform2f(location, value[0], value[1])', - 'vec3': 'uniform3f(location, value[0], value[1], value[2])', - 'vec4': 'uniform4f(location, value[0], value[1], value[2], value[3])', - - 'int': 'uniform1i(location, value)', - 'ivec2': 'uniform2i(location, value[0], value[1])', - 'ivec3': 'uniform3i(location, value[0], value[1], value[2])', - 'ivec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', - - 'bool': 'uniform1i(location, value)', - 'bvec2': 'uniform2i(location, value[0], value[1])', - 'bvec3': 'uniform3i(location, value[0], value[1], value[2])', - 'bvec4': 'uniform4i(location, value[0], value[1], value[2], value[3])', - - 'mat2': 'uniformMatrix2fv(location, false, value)', - 'mat3': 'uniformMatrix3fv(location, false, value)', - 'mat4': 'uniformMatrix4fv(location, false, value)', - - 'sampler2D':'uniform1i(location, value)' -} - -var GLSL_TO_ARRAY_SETTERS = { - - 'float': 'uniform1fv(location, value)', - - 'vec2': 'uniform2fv(location, value)', - 'vec3': 'uniform3fv(location, value)', - 'vec4': 'uniform4fv(location, value)', - - 'int': 'uniform1iv(location, value)', - 'ivec2': 'uniform2iv(location, value)', - 'ivec3': 'uniform3iv(location, value)', - 'ivec4': 'uniform4iv(location, value)', - - 'bool': 'uniform1iv(location, value)', - 'bvec2': 'uniform2iv(location, value)', - 'bvec3': 'uniform3iv(location, value)', - 'bvec4': 'uniform4iv(location, value)', - - 'sampler2D':'uniform1iv(location, value)' -} - -module.exports = generateUniformAccessObject; - -},{}],28:[function(require,module,exports){ - - -var mapSize = function(type) -{ - return GLSL_TO_SIZE[type]; -} - - -var GLSL_TO_SIZE = { - 'float': 1, - 'vec2': 2, - 'vec3': 3, - 'vec4': 4, - - 'int': 1, - 'ivec2': 2, - 'ivec3': 3, - 'ivec4': 4, - - 'bool': 1, - 'bvec2': 2, - 'bvec3': 3, - 'bvec4': 4, - - 'mat2': 4, - 'mat3': 9, - 'mat4': 16, - - 'sampler2D': 1 -} - -module.exports = mapSize; - -},{}],29:[function(require,module,exports){ - - -var mapSize = function(gl, type) -{ - if(!GL_TABLE) - { - var typeNames = Object.keys(GL_TO_GLSL_TYPES); - - GL_TABLE = {}; - - for(var i = 0; i < typeNames.length; ++i) - { - var tn = typeNames[i]; - GL_TABLE[ gl[tn] ] = GL_TO_GLSL_TYPES[tn]; + else { + this.data.appendChild(this._createSource(type, this.url)); } } - return GL_TABLE[type]; + this['is' + type[0].toUpperCase() + type.substring(1)] = true; + + this.data.addEventListener('error', this._boundOnError, false); + this.data.addEventListener('load', this._boundComplete, false); + this.data.addEventListener('progress', this._boundOnProgress, false); + this.data.addEventListener('canplaythrough', this._boundComplete, false); + + this.data.load(); +}; + +/** + * Loads this resources using an XMLHttpRequest. + * + * @private + */ +Resource.prototype._loadXhr = function () { + // if unset, determine the value + if (typeof this.xhrType !== 'string') { + this.xhrType = this._determineXhrType(); + } + + var xhr = this.xhr = new XMLHttpRequest(); + + // set the request type and url + xhr.open('GET', this.url, true); + + // load json as text and parse it ourselves. We do this because some browsers + // *cough* safari *cough* can't deal with it. + if (this.xhrType === Resource.XHR_RESPONSE_TYPE.JSON || this.xhrType === Resource.XHR_RESPONSE_TYPE.DOCUMENT) { + xhr.responseType = Resource.XHR_RESPONSE_TYPE.TEXT; + } + else { + xhr.responseType = this.xhrType; + } + + xhr.addEventListener('error', this._boundXhrOnError, false); + xhr.addEventListener('abort', this._boundXhrOnAbort, false); + xhr.addEventListener('progress', this._boundOnProgress, false); + xhr.addEventListener('load', this._boundXhrOnLoad, false); + + xhr.send(); +}; + +/** + * Loads this resources using an XDomainRequest. This is here because we need to support IE9 (gross). + * + * @private + */ +Resource.prototype._loadXdr = function () { + // if unset, determine the value + if (typeof this.xhrType !== 'string') { + this.xhrType = this._determineXhrType(); + } + + var xdr = this.xhr = new XDomainRequest(); + + // XDomainRequest has a few quirks. Occasionally it will abort requests + // A way to avoid this is to make sure ALL callbacks are set even if not used + // More info here: http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9 + xdr.timeout = 5000; + + xdr.onerror = this._boundXhrOnError; + xdr.ontimeout = this._boundXdrOnTimeout; + xdr.onprogress = this._boundOnProgress; + xdr.onload = this._boundXhrOnLoad; + + xdr.open('GET', this.url, true); + + // Note: The xdr.send() call is wrapped in a timeout to prevent an issue with the interface where some requests are lost + // if multiple XDomainRequests are being sent at the same time. + // Some info here: https://github.com/photonstorm/phaser/issues/1248 + setTimeout(function () { + xdr.send(); + }, 0); +}; + +/** + * Creates a source used in loading via an element. + * + * @param type {string} The element type (video or audio). + * @param url {string} The source URL to load from. + * @param [mime] {string} The mime type of the video + * @private + */ +Resource.prototype._createSource = function (type, url, mime) { + if (!mime) { + mime = type + '/' + url.substr(url.lastIndexOf('.') + 1); + } + + var source = document.createElement('source'); + + source.src = url; + source.type = mime; + + return source; +}; + +/** + * Called if a load errors out. + * + * @param event {Event} The error event from the element that emits it. + * @private + */ +Resource.prototype._onError = function (event) { + this.error = new Error('Failed to load element using ' + event.target.nodeName); + this.complete(); +}; + +/** + * Called if a load progress event fires for xhr/xdr. + * + * @fires progress + * @param event {XMLHttpRequestProgressEvent|Event} + * @private + */ +Resource.prototype._onProgress = function (event) { + if (event && event.lengthComputable) { + this.emit('progress', this, event.loaded / event.total); + } +}; + +/** + * Called if an error event fires for xhr/xdr. + * + * @param event {XMLHttpRequestErrorEvent|Event} + * @private + */ +Resource.prototype._xhrOnError = function () { + this.error = new Error( + reqType(this.xhr) + ' Request failed. ' + + 'Status: ' + this.xhr.status + ', text: "' + this.xhr.statusText + '"' + ); + + this.complete(); +}; + +/** + * Called if an abort event fires for xhr. + * + * @param event {XMLHttpRequestAbortEvent} + * @private + */ +Resource.prototype._xhrOnAbort = function () { + this.error = new Error(reqType(this.xhr) + ' Request was aborted by the user.'); + this.complete(); +}; + +/** + * Called if a timeout event fires for xdr. + * + * @param event {Event} + * @private + */ +Resource.prototype._xdrOnTimeout = function () { + this.error = new Error(reqType(this.xhr) + ' Request timed out.'); + this.complete(); +}; + +/** + * Called when data successfully loads from an xhr/xdr request. + * + * @param event {XMLHttpRequestLoadEvent|Event} + * @private + */ +Resource.prototype._xhrOnLoad = function () { + var xhr = this.xhr, + status = xhr.status !== undefined ? xhr.status : 200; //XDR has no `.status`, assume 200. + + // status can be 0 when using the file:// protocol, also check if a response was found + if (status === 200 || status === 204 || (status === 0 && xhr.responseText.length > 0)) { + // if text, just return it + if (this.xhrType === Resource.XHR_RESPONSE_TYPE.TEXT) { + this.data = xhr.responseText; + } + // if json, parse into json object + else if (this.xhrType === Resource.XHR_RESPONSE_TYPE.JSON) { + try { + this.data = JSON.parse(xhr.responseText); + this.isJson = true; + } catch(e) { + this.error = new Error('Error trying to parse loaded json:', e); + } + } + // if xml, parse into an xml document or div element + else if (this.xhrType === Resource.XHR_RESPONSE_TYPE.DOCUMENT) { + try { + if (window.DOMParser) { + var domparser = new DOMParser(); + this.data = domparser.parseFromString(xhr.responseText, 'text/xml'); + } + else { + var div = document.createElement('div'); + div.innerHTML = xhr.responseText; + this.data = div; + } + this.isXml = true; + } catch (e) { + this.error = new Error('Error trying to parse loaded xml:', e); + } + } + // other types just return the response + else { + this.data = xhr.response || xhr.responseText; + } + } + else { + this.error = new Error('[' + xhr.status + ']' + xhr.statusText + ':' + xhr.responseURL); + } + + this.complete(); +}; + +function reqType(xhr) { + return xhr.toString().replace('object ', ''); } -var GL_TABLE = null; +/** + * Sets the `crossOrigin` property for this resource based on if the url + * for this resource is cross-origin. If crossOrigin was manually set, this + * function does nothing. + * + * @private + * @param url {string} The url to test. + * @param [location=window.location] {object} The location object to test against. + * @return {string} The crossOrigin value to use (or empty string for none). + */ +Resource.prototype._determineCrossOrigin = function (url, loc) { + // data: and javascript: urls are considered same-origin + if (url.indexOf('data:') === 0) { + return ''; + } -var GL_TO_GLSL_TYPES = { - 'FLOAT': 'float', - 'FLOAT_VEC2': 'vec2', - 'FLOAT_VEC3': 'vec3', - 'FLOAT_VEC4': 'vec4', + // default is window.location + loc = loc || window.location; - 'INT': 'int', - 'INT_VEC2': 'ivec2', - 'INT_VEC3': 'ivec3', - 'INT_VEC4': 'ivec4', - - 'BOOL': 'bool', - 'BOOL_VEC2': 'bvec2', - 'BOOL_VEC3': 'bvec3', - 'BOOL_VEC4': 'bvec4', - - 'FLOAT_MAT2': 'mat2', - 'FLOAT_MAT3': 'mat3', - 'FLOAT_MAT4': 'mat4', - - 'SAMPLER_2D': 'sampler2D' + if (!tempAnchor) { + tempAnchor = document.createElement('a'); + } + + // let the browser determine the full href for the url of this resource and then + // parse with the node url lib, we can't use the properties of the anchor element + // because they don't work in IE9 :( + tempAnchor.href = url; + url = _url.parse(tempAnchor.href); + + var samePort = (!url.port && loc.port === '') || (url.port === loc.port); + + // if cross origin + if (url.hostname !== loc.hostname || !samePort || url.protocol !== loc.protocol) { + return 'anonymous'; + } + + return ''; +}; + +/** + * Determines the responseType of an XHR request based on the extension of the + * resource being loaded. + * + * @private + * @return {Resource.XHR_RESPONSE_TYPE} The responseType to use. + */ +Resource.prototype._determineXhrType = function () { + return Resource._xhrTypeMap[this._getExtension()] || Resource.XHR_RESPONSE_TYPE.TEXT; +}; + +Resource.prototype._determineLoadType = function () { + return Resource._loadTypeMap[this._getExtension()] || Resource.LOAD_TYPE.XHR; +}; + +Resource.prototype._getExtension = function () { + var url = this.url, + ext; + + if (this.isDataUrl) { + var slashIndex = url.indexOf('/'); + ext = url.substring(slashIndex + 1, url.indexOf(';', slashIndex)); + } + else { + var queryStart = url.indexOf('?'); + if (queryStart !== -1) { + url = url.substring(0, queryStart); + } + + ext = url.substring(url.lastIndexOf('.') + 1); + } + + return ext; +}; + +/** + * Determines the mime type of an XHR request based on the responseType of + * resource being loaded. + * + * @private + * @return {string} The mime type to use. + */ +Resource.prototype._getMimeFromXhrType = function (type) { + switch(type) { + case Resource.XHR_RESPONSE_TYPE.BUFFER: + return 'application/octet-binary'; + + case Resource.XHR_RESPONSE_TYPE.BLOB: + return 'application/blob'; + + case Resource.XHR_RESPONSE_TYPE.DOCUMENT: + return 'application/xml'; + + case Resource.XHR_RESPONSE_TYPE.JSON: + return 'application/json'; + + case Resource.XHR_RESPONSE_TYPE.DEFAULT: + case Resource.XHR_RESPONSE_TYPE.TEXT: + /* falls through */ + default: + return 'text/plain'; + + } +}; + +/** + * The types of loading a resource can use. + * + * @static + * @constant + * @property {object} LOAD_TYPE + * @property {number} LOAD_TYPE.XHR - Uses XMLHttpRequest to load the resource. + * @property {number} LOAD_TYPE.IMAGE - Uses an `Image` object to load the resource. + * @property {number} LOAD_TYPE.AUDIO - Uses an `Audio` object to load the resource. + * @property {number} LOAD_TYPE.VIDEO - Uses a `Video` object to load the resource. + */ +Resource.LOAD_TYPE = { + XHR: 1, + IMAGE: 2, + AUDIO: 3, + VIDEO: 4 +}; + +/** + * The XHR ready states, used internally. + * + * @static + * @constant + * @property {object} XHR_READY_STATE + * @property {number} XHR_READY_STATE.UNSENT - open()has not been called yet. + * @property {number} XHR_READY_STATE.OPENED - send()has not been called yet. + * @property {number} XHR_READY_STATE.HEADERS_RECEIVED - send() has been called, and headers and status are available. + * @property {number} XHR_READY_STATE.LOADING - Downloading; responseText holds partial data. + * @property {number} XHR_READY_STATE.DONE - The operation is complete. + */ +Resource.XHR_READY_STATE = { + UNSENT: 0, + OPENED: 1, + HEADERS_RECEIVED: 2, + LOADING: 3, + DONE: 4 +}; + +/** + * The XHR ready states, used internally. + * + * @static + * @constant + * @property {object} XHR_RESPONSE_TYPE + * @property {string} XHR_RESPONSE_TYPE.DEFAULT - defaults to text + * @property {string} XHR_RESPONSE_TYPE.BUFFER - ArrayBuffer + * @property {string} XHR_RESPONSE_TYPE.BLOB - Blob + * @property {string} XHR_RESPONSE_TYPE.DOCUMENT - Document + * @property {string} XHR_RESPONSE_TYPE.JSON - Object + * @property {string} XHR_RESPONSE_TYPE.TEXT - String + */ +Resource.XHR_RESPONSE_TYPE = { + DEFAULT: 'text', + BUFFER: 'arraybuffer', + BLOB: 'blob', + DOCUMENT: 'document', + JSON: 'json', + TEXT: 'text' +}; + +Resource._loadTypeMap = { + 'gif': Resource.LOAD_TYPE.IMAGE, + 'png': Resource.LOAD_TYPE.IMAGE, + 'bmp': Resource.LOAD_TYPE.IMAGE, + 'jpg': Resource.LOAD_TYPE.IMAGE, + 'jpeg': Resource.LOAD_TYPE.IMAGE, + 'tif': Resource.LOAD_TYPE.IMAGE, + 'tiff': Resource.LOAD_TYPE.IMAGE, + 'webp': Resource.LOAD_TYPE.IMAGE, + 'tga': Resource.LOAD_TYPE.IMAGE +}; + +Resource._xhrTypeMap = { + // xml + 'xhtml': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'html': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'htm': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'xml': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'tmx': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'tsx': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + 'svg': Resource.XHR_RESPONSE_TYPE.DOCUMENT, + + // images + 'gif': Resource.XHR_RESPONSE_TYPE.BLOB, + 'png': Resource.XHR_RESPONSE_TYPE.BLOB, + 'bmp': Resource.XHR_RESPONSE_TYPE.BLOB, + 'jpg': Resource.XHR_RESPONSE_TYPE.BLOB, + 'jpeg': Resource.XHR_RESPONSE_TYPE.BLOB, + 'tif': Resource.XHR_RESPONSE_TYPE.BLOB, + 'tiff': Resource.XHR_RESPONSE_TYPE.BLOB, + 'webp': Resource.XHR_RESPONSE_TYPE.BLOB, + 'tga': Resource.XHR_RESPONSE_TYPE.BLOB, + + // json + 'json': Resource.XHR_RESPONSE_TYPE.JSON, + + // text + 'text': Resource.XHR_RESPONSE_TYPE.TEXT, + 'txt': Resource.XHR_RESPONSE_TYPE.TEXT +}; + +/** + * Sets the load type to be used for a specific extension. + * + * @static + * @param extname {string} The extension to set the type for, e.g. "png" or "fnt" + * @param loadType {Resource.LOAD_TYPE} The load type to set it to. + */ +Resource.setExtensionLoadType = function (extname, loadType) { + setExtMap(Resource._loadTypeMap, extname, loadType); +}; + +/** + * Sets the load type to be used for a specific extension. + * + * @static + * @param extname {string} The extension to set the type for, e.g. "png" or "fnt" + * @param xhrType {Resource.XHR_RESPONSE_TYPE} The xhr type to set it to. + */ +Resource.setExtensionXhrType = function (extname, xhrType) { + setExtMap(Resource._xhrTypeMap, extname, xhrType); +}; + +function setExtMap(map, extname, val) { + if (extname && extname.indexOf('.') === 0) { + extname = extname.substring(1); + } + + if (!extname) { + return; + } + + map[extname] = val; } -module.exports = mapSize; +},{"eventemitter3":25,"url":23}],31:[function(require,module,exports){ +module.exports = { -},{}],30:[function(require,module,exports){ + // private property + _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", + + encodeBinary: function (input) { + var output = ""; + var bytebuffer; + var encodedCharIndexes = new Array(4); + var inx = 0; + var jnx = 0; + var paddingBytes = 0; + + while (inx < input.length) { + // Fill byte buffer array + bytebuffer = new Array(3); + for (jnx = 0; jnx < bytebuffer.length; jnx++) { + if (inx < input.length) { + // throw away high-order byte, as documented at: + // https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data + bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff; + } + else { + bytebuffer[jnx] = 0; + } + } + + // Get each encoded character, 6 bits at a time + // index 1: first 6 bits + encodedCharIndexes[0] = bytebuffer[0] >> 2; + // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2) + encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4); + // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3) + encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6); + // index 3: forth 6 bits (6 least significant bits from input byte 3) + encodedCharIndexes[3] = bytebuffer[2] & 0x3f; + + // Determine whether padding happened, and adjust accordingly + paddingBytes = inx - (input.length - 1); + switch (paddingBytes) { + case 2: + // Set last 2 characters to padding char + encodedCharIndexes[3] = 64; + encodedCharIndexes[2] = 64; + break; + + case 1: + // Set last character to padding char + encodedCharIndexes[3] = 64; + break; + + default: + break; // No padding - proceed + } + + // Now we will grab each appropriate character out of our keystring + // based on our index array and append it to the output string + for (jnx = 0; jnx < encodedCharIndexes.length; jnx++) { + output += this._keyStr.charAt(encodedCharIndexes[jnx]); + } + } + return output; + } +}; + +},{}],32:[function(require,module,exports){ +module.exports = require('./Loader'); + +module.exports.Resource = require('./Resource'); + +module.exports.middleware = { + caching: { + memory: require('./middlewares/caching/memory') + }, + parsing: { + blob: require('./middlewares/parsing/blob') + } +}; + +},{"./Loader":29,"./Resource":30,"./middlewares/caching/memory":33,"./middlewares/parsing/blob":34}],33:[function(require,module,exports){ +// a simple in-memory cache for resources +var cache = {}; + +module.exports = function () { + return function (resource, next) { + // if cached, then set data and complete the resource + if (cache[resource.url]) { + resource.data = cache[resource.url]; + resource.complete(); + } + // if not cached, wait for complete and store it in the cache. + else { + resource.once('complete', function () { + cache[this.url] = this.data; + }); + } + + next(); + }; +}; + +},{}],34:[function(require,module,exports){ +var Resource = require('../../Resource'), + b64 = require('../../b64'); + +window.URL = window.URL || window.webkitURL; + +// a middleware for transforming XHR loaded Blobs into more useful objects + +module.exports = function () { + return function (resource, next) { + if (!resource.data) { + return next(); + } + + // if this was an XHR load of a blob + if (resource.xhr && resource.xhrType === Resource.XHR_RESPONSE_TYPE.BLOB) { + // if there is no blob support we probably got a binary string back + if (!window.Blob || typeof resource.data === 'string') { + var type = resource.xhr.getResponseHeader('content-type'); + + // this is an image, convert the binary string into a data url + if (type && type.indexOf('image') === 0) { + resource.data = new Image(); + resource.data.src = 'data:' + type + ';base64,' + b64.encodeBinary(resource.xhr.responseText); + + resource.isImage = true; + + // wait until the image loads and then callback + resource.data.onload = function () { + resource.data.onload = null; + + next(); + }; + } + } + // if content type says this is an image, then we should transform the blob into an Image object + else if (resource.data.type.indexOf('image') === 0) { + var src = URL.createObjectURL(resource.data); + + resource.blob = resource.data; + resource.data = new Image(); + resource.data.src = src; + + resource.isImage = true; + + // cleanup the no longer used blob after the image loads + resource.data.onload = function () { + URL.revokeObjectURL(src); + resource.data.onload = null; + + next(); + }; + } + } + else { + next(); + } + }; +}; + +},{"../../Resource":30,"../../b64":31}],35:[function(require,module,exports){ var core = require('../core'); // add some extra variables to the container.. @@ -6000,7 +7435,7 @@ core.WebGLRenderer.registerPlugin('accessibility', AccessibilityManager); core.CanvasRenderer.registerPlugin('accessibility', AccessibilityManager); -},{"../core":51,"./accessibleTarget":31}],31:[function(require,module,exports){ +},{"../core":56,"./accessibleTarget":36}],36:[function(require,module,exports){ /** * Default property values of accessible objects * used by {@link PIXI.accessibility.AccessibilityManager}. @@ -6046,7 +7481,7 @@ module.exports = accessibleTarget; -},{}],32:[function(require,module,exports){ +},{}],37:[function(require,module,exports){ /** * @file Main export of the PIXI accessibility library * @author Mat Groves @@ -6062,7 +7497,7 @@ AccessibilityManager: require('./AccessibilityManager') }; -},{"./AccessibilityManager":30,"./accessibleTarget":31}],33:[function(require,module,exports){ +},{"./AccessibilityManager":35,"./accessibleTarget":36}],38:[function(require,module,exports){ /** * Constant values used in pixi @@ -6318,9 +7753,9 @@ module.exports = CONST; -},{"./utils/maxRecommendedTextures":100}],34:[function(require,module,exports){ -arguments[4][33][0].apply(exports,arguments) -},{"./utils/maxRecommendedTextures":100,"dup":33}],35:[function(require,module,exports){ +},{"./utils/maxRecommendedTextures":106}],39:[function(require,module,exports){ +arguments[4][38][0].apply(exports,arguments) +},{"./utils/maxRecommendedTextures":106,"dup":38}],40:[function(require,module,exports){ var math = require('../math'), utils = require('../utils'), DisplayObject = require('./DisplayObject'), @@ -6745,9 +8180,11 @@ continue; } - childVisible = true; - childBounds = this.children[i].getBounds(); + if (childBounds === math.Rectangle.EMPTY) { + continue; + } + childVisible = true; minX = minX < childBounds.x ? minX : childBounds.x; minY = minY < childBounds.y ? minY : childBounds.y; @@ -6761,7 +8198,7 @@ if (!childVisible) { - return math.Rectangle.EMPTY; + return this._currentBounds = math.Rectangle.EMPTY; } var bounds = this._bounds; @@ -6947,7 +8384,7 @@ this.children = null; }; -},{"../math":55,"../textures/RenderTexture":92,"../utils":99,"./DisplayObject":36}],36:[function(require,module,exports){ +},{"../math":60,"../textures/RenderTexture":97,"../utils":105,"./DisplayObject":41}],41:[function(require,module,exports){ var math = require('../math'), RenderTexture = require('../textures/RenderTexture'), EventEmitter = require('eventemitter3'), @@ -7063,7 +8500,7 @@ }, set: function (value) { - this.position.x = value; + this.transform.position.x = value; } }, @@ -7080,7 +8517,7 @@ }, set: function (value) { - this.position.y = value; + this.transform.position.y = value; } }, @@ -7446,7 +8883,7 @@ this.filterArea = null; }; -},{"../math":55,"../textures/RenderTexture":92,"./Transform":38,"eventemitter3":12}],37:[function(require,module,exports){ +},{"../math":60,"../textures/RenderTexture":97,"./Transform":43,"eventemitter3":25}],42:[function(require,module,exports){ /** * The Point object represents a location in a two-dimensional coordinate system, where x represents * the horizontal axis and y represents the vertical axis. @@ -7523,7 +8960,7 @@ this.transform._versionLocal++; }; -},{}],38:[function(require,module,exports){ +},{}],43:[function(require,module,exports){ var math = require('../math'), ObservablePoint = require('./ObservablePoint'); @@ -7660,15 +9097,19 @@ module.exports = Transform; -},{"../math":55,"./ObservablePoint":37}],39:[function(require,module,exports){ +},{"../math":60,"./ObservablePoint":42}],44:[function(require,module,exports){ var Container = require('../display/Container'), RenderTexture = require('../textures/RenderTexture'), + Texture = require('../textures/Texture'), GraphicsData = require('./GraphicsData'), Sprite = require('../sprites/Sprite'), math = require('../math'), CONST = require('../const'), bezierCurveTo = require('./utils/bezierCurveTo'), - + CanvasRenderTarget = require('../renderers/canvas/utils/CanvasRenderTarget'), + CanvasRenderer = require('../renderers/canvas/CanvasRenderer'), + canvasRenderer, + tempMatrix = new math.Matrix(), tempPoint = new math.Point(); /** @@ -8672,6 +10113,30 @@ return data; }; +Graphics.prototype.generateCanvasTexture = function(scaleMode, resolution) +{ + resolution = resolution || 1; + + var bounds = this.getLocalBounds(); + + var canvasBuffer = new RenderTexture.create(bounds.width * resolution, bounds.height * resolution); + + if(!canvasRenderer) + { + canvasRenderer = new CanvasRenderer(); + } + + tempMatrix.tx = -bounds.x; + tempMatrix.ty = -bounds.y; + + canvasRenderer.render(this, canvasBuffer, false, tempMatrix); + + var texture = Texture.fromCanvas(canvasBuffer.baseTexture._canvasRenderTarget.canvas, scaleMode); + texture.baseTexture.resolution = resolution; + + return texture; +} + /** * Destroys the Graphics object. */ @@ -8698,7 +10163,7 @@ this._localBounds = null; }; -},{"../const":34,"../display/Container":35,"../math":55,"../sprites/Sprite":83,"../textures/RenderTexture":92,"./GraphicsData":40,"./utils/bezierCurveTo":42}],40:[function(require,module,exports){ +},{"../const":39,"../display/Container":40,"../math":60,"../renderers/canvas/CanvasRenderer":67,"../renderers/canvas/utils/CanvasRenderTarget":69,"../sprites/Sprite":88,"../textures/RenderTexture":97,"../textures/Texture":98,"./GraphicsData":45,"./utils/bezierCurveTo":47}],45:[function(require,module,exports){ /** * A GraphicsData object. * @@ -8791,7 +10256,7 @@ this.shape = null; }; -},{}],41:[function(require,module,exports){ +},{}],46:[function(require,module,exports){ var CanvasRenderer = require('../../renderers/canvas/CanvasRenderer'), CONST = require('../../const'); @@ -9070,7 +10535,7 @@ this.renderer = null; }; -},{"../../const":34,"../../renderers/canvas/CanvasRenderer":62}],42:[function(require,module,exports){ +},{"../../const":39,"../../renderers/canvas/CanvasRenderer":67}],47:[function(require,module,exports){ /** * Calculate the points for a bezier curve and then draws it. @@ -9118,7 +10583,7 @@ module.exports = bezierCurveTo; -},{}],43:[function(require,module,exports){ +},{}],48:[function(require,module,exports){ var utils = require('../../utils'), CONST = require('../../const'), ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), @@ -9339,7 +10804,7 @@ return webGLData; }; -},{"../../const":34,"../../renderers/webgl/WebGLRenderer":68,"../../renderers/webgl/utils/ObjectRenderer":78,"../../utils":99,"./WebGLGraphicsData":44,"./shaders/PrimitiveShader":45,"./utils/buildCircle":46,"./utils/buildPoly":48,"./utils/buildRectangle":49,"./utils/buildRoundedRectangle":50}],44:[function(require,module,exports){ +},{"../../const":39,"../../renderers/webgl/WebGLRenderer":73,"../../renderers/webgl/utils/ObjectRenderer":83,"../../utils":105,"./WebGLGraphicsData":49,"./shaders/PrimitiveShader":50,"./utils/buildCircle":51,"./utils/buildPoly":53,"./utils/buildRectangle":54,"./utils/buildRoundedRectangle":55}],49:[function(require,module,exports){ var glCore = require('pixi-gl-core'); @@ -9464,7 +10929,7 @@ this.glIndices = null; }; -},{"pixi-gl-core":15}],45:[function(require,module,exports){ +},{"pixi-gl-core":1}],50:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; /** @@ -9515,7 +10980,7 @@ module.exports = PrimitiveShader; -},{"pixi-gl-core":15}],46:[function(require,module,exports){ +},{"pixi-gl-core":1}],51:[function(require,module,exports){ var buildLine = require('./buildLine'), CONST = require('../../../const'), utils = require('../../../utils'); @@ -9604,7 +11069,7 @@ module.exports = buildCircle; -},{"../../../const":34,"../../../utils":99,"./buildLine":47}],47:[function(require,module,exports){ +},{"../../../const":39,"../../../utils":105,"./buildLine":52}],52:[function(require,module,exports){ var math = require('../../../math'), utils = require('../../../utils'); @@ -9824,7 +11289,7 @@ }; module.exports = buildLine; -},{"../../../math":55,"../../../utils":99}],48:[function(require,module,exports){ +},{"../../../math":60,"../../../utils":105}],53:[function(require,module,exports){ var buildLine = require('./buildLine'), utils = require('../../../utils'), earcut = require('earcut'); @@ -9904,7 +11369,7 @@ module.exports = buildPoly; -},{"../../../utils":99,"./buildLine":47,"earcut":11}],49:[function(require,module,exports){ +},{"../../../utils":105,"./buildLine":52,"earcut":24}],54:[function(require,module,exports){ var buildLine = require('./buildLine'), utils = require('../../../utils'); @@ -9975,7 +11440,7 @@ }; module.exports = buildRectangle; -},{"../../../utils":99,"./buildLine":47}],50:[function(require,module,exports){ +},{"../../../utils":105,"./buildLine":52}],55:[function(require,module,exports){ var earcut = require('earcut'), // buildLine = require('./buildLine'), utils = require('../../../utils'); @@ -10105,7 +11570,7 @@ module.exports = buildRoundedRectangle; -},{"../../../utils":99,"earcut":11}],51:[function(require,module,exports){ +},{"../../../utils":105,"earcut":24}],56:[function(require,module,exports){ /** * @file Main export of the PIXI core library * @author Mat Groves @@ -10198,7 +11663,7 @@ } }); -},{"./const":34,"./display/Container":35,"./display/DisplayObject":36,"./graphics/Graphics":39,"./graphics/GraphicsData":40,"./graphics/canvas/CanvasGraphicsRenderer":41,"./graphics/webgl/GraphicsRenderer":43,"./math":55,"./renderers/canvas/CanvasRenderer":62,"./renderers/canvas/utils/CanvasRenderTarget":64,"./renderers/webgl/WebGLRenderer":68,"./renderers/webgl/filters/Filter":70,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":73,"./renderers/webgl/managers/WebGLManager":77,"./renderers/webgl/utils/ObjectRenderer":78,"./renderers/webgl/utils/Quad":79,"./renderers/webgl/utils/RenderTarget":80,"./sprites/Sprite":83,"./sprites/canvas/CanvasSpriteRenderer":84,"./sprites/webgl/SpriteRenderer":87,"./text/Text":89,"./textures/BaseRenderTexture":90,"./textures/BaseTexture":91,"./textures/RenderTexture":92,"./textures/Texture":93,"./textures/TextureUvs":94,"./textures/VideoBaseTexture":95,"./ticker":97,"./utils":99,"pixi-gl-core":15}],52:[function(require,module,exports){ +},{"./const":39,"./display/Container":40,"./display/DisplayObject":41,"./graphics/Graphics":44,"./graphics/GraphicsData":45,"./graphics/canvas/CanvasGraphicsRenderer":46,"./graphics/webgl/GraphicsRenderer":48,"./math":60,"./renderers/canvas/CanvasRenderer":67,"./renderers/canvas/utils/CanvasRenderTarget":69,"./renderers/webgl/WebGLRenderer":73,"./renderers/webgl/filters/Filter":75,"./renderers/webgl/filters/spriteMask/SpriteMaskFilter":78,"./renderers/webgl/managers/WebGLManager":82,"./renderers/webgl/utils/ObjectRenderer":83,"./renderers/webgl/utils/Quad":84,"./renderers/webgl/utils/RenderTarget":85,"./sprites/Sprite":88,"./sprites/canvas/CanvasSpriteRenderer":89,"./sprites/webgl/SpriteRenderer":92,"./text/Text":94,"./textures/BaseRenderTexture":95,"./textures/BaseTexture":96,"./textures/RenderTexture":97,"./textures/Texture":98,"./textures/TextureUvs":99,"./textures/VideoBaseTexture":100,"./ticker":102,"./utils":105,"pixi-gl-core":1}],57:[function(require,module,exports){ // Your friendly neighbour https://en.wikipedia.org/wiki/Dihedral_group of order 16 var ux = [1, 1, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1]; @@ -10362,7 +11827,7 @@ module.exports = GroupD8; -},{"./Matrix":53}],53:[function(require,module,exports){ +},{"./Matrix":58}],58:[function(require,module,exports){ // @todo - ignore the too many parameters warning for now // should either fix it or change the jshint config // jshint -W072 @@ -10803,7 +12268,7 @@ */ Matrix.TEMP_MATRIX = new Matrix(); -},{"./Point":54}],54:[function(require,module,exports){ +},{"./Point":59}],59:[function(require,module,exports){ /** * The Point object represents a location in a two-dimensional coordinate system, where x represents * the horizontal axis and y represents the vertical axis. @@ -10873,7 +12338,7 @@ this.y = y || ( (y !== 0) ? this.x : 0 ) ; }; -},{}],55:[function(require,module,exports){ +},{}],60:[function(require,module,exports){ /** * Math classes and utilities mixed into PIXI namespace. * @@ -10896,7 +12361,7 @@ RoundedRectangle: require('./shapes/RoundedRectangle') }; -},{"./GroupD8":52,"./Matrix":53,"./Point":54,"./shapes/Circle":56,"./shapes/Ellipse":57,"./shapes/Polygon":58,"./shapes/Rectangle":59,"./shapes/RoundedRectangle":60}],56:[function(require,module,exports){ +},{"./GroupD8":57,"./Matrix":58,"./Point":59,"./shapes/Circle":61,"./shapes/Ellipse":62,"./shapes/Polygon":63,"./shapes/Rectangle":64,"./shapes/RoundedRectangle":65}],61:[function(require,module,exports){ var Rectangle = require('./Rectangle'), CONST = require('../../const'); @@ -10984,7 +12449,7 @@ return new Rectangle(this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2); }; -},{"../../const":34,"./Rectangle":59}],57:[function(require,module,exports){ +},{"../../const":39,"./Rectangle":64}],62:[function(require,module,exports){ var Rectangle = require('./Rectangle'), CONST = require('../../const'); @@ -11079,7 +12544,7 @@ return new Rectangle(this.x - this.width, this.y - this.height, this.width, this.height); }; -},{"../../const":34,"./Rectangle":59}],58:[function(require,module,exports){ +},{"../../const":39,"./Rectangle":64}],63:[function(require,module,exports){ var Point = require('../Point'), CONST = require('../../const'); @@ -11182,7 +12647,7 @@ return inside; }; -},{"../../const":34,"../Point":54}],59:[function(require,module,exports){ +},{"../../const":39,"../Point":59}],64:[function(require,module,exports){ var CONST = require('../../const'); /** @@ -11336,7 +12801,19 @@ } }; -},{"../../const":34}],60:[function(require,module,exports){ +Rectangle.prototype.enlarge = function (rect) { + if (rect === Rectangle.EMPTY) return; + var x1 = Math.min(this.x, rect.x); + var x2 = Math.max(this.x + this.width, rect.x + rect.width); + var y1 = Math.min(this.y, rect.y); + var y2 = Math.max(this.y + this.height, rect.y + rect.height); + this.x = x1; + this.width = x2 - x1; + this.y = y1; + this.height = y2 - y1; +}; + +},{"../../const":39}],65:[function(require,module,exports){ var CONST = require('../../const'); /** @@ -11428,7 +12905,7 @@ return false; }; -},{"../../const":34}],61:[function(require,module,exports){ +},{"../../const":39}],66:[function(require,module,exports){ var utils = require('../utils'), math = require('../math'), CONST = require('../const'), @@ -11718,7 +13195,7 @@ this._lastObjectRendered = null; }; -},{"../const":34,"../display/Container":35,"../math":55,"../textures/RenderTexture":92,"../utils":99,"eventemitter3":12}],62:[function(require,module,exports){ +},{"../const":39,"../display/Container":40,"../math":60,"../textures/RenderTexture":97,"../utils":105,"eventemitter3":25}],67:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), CanvasMaskManager = require('./utils/CanvasMaskManager'), CanvasRenderTarget = require('./utils/CanvasRenderTarget'), @@ -11840,9 +13317,10 @@ if(renderTexture) { renderTexture = renderTexture.baseTexture || renderTexture; - + if(!renderTexture._canvasRenderTarget) { + renderTexture._canvasRenderTarget = new CanvasRenderTarget(renderTexture.width, renderTexture.height, renderTexture.resolution); renderTexture.source = renderTexture._canvasRenderTarget.canvas; renderTexture.valid = true; @@ -11972,7 +13450,7 @@ }; -},{"../../const":34,"../../utils":99,"../SystemRenderer":61,"./utils/CanvasMaskManager":63,"./utils/CanvasRenderTarget":64,"./utils/mapCanvasBlendModesToPixi":66}],63:[function(require,module,exports){ +},{"../../const":39,"../../utils":105,"../SystemRenderer":66,"./utils/CanvasMaskManager":68,"./utils/CanvasRenderTarget":69,"./utils/mapCanvasBlendModesToPixi":71}],68:[function(require,module,exports){ var CONST = require('../../../const'); /** * A set of functions used to handle masking. @@ -12135,7 +13613,7 @@ CanvasMaskManager.prototype.destroy = function () {}; -},{"../../../const":34}],64:[function(require,module,exports){ +},{"../../../const":39}],69:[function(require,module,exports){ var CONST = require('../../../const'); /** @@ -12239,7 +13717,7 @@ this.canvas = null; }; -},{"../../../const":34}],65:[function(require,module,exports){ +},{"../../../const":39}],70:[function(require,module,exports){ /** * Checks whether the Canvas BlendModes are supported by the current browser @@ -12278,7 +13756,7 @@ module.exports = canUseNewCanvasBlendModes; -},{}],66:[function(require,module,exports){ +},{}],71:[function(require,module,exports){ var CONST = require('../../../Const'), canUseNewCanvasBlendModes = require('./canUseNewCanvasBlendModes'); @@ -12338,7 +13816,7 @@ module.exports = mapWebGLBlendModesToPixi; -},{"../../../Const":33,"./canUseNewCanvasBlendModes":65}],67:[function(require,module,exports){ +},{"../../../Const":38,"./canUseNewCanvasBlendModes":70}],72:[function(require,module,exports){ var GLTexture = require('pixi-gl-core').GLTexture, CONST = require('../../const'), RenderTarget = require('./utils/RenderTarget'), @@ -12544,7 +14022,7 @@ module.exports = TextureManager; -},{"../../const":34,"../../utils":99,"./utils/RenderTarget":80,"pixi-gl-core":15}],68:[function(require,module,exports){ +},{"../../const":39,"../../utils":105,"./utils/RenderTarget":85,"pixi-gl-core":1}],73:[function(require,module,exports){ var SystemRenderer = require('../SystemRenderer'), MaskManager = require('./managers/MaskManager'), StencilManager = require('./managers/StencilManager'), @@ -13087,7 +14565,7 @@ // this = null; }; -},{"../../const":34,"../../utils":99,"../SystemRenderer":61,"./TextureManager":67,"./WebGLState":69,"./managers/FilterManager":74,"./managers/MaskManager":75,"./managers/StencilManager":76,"./utils/ObjectRenderer":78,"./utils/RenderTarget":80,"./utils/mapWebGLDrawModesToPixi":82,"pixi-gl-core":15}],69:[function(require,module,exports){ +},{"../../const":39,"../../utils":105,"../SystemRenderer":66,"./TextureManager":72,"./WebGLState":74,"./managers/FilterManager":79,"./managers/MaskManager":80,"./managers/StencilManager":81,"./utils/ObjectRenderer":83,"./utils/RenderTarget":85,"./utils/mapWebGLDrawModesToPixi":87,"pixi-gl-core":1}],74:[function(require,module,exports){ var mapWebGLBlendModesToPixi = require('./utils/mapWebGLBlendModesToPixi'); @@ -13357,7 +14835,7 @@ module.exports = WebGLState; -},{"./utils/mapWebGLBlendModesToPixi":81}],70:[function(require,module,exports){ +},{"./utils/mapWebGLBlendModesToPixi":86}],75:[function(require,module,exports){ var extractUniformsFromSrc = require('./extractUniformsFromSrc'); // var math = require('../../../math'); /** @@ -13485,7 +14963,7 @@ '}' ].join('\n'); -},{"./extractUniformsFromSrc":71}],71:[function(require,module,exports){ +},{"./extractUniformsFromSrc":76}],76:[function(require,module,exports){ var defaultValue = require('pixi-gl-core/lib/shader/defaultValue'); var mapSize = require('pixi-gl-core/lib/shader/mapSize'); @@ -13548,7 +15026,7 @@ module.exports = extractUniformsFromSrc; -},{"pixi-gl-core/lib/shader/defaultValue":24,"pixi-gl-core/lib/shader/mapSize":28}],72:[function(require,module,exports){ +},{"pixi-gl-core/lib/shader/defaultValue":10,"pixi-gl-core/lib/shader/mapSize":14}],77:[function(require,module,exports){ var math = require('../../../math'); /* @@ -13657,7 +15135,7 @@ calculateSpriteMatrix:calculateSpriteMatrix }; -},{"../../../math":55}],73:[function(require,module,exports){ +},{"../../../math":60}],78:[function(require,module,exports){ var Filter = require('../Filter'), math = require('../../../../math'); @@ -13676,8 +15154,8 @@ var maskMatrix = new math.Matrix(); Filter.call(this, - "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nuniform mat3 otherMatrix;\n\nvarying vec2 vMaskCoord;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n\n{\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n\n}\n\n", - "precision lowp float;\n#define GLSLIFY 1\n\nvarying vec2 vMaskCoord;\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nuniform float alpha;\n\nuniform sampler2D mask;\n\nvoid main(void)\n\n{\n\n // check clip! this will stop the mask bleeding out from the edges\r\n vec2 text = abs( vMaskCoord - 0.5 );\n\n text = step(0.5, text);\n\n float clip = 1.0 - max(text.y, text.x);\n\n vec4 original = texture2D(uSampler, vTextureCoord);\n\n vec4 masky = texture2D(mask, vMaskCoord);\n\n original *= (masky.r * masky.a * alpha * clip);\n\n gl_FragColor = original;\n\n}\n\n" + "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nuniform mat3 otherMatrix;\n\nvarying vec2 vMaskCoord;\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n}\n", + "precision lowp float;\n#define GLSLIFY 1\n\nvarying vec2 vMaskCoord;\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float alpha;\nuniform sampler2D mask;\n\nvoid main(void)\n{\n // check clip! this will stop the mask bleeding out from the edges\n vec2 text = abs( vMaskCoord - 0.5 );\n text = step(0.5, text);\n float clip = 1.0 - max(text.y, text.x);\n vec4 original = texture2D(uSampler, vTextureCoord);\n vec4 masky = texture2D(mask, vMaskCoord);\n original *= (masky.r * masky.a * alpha * clip);\n gl_FragColor = original;\n}\n" ); sprite.renderable = false; @@ -13708,7 +15186,7 @@ filterManager.applyFilter(this, input, output); }; -},{"../../../../math":55,"../Filter":70}],74:[function(require,module,exports){ +},{"../../../../math":60,"../Filter":75}],79:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'), RenderTarget = require('../utils/RenderTarget'), @@ -14052,7 +15530,7 @@ FilterManager.pool[key].push(renderTarget); }; -},{"../../../math":55,"../filters/filterTransforms":72,"../utils/Quad":79,"../utils/RenderTarget":80,"./WebGLManager":77,"bit-twiddle":3,"pixi-gl-core":15}],75:[function(require,module,exports){ +},{"../../../math":60,"../filters/filterTransforms":77,"../utils/Quad":84,"../utils/RenderTarget":85,"./WebGLManager":82,"bit-twiddle":16,"pixi-gl-core":1}],80:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'), AlphaMaskFilter = require('../filters/spriteMask/SpriteMaskFilter'); @@ -14231,7 +15709,7 @@ gl.disable(gl.SCISSOR_TEST); }; -},{"../filters/spriteMask/SpriteMaskFilter":73,"./WebGLManager":77}],76:[function(require,module,exports){ +},{"../filters/spriteMask/SpriteMaskFilter":78,"./WebGLManager":82}],81:[function(require,module,exports){ var WebGLManager = require('./WebGLManager'); /** @@ -14347,7 +15825,7 @@ this.stencilMaskStack.stencilStack = null; }; -},{"./WebGLManager":77}],77:[function(require,module,exports){ +},{"./WebGLManager":82}],82:[function(require,module,exports){ /** * @class * @memberof PIXI @@ -14388,7 +15866,7 @@ this.renderer = null; }; -},{}],78:[function(require,module,exports){ +},{}],83:[function(require,module,exports){ var WebGLManager = require('../managers/WebGLManager'); /** @@ -14446,7 +15924,7 @@ // render the object }; -},{"../managers/WebGLManager":77}],79:[function(require,module,exports){ +},{"../managers/WebGLManager":82}],84:[function(require,module,exports){ var glCore = require('pixi-gl-core'), createIndicesForQuads = require('../../../utils/createIndicesForQuads'); @@ -14618,7 +16096,7 @@ module.exports = Quad; -},{"../../../utils/createIndicesForQuads":98,"pixi-gl-core":15}],80:[function(require,module,exports){ +},{"../../../utils/createIndicesForQuads":103,"pixi-gl-core":1}],85:[function(require,module,exports){ var math = require('../../../math'), CONST = require('../../../const'), GLTexture = require('pixi-gl-core').GLTexture, @@ -14945,7 +16423,7 @@ this.texture = null; }; -},{"../../../const":34,"../../../math":55,"pixi-gl-core":15}],81:[function(require,module,exports){ +},{"../../../const":39,"../../../math":60,"pixi-gl-core":1}],86:[function(require,module,exports){ var CONST = require('../../../const'); /** @@ -14982,7 +16460,7 @@ module.exports = mapWebGLBlendModesToPixi; -},{"../../../const":34}],82:[function(require,module,exports){ +},{"../../../const":39}],87:[function(require,module,exports){ var CONST = require('../../../const'); /** @@ -15006,7 +16484,7 @@ module.exports = mapWebGLDrawModesToPixi; -},{"../../../const":34}],83:[function(require,module,exports){ +},{"../../../const":39}],88:[function(require,module,exports){ var math = require('../math'), Texture = require('../textures/Texture'), Container = require('../display/Container'), @@ -15486,7 +16964,7 @@ return new Sprite(Texture.fromImage(imageId, crossorigin, scaleMode)); }; -},{"../const":34,"../display/Container":35,"../math":55,"../textures/Texture":93,"../utils":99}],84:[function(require,module,exports){ +},{"../const":39,"../display/Container":40,"../math":60,"../textures/Texture":98,"../utils":105}],89:[function(require,module,exports){ var CanvasRenderer = require('../../renderers/canvas/CanvasRenderer'), CONST = require('../../const'), math = require('../../math'), @@ -15652,7 +17130,7 @@ this.renderer = null; }; -},{"../../const":34,"../../math":55,"../../renderers/canvas/CanvasRenderer":62,"./CanvasTinter":85}],85:[function(require,module,exports){ +},{"../../const":39,"../../math":60,"../../renderers/canvas/CanvasRenderer":67,"./CanvasTinter":90}],90:[function(require,module,exports){ var utils = require('../../utils'), canUseNewCanvasBlendModes = require('../../renderers/canvas/utils/canUseNewCanvasBlendModes'); /** @@ -15885,7 +17363,7 @@ */ CanvasTinter.tintMethod = CanvasTinter.canUseMultiply ? CanvasTinter.tintWithMultiply : CanvasTinter.tintWithPerPixel; -},{"../../renderers/canvas/utils/canUseNewCanvasBlendModes":65,"../../utils":99}],86:[function(require,module,exports){ +},{"../../renderers/canvas/utils/canUseNewCanvasBlendModes":70,"../../utils":105}],91:[function(require,module,exports){ var Buffer = function(size) @@ -15916,7 +17394,7 @@ this.uvs = null; this.colors = null; }; -},{}],87:[function(require,module,exports){ +},{}],92:[function(require,module,exports){ var ObjectRenderer = require('../../renderers/webgl/utils/ObjectRenderer'), WebGLRenderer = require('../../renderers/webgl/WebGLRenderer'), createIndicesForQuads = require('../../utils/createIndicesForQuads'), @@ -16000,7 +17478,7 @@ this.vertexBuffers = []; this.vaos = []; - this.vaoMax = 10 + this.vaoMax = 20; this.vertexCount = 0; } @@ -16270,7 +17748,7 @@ }; -},{"../../const":34,"../../renderers/webgl/WebGLRenderer":68,"../../renderers/webgl/utils/ObjectRenderer":78,"../../utils/createIndicesForQuads":98,"./BatchBuffer":86,"./generateMultiTextureShader":88,"bit-twiddle":3,"pixi-gl-core":15}],88:[function(require,module,exports){ +},{"../../const":39,"../../renderers/webgl/WebGLRenderer":73,"../../renderers/webgl/utils/ObjectRenderer":83,"../../utils/createIndicesForQuads":103,"./BatchBuffer":91,"./generateMultiTextureShader":93,"bit-twiddle":16,"pixi-gl-core":1}],93:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; var fragTemplate = [ @@ -16290,7 +17768,7 @@ function generateMultiTextureShader(gl, maxTextures) { - var vertexSrc = "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nattribute vec4 aColor;\n\nattribute float aTextureId;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvarying vec4 vColor;\n\nvarying float vTextureId;\n\nvoid main(void){\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n vTextureId = aTextureId;\n\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n\n}"; + var vertexSrc = "precision lowp float;\n#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\nattribute float aTextureId;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\nvarying float vTextureId;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vTextureId = aTextureId;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}"; var fragmentSrc = fragTemplate; fragmentSrc = fragmentSrc.replace(/\%count\%/gi, maxTextures); @@ -16344,7 +17822,7 @@ module.exports = generateMultiTextureShader; -},{"pixi-gl-core":15}],89:[function(require,module,exports){ +},{"pixi-gl-core":1}],94:[function(require,module,exports){ var Sprite = require('../sprites/Sprite'), Texture = require('../textures/Texture'), math = require('../math'), @@ -16965,7 +18443,7 @@ this._texture.destroy(destroyBaseTexture === undefined ? true : destroyBaseTexture); }; -},{"../const":34,"../math":55,"../sprites/Sprite":83,"../textures/Texture":93,"../utils":99}],90:[function(require,module,exports){ +},{"../const":39,"../math":60,"../sprites/Sprite":88,"../textures/Texture":98,"../utils":105}],95:[function(require,module,exports){ var BaseTexture = require('./BaseTexture'), math = require('../math'), CONST = require('../const'), @@ -17033,7 +18511,6 @@ * * @member {PIXI.CanvasRenderer|PIXI.WebGLRenderer} */ - this.renderer = renderer; /** * @member {boolean} @@ -17243,10 +18720,11 @@ return this.getPixels(tempRect); }; -},{"../const":34,"../math":55,"./BaseTexture":91}],91:[function(require,module,exports){ +},{"../const":39,"../math":60,"./BaseTexture":96}],96:[function(require,module,exports){ var utils = require('../utils'), CONST = require('../const'), EventEmitter = require('eventemitter3'), + determineCrossOrigin = require('../utils/determineCrossOrigin'), bitTwiddle = require('bit-twiddle'); /** @@ -17637,19 +19115,16 @@ { var baseTexture = utils.BaseTextureCache[imageUrl]; - if (crossorigin === undefined && imageUrl.indexOf('data:') !== 0) - { - crossorigin = true; - } - if (!baseTexture) { // new Image() breaks tex loading in some versions of Chrome. // See https://code.google.com/p/chromium/issues/detail?id=238071 var image = new Image();//document.createElement('img'); - if (crossorigin) + + + if (crossorigin === undefined && imageUrl.indexOf('data:') !== 0) { - image.crossOrigin = ''; + image.crossOrigin = determineCrossOrigin(imageUrl); } baseTexture = new BaseTexture(image, scaleMode); @@ -17692,7 +19167,7 @@ return baseTexture; }; -},{"../const":34,"../utils":99,"bit-twiddle":3,"eventemitter3":12}],92:[function(require,module,exports){ +},{"../const":39,"../utils":105,"../utils/determineCrossOrigin":104,"bit-twiddle":16,"eventemitter3":25}],97:[function(require,module,exports){ var BaseRenderTexture = require('./BaseRenderTexture'), Texture = require('./Texture'); @@ -17803,7 +19278,7 @@ return new RenderTexture(new BaseRenderTexture(width, height, scaleMode, resolution)); }; -},{"./BaseRenderTexture":90,"./Texture":93}],93:[function(require,module,exports){ +},{"./BaseRenderTexture":95,"./Texture":98}],98:[function(require,module,exports){ var BaseTexture = require('./BaseTexture'), VideoBaseTexture = require('./VideoBaseTexture'), TextureUvs = require('./TextureUvs'), @@ -18298,7 +19773,7 @@ */ Texture.EMPTY = new Texture(new BaseTexture()); -},{"../math":55,"../utils":99,"./BaseTexture":91,"./TextureUvs":94,"./VideoBaseTexture":95,"eventemitter3":12}],94:[function(require,module,exports){ +},{"../math":60,"../utils":105,"./BaseTexture":96,"./TextureUvs":99,"./VideoBaseTexture":100,"eventemitter3":25}],99:[function(require,module,exports){ /** * A standard object to store the Uvs of a texture @@ -18388,7 +19863,7 @@ this.uvs_uint32[3] = (((this.y3 * 65535) & 0xFFFF) << 16) | ((this.x3 * 65535) & 0xFFFF); }; -},{"../math/GroupD8":52}],95:[function(require,module,exports){ +},{"../math/GroupD8":57}],100:[function(require,module,exports){ var BaseTexture = require('./BaseTexture'), utils = require('../utils'); @@ -18625,7 +20100,7 @@ return source; } -},{"../utils":99,"./BaseTexture":91}],96:[function(require,module,exports){ +},{"../utils":105,"./BaseTexture":96}],101:[function(require,module,exports){ var CONST = require('../const'), EventEmitter = require('eventemitter3'), // Internal event used by composed emitter @@ -18980,7 +20455,7 @@ module.exports = Ticker; -},{"../const":34,"eventemitter3":12}],97:[function(require,module,exports){ +},{"../const":39,"eventemitter3":25}],102:[function(require,module,exports){ var Ticker = require('./Ticker'); /** @@ -19036,7 +20511,7 @@ Ticker: Ticker }; -},{"./Ticker":96}],98:[function(require,module,exports){ +},{"./Ticker":101}],103:[function(require,module,exports){ /** * Generic Mask Stack data structure * @class @@ -19067,7 +20542,51 @@ module.exports = createIndicesForQuads; -},{}],99:[function(require,module,exports){ +},{}],104:[function(require,module,exports){ +var tempAnchor; +var _url = require('url'); + +/** + * Sets the `crossOrigin` property for this resource based on if the url + * for this resource is cross-origin. If crossOrigin was manually set, this + * function does nothing. + * Nipped from the resource loader! + * @private + * @param url {string} The url to test. + * @param [location=window.location] {object} The location object to test against. + * @return {string} The crossOrigin value to use (or empty string for none). + */ +var determineCrossOrigin = function (url, loc) { + // data: and javascript: urls are considered same-origin + if (url.indexOf('data:') === 0) { + return ''; + } + + // default is window.location + loc = loc || window.location; + + if (!tempAnchor) { + tempAnchor = document.createElement('a'); + } + + // let the browser determine the full href for the url of this resource and then + // parse with the node url lib, we can't use the properties of the anchor element + // because they don't work in IE9 :( + tempAnchor.href = url; + url = _url.parse(tempAnchor.href); + + var samePort = (!url.port && loc.port === '') || (url.port === loc.port); + + // if cross origin + if (url.hostname !== loc.hostname || !samePort || url.protocol !== loc.protocol) { + return 'anonymous'; + } + + return ''; +}; + +module.exports = determineCrossOrigin; +},{"url":23}],105:[function(require,module,exports){ var CONST = require('../const'); /** @@ -19270,7 +20789,7 @@ BaseTextureCache: {} }; -},{"../const":34,"./pluginTarget":101,"eventemitter3":12}],100:[function(require,module,exports){ +},{"../const":39,"./pluginTarget":107,"eventemitter3":25}],106:[function(require,module,exports){ var Device = require('ismobilejs'); @@ -19291,7 +20810,7 @@ } module.exports = maxRecommendedTextures; -},{"ismobilejs":13}],101:[function(require,module,exports){ +},{"ismobilejs":26}],107:[function(require,module,exports){ /** * Mixins functionality to make an object have "plugins". * @@ -19361,7 +20880,7 @@ } }; -},{}],102:[function(require,module,exports){ +},{}],108:[function(require,module,exports){ /*global console */ var core = require('./core'), mesh = require('./mesh'), @@ -19597,6 +21116,14 @@ console.warn('generateTexture has moved to the renderer, please use renderer.generateTexture(displayObject)'); }; + +core.Graphics.prototype.generateTexture = function(scaleMode, resolution) +{ + console.warn('graphics generate texture has moved to the renderer. Or to render a graphics to a texture using canvas please use generateCanvasTexture'); + + return this.generateCanvasTexture(scaleMode, resolution) +} + core.RenderTexture.prototype.render = function() { //displayObject, matrix, clear, updateTransform @@ -19616,6 +21143,8 @@ console.warn('setTexture is now deprecated, please use the texture property, e.g : sprite.texture = texture;'); }; + + /** * @method * @name PIXI.extras.BitmapText#setText @@ -19724,7 +21253,7 @@ return core.utils.uid(); }; -},{"./core":51,"./extras":109,"./filters":121,"./mesh":136}],103:[function(require,module,exports){ +},{"./core":56,"./extras":115,"./filters":127,"./mesh":142}],109:[function(require,module,exports){ var core = require('../core'); /** @@ -20112,7 +21641,7 @@ BitmapText.fonts = {}; -},{"../core":51}],104:[function(require,module,exports){ +},{"../core":56}],110:[function(require,module,exports){ var core = require('../core'); /** @@ -20432,7 +21961,7 @@ return new MovieClip(textures); }; -},{"../core":51}],105:[function(require,module,exports){ +},{"../core":56}],111:[function(require,module,exports){ var core = require('../core'), // a sprite use dfor rendering textures.. tempPoint = new core.Point(), @@ -20864,7 +22393,7 @@ return new TilingSprite(core.Texture.fromImage(imageId, crossorigin, scaleMode),width,height); }; -},{"../core":51,"../core/sprites/canvas/CanvasTinter":85,"./webgl/TilingShader":110}],106:[function(require,module,exports){ +},{"../core":56,"../core/sprites/canvas/CanvasTinter":90,"./webgl/TilingShader":116}],112:[function(require,module,exports){ var core = require('../core'), DisplayObject = core.DisplayObject, _tempMatrix = new core.Matrix(); @@ -21140,7 +22669,7 @@ this._originalDestroy(); }; -},{"../core":51}],107:[function(require,module,exports){ +},{"../core":56}],113:[function(require,module,exports){ var core = require('../core'); /** @@ -21170,7 +22699,7 @@ return null; }; -},{"../core":51}],108:[function(require,module,exports){ +},{"../core":56}],114:[function(require,module,exports){ var core = require('../core'); /** @@ -21200,7 +22729,7 @@ return point; }; -},{"../core":51}],109:[function(require,module,exports){ +},{"../core":56}],115:[function(require,module,exports){ /** * @file Main export of the PIXI extras library * @author Mat Groves @@ -21221,7 +22750,7 @@ BitmapText: require('./BitmapText') }; -},{"./BitmapText":103,"./MovieClip":104,"./TilingSprite":105,"./cacheAsBitmap":106,"./getChildByName":107,"./getGlobalPosition":108}],110:[function(require,module,exports){ +},{"./BitmapText":109,"./MovieClip":110,"./TilingSprite":111,"./cacheAsBitmap":112,"./getChildByName":113,"./getGlobalPosition":114}],116:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; @@ -21235,8 +22764,8 @@ { Shader.call(this, gl, - "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\n\nuniform mat3 translationMatrix;\n\nuniform vec4 uFrame;\n\nuniform vec4 uTransform;\n\nvarying vec2 vTextureCoord;\n\nvarying vec4 vColor;\n\nvoid main(void)\n\n{\n\n gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n \n\n vec2 coord = aTextureCoord;\n\n coord -= uTransform.xy;\n\n coord /= uTransform.zw;\n\n vTextureCoord = coord;\n\n \n\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n\n}", - "precision lowp float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nvarying vec4 vColor;\n\nuniform sampler2D uSampler;\n\nuniform vec4 uFrame;\n\nuniform vec2 uPixelSize;\n\nvoid main(void)\n\n{\n\n vec2 coord = mod(vTextureCoord, uFrame.zw);\n\n coord = clamp(coord, uPixelSize, uFrame.zw - uPixelSize);\n\n coord += uFrame.xy;\n\n gl_FragColor = texture2D(uSampler, coord) ;\n\n}" + "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\nuniform mat3 translationMatrix;\n\nuniform vec4 uFrame;\nuniform vec4 uTransform;\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n \n vec2 coord = aTextureCoord;\n coord -= uTransform.xy;\n coord /= uTransform.zw;\n vTextureCoord = coord;\n \n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}", + "precision lowp float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform sampler2D uSampler;\nuniform vec4 uFrame;\nuniform vec2 uPixelSize;\n\nvoid main(void)\n{\n\n vec2 coord = mod(vTextureCoord, uFrame.zw);\n coord = clamp(coord, uPixelSize, uFrame.zw - uPixelSize);\n coord += uFrame.xy;\n\n gl_FragColor = texture2D(uSampler, coord) ;\n}" ); } @@ -21245,7 +22774,7 @@ module.exports = TilingShader; -},{"pixi-gl-core":15}],111:[function(require,module,exports){ +},{"pixi-gl-core":1}],117:[function(require,module,exports){ var core = require('../../core'), BlurXFilter = require('./BlurXFilter'), BlurYFilter = require('./BlurYFilter'); @@ -21361,7 +22890,7 @@ } }); -},{"../../core":51,"./BlurXFilter":112,"./BlurYFilter":113}],112:[function(require,module,exports){ +},{"../../core":56,"./BlurXFilter":118,"./BlurYFilter":119}],118:[function(require,module,exports){ var core = require('../../core'); var generateBlurVertSource = require('./generateBlurVertSource'); var generateBlurFragSource = require('./generateBlurFragSource'); @@ -21469,7 +22998,7 @@ } }); -},{"../../core":51,"./generateBlurFragSource":114,"./generateBlurVertSource":115,"./getMaxBlurKernelSize":116}],113:[function(require,module,exports){ +},{"../../core":56,"./generateBlurFragSource":120,"./generateBlurVertSource":121,"./getMaxBlurKernelSize":122}],119:[function(require,module,exports){ var core = require('../../core'); var generateBlurVertSource = require('./generateBlurVertSource'); var generateBlurFragSource = require('./generateBlurFragSource'); @@ -21567,7 +23096,7 @@ } }); -},{"../../core":51,"./generateBlurFragSource":114,"./generateBlurVertSource":115,"./getMaxBlurKernelSize":116}],114:[function(require,module,exports){ +},{"../../core":56,"./generateBlurFragSource":120,"./generateBlurVertSource":121,"./getMaxBlurKernelSize":122}],120:[function(require,module,exports){ var GAUSSIAN_VALUES = { 5:[0.153388, 0.221461, 0.250301], 7:[0.071303, 0.131514, 0.189879, 0.214607], @@ -21632,7 +23161,7 @@ module.exports = generateFragBlurSource; -},{}],115:[function(require,module,exports){ +},{}],121:[function(require,module,exports){ var vertTemplate = [ 'attribute vec2 aVertexPosition;', @@ -21698,7 +23227,7 @@ module.exports = generateVertBlurSource; -},{}],116:[function(require,module,exports){ +},{}],122:[function(require,module,exports){ var getMaxKernelSize = function(gl) @@ -21716,7 +23245,7 @@ module.exports = getMaxKernelSize; -},{}],117:[function(require,module,exports){ +},{}],123:[function(require,module,exports){ var core = require('../../core'); // @see https://github.com/substack/brfs/issues/25 @@ -21740,9 +23269,9 @@ { core.Filter.call(this, // vertex shader - "precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n}", + "precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nuniform float m[20];\n\nvoid main(void)\n\n{\n\n vec4 c = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.r = (m[0] * c.r);\n\n gl_FragColor.r += (m[1] * c.g);\n\n gl_FragColor.r += (m[2] * c.b);\n\n gl_FragColor.r += (m[3] * c.a);\n\n gl_FragColor.r += m[4];\n\n gl_FragColor.g = (m[5] * c.r);\n\n gl_FragColor.g += (m[6] * c.g);\n\n gl_FragColor.g += (m[7] * c.b);\n\n gl_FragColor.g += (m[8] * c.a);\n\n gl_FragColor.g += m[9];\n\n gl_FragColor.b = (m[10] * c.r);\n\n gl_FragColor.b += (m[11] * c.g);\n\n gl_FragColor.b += (m[12] * c.b);\n\n gl_FragColor.b += (m[13] * c.a);\n\n gl_FragColor.b += m[14];\n\n gl_FragColor.a = (m[15] * c.r);\n\n gl_FragColor.a += (m[16] * c.g);\n\n gl_FragColor.a += (m[17] * c.b);\n\n gl_FragColor.a += (m[18] * c.a);\n\n gl_FragColor.a += m[19];\n\n// gl_FragColor = vec4(m[0]);\r\n}\n\n" + "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\nuniform sampler2D uSampler;\nuniform float m[20];\n\nvoid main(void)\n{\n\n vec4 c = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.r = (m[0] * c.r);\n gl_FragColor.r += (m[1] * c.g);\n gl_FragColor.r += (m[2] * c.b);\n gl_FragColor.r += (m[3] * c.a);\n gl_FragColor.r += m[4];\n\n gl_FragColor.g = (m[5] * c.r);\n gl_FragColor.g += (m[6] * c.g);\n gl_FragColor.g += (m[7] * c.b);\n gl_FragColor.g += (m[8] * c.a);\n gl_FragColor.g += m[9];\n\n gl_FragColor.b = (m[10] * c.r);\n gl_FragColor.b += (m[11] * c.g);\n gl_FragColor.b += (m[12] * c.b);\n gl_FragColor.b += (m[13] * c.a);\n gl_FragColor.b += m[14];\n\n gl_FragColor.a = (m[15] * c.r);\n gl_FragColor.a += (m[16] * c.g);\n gl_FragColor.a += (m[17] * c.b);\n gl_FragColor.a += (m[18] * c.a);\n gl_FragColor.a += m[19];\n\n// gl_FragColor = vec4(m[0]);\n}\n" ); this.uniforms.m = [ @@ -22250,7 +23779,7 @@ } }); -},{"../../core":51}],118:[function(require,module,exports){ +},{"../../core":56}],124:[function(require,module,exports){ var core = require('../../core'); @@ -22271,9 +23800,9 @@ core.Filter.call(this, // vertex shader - "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\n\nuniform mat3 otherMatrix;\n\nvarying vec2 vMapCoord;\n\nvarying vec2 vTextureCoord;\n\nvarying vec4 vColor;\n\nvoid main(void)\n\n{\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n vMapCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n\n}\n\n", + "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\nattribute vec4 aColor;\n\nuniform mat3 projectionMatrix;\nuniform mat3 otherMatrix;\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n vMapCoord = ( otherMatrix * vec3( aTextureCoord, 1.0) ).xy;\n vColor = vec4(aColor.rgb * aColor.a, aColor.a);\n}\n", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vMapCoord;\n\nvarying vec2 vTextureCoord;\n\nvarying vec4 vColor;\n\nuniform vec2 scale;\n\nuniform sampler2D uSampler;\n\nuniform sampler2D mapSampler;\n\nvoid main(void)\n\n{\n\n vec4 map = texture2D(mapSampler, vMapCoord);\n\n map -= 0.5;\n\n map.xy *= scale;\n\n gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y));\n\n}\n\n" + "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vMapCoord;\nvarying vec2 vTextureCoord;\nvarying vec4 vColor;\n\nuniform vec2 scale;\n\nuniform sampler2D uSampler;\nuniform sampler2D mapSampler;\n\nvoid main(void)\n{\n vec4 map = texture2D(mapSampler, vMapCoord);\n\n map -= 0.5;\n map.xy *= scale;\n\n gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.x + map.x, vTextureCoord.y + map.y));\n}\n" ); @@ -22301,8 +23830,10 @@ var ratio = (1/output.destinationFrame.width) * (output.size.width/input.size.width); /// // * 2 //4//this.strength / 4 / this.passes * (input.frame.width / input.size.width); this.uniforms.otherMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, this.maskSprite); - this.uniforms.scale.x = this.scale.x * ratio; - this.uniforms.scale.y = this.scale.y * ratio; + this.uniforms.scale.x = 0.01//this.scale.x * ratio; + this.uniforms.scale.y = 0.01//this.scale.y * ratio; + + // console.log( this.scale) // draw the filter... filterManager.applyFilter(this, input, output); @@ -22329,7 +23860,7 @@ } }); -},{"../../core":51}],119:[function(require,module,exports){ +},{"../../core":56}],125:[function(require,module,exports){ var core = require('../../core'); @@ -22345,9 +23876,9 @@ core.Filter.call(this, // vertex shader - "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n\n{\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n}\n\n", + "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}\n\n", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform float exposure;\n\nuniform float decay;\n\nuniform float density;\n\nuniform float weight;\n\nuniform vec2 lightPositionOnScreen;\n\nuniform sampler2D uSampler;\n\nconst int NUM_SAMPLES = 100;\n\nvoid main()\n\n{\n\n vec2 deltaTextCoord = vec2( vTextureCoord - lightPositionOnScreen.xy );\n\n vec2 textCoo = vTextureCoord;\n\n deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * density;\n\n float illuminationDecay = 1.0;\n\n \n\n for(int i=0; i < NUM_SAMPLES ; i++)\n\n {\n\n textCoo -= deltaTextCoord;\n\n vec4 sample = texture2D(uSampler, textCoo );\n\n sample *= illuminationDecay * weight;\n\n gl_FragColor += sample;\n\n illuminationDecay *= decay;\n\n }\n\n \n\n gl_FragColor *= exposure;\n\n}" + "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\nuniform float exposure;\nuniform float decay;\nuniform float density;\nuniform float weight;\nuniform vec2 lightPositionOnScreen;\nuniform sampler2D uSampler;\n\nconst int NUM_SAMPLES = 100;\n\nvoid main()\n{\n vec2 deltaTextCoord = vec2( vTextureCoord - lightPositionOnScreen.xy );\n vec2 textCoo = vTextureCoord;\n deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * density;\n float illuminationDecay = 1.0;\n \n for(int i=0; i < NUM_SAMPLES ; i++)\n {\n textCoo -= deltaTextCoord;\n vec4 sample = texture2D(uSampler, textCoo );\n\n sample *= illuminationDecay * weight;\n\n gl_FragColor += sample;\n\n illuminationDecay *= decay;\n }\n \n gl_FragColor *= exposure;\n}" ); this.uniforms.exposure = 0.0034; @@ -22422,7 +23953,7 @@ } }); -},{"../../core":51}],120:[function(require,module,exports){ +},{"../../core":56}],126:[function(require,module,exports){ var core = require('../../core'); // @see https://github.com/substack/brfs/issues/25 @@ -22438,9 +23969,9 @@ { core.Filter.call(this, // vertex shader - "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n}", + "precision lowp float;\n#define GLSLIFY 1\n\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void){\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nuniform float gray;\n\nvoid main(void)\n\n{\n\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n\n gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);\n\n}\n\n" + "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float gray;\n\nvoid main(void)\n{\n gl_FragColor = texture2D(uSampler, vTextureCoord);\n gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.2126*gl_FragColor.r + 0.7152*gl_FragColor.g + 0.0722*gl_FragColor.b), gray);\n}\n" ); this.uniforms.gray = 1; @@ -22471,7 +24002,7 @@ } }); -},{"../../core":51}],121:[function(require,module,exports){ +},{"../../core":56}],127:[function(require,module,exports){ /** * @file Main export of the PIXI filters library * @author Mat Groves @@ -22512,7 +24043,7 @@ GodrayFilter: require('./godray/GodrayFilter') }; -},{"./blur/BlurFilter":111,"./blur/BlurXFilter":112,"./blur/BlurYFilter":113,"./colormatrix/ColorMatrixFilter":117,"./displacement/DisplacementFilter":118,"./godray/GodrayFilter":119,"./gray/GrayFilter":120,"./twist/TwistFilter":122}],122:[function(require,module,exports){ +},{"./blur/BlurFilter":117,"./blur/BlurXFilter":118,"./blur/BlurYFilter":119,"./colormatrix/ColorMatrixFilter":123,"./displacement/DisplacementFilter":124,"./godray/GodrayFilter":125,"./gray/GrayFilter":126,"./twist/TwistFilter":128}],128:[function(require,module,exports){ var core = require('../../core'); @@ -22528,9 +24059,9 @@ core.Filter.call(this, // vertex shader - "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\n\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\n\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n\n{\n\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n\n vTextureCoord = aTextureCoord;\n\n}\n\n", + "#define GLSLIFY 1\nattribute vec2 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nuniform mat3 projectionMatrix;\nvarying vec2 vTextureCoord;\n\nvoid main(void)\n{\n gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);\n vTextureCoord = aTextureCoord;\n}\n\n", // fragment shader - "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\n\nuniform float radius;\n\nuniform float angle;\n\nuniform vec2 offset;\n\nuniform vec4 filterArea;\n\nvec2 mapCoord( vec2 coord )\n\n{\n\n coord *= filterArea.xy;\n\n coord += filterArea.zw;\n\n return coord;\n\n}\n\nvec2 unmapCoord( vec2 coord )\n\n{\n\n coord -= filterArea.zw;\n\n coord /= filterArea.xy;\n\n return coord;\n\n}\n\nvec2 twist(vec2 coord)\n\n{\n\n coord -= offset;\n\n float dist = length(coord);\n\n if (dist < radius)\n\n {\n\n float ratioDist = (radius - dist) / radius;\n\n float angleMod = ratioDist * ratioDist * angle;\n\n float s = sin(angleMod);\n\n float c = cos(angleMod);\n\n coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);\n\n }\n\n coord += offset;\n\n return coord;\n\n}\n\nvoid main(void)\n\n{\n\n vec2 coord = mapCoord(vTextureCoord);\n\n coord = twist(coord);\n\n coord = unmapCoord(coord);\n\n gl_FragColor = texture2D(uSampler, coord );\n\n}\n\n" + "precision mediump float;\n#define GLSLIFY 1\n\nvarying vec2 vTextureCoord;\n\nuniform sampler2D uSampler;\nuniform float radius;\nuniform float angle;\nuniform vec2 offset;\nuniform vec4 filterArea;\n\nvec2 mapCoord( vec2 coord )\n{\n coord *= filterArea.xy;\n coord += filterArea.zw;\n\n return coord;\n}\n\nvec2 unmapCoord( vec2 coord )\n{\n coord -= filterArea.zw;\n coord /= filterArea.xy;\n\n return coord;\n}\n\nvec2 twist(vec2 coord)\n{\n coord -= offset;\n\n float dist = length(coord);\n\n if (dist < radius)\n {\n float ratioDist = (radius - dist) / radius;\n float angleMod = ratioDist * ratioDist * angle;\n float s = sin(angleMod);\n float c = cos(angleMod);\n coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);\n }\n\n coord += offset;\n\n return coord;\n}\n\nvoid main(void)\n{\n\n vec2 coord = mapCoord(vTextureCoord);\n\n coord = twist(coord);\n\n coord = unmapCoord(coord);\n\n gl_FragColor = texture2D(uSampler, coord );\n\n}\n" ); this.uniforms.radius = 400; @@ -22610,7 +24141,7 @@ } }); -},{"../../core":51}],123:[function(require,module,exports){ +},{"../../core":56}],129:[function(require,module,exports){ (function (global){ // run the polyfills require('./polyfill'); @@ -22643,7 +24174,7 @@ global.PIXI = core; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./accessibility":32,"./core":51,"./deprecation":102,"./extras":109,"./filters":121,"./interaction":126,"./loaders":129,"./mesh":136,"./particles":139,"./polyfill":145}],124:[function(require,module,exports){ +},{"./accessibility":37,"./core":56,"./deprecation":108,"./extras":115,"./filters":127,"./interaction":132,"./loaders":135,"./mesh":142,"./particles":145,"./polyfill":151}],130:[function(require,module,exports){ var core = require('../core'); /** @@ -22692,7 +24223,7 @@ return displayObject.worldTransform.applyInverse(globalPos || this.global, point); }; -},{"../core":51}],125:[function(require,module,exports){ +},{"../core":56}],131:[function(require,module,exports){ var core = require('../core'), InteractionData = require('./InteractionData'); @@ -23612,7 +25143,7 @@ core.WebGLRenderer.registerPlugin('interaction', InteractionManager); core.CanvasRenderer.registerPlugin('interaction', InteractionManager); -},{"../core":51,"./InteractionData":124,"./interactiveTarget":127}],126:[function(require,module,exports){ +},{"../core":56,"./InteractionData":130,"./interactiveTarget":133}],132:[function(require,module,exports){ /** * @file Main export of the PIXI interactions library * @author Mat Groves @@ -23629,7 +25160,7 @@ interactiveTarget: require('./interactiveTarget') }; -},{"./InteractionData":124,"./InteractionManager":125,"./interactiveTarget":127}],127:[function(require,module,exports){ +},{"./InteractionData":130,"./InteractionManager":131,"./interactiveTarget":133}],133:[function(require,module,exports){ /** * Default property values of interactive objects * used by {@link PIXI.interaction.InteractionManager}. @@ -23678,7 +25209,7 @@ module.exports = interactiveTarget; -},{}],128:[function(require,module,exports){ +},{}],134:[function(require,module,exports){ var Resource = require('resource-loader').Resource, core = require('../core'), extras = require('../extras'), @@ -23802,7 +25333,7 @@ }; }; -},{"../core":51,"../extras":109,"path":4,"resource-loader":150}],129:[function(require,module,exports){ +},{"../core":56,"../extras":115,"path":17,"resource-loader":32}],135:[function(require,module,exports){ /** * @file Main export of the PIXI loaders library * @author Mat Groves @@ -23823,7 +25354,7 @@ Resource: require('resource-loader').Resource }; -},{"./bitmapFontParser":128,"./loader":130,"./spritesheetParser":131,"./textureParser":132,"resource-loader":150}],130:[function(require,module,exports){ +},{"./bitmapFontParser":134,"./loader":136,"./spritesheetParser":137,"./textureParser":138,"resource-loader":32}],136:[function(require,module,exports){ var ResourceLoader = require('resource-loader'), textureParser = require('./textureParser'), spritesheetParser = require('./spritesheetParser'), @@ -23885,7 +25416,7 @@ Resource.setExtensionXhrType('fnt', Resource.XHR_RESPONSE_TYPE.DOCUMENT); -},{"./bitmapFontParser":128,"./spritesheetParser":131,"./textureParser":132,"resource-loader":150}],131:[function(require,module,exports){ +},{"./bitmapFontParser":134,"./spritesheetParser":137,"./textureParser":138,"resource-loader":32}],137:[function(require,module,exports){ var Resource = require('resource-loader').Resource, path = require('path'), core = require('../core'); @@ -23957,7 +25488,7 @@ }; }; -},{"../core":51,"path":4,"resource-loader":150}],132:[function(require,module,exports){ +},{"../core":56,"path":17,"resource-loader":32}],138:[function(require,module,exports){ var core = require('../core'); module.exports = function () @@ -23979,7 +25510,7 @@ }; }; -},{"../core":51}],133:[function(require,module,exports){ +},{"../core":56}],139:[function(require,module,exports){ var core = require('../core'), glCore = require('pixi-gl-core'), Shader = require('./webgl/MeshShader'), @@ -24504,7 +26035,7 @@ TRIANGLES: 1 }; -},{"../core":51,"./webgl/MeshShader":137,"pixi-gl-core":15}],134:[function(require,module,exports){ +},{"../core":56,"./webgl/MeshShader":143,"pixi-gl-core":1}],140:[function(require,module,exports){ var Mesh = require('./Mesh'); /** @@ -24630,7 +26161,7 @@ } }; -},{"./Mesh":133}],135:[function(require,module,exports){ +},{"./Mesh":139}],141:[function(require,module,exports){ var Mesh = require('./Mesh'); var core = require('../core'); @@ -24843,7 +26374,7 @@ this.containerUpdateTransform(); }; -},{"../core":51,"./Mesh":133}],136:[function(require,module,exports){ +},{"../core":56,"./Mesh":139}],142:[function(require,module,exports){ /** * @file Main export of the PIXI extras library * @author Mat Groves @@ -24861,7 +26392,7 @@ MeshShader: require('./webgl/MeshShader') }; -},{"./Mesh":133,"./Plane":134,"./Rope":135,"./webgl/MeshShader":137}],137:[function(require,module,exports){ +},{"./Mesh":139,"./Plane":140,"./Rope":141,"./webgl/MeshShader":143}],143:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; /** @@ -24911,7 +26442,7 @@ module.exports = MeshShader; -},{"pixi-gl-core":15}],138:[function(require,module,exports){ +},{"pixi-gl-core":1}],144:[function(require,module,exports){ var core = require('../core'); /** @@ -25244,7 +26775,7 @@ this._buffers = null; }; -},{"../core":51}],139:[function(require,module,exports){ +},{"../core":56}],145:[function(require,module,exports){ /** * @file Main export of the PIXI extras library * @author Mat Groves @@ -25260,7 +26791,7 @@ ParticleRenderer: require('./webgl/ParticleRenderer') }; -},{"./ParticleContainer":138,"./webgl/ParticleRenderer":141}],140:[function(require,module,exports){ +},{"./ParticleContainer":144,"./webgl/ParticleRenderer":147}],146:[function(require,module,exports){ var glCore = require('pixi-gl-core'), createIndicesForQuads = require('../../core/utils/createIndicesForQuads'); @@ -25481,7 +27012,7 @@ this.staticBuffer.destroy(); }; -},{"../../core/utils/createIndicesForQuads":98,"pixi-gl-core":15}],141:[function(require,module,exports){ +},{"../../core/utils/createIndicesForQuads":103,"pixi-gl-core":1}],147:[function(require,module,exports){ var core = require('../../core'), ParticleShader = require('./ParticleShader'), ParticleBuffer = require('./ParticleBuffer'); @@ -25912,7 +27443,7 @@ this.tempMatrix = null; }; -},{"../../core":51,"./ParticleBuffer":140,"./ParticleShader":142}],142:[function(require,module,exports){ +},{"../../core":56,"./ParticleBuffer":146,"./ParticleShader":148}],148:[function(require,module,exports){ var Shader = require('pixi-gl-core').GLShader; /** @@ -25980,7 +27511,7 @@ module.exports = ParticleShader; -},{"pixi-gl-core":15}],143:[function(require,module,exports){ +},{"pixi-gl-core":1}],149:[function(require,module,exports){ // References: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign @@ -25996,7 +27527,7 @@ }; } -},{}],144:[function(require,module,exports){ +},{}],150:[function(require,module,exports){ // References: // https://github.com/sindresorhus/object-assign // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign @@ -26006,7 +27537,7 @@ Object.assign = require('object-assign'); } -},{"object-assign":14}],145:[function(require,module,exports){ +},{"object-assign":27}],151:[function(require,module,exports){ require('./Object.assign'); require('./requestAnimationFrame'); require('./Math.sign'); @@ -26024,7 +27555,7 @@ window.Uint16Array = Array; } -},{"./Math.sign":143,"./Object.assign":144,"./requestAnimationFrame":146}],146:[function(require,module,exports){ +},{"./Math.sign":149,"./Object.assign":150,"./requestAnimationFrame":152}],152:[function(require,module,exports){ (function (global){ // References: // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ @@ -26094,1436 +27625,6 @@ } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],147:[function(require,module,exports){ -var async = require('async'), - urlParser = require('url'), - Resource = require('./Resource'), - EventEmitter = require('eventemitter3'); - -/** - * Manages the state and loading of multiple resources to load. - * - * @class - * @param [baseUrl=''] {string} The base url for all resources loaded by this loader. - * @param [concurrency=10] {number} The number of resources to load concurrently. - */ -function Loader(baseUrl, concurrency) { - EventEmitter.call(this); - - concurrency = concurrency || 10; - - /** - * The base url for all resources loaded by this loader. - * - * @member {string} - */ - this.baseUrl = baseUrl || ''; - - /** - * The progress percent of the loader going through the queue. - * - * @member {number} - */ - this.progress = 0; - - /** - * Loading state of the loader, true if it is currently loading resources. - * - * @member {boolean} - */ - this.loading = false; - - /** - * The percentage of total progress that a single resource represents. - * - * @member {number} - */ - this._progressChunk = 0; - - /** - * The middleware to run before loading each resource. - * - * @member {function[]} - */ - this._beforeMiddleware = []; - - /** - * The middleware to run after loading each resource. - * - * @member {function[]} - */ - this._afterMiddleware = []; - - /** - * The `_loadResource` function bound with this object context. - * - * @private - * @member {function} - */ - this._boundLoadResource = this._loadResource.bind(this); - - /** - * The `_onLoad` function bound with this object context. - * - * @private - * @member {function} - */ - this._boundOnLoad = this._onLoad.bind(this); - - /** - * The resource buffer that fills until `load` is called to start loading resources. - * - * @private - * @member {Resource[]} - */ - this._buffer = []; - - /** - * Used to track load completion. - * - * @private - * @member {number} - */ - this._numToLoad = 0; - - /** - * The resources waiting to be loaded. - * - * @private - * @member {Resource[]} - */ - this._queue = async.queue(this._boundLoadResource, concurrency); - - /** - * All the resources for this loader keyed by name. - * - * @member {object} - */ - this.resources = {}; - - /** - * Emitted once per loaded or errored resource. - * - * @event progress - * @memberof Loader# - */ - - /** - * Emitted once per errored resource. - * - * @event error - * @memberof Loader# - */ - - /** - * Emitted once per loaded resource. - * - * @event load - * @memberof Loader# - */ - - /** - * Emitted when the loader begins to process the queue. - * - * @event start - * @memberof Loader# - */ - - /** - * Emitted when the queued resources all load. - * - * @event complete - * @memberof Loader# - */ -} - -Loader.prototype = Object.create(EventEmitter.prototype); -Loader.prototype.constructor = Loader; -module.exports = Loader; - -/** - * Adds a resource (or multiple resources) to the loader queue. - * - * This function can take a wide variety of different parameters. The only thing that is always - * required the url to load. All the following will work: - * - * ```js - * loader - * // normal param syntax - * .add('key', 'http://...', function () {}) - * .add('http://...', function () {}) - * .add('http://...') - * - * // object syntax - * .add({ - * name: 'key2', - * url: 'http://...' - * }, function () {}) - * .add({ - * url: 'http://...' - * }, function () {}) - * .add({ - * name: 'key3', - * url: 'http://...' - * onComplete: function () {} - * }) - * .add({ - * url: 'https://...', - * onComplete: function () {}, - * crossOrigin: true - * }) - * - * // you can also pass an array of objects or urls or both - * .add([ - * { name: 'key4', url: 'http://...', onComplete: function () {} }, - * { url: 'http://...', onComplete: function () {} }, - * 'http://...' - * ]); - * ``` - * - * @alias enqueue - * @param [name] {string} The name of the resource to load, if not passed the url is used. - * @param url {string} The url for this resource, relative to the baseUrl of this loader. - * @param [options] {object} The options for the load. - * @param [options.crossOrigin] {boolean} Is this request cross-origin? Default is to determine automatically. - * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.XHR_LOAD_TYPE} How should this resource be loaded? - * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being - * loaded be interpreted when using XHR? - * @param [callback] {function} Function to call when this specific resource completes loading. - * @return {Loader} - */ -Loader.prototype.add = Loader.prototype.enqueue = function (name, url, options, cb) { - // special case of an array of objects or urls - if (Array.isArray(name)) { - for (var i = 0; i < name.length; ++i) { - this.add(name[i]); - } - - return this; - } - - // if an object is passed instead of params - if (typeof name === 'object') { - cb = url || name.callback || name.onComplete; - options = name; - url = name.url; - name = name.name || name.key || name.url; - } - - // case where no name is passed shift all args over by one. - if (typeof url !== 'string') { - cb = options; - options = url; - url = name; - } - - // now that we shifted make sure we have a proper url. - if (typeof url !== 'string') { - throw new Error('No url passed to add resource to loader.'); - } - - // options are optional so people might pass a function and no options - if (typeof options === 'function') { - cb = options; - options = null; - } - - // check if resource already exists. - if (this.resources[name]) { - throw new Error('Resource with name "' + name + '" already exists.'); - } - - // add base url if this isn't an absolute url - url = this._handleBaseUrl(url); - - // create the store the resource - this.resources[name] = new Resource(name, url, options); - - if (typeof cb === 'function') { - this.resources[name].once('afterMiddleware', cb); - } - - this._numToLoad++; - - // if already loading add it to the worker queue - if (this._queue.started) { - this._queue.push(this.resources[name]); - this._progressChunk = (100 - this.progress) / (this._queue.length() + this._queue.running()); - } - // otherwise buffer it to be added to the queue later - else { - this._buffer.push(this.resources[name]); - this._progressChunk = 100 / this._buffer.length; - } - - return this; -}; - -Loader.prototype._handleBaseUrl = function (url) { - var parsedUrl = urlParser.parse(url); - - // absolute url, just use it as is. - if (parsedUrl.protocol || parsedUrl.pathname.indexOf('//') === 0) { - return url; - } - - // if baseUrl doesn't end in slash and url doesn't start with slash, then add a slash inbetween - if ( - this.baseUrl.length && - this.baseUrl.lastIndexOf('/') !== this.baseUrl.length - 1 && - url.charAt(0) !== '/' - ) { - return this.baseUrl + '/' + url; - } - else { - return this.baseUrl + url; - } -}; - - -/** - * Sets up a middleware function that will run *before* the - * resource is loaded. - * - * @alias pre - * @param middleware {function} The middleware function to register. - * @return {Loader} - */ -Loader.prototype.before = Loader.prototype.pre = function (fn) { - this._beforeMiddleware.push(fn); - - return this; -}; - -/** - * Sets up a middleware function that will run *after* the - * resource is loaded. - * - * @alias use - * @param middleware {function} The middleware function to register. - * @return {Loader} - */ -Loader.prototype.after = Loader.prototype.use = function (fn) { - this._afterMiddleware.push(fn); - - return this; -}; - -/** - * Resets the queue of the loader to prepare for a new load. - * - * @return {Loader} - */ -Loader.prototype.reset = function () { - // this.baseUrl = baseUrl || ''; - - this.progress = 0; - - this.loading = false; - - this._progressChunk = 0; - - // this._beforeMiddleware.length = 0; - // this._afterMiddleware.length = 0; - - this._buffer.length = 0; - - this._numToLoad = 0; - - this._queue.kill(); - this._queue.started = false; - - this.resources = {}; -}; - -/** - * Starts loading the queued resources. - * - * @fires start - * @param [callback] {function} Optional callback that will be bound to the `complete` event. - * @return {Loader} - */ -Loader.prototype.load = function (cb) { - // register complete callback if they pass one - if (typeof cb === 'function') { - this.once('complete', cb); - } - - // if the queue has already started we are done here - if (this._queue.started) { - return this; - } - - // notify of start - this.emit('start', this); - - // start the internal queue - for (var i = 0; i < this._buffer.length; ++i) { - this._queue.push(this._buffer[i]); - } - - // empty the buffer - this._buffer.length = 0; - - return this; -}; - -/** - * Loads a single resource. - * - * @fires progress - * @private - */ -Loader.prototype._loadResource = function (resource, dequeue) { - var self = this; - - resource._dequeue = dequeue; - - this._runMiddleware(resource, this._beforeMiddleware, function () { - // resource.on('progress', self.emit.bind(self, 'progress')); - - resource.load(self._boundOnLoad); - }); -}; - -/** - * Called once each resource has loaded. - * - * @fires complete - * @private - */ -Loader.prototype._onComplete = function () { - this.emit('complete', this, this.resources); -}; - -/** - * Called each time a resources is loaded. - * - * @fires progress - * @fires error - * @fires load - * @private - */ -Loader.prototype._onLoad = function (resource) { - this.progress += this._progressChunk; - - this.emit('progress', this, resource); - - // run middleware, this *must* happen before dequeue so sub-assets get added properly - this._runMiddleware(resource, this._afterMiddleware, function () { - resource.emit('afterMiddleware', resource); - - this._numToLoad--; - - // do completion check - if (this._numToLoad === 0) { - this.progress = 100; - this._onComplete(); - } - - if (resource.error) { - this.emit('error', resource.error, this, resource); - } - else { - this.emit('load', this, resource); - } - }); - - - - // remove this resource from the async queue - resource._dequeue(); -}; - -/** - * Run middleware functions on a resource. - * - * @private - */ -Loader.prototype._runMiddleware = function (resource, fns, cb) { - var self = this; - - async.eachSeries(fns, function (fn, next) { - fn.call(self, resource, next); - }, cb.bind(this, resource)); -}; - -Loader.LOAD_TYPE = Resource.LOAD_TYPE; -Loader.XHR_READY_STATE = Resource.XHR_READY_STATE; -Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE; - -},{"./Resource":148,"async":1,"eventemitter3":2,"url":10}],148:[function(require,module,exports){ -var EventEmitter = require('eventemitter3'), - _url = require('url'), - // tests is CORS is supported in XHR, if not we need to use XDR - useXdr = !!(window.XDomainRequest && !('withCredentials' in (new XMLHttpRequest()))), - tempAnchor = null; - -/** - * Manages the state and loading of a single resource represented by - * a single URL. - * - * @class - * @param name {string} The name of the resource to load. - * @param url {string|string[]} The url for this resource, for audio/video loads you can pass an array of sources. - * @param [options] {object} The options for the load. - * @param [options.crossOrigin] {string|boolean} Is this request cross-origin? Default is to determine automatically. - * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.LOAD_TYPE} How should this resource be loaded? - * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being - * loaded be interpreted when using XHR? - * @param [options.metadata] {object} Extra info for middleware. - */ -function Resource(name, url, options) { - EventEmitter.call(this); - - options = options || {}; - - if (typeof name !== 'string' || typeof url !== 'string') { - throw new Error('Both name and url are required for constructing a resource.'); - } - - /** - * The name of this resource. - * - * @member {string} - * @readonly - */ - this.name = name; - - /** - * The url used to load this resource. - * - * @member {string} - * @readonly - */ - this.url = url; - - /** - * Stores whether or not this url is a data url. - * - * @member {boolean} - * @readonly - */ - this.isDataUrl = this.url.indexOf('data:') === 0; - - /** - * The data that was loaded by the resource. - * - * @member {any} - */ - this.data = null; - - /** - * Is this request cross-origin? If unset, determined automatically. - * - * @member {string} - */ - this.crossOrigin = options.crossOrigin === true ? 'anonymous' : options.crossOrigin; - - /** - * The method of loading to use for this resource. - * - * @member {Resource.LOAD_TYPE} - */ - this.loadType = options.loadType || this._determineLoadType(); - - /** - * The type used to load the resource via XHR. If unset, determined automatically. - * - * @member {string} - */ - this.xhrType = options.xhrType; - - /** - * Extra info for middleware - * - * @member {object} - */ - this.metadata = options.metadata || {}; - - /** - * The error that occurred while loading (if any). - * - * @member {Error} - * @readonly - */ - this.error = null; - - /** - * The XHR object that was used to load this resource. This is only set - * when `loadType` is `Resource.LOAD_TYPE.XHR`. - * - * @member {XMLHttpRequest} - */ - this.xhr = null; - - /** - * Describes if this resource was loaded as json. Only valid after the resource - * has completely loaded. - * - * @member {boolean} - */ - this.isJson = false; - - /** - * Describes if this resource was loaded as xml. Only valid after the resource - * has completely loaded. - * - * @member {boolean} - */ - this.isXml = false; - - /** - * Describes if this resource was loaded as an image tag. Only valid after the resource - * has completely loaded. - * - * @member {boolean} - */ - this.isImage = false; - - /** - * Describes if this resource was loaded as an audio tag. Only valid after the resource - * has completely loaded. - * - * @member {boolean} - */ - this.isAudio = false; - - /** - * Describes if this resource was loaded as a video tag. Only valid after the resource - * has completely loaded. - * - * @member {boolean} - */ - this.isVideo = false; - - /** - * The `dequeue` method that will be used a storage place for the async queue dequeue method - * used privately by the loader. - * - * @member {function} - * @private - */ - this._dequeue = null; - - /** - * The `complete` function bound to this resource's context. - * - * @member {function} - * @private - */ - this._boundComplete = this.complete.bind(this); - - /** - * The `_onError` function bound to this resource's context. - * - * @member {function} - * @private - */ - this._boundOnError = this._onError.bind(this); - - /** - * The `_onProgress` function bound to this resource's context. - * - * @member {function} - * @private - */ - this._boundOnProgress = this._onProgress.bind(this); - - // xhr callbacks - this._boundXhrOnError = this._xhrOnError.bind(this); - this._boundXhrOnAbort = this._xhrOnAbort.bind(this); - this._boundXhrOnLoad = this._xhrOnLoad.bind(this); - this._boundXdrOnTimeout = this._xdrOnTimeout.bind(this); - - /** - * Emitted when the resource beings to load. - * - * @event start - * @memberof Resource# - */ - - /** - * Emitted each time progress of this resource load updates. - * Not all resources types and loader systems can support this event - * so sometimes it may not be available. If the resource - * is being loaded on a modern browser, using XHR, and the remote server - * properly sets Content-Length headers, then this will be available. - * - * @event progress - * @memberof Resource# - */ - - /** - * Emitted once this resource has loaded, if there was an error it will - * be in the `error` property. - * - * @event complete - * @memberof Resource# - */ -} - -Resource.prototype = Object.create(EventEmitter.prototype); -Resource.prototype.constructor = Resource; -module.exports = Resource; - -/** - * Marks the resource as complete. - * - * @fires complete - */ -Resource.prototype.complete = function () { - // TODO: Clean this up in a wrapper or something...gross.... - if (this.data && this.data.removeEventListener) { - this.data.removeEventListener('error', this._boundOnError); - this.data.removeEventListener('load', this._boundComplete); - this.data.removeEventListener('progress', this._boundOnProgress); - this.data.removeEventListener('canplaythrough', this._boundComplete); - } - - if (this.xhr) { - if (this.xhr.removeEventListener) { - this.xhr.removeEventListener('error', this._boundXhrOnError); - this.xhr.removeEventListener('abort', this._boundXhrOnAbort); - this.xhr.removeEventListener('progress', this._boundOnProgress); - this.xhr.removeEventListener('load', this._boundXhrOnLoad); - } - else { - this.xhr.onerror = null; - this.xhr.ontimeout = null; - this.xhr.onprogress = null; - this.xhr.onload = null; - } - } - - this.emit('complete', this); -}; - -/** - * Kicks off loading of this resource. - * - * @fires start - * @param [callback] {function} Optional callback to call once the resource is loaded. - */ -Resource.prototype.load = function (cb) { - this.emit('start', this); - - // if a callback is set, listen for complete event - if (cb) { - this.once('complete', cb); - } - - // if unset, determine the value - if (this.crossOrigin === false || typeof this.crossOrigin !== 'string') { - this.crossOrigin = this._determineCrossOrigin(this.url); - } - - switch(this.loadType) { - case Resource.LOAD_TYPE.IMAGE: - this._loadImage(); - break; - - case Resource.LOAD_TYPE.AUDIO: - this._loadElement('audio'); - break; - - case Resource.LOAD_TYPE.VIDEO: - this._loadElement('video'); - break; - - case Resource.LOAD_TYPE.XHR: - /* falls through */ - default: - if (useXdr && this.crossOrigin) { - this._loadXdr(); - } - else { - this._loadXhr(); - } - break; - } -}; - -/** - * Loads this resources using an Image object. - * - * @private - */ -Resource.prototype._loadImage = function () { - if (!this.data) { - this.prepareImage(); - } - this.data.src = this.url; -}; - -/** - * Prepares image for loading, but does not set src yet - */ -Resource.prototype.prepareImage = function () { - this.data = new Image(); - - if (this.crossOrigin) { - this.data.crossOrigin = this.crossOrigin; - } - - this.isImage = true; - - this.data.addEventListener('error', this._boundOnError, false); - this.data.addEventListener('load', this._boundComplete, false); - this.data.addEventListener('progress', this._boundOnProgress, false); -}; - -/** - * Loads this resources using an HTMLAudioElement or HTMLVideoElement. - * - * @private - */ -Resource.prototype._loadElement = function (type) { - if (type === 'audio' && typeof Audio !== 'undefined') { - this.data = new Audio(); - } - else { - this.data = document.createElement(type); - } - - if (this.data === null) { - this.error = new Error('Unsupported element ' + type); - this.complete(); - return; - } - - // support for CocoonJS Canvas+ runtime, lacks document.createElement('source') - if (navigator.isCocoonJS) { - this.data.src = Array.isArray(this.url) ? this.url[0] : this.url; - } - else { - if (Array.isArray(this.url)) { - for (var i = 0; i < this.url.length; ++i) { - this.data.appendChild(this._createSource(type, this.url[i])); - } - } - else { - this.data.appendChild(this._createSource(type, this.url)); - } - } - - this['is' + type[0].toUpperCase() + type.substring(1)] = true; - - this.data.addEventListener('error', this._boundOnError, false); - this.data.addEventListener('load', this._boundComplete, false); - this.data.addEventListener('progress', this._boundOnProgress, false); - this.data.addEventListener('canplaythrough', this._boundComplete, false); - - this.data.load(); -}; - -/** - * Loads this resources using an XMLHttpRequest. - * - * @private - */ -Resource.prototype._loadXhr = function () { - // if unset, determine the value - if (typeof this.xhrType !== 'string') { - this.xhrType = this._determineXhrType(); - } - - var xhr = this.xhr = new XMLHttpRequest(); - - // set the request type and url - xhr.open('GET', this.url, true); - - // load json as text and parse it ourselves. We do this because some browsers - // *cough* safari *cough* can't deal with it. - if (this.xhrType === Resource.XHR_RESPONSE_TYPE.JSON || this.xhrType === Resource.XHR_RESPONSE_TYPE.DOCUMENT) { - xhr.responseType = Resource.XHR_RESPONSE_TYPE.TEXT; - } - else { - xhr.responseType = this.xhrType; - } - - xhr.addEventListener('error', this._boundXhrOnError, false); - xhr.addEventListener('abort', this._boundXhrOnAbort, false); - xhr.addEventListener('progress', this._boundOnProgress, false); - xhr.addEventListener('load', this._boundXhrOnLoad, false); - - xhr.send(); -}; - -/** - * Loads this resources using an XDomainRequest. This is here because we need to support IE9 (gross). - * - * @private - */ -Resource.prototype._loadXdr = function () { - // if unset, determine the value - if (typeof this.xhrType !== 'string') { - this.xhrType = this._determineXhrType(); - } - - var xdr = this.xhr = new XDomainRequest(); - - // XDomainRequest has a few quirks. Occasionally it will abort requests - // A way to avoid this is to make sure ALL callbacks are set even if not used - // More info here: http://stackoverflow.com/questions/15786966/xdomainrequest-aborts-post-on-ie-9 - xdr.timeout = 5000; - - xdr.onerror = this._boundXhrOnError; - xdr.ontimeout = this._boundXdrOnTimeout; - xdr.onprogress = this._boundOnProgress; - xdr.onload = this._boundXhrOnLoad; - - xdr.open('GET', this.url, true); - - // Note: The xdr.send() call is wrapped in a timeout to prevent an issue with the interface where some requests are lost - // if multiple XDomainRequests are being sent at the same time. - // Some info here: https://github.com/photonstorm/phaser/issues/1248 - setTimeout(function () { - xdr.send(); - }, 0); -}; - -/** - * Creates a source used in loading via an element. - * - * @param type {string} The element type (video or audio). - * @param url {string} The source URL to load from. - * @param [mime] {string} The mime type of the video - * @private - */ -Resource.prototype._createSource = function (type, url, mime) { - if (!mime) { - mime = type + '/' + url.substr(url.lastIndexOf('.') + 1); - } - - var source = document.createElement('source'); - - source.src = url; - source.type = mime; - - return source; -}; - -/** - * Called if a load errors out. - * - * @param event {Event} The error event from the element that emits it. - * @private - */ -Resource.prototype._onError = function (event) { - this.error = new Error('Failed to load element using ' + event.target.nodeName); - this.complete(); -}; - -/** - * Called if a load progress event fires for xhr/xdr. - * - * @fires progress - * @param event {XMLHttpRequestProgressEvent|Event} - * @private - */ -Resource.prototype._onProgress = function (event) { - if (event && event.lengthComputable) { - this.emit('progress', this, event.loaded / event.total); - } -}; - -/** - * Called if an error event fires for xhr/xdr. - * - * @param event {XMLHttpRequestErrorEvent|Event} - * @private - */ -Resource.prototype._xhrOnError = function () { - this.error = new Error( - reqType(this.xhr) + ' Request failed. ' + - 'Status: ' + this.xhr.status + ', text: "' + this.xhr.statusText + '"' - ); - - this.complete(); -}; - -/** - * Called if an abort event fires for xhr. - * - * @param event {XMLHttpRequestAbortEvent} - * @private - */ -Resource.prototype._xhrOnAbort = function () { - this.error = new Error(reqType(this.xhr) + ' Request was aborted by the user.'); - this.complete(); -}; - -/** - * Called if a timeout event fires for xdr. - * - * @param event {Event} - * @private - */ -Resource.prototype._xdrOnTimeout = function () { - this.error = new Error(reqType(this.xhr) + ' Request timed out.'); - this.complete(); -}; - -/** - * Called when data successfully loads from an xhr/xdr request. - * - * @param event {XMLHttpRequestLoadEvent|Event} - * @private - */ -Resource.prototype._xhrOnLoad = function () { - var xhr = this.xhr, - status = xhr.status !== undefined ? xhr.status : 200; //XDR has no `.status`, assume 200. - - // status can be 0 when using the file:// protocol, also check if a response was found - if (status === 200 || status === 204 || (status === 0 && xhr.responseText.length > 0)) { - // if text, just return it - if (this.xhrType === Resource.XHR_RESPONSE_TYPE.TEXT) { - this.data = xhr.responseText; - } - // if json, parse into json object - else if (this.xhrType === Resource.XHR_RESPONSE_TYPE.JSON) { - try { - this.data = JSON.parse(xhr.responseText); - this.isJson = true; - } catch(e) { - this.error = new Error('Error trying to parse loaded json:', e); - } - } - // if xml, parse into an xml document or div element - else if (this.xhrType === Resource.XHR_RESPONSE_TYPE.DOCUMENT) { - try { - if (window.DOMParser) { - var domparser = new DOMParser(); - this.data = domparser.parseFromString(xhr.responseText, 'text/xml'); - } - else { - var div = document.createElement('div'); - div.innerHTML = xhr.responseText; - this.data = div; - } - this.isXml = true; - } catch (e) { - this.error = new Error('Error trying to parse loaded xml:', e); - } - } - // other types just return the response - else { - this.data = xhr.response || xhr.responseText; - } - } - else { - this.error = new Error('[' + xhr.status + ']' + xhr.statusText + ':' + xhr.responseURL); - } - - this.complete(); -}; - -function reqType(xhr) { - return xhr.toString().replace('object ', ''); -} - -/** - * Sets the `crossOrigin` property for this resource based on if the url - * for this resource is cross-origin. If crossOrigin was manually set, this - * function does nothing. - * - * @private - * @param url {string} The url to test. - * @param [location=window.location] {object} The location object to test against. - * @return {string} The crossOrigin value to use (or empty string for none). - */ -Resource.prototype._determineCrossOrigin = function (url, loc) { - // data: and javascript: urls are considered same-origin - if (url.indexOf('data:') === 0) { - return ''; - } - - // default is window.location - loc = loc || window.location; - - if (!tempAnchor) { - tempAnchor = document.createElement('a'); - } - - // let the browser determine the full href for the url of this resource and then - // parse with the node url lib, we can't use the properties of the anchor element - // because they don't work in IE9 :( - tempAnchor.href = url; - url = _url.parse(tempAnchor.href); - - var samePort = (!url.port && loc.port === '') || (url.port === loc.port); - - // if cross origin - if (url.hostname !== loc.hostname || !samePort || url.protocol !== loc.protocol) { - return 'anonymous'; - } - - return ''; -}; - -/** - * Determines the responseType of an XHR request based on the extension of the - * resource being loaded. - * - * @private - * @return {Resource.XHR_RESPONSE_TYPE} The responseType to use. - */ -Resource.prototype._determineXhrType = function () { - return Resource._xhrTypeMap[this._getExtension()] || Resource.XHR_RESPONSE_TYPE.TEXT; -}; - -Resource.prototype._determineLoadType = function () { - return Resource._loadTypeMap[this._getExtension()] || Resource.LOAD_TYPE.XHR; -}; - -Resource.prototype._getExtension = function () { - var url = this.url, - ext; - - if (this.isDataUrl) { - var slashIndex = url.indexOf('/'); - ext = url.substring(slashIndex + 1, url.indexOf(';', slashIndex)); - } - else { - var queryStart = url.indexOf('?'); - if (queryStart !== -1) { - url = url.substring(0, queryStart); - } - - ext = url.substring(url.lastIndexOf('.') + 1); - } - - return ext; -}; - -/** - * Determines the mime type of an XHR request based on the responseType of - * resource being loaded. - * - * @private - * @return {string} The mime type to use. - */ -Resource.prototype._getMimeFromXhrType = function (type) { - switch(type) { - case Resource.XHR_RESPONSE_TYPE.BUFFER: - return 'application/octet-binary'; - - case Resource.XHR_RESPONSE_TYPE.BLOB: - return 'application/blob'; - - case Resource.XHR_RESPONSE_TYPE.DOCUMENT: - return 'application/xml'; - - case Resource.XHR_RESPONSE_TYPE.JSON: - return 'application/json'; - - case Resource.XHR_RESPONSE_TYPE.DEFAULT: - case Resource.XHR_RESPONSE_TYPE.TEXT: - /* falls through */ - default: - return 'text/plain'; - - } -}; - -/** - * The types of loading a resource can use. - * - * @static - * @constant - * @property {object} LOAD_TYPE - * @property {number} LOAD_TYPE.XHR - Uses XMLHttpRequest to load the resource. - * @property {number} LOAD_TYPE.IMAGE - Uses an `Image` object to load the resource. - * @property {number} LOAD_TYPE.AUDIO - Uses an `Audio` object to load the resource. - * @property {number} LOAD_TYPE.VIDEO - Uses a `Video` object to load the resource. - */ -Resource.LOAD_TYPE = { - XHR: 1, - IMAGE: 2, - AUDIO: 3, - VIDEO: 4 -}; - -/** - * The XHR ready states, used internally. - * - * @static - * @constant - * @property {object} XHR_READY_STATE - * @property {number} XHR_READY_STATE.UNSENT - open()has not been called yet. - * @property {number} XHR_READY_STATE.OPENED - send()has not been called yet. - * @property {number} XHR_READY_STATE.HEADERS_RECEIVED - send() has been called, and headers and status are available. - * @property {number} XHR_READY_STATE.LOADING - Downloading; responseText holds partial data. - * @property {number} XHR_READY_STATE.DONE - The operation is complete. - */ -Resource.XHR_READY_STATE = { - UNSENT: 0, - OPENED: 1, - HEADERS_RECEIVED: 2, - LOADING: 3, - DONE: 4 -}; - -/** - * The XHR ready states, used internally. - * - * @static - * @constant - * @property {object} XHR_RESPONSE_TYPE - * @property {string} XHR_RESPONSE_TYPE.DEFAULT - defaults to text - * @property {string} XHR_RESPONSE_TYPE.BUFFER - ArrayBuffer - * @property {string} XHR_RESPONSE_TYPE.BLOB - Blob - * @property {string} XHR_RESPONSE_TYPE.DOCUMENT - Document - * @property {string} XHR_RESPONSE_TYPE.JSON - Object - * @property {string} XHR_RESPONSE_TYPE.TEXT - String - */ -Resource.XHR_RESPONSE_TYPE = { - DEFAULT: 'text', - BUFFER: 'arraybuffer', - BLOB: 'blob', - DOCUMENT: 'document', - JSON: 'json', - TEXT: 'text' -}; - -Resource._loadTypeMap = { - 'gif': Resource.LOAD_TYPE.IMAGE, - 'png': Resource.LOAD_TYPE.IMAGE, - 'bmp': Resource.LOAD_TYPE.IMAGE, - 'jpg': Resource.LOAD_TYPE.IMAGE, - 'jpeg': Resource.LOAD_TYPE.IMAGE, - 'tif': Resource.LOAD_TYPE.IMAGE, - 'tiff': Resource.LOAD_TYPE.IMAGE, - 'webp': Resource.LOAD_TYPE.IMAGE, - 'tga': Resource.LOAD_TYPE.IMAGE -}; - -Resource._xhrTypeMap = { - // xml - 'xhtml': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'html': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'htm': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'xml': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'tmx': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'tsx': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - 'svg': Resource.XHR_RESPONSE_TYPE.DOCUMENT, - - // images - 'gif': Resource.XHR_RESPONSE_TYPE.BLOB, - 'png': Resource.XHR_RESPONSE_TYPE.BLOB, - 'bmp': Resource.XHR_RESPONSE_TYPE.BLOB, - 'jpg': Resource.XHR_RESPONSE_TYPE.BLOB, - 'jpeg': Resource.XHR_RESPONSE_TYPE.BLOB, - 'tif': Resource.XHR_RESPONSE_TYPE.BLOB, - 'tiff': Resource.XHR_RESPONSE_TYPE.BLOB, - 'webp': Resource.XHR_RESPONSE_TYPE.BLOB, - 'tga': Resource.XHR_RESPONSE_TYPE.BLOB, - - // json - 'json': Resource.XHR_RESPONSE_TYPE.JSON, - - // text - 'text': Resource.XHR_RESPONSE_TYPE.TEXT, - 'txt': Resource.XHR_RESPONSE_TYPE.TEXT -}; - -/** - * Sets the load type to be used for a specific extension. - * - * @static - * @param extname {string} The extension to set the type for, e.g. "png" or "fnt" - * @param loadType {Resource.LOAD_TYPE} The load type to set it to. - */ -Resource.setExtensionLoadType = function (extname, loadType) { - setExtMap(Resource._loadTypeMap, extname, loadType); -}; - -/** - * Sets the load type to be used for a specific extension. - * - * @static - * @param extname {string} The extension to set the type for, e.g. "png" or "fnt" - * @param xhrType {Resource.XHR_RESPONSE_TYPE} The xhr type to set it to. - */ -Resource.setExtensionXhrType = function (extname, xhrType) { - setExtMap(Resource._xhrTypeMap, extname, xhrType); -}; - -function setExtMap(map, extname, val) { - if (extname && extname.indexOf('.') === 0) { - extname = extname.substring(1); - } - - if (!extname) { - return; - } - - map[extname] = val; -} - -},{"eventemitter3":2,"url":10}],149:[function(require,module,exports){ -module.exports = { - - // private property - _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", - - encodeBinary: function (input) { - var output = ""; - var bytebuffer; - var encodedCharIndexes = new Array(4); - var inx = 0; - var jnx = 0; - var paddingBytes = 0; - - while (inx < input.length) { - // Fill byte buffer array - bytebuffer = new Array(3); - for (jnx = 0; jnx < bytebuffer.length; jnx++) { - if (inx < input.length) { - // throw away high-order byte, as documented at: - // https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data - bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff; - } - else { - bytebuffer[jnx] = 0; - } - } - - // Get each encoded character, 6 bits at a time - // index 1: first 6 bits - encodedCharIndexes[0] = bytebuffer[0] >> 2; - // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2) - encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4); - // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3) - encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6); - // index 3: forth 6 bits (6 least significant bits from input byte 3) - encodedCharIndexes[3] = bytebuffer[2] & 0x3f; - - // Determine whether padding happened, and adjust accordingly - paddingBytes = inx - (input.length - 1); - switch (paddingBytes) { - case 2: - // Set last 2 characters to padding char - encodedCharIndexes[3] = 64; - encodedCharIndexes[2] = 64; - break; - - case 1: - // Set last character to padding char - encodedCharIndexes[3] = 64; - break; - - default: - break; // No padding - proceed - } - - // Now we will grab each appropriate character out of our keystring - // based on our index array and append it to the output string - for (jnx = 0; jnx < encodedCharIndexes.length; jnx++) { - output += this._keyStr.charAt(encodedCharIndexes[jnx]); - } - } - return output; - } -}; - -},{}],150:[function(require,module,exports){ -module.exports = require('./Loader'); - -module.exports.Resource = require('./Resource'); - -module.exports.middleware = { - caching: { - memory: require('./middlewares/caching/memory') - }, - parsing: { - blob: require('./middlewares/parsing/blob') - } -}; - -},{"./Loader":147,"./Resource":148,"./middlewares/caching/memory":151,"./middlewares/parsing/blob":152}],151:[function(require,module,exports){ -// a simple in-memory cache for resources -var cache = {}; - -module.exports = function () { - return function (resource, next) { - // if cached, then set data and complete the resource - if (cache[resource.url]) { - resource.data = cache[resource.url]; - resource.complete(); - } - // if not cached, wait for complete and store it in the cache. - else { - resource.once('complete', function () { - cache[this.url] = this.data; - }); - } - - next(); - }; -}; - -},{}],152:[function(require,module,exports){ -var Resource = require('../../Resource'), - b64 = require('../../b64'); - -window.URL = window.URL || window.webkitURL; - -// a middleware for transforming XHR loaded Blobs into more useful objects - -module.exports = function () { - return function (resource, next) { - if (!resource.data) { - return next(); - } - - // if this was an XHR load of a blob - if (resource.xhr && resource.xhrType === Resource.XHR_RESPONSE_TYPE.BLOB) { - // if there is no blob support we probably got a binary string back - if (!window.Blob || typeof resource.data === 'string') { - var type = resource.xhr.getResponseHeader('content-type'); - - // this is an image, convert the binary string into a data url - if (type && type.indexOf('image') === 0) { - resource.data = new Image(); - resource.data.src = 'data:' + type + ';base64,' + b64.encodeBinary(resource.xhr.responseText); - - resource.isImage = true; - - // wait until the image loads and then callback - resource.data.onload = function () { - resource.data.onload = null; - - next(); - }; - } - } - // if content type says this is an image, then we should transform the blob into an Image object - else if (resource.data.type.indexOf('image') === 0) { - var src = URL.createObjectURL(resource.data); - - resource.blob = resource.data; - resource.data = new Image(); - resource.data.src = src; - - resource.isImage = true; - - // cleanup the no longer used blob after the image loads - resource.data.onload = function () { - URL.revokeObjectURL(src); - resource.data.onload = null; - - next(); - }; - } - } - else { - next(); - } - }; -}; - -},{"../../Resource":148,"../../b64":149}]},{},[123])(123) +},{}]},{},[129])(129) }); //# sourceMappingURL=pixi.js.map diff --git a/bin/pixi.js.map b/bin/pixi.js.map index 75ad743..7bc8c32 100644 --- a/bin/pixi.js.map +++ b/bin/pixi.js.map @@ -1 +1 @@ -{"version":3,"names":[],"mappings":"","sources":["pixi.js"],"sourcesContent":["(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.PIXI = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o= arr.length) {\n callback();\n }\n }\n }\n };\n async.forEach = async.each;\n\n async.eachSeries = function (arr, iterator, callback) {\n callback = callback || function () {};\n if (!arr.length) {\n return callback();\n }\n var completed = 0;\n var iterate = function () {\n iterator(arr[completed], function (err) {\n if (err) {\n callback(err);\n callback = function () {};\n }\n else {\n completed += 1;\n if (completed >= arr.length) {\n callback();\n }\n else {\n iterate();\n }\n }\n });\n };\n iterate();\n };\n async.forEachSeries = async.eachSeries;\n\n async.eachLimit = function (arr, limit, iterator, callback) {\n var fn = _eachLimit(limit);\n fn.apply(null, [arr, iterator, callback]);\n };\n async.forEachLimit = async.eachLimit;\n\n var _eachLimit = function (limit) {\n\n return function (arr, iterator, callback) {\n callback = callback || function () {};\n if (!arr.length || limit <= 0) {\n return callback();\n }\n var completed = 0;\n var started = 0;\n var running = 0;\n\n (function replenish () {\n if (completed >= arr.length) {\n return callback();\n }\n\n while (running < limit && started < arr.length) {\n started += 1;\n running += 1;\n iterator(arr[started - 1], function (err) {\n if (err) {\n callback(err);\n callback = function () {};\n }\n else {\n completed += 1;\n running -= 1;\n if (completed >= arr.length) {\n callback();\n }\n else {\n replenish();\n }\n }\n });\n }\n })();\n };\n };\n\n\n var doParallel = function (fn) {\n return function () {\n var args = Array.prototype.slice.call(arguments);\n return fn.apply(null, [async.each].concat(args));\n };\n };\n var doParallelLimit = function(limit, fn) {\n return function () {\n var args = Array.prototype.slice.call(arguments);\n return fn.apply(null, [_eachLimit(limit)].concat(args));\n };\n };\n var doSeries = function (fn) {\n return function () {\n var args = Array.prototype.slice.call(arguments);\n return fn.apply(null, [async.eachSeries].concat(args));\n };\n };\n\n\n var _asyncMap = function (eachfn, arr, iterator, callback) {\n arr = _map(arr, function (x, i) {\n return {index: i, value: x};\n });\n if (!callback) {\n eachfn(arr, function (x, callback) {\n iterator(x.value, function (err) {\n callback(err);\n });\n });\n } else {\n var results = [];\n eachfn(arr, function (x, callback) {\n iterator(x.value, function (err, v) {\n results[x.index] = v;\n callback(err);\n });\n }, function (err) {\n callback(err, results);\n });\n }\n };\n async.map = doParallel(_asyncMap);\n async.mapSeries = doSeries(_asyncMap);\n async.mapLimit = function (arr, limit, iterator, callback) {\n return _mapLimit(limit)(arr, iterator, callback);\n };\n\n var _mapLimit = function(limit) {\n return doParallelLimit(limit, _asyncMap);\n };\n\n // reduce only has a series version, as doing reduce in parallel won't\n // work in many situations.\n async.reduce = function (arr, memo, iterator, callback) {\n async.eachSeries(arr, function (x, callback) {\n iterator(memo, x, function (err, v) {\n memo = v;\n callback(err);\n });\n }, function (err) {\n callback(err, memo);\n });\n };\n // inject alias\n async.inject = async.reduce;\n // foldl alias\n async.foldl = async.reduce;\n\n async.reduceRight = function (arr, memo, iterator, callback) {\n var reversed = _map(arr, function (x) {\n return x;\n }).reverse();\n async.reduce(reversed, memo, iterator, callback);\n };\n // foldr alias\n async.foldr = async.reduceRight;\n\n var _filter = function (eachfn, arr, iterator, callback) {\n var results = [];\n arr = _map(arr, function (x, i) {\n return {index: i, value: x};\n });\n eachfn(arr, function (x, callback) {\n iterator(x.value, function (v) {\n if (v) {\n results.push(x);\n }\n callback();\n });\n }, function (err) {\n callback(_map(results.sort(function (a, b) {\n return a.index - b.index;\n }), function (x) {\n return x.value;\n }));\n });\n };\n async.filter = doParallel(_filter);\n async.filterSeries = doSeries(_filter);\n // select alias\n async.select = async.filter;\n async.selectSeries = async.filterSeries;\n\n var _reject = function (eachfn, arr, iterator, callback) {\n var results = [];\n arr = _map(arr, function (x, i) {\n return {index: i, value: x};\n });\n eachfn(arr, function (x, callback) {\n iterator(x.value, function (v) {\n if (!v) {\n results.push(x);\n }\n callback();\n });\n }, function (err) {\n callback(_map(results.sort(function (a, b) {\n return a.index - b.index;\n }), function (x) {\n return x.value;\n }));\n });\n };\n async.reject = doParallel(_reject);\n async.rejectSeries = doSeries(_reject);\n\n var _detect = function (eachfn, arr, iterator, main_callback) {\n eachfn(arr, function (x, callback) {\n iterator(x, function (result) {\n if (result) {\n main_callback(x);\n main_callback = function () {};\n }\n else {\n callback();\n }\n });\n }, function (err) {\n main_callback();\n });\n };\n async.detect = doParallel(_detect);\n async.detectSeries = doSeries(_detect);\n\n async.some = function (arr, iterator, main_callback) {\n async.each(arr, function (x, callback) {\n iterator(x, function (v) {\n if (v) {\n main_callback(true);\n main_callback = function () {};\n }\n callback();\n });\n }, function (err) {\n main_callback(false);\n });\n };\n // any alias\n async.any = async.some;\n\n async.every = function (arr, iterator, main_callback) {\n async.each(arr, function (x, callback) {\n iterator(x, function (v) {\n if (!v) {\n main_callback(false);\n main_callback = function () {};\n }\n callback();\n });\n }, function (err) {\n main_callback(true);\n });\n };\n // all alias\n async.all = async.every;\n\n async.sortBy = function (arr, iterator, callback) {\n async.map(arr, function (x, callback) {\n iterator(x, function (err, criteria) {\n if (err) {\n callback(err);\n }\n else {\n callback(null, {value: x, criteria: criteria});\n }\n });\n }, function (err, results) {\n if (err) {\n return callback(err);\n }\n else {\n var fn = function (left, right) {\n var a = left.criteria, b = right.criteria;\n return a < b ? -1 : a > b ? 1 : 0;\n };\n callback(null, _map(results.sort(fn), function (x) {\n return x.value;\n }));\n }\n });\n };\n\n async.auto = function (tasks, callback) {\n callback = callback || function () {};\n var keys = _keys(tasks);\n var remainingTasks = keys.length\n if (!remainingTasks) {\n return callback();\n }\n\n var results = {};\n\n var listeners = [];\n var addListener = function (fn) {\n listeners.unshift(fn);\n };\n var removeListener = function (fn) {\n for (var i = 0; i < listeners.length; i += 1) {\n if (listeners[i] === fn) {\n listeners.splice(i, 1);\n return;\n }\n }\n };\n var taskComplete = function () {\n remainingTasks--\n _each(listeners.slice(0), function (fn) {\n fn();\n });\n };\n\n addListener(function () {\n if (!remainingTasks) {\n var theCallback = callback;\n // prevent final callback from calling itself if it errors\n callback = function () {};\n\n theCallback(null, results);\n }\n });\n\n _each(keys, function (k) {\n var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];\n var taskCallback = function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (args.length <= 1) {\n args = args[0];\n }\n if (err) {\n var safeResults = {};\n _each(_keys(results), function(rkey) {\n safeResults[rkey] = results[rkey];\n });\n safeResults[k] = args;\n callback(err, safeResults);\n // stop subsequent errors hitting callback multiple times\n callback = function () {};\n }\n else {\n results[k] = args;\n async.setImmediate(taskComplete);\n }\n };\n var requires = task.slice(0, Math.abs(task.length - 1)) || [];\n var ready = function () {\n return _reduce(requires, function (a, x) {\n return (a && results.hasOwnProperty(x));\n }, true) && !results.hasOwnProperty(k);\n };\n if (ready()) {\n task[task.length - 1](taskCallback, results);\n }\n else {\n var listener = function () {\n if (ready()) {\n removeListener(listener);\n task[task.length - 1](taskCallback, results);\n }\n };\n addListener(listener);\n }\n });\n };\n\n async.retry = function(times, task, callback) {\n var DEFAULT_TIMES = 5;\n var attempts = [];\n // Use defaults if times not passed\n if (typeof times === 'function') {\n callback = task;\n task = times;\n times = DEFAULT_TIMES;\n }\n // Make sure times is a number\n times = parseInt(times, 10) || DEFAULT_TIMES;\n var wrappedTask = function(wrappedCallback, wrappedResults) {\n var retryAttempt = function(task, finalAttempt) {\n return function(seriesCallback) {\n task(function(err, result){\n seriesCallback(!err || finalAttempt, {err: err, result: result});\n }, wrappedResults);\n };\n };\n while (times) {\n attempts.push(retryAttempt(task, !(times-=1)));\n }\n async.series(attempts, function(done, data){\n data = data[data.length - 1];\n (wrappedCallback || callback)(data.err, data.result);\n });\n }\n // If a callback is passed, run this as a controll flow\n return callback ? wrappedTask() : wrappedTask\n };\n\n async.waterfall = function (tasks, callback) {\n callback = callback || function () {};\n if (!_isArray(tasks)) {\n var err = new Error('First argument to waterfall must be an array of functions');\n return callback(err);\n }\n if (!tasks.length) {\n return callback();\n }\n var wrapIterator = function (iterator) {\n return function (err) {\n if (err) {\n callback.apply(null, arguments);\n callback = function () {};\n }\n else {\n var args = Array.prototype.slice.call(arguments, 1);\n var next = iterator.next();\n if (next) {\n args.push(wrapIterator(next));\n }\n else {\n args.push(callback);\n }\n async.setImmediate(function () {\n iterator.apply(null, args);\n });\n }\n };\n };\n wrapIterator(async.iterator(tasks))();\n };\n\n var _parallel = function(eachfn, tasks, callback) {\n callback = callback || function () {};\n if (_isArray(tasks)) {\n eachfn.map(tasks, function (fn, callback) {\n if (fn) {\n fn(function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (args.length <= 1) {\n args = args[0];\n }\n callback.call(null, err, args);\n });\n }\n }, callback);\n }\n else {\n var results = {};\n eachfn.each(_keys(tasks), function (k, callback) {\n tasks[k](function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (args.length <= 1) {\n args = args[0];\n }\n results[k] = args;\n callback(err);\n });\n }, function (err) {\n callback(err, results);\n });\n }\n };\n\n async.parallel = function (tasks, callback) {\n _parallel({ map: async.map, each: async.each }, tasks, callback);\n };\n\n async.parallelLimit = function(tasks, limit, callback) {\n _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);\n };\n\n async.series = function (tasks, callback) {\n callback = callback || function () {};\n if (_isArray(tasks)) {\n async.mapSeries(tasks, function (fn, callback) {\n if (fn) {\n fn(function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (args.length <= 1) {\n args = args[0];\n }\n callback.call(null, err, args);\n });\n }\n }, callback);\n }\n else {\n var results = {};\n async.eachSeries(_keys(tasks), function (k, callback) {\n tasks[k](function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (args.length <= 1) {\n args = args[0];\n }\n results[k] = args;\n callback(err);\n });\n }, function (err) {\n callback(err, results);\n });\n }\n };\n\n async.iterator = function (tasks) {\n var makeCallback = function (index) {\n var fn = function () {\n if (tasks.length) {\n tasks[index].apply(null, arguments);\n }\n return fn.next();\n };\n fn.next = function () {\n return (index < tasks.length - 1) ? makeCallback(index + 1): null;\n };\n return fn;\n };\n return makeCallback(0);\n };\n\n async.apply = function (fn) {\n var args = Array.prototype.slice.call(arguments, 1);\n return function () {\n return fn.apply(\n null, args.concat(Array.prototype.slice.call(arguments))\n );\n };\n };\n\n var _concat = function (eachfn, arr, fn, callback) {\n var r = [];\n eachfn(arr, function (x, cb) {\n fn(x, function (err, y) {\n r = r.concat(y || []);\n cb(err);\n });\n }, function (err) {\n callback(err, r);\n });\n };\n async.concat = doParallel(_concat);\n async.concatSeries = doSeries(_concat);\n\n async.whilst = function (test, iterator, callback) {\n if (test()) {\n iterator(function (err) {\n if (err) {\n return callback(err);\n }\n async.whilst(test, iterator, callback);\n });\n }\n else {\n callback();\n }\n };\n\n async.doWhilst = function (iterator, test, callback) {\n iterator(function (err) {\n if (err) {\n return callback(err);\n }\n var args = Array.prototype.slice.call(arguments, 1);\n if (test.apply(null, args)) {\n async.doWhilst(iterator, test, callback);\n }\n else {\n callback();\n }\n });\n };\n\n async.until = function (test, iterator, callback) {\n if (!test()) {\n iterator(function (err) {\n if (err) {\n return callback(err);\n }\n async.until(test, iterator, callback);\n });\n }\n else {\n callback();\n }\n };\n\n async.doUntil = function (iterator, test, callback) {\n iterator(function (err) {\n if (err) {\n return callback(err);\n }\n var args = Array.prototype.slice.call(arguments, 1);\n if (!test.apply(null, args)) {\n async.doUntil(iterator, test, callback);\n }\n else {\n callback();\n }\n });\n };\n\n async.queue = function (worker, concurrency) {\n if (concurrency === undefined) {\n concurrency = 1;\n }\n function _insert(q, data, pos, callback) {\n if (!q.started){\n q.started = true;\n }\n if (!_isArray(data)) {\n data = [data];\n }\n if(data.length == 0) {\n // call drain immediately if there are no tasks\n return async.setImmediate(function() {\n if (q.drain) {\n q.drain();\n }\n });\n }\n _each(data, function(task) {\n var item = {\n data: task,\n callback: typeof callback === 'function' ? callback : null\n };\n\n if (pos) {\n q.tasks.unshift(item);\n } else {\n q.tasks.push(item);\n }\n\n if (q.saturated && q.tasks.length === q.concurrency) {\n q.saturated();\n }\n async.setImmediate(q.process);\n });\n }\n\n var workers = 0;\n var q = {\n tasks: [],\n concurrency: concurrency,\n saturated: null,\n empty: null,\n drain: null,\n started: false,\n paused: false,\n push: function (data, callback) {\n _insert(q, data, false, callback);\n },\n kill: function () {\n q.drain = null;\n q.tasks = [];\n },\n unshift: function (data, callback) {\n _insert(q, data, true, callback);\n },\n process: function () {\n if (!q.paused && workers < q.concurrency && q.tasks.length) {\n var task = q.tasks.shift();\n if (q.empty && q.tasks.length === 0) {\n q.empty();\n }\n workers += 1;\n var next = function () {\n workers -= 1;\n if (task.callback) {\n task.callback.apply(task, arguments);\n }\n if (q.drain && q.tasks.length + workers === 0) {\n q.drain();\n }\n q.process();\n };\n var cb = only_once(next);\n worker(task.data, cb);\n }\n },\n length: function () {\n return q.tasks.length;\n },\n running: function () {\n return workers;\n },\n idle: function() {\n return q.tasks.length + workers === 0;\n },\n pause: function () {\n if (q.paused === true) { return; }\n q.paused = true;\n },\n resume: function () {\n if (q.paused === false) { return; }\n q.paused = false;\n // Need to call q.process once per concurrent\n // worker to preserve full concurrency after pause\n for (var w = 1; w <= q.concurrency; w++) {\n async.setImmediate(q.process);\n }\n }\n };\n return q;\n };\n\n async.priorityQueue = function (worker, concurrency) {\n\n function _compareTasks(a, b){\n return a.priority - b.priority;\n };\n\n function _binarySearch(sequence, item, compare) {\n var beg = -1,\n end = sequence.length - 1;\n while (beg < end) {\n var mid = beg + ((end - beg + 1) >>> 1);\n if (compare(item, sequence[mid]) >= 0) {\n beg = mid;\n } else {\n end = mid - 1;\n }\n }\n return beg;\n }\n\n function _insert(q, data, priority, callback) {\n if (!q.started){\n q.started = true;\n }\n if (!_isArray(data)) {\n data = [data];\n }\n if(data.length == 0) {\n // call drain immediately if there are no tasks\n return async.setImmediate(function() {\n if (q.drain) {\n q.drain();\n }\n });\n }\n _each(data, function(task) {\n var item = {\n data: task,\n priority: priority,\n callback: typeof callback === 'function' ? callback : null\n };\n\n q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);\n\n if (q.saturated && q.tasks.length === q.concurrency) {\n q.saturated();\n }\n async.setImmediate(q.process);\n });\n }\n\n // Start with a normal queue\n var q = async.queue(worker, concurrency);\n\n // Override push to accept second parameter representing priority\n q.push = function (data, priority, callback) {\n _insert(q, data, priority, callback);\n };\n\n // Remove unshift function\n delete q.unshift;\n\n return q;\n };\n\n async.cargo = function (worker, payload) {\n var working = false,\n tasks = [];\n\n var cargo = {\n tasks: tasks,\n payload: payload,\n saturated: null,\n empty: null,\n drain: null,\n drained: true,\n push: function (data, callback) {\n if (!_isArray(data)) {\n data = [data];\n }\n _each(data, function(task) {\n tasks.push({\n data: task,\n callback: typeof callback === 'function' ? callback : null\n });\n cargo.drained = false;\n if (cargo.saturated && tasks.length === payload) {\n cargo.saturated();\n }\n });\n async.setImmediate(cargo.process);\n },\n process: function process() {\n if (working) return;\n if (tasks.length === 0) {\n if(cargo.drain && !cargo.drained) cargo.drain();\n cargo.drained = true;\n return;\n }\n\n var ts = typeof payload === 'number'\n ? tasks.splice(0, payload)\n : tasks.splice(0, tasks.length);\n\n var ds = _map(ts, function (task) {\n return task.data;\n });\n\n if(cargo.empty) cargo.empty();\n working = true;\n worker(ds, function () {\n working = false;\n\n var args = arguments;\n _each(ts, function (data) {\n if (data.callback) {\n data.callback.apply(null, args);\n }\n });\n\n process();\n });\n },\n length: function () {\n return tasks.length;\n },\n running: function () {\n return working;\n }\n };\n return cargo;\n };\n\n var _console_fn = function (name) {\n return function (fn) {\n var args = Array.prototype.slice.call(arguments, 1);\n fn.apply(null, args.concat([function (err) {\n var args = Array.prototype.slice.call(arguments, 1);\n if (typeof console !== 'undefined') {\n if (err) {\n if (console.error) {\n console.error(err);\n }\n }\n else if (console[name]) {\n _each(args, function (x) {\n console[name](x);\n });\n }\n }\n }]));\n };\n };\n async.log = _console_fn('log');\n async.dir = _console_fn('dir');\n /*async.info = _console_fn('info');\n async.warn = _console_fn('warn');\n async.error = _console_fn('error');*/\n\n async.memoize = function (fn, hasher) {\n var memo = {};\n var queues = {};\n hasher = hasher || function (x) {\n return x;\n };\n var memoized = function () {\n var args = Array.prototype.slice.call(arguments);\n var callback = args.pop();\n var key = hasher.apply(null, args);\n if (key in memo) {\n async.nextTick(function () {\n callback.apply(null, memo[key]);\n });\n }\n else if (key in queues) {\n queues[key].push(callback);\n }\n else {\n queues[key] = [callback];\n fn.apply(null, args.concat([function () {\n memo[key] = arguments;\n var q = queues[key];\n delete queues[key];\n for (var i = 0, l = q.length; i < l; i++) {\n q[i].apply(null, arguments);\n }\n }]));\n }\n };\n memoized.memo = memo;\n memoized.unmemoized = fn;\n return memoized;\n };\n\n async.unmemoize = function (fn) {\n return function () {\n return (fn.unmemoized || fn).apply(null, arguments);\n };\n };\n\n async.times = function (count, iterator, callback) {\n var counter = [];\n for (var i = 0; i < count; i++) {\n counter.push(i);\n }\n return async.map(counter, iterator, callback);\n };\n\n async.timesSeries = function (count, iterator, callback) {\n var counter = [];\n for (var i = 0; i < count; i++) {\n counter.push(i);\n }\n return async.mapSeries(counter, iterator, callback);\n };\n\n async.seq = function (/* functions... */) {\n var fns = arguments;\n return function () {\n var that = this;\n var args = Array.prototype.slice.call(arguments);\n var callback = args.pop();\n async.reduce(fns, args, function (newargs, fn, cb) {\n fn.apply(that, newargs.concat([function () {\n var err = arguments[0];\n var nextargs = Array.prototype.slice.call(arguments, 1);\n cb(err, nextargs);\n }]))\n },\n function (err, results) {\n callback.apply(that, [err].concat(results));\n });\n };\n };\n\n async.compose = function (/* functions... */) {\n return async.seq.apply(null, Array.prototype.reverse.call(arguments));\n };\n\n var _applyEach = function (eachfn, fns /*args...*/) {\n var go = function () {\n var that = this;\n var args = Array.prototype.slice.call(arguments);\n var callback = args.pop();\n return eachfn(fns, function (fn, cb) {\n fn.apply(that, args.concat([cb]));\n },\n callback);\n };\n if (arguments.length > 2) {\n var args = Array.prototype.slice.call(arguments, 2);\n return go.apply(this, args);\n }\n else {\n return go;\n }\n };\n async.applyEach = doParallel(_applyEach);\n async.applyEachSeries = doSeries(_applyEach);\n\n async.forever = function (fn, callback) {\n function next(err) {\n if (err) {\n if (callback) {\n return callback(err);\n }\n throw err;\n }\n fn(next);\n }\n next();\n };\n\n // Node.js\n if (typeof module !== 'undefined' && module.exports) {\n module.exports = async;\n }\n // AMD / RequireJS\n else if (typeof define !== 'undefined' && define.amd) {\n define([], function () {\n return async;\n });\n }\n // included directly via