summaryrefslogtreecommitdiff
path: root/jaws/src/core.js
diff options
context:
space:
mode:
Diffstat (limited to 'jaws/src/core.js')
-rwxr-xr-xjaws/src/core.js714
1 files changed, 714 insertions, 0 deletions
diff --git a/jaws/src/core.js b/jaws/src/core.js
new file mode 100755
index 0000000..ac28595
--- /dev/null
+++ b/jaws/src/core.js
@@ -0,0 +1,714 @@
+/**
+ * @namespace JawsJS core functions.
+ *
+ * Jaws, a HTML5 canvas/javascript 2D game development framework
+ *
+ * Homepage: http://jawsjs.com/
+ * Source: http://github.com/ippa/jaws/
+ * Documentation: http://jawsjs.com/docs/
+ *
+ * Works with: Chrome 6.0+, Firefox 3.6+, 4+, IE 9+
+ * License: LGPL - http://www.gnu.org/licenses/lgpl.html
+ *
+ * Jaws uses the "module pattern".
+ * Adds 1 global, <b>jaws</b>, so plays nice with all other JS libs.
+ *
+ * Formating guide:
+ * jaws.oneFunction()
+ * jaws.one_variable = 1
+ * new jaws.OneConstructor
+ *
+ * @property {int} mouse_x Mouse X position with respect to the canvas-element
+ * @property {int} mouse_y Mouse Y position with respect to the canvas-element
+ * @property {canvas} canvas The detected/created canvas-element used for the game
+ * @property {context} context The detected/created canvas 2D-context, used for all draw-operations
+ * @property {int} width Width of the canvas-element
+ * @property {int} height Height of the canvas-element
+ */
+var jaws = (function(jaws) {
+
+ var title;
+ var log_tag;
+
+ /*
+ * Placeholders for constructors in extras-dir. We define the constructors here to be able to give ppl better error-msgs.
+ * When the correct from extras-dir is included, these will be overwritten.
+ *
+ */
+ //jaws.Parallax = function() { throw("To use jaws.Parallax() you need to include src/extras/parallax.js") }
+ //jaws.QuadTree = function() { throw("To use QuadTree() you need to include src/extras/quadtree.js") }
+ //jaws.PixelMap = function() { throw("To use PixelMap() you need to include src/extras/pixel_map.js") }
+ //jaws.TileMap = function() { throw("To use TileMap() you need to include src/extras/tile_map.js") }
+ jaws.SpriteList = function() { throw("To use SpriteList() you need to include src/extras/sprite_list.js") }
+ jaws.Audio = function() { throw("To use jaws.Audio() you need to include src/extras/audio.js") }
+
+ /**
+ * Returns or sets contents of title's innerHTML
+ * @private
+ * @param {type} value The new value to set the innerHTML of title
+ * @returns {string} The innerHTML of title
+ */
+ jaws.title = function(value) {
+
+ if (!jaws.isString(value)) {
+ jaws.log.error("jaws.title: Passed in value is not a String.");
+ return;
+ }
+
+ if (value) {
+ return (title.innerHTML = value);
+ }
+ return title.innerHTML;
+ };
+
+ /**
+ * Unpacks Jaws core-constructors into the global namespace.
+ * If a global property is already taken, a warning will be written to jaws log.
+ */
+ jaws.unpack = function() {
+ var make_global = ["Sprite", "SpriteList", "Animation", "Viewport", "SpriteSheet", "Parallax", "TileMap", "pressed", "QuadTree"];
+
+ make_global.forEach(function(item) {
+ if (window[item]) {
+ jaws.log.warn("jaws.unpack: " + item + " already exists in global namespace.");
+ }
+ else {
+ window[item] = jaws[item];
+ }
+ });
+ };
+
+ /**
+ * Writes messages to either log_tag (if set) or console.log (if available)
+ * @param {string} msg The string to write
+ * @param {boolean} append If messages should be appended or not
+ */
+ jaws.log = function(msg, append) {
+ if (!jaws.isString(msg)) {
+ msg = JSON.stringify(msg);
+ }
+
+ if (jaws.log.on) {
+ if (log_tag && jaws.log.use_log_element) {
+ if (append) {
+ log_tag.innerHTML += msg + "<br />";
+ }
+ else {
+ log_tag.innerHTML = msg;
+ }
+ }
+ if (console.log && jaws.log.use_console) {
+ console.log("JawsJS: ", msg);
+ }
+ }
+ };
+
+ /**
+ * If logging should take place or not
+ * @type {boolean}
+ */
+ jaws.log.on = true;
+
+ /**
+ * If console.log should be used during log writing
+ * @type {boolean}
+ */
+ jaws.log.use_console = false;
+
+ /**
+ * If log_tag should be used during log writing
+ * @type {boolean}
+ */
+ jaws.log.use_log_element = true;
+
+ /**
+ * Write messages to console.warn (if it exists) or append current log
+ * @param {string|object} msg String or object to record
+ * @see jaws.log
+ */
+ jaws.log.warn = function(msg) {
+ if (console.warn && jaws.log.use_console && jaws.log.on) {
+ console.warn(msg);
+ } else {
+ jaws.log("[WARNING]: " + JSON.stringify(msg), true);
+ }
+ };
+
+ /**
+ * Write messages to console.error (if it exists) or append current log
+ * @param {string|object} msg String or object to record
+ * @see jaws.log
+ */
+ jaws.log.error = function(msg) {
+ if (console.error && jaws.log.use_console && jaws.log.on) {
+ console.error(msg);
+ } else {
+ jaws.log("[ERROR]: " + JSON.stringify(msg), true);
+ }
+ };
+
+ /**
+ * Write messages to console.info (if it exists) or append current log
+ * @param {string|object} msg String or object to record
+ * @see jaws.log
+ */
+ jaws.log.info = function(msg) {
+ if (console.info && jaws.log.use_console && jaws.log.on) {
+ console.info(msg);
+ } else {
+ jaws.log("[INFO]: " + JSON.stringify(msg), true);
+ }
+ };
+
+ /**
+ * Write messages to console.debug (if it exists) or append current log
+ * @param {string|object} msg String or object to record
+ * @see jaws.log
+ */
+ jaws.log.debug = function(msg) {
+ if (console.debug && jaws.log.use_console && jaws.log.on) {
+ console.debug(msg);
+ } else {
+ jaws.log("[DEBUG]: " + JSON.stringify(msg), true);
+ }
+ };
+
+ /**
+ * Clears the contents of log_tag element (if set) and console.log (if set)
+ */
+ jaws.log.clear = function() {
+ if (log_tag) {
+ log_tag.innerHTML = "";
+ }
+ if (console.clear) {
+ console.clear();
+ }
+ };
+
+ /**
+ * Initalizes jaws{canvas, context, dom, width, height}
+ * @private
+ * @param {object} options Object-literal of constructor properties
+ * @see jaws.url_parameters()
+ */
+ jaws.init = function(options) {
+
+ /* Find <title> tag */
+ title = document.getElementsByTagName('title')[0];
+ jaws.url_parameters = jaws.getUrlParameters();
+
+ jaws.canvas = document.getElementsByTagName('canvas')[0];
+ if (!jaws.canvas) {
+ jaws.dom = document.getElementById("canvas");
+ }
+
+ // Ordinary <canvas>, get context
+ if (jaws.canvas) {
+ jaws.context = jaws.canvas.getContext('2d');
+ }
+ else if (jaws.dom) {
+ jaws.dom.style.position = "relative";
+ }
+ else {
+ jaws.canvas = document.createElement("canvas");
+ jaws.canvas.width = options.width;
+ jaws.canvas.height = options.height;
+ jaws.context = jaws.canvas.getContext('2d');
+ document.body.appendChild(jaws.canvas);
+ }
+
+ /*
+ * If debug=1 parameter is present in the URL, let's either find <div id="jaws-log"> or create the tag.
+ * jaws.log(message) will use this div for debug/info output to the gamer or developer
+ *
+ */
+ log_tag = document.getElementById('jaws-log');
+ if (jaws.url_parameters["debug"]) {
+ if (!log_tag) {
+ log_tag = document.createElement("div");
+ log_tag.id = "jaws-log";
+ log_tag.style.cssText = "overflow: auto; color: #aaaaaa; width: 300px; height: 150px; margin: 40px auto 0px auto; padding: 5px; border: #444444 1px solid; clear: both; font: 10px verdana; text-align: left;";
+ document.body.appendChild(log_tag);
+ }
+ }
+
+
+ if(jaws.url_parameters["bust_cache"]) {
+ jaws.log.info("Busting cache when loading assets")
+ jaws.assets.bust_cache = true;
+ }
+
+ /* Let's scale sprites retro-style by default */
+ if (jaws.context)
+ jaws.useCrispScaling();
+
+ jaws.width = jaws.canvas ? jaws.canvas.width : jaws.dom.offsetWidth;
+ jaws.height = jaws.canvas ? jaws.canvas.height : jaws.dom.offsetHeight;
+
+ jaws.mouse_x = 0;
+ jaws.mouse_y = 0;
+ window.addEventListener("mousemove", saveMousePosition);
+ };
+
+ /**
+ * Use 'retro' crisp scaling when drawing sprites through the canvas API, this is the default
+ */
+ jaws.useCrispScaling = function() {
+ jaws.context.imageSmoothingEnabled = false;
+ jaws.context.webkitImageSmoothingEnabled = false;
+ jaws.context.mozImageSmoothingEnabled = false;
+ };
+
+ /**
+ * Use smooth antialiased scaling when drawing sprites through the canvas API
+ */
+ jaws.useSmoothScaling = function() {
+ jaws.context.imageSmoothingEnabled = true;
+ jaws.context.webkitImageSmoothingEnabled = true;
+ jaws.context.mozImageSmoothingEnabled = true;
+ };
+
+ /**
+ * Keeps updated mouse coordinates in jaws.mouse_x and jaws.mouse_y
+ * This is called each time event "mousemove" triggers.
+ * @private
+ * @param {EventObject} e The EventObject populated by the calling event
+ */
+ function saveMousePosition(e) {
+ jaws.mouse_x = (e.pageX || e.clientX);
+ jaws.mouse_y = (e.pageY || e.clientY);
+
+ var game_area = jaws.canvas ? jaws.canvas : jaws.dom;
+ jaws.mouse_x -= game_area.offsetLeft;
+ jaws.mouse_y -= game_area.offsetTop;
+ }
+
+ /**
+ * 1) Calls jaws.init(), detects or creats a canvas, and sets up the 2D context (jaws.canvas and jaws.context).
+ * 2) Pre-loads all defined assets with jaws.assets.loadAll().
+ * 3) Creates an instance of game_state and calls setup() on that instance.
+ * 4) Loops calls to update() and draw() with given FPS until game ends or another game state is activated.
+ * @param {function} game_state The game state function to be started
+ * @param {object} options Object-literal of game loop properties
+ * @param {object} game_state_setup_options Object-literal of game state properties and values
+ * @see jaws.init()
+ * @see jaws.setupInput()
+ * @see jaws.assets.loadAll()
+ * @see jaws.switchGameState()
+ * @example
+ *
+ * jaws.start(MyGame) // Start game state Game() with default options
+ * jaws.start(MyGame, {fps: 30}) // Start game state Game() with options, in this case jaws will run your game with 30 frames per second.
+ * jaws.start(window) // Use global functions setup(), update() and draw() if available. Not the recommended way but useful for testing and mini-games.
+ *
+ */
+ jaws.start = function(game_state, options, game_state_setup_options) {
+ if (!options) options = {};
+
+ var fps = options.fps || 60;
+ if (options.loading_screen === undefined) options.loading_screen = true;
+ if (!options.width) options.width = 500;
+ if (!options.height) options.height = 300;
+
+ /* Takes care of finding/creating canvas-element and debug-div */
+ jaws.init(options);
+
+ if (!jaws.isFunction(game_state) && !jaws.isObject(game_state)) {
+ jaws.log.error("jaws.start: Passed in GameState is niether function or object");
+ return;
+ }
+ if (!jaws.isObject(game_state_setup_options) && game_state_setup_options !== undefined) {
+ jaws.log.error("jaws.start: The setup options for the game state is not an object.");
+ return;
+ }
+
+ if (options.loading_screen) {
+ jaws.assets.displayProgress(0);
+ }
+
+ jaws.log.info("setupInput()", true);
+ jaws.setupInput();
+
+ /* Callback for when one single asset has been loaded */
+ function assetProgress(src, percent_done) {
+ jaws.log.info(percent_done + "%: " + src, true);
+ if (options.loading_screen) {
+ jaws.assets.displayProgress(percent_done);
+ }
+ }
+
+ /* Callback for when an asset can't be loaded*/
+ function assetError(src, percent_done) {
+ jaws.log.info(percent_done + "%: Error loading asset " + src, true);
+ }
+
+ /* Callback for when all assets are loaded */
+ function assetsLoaded() {
+ jaws.log.info("all assets loaded", true);
+ jaws.switchGameState(game_state || window, {fps: fps}, game_state_setup_options);
+ }
+
+ jaws.log.info("assets.loadAll()", true);
+ if (jaws.assets.length() > 0) {
+ jaws.assets.loadAll({onprogress: assetProgress, onerror: assetError, onload: assetsLoaded});
+ }
+ else {
+ assetsLoaded();
+ }
+ };
+
+ /**
+ * Switchs to a new active game state and saves previous game state in jaws.previous_game_state
+ * @param {function} game_state The game state function to start
+ * @param {object} options The object-literal properties to pass to the new game loop
+ * @param {object} game_state_setup_options The object-literal properties to pass to starting game state
+ * @example
+ *
+ * function MenuState() {
+ * this.setup = function() { ... }
+ * this.draw = function() { ... }
+ * this.update = function() {
+ * if(pressed("enter")) jaws.switchGameState(GameState); // Start game when Enter is pressed
+ * }
+ * }
+ *
+ * function GameState() {
+ * this.setup = function() { ... }
+ * this.update = function() { ... }
+ * this.draw = function() { ... }
+ * }
+ *
+ * jaws.start(MenuState)
+ *
+ */
+ jaws.switchGameState = function(game_state, options, game_state_setup_options) {
+ if(options === undefined) options = {};
+
+ if(jaws.isFunction(game_state)) {
+ game_state = new game_state;
+ }
+ if(!jaws.isObject(game_state)) {
+ jaws.log.error("jaws.switchGameState: Passed in GameState should be a Function or an Object.");
+ return;
+ }
+
+ var fps = (options && options.fps) || (jaws.game_loop && jaws.game_loop.fps) || 60;
+ var setup = options.setup
+
+ jaws.game_loop && jaws.game_loop.stop();
+ jaws.clearKeyCallbacks();
+
+ jaws.previous_game_state = jaws.game_state;
+ jaws.game_state = game_state;
+ jaws.game_loop = new jaws.GameLoop(game_state, {fps: fps, setup: setup}, game_state_setup_options);
+ jaws.game_loop.start();
+ };
+
+ /**
+ * Creates a new HTMLCanvasElement from a HTMLImageElement
+ * @param {HTMLImageElement} image The HTMLImageElement to convert to a HTMLCanvasElement
+ * @returns {HTMLCanvasElement} A HTMLCanvasElement with drawn HTMLImageElement content
+ */
+ jaws.imageToCanvas = function(image) {
+ if (jaws.isCanvas(image)) return image;
+
+ if (!jaws.isImage(image)) {
+ jaws.log.error("jaws.imageToCanvas: Passed in object is not an Image.");
+ return;
+ }
+
+ var canvas = document.createElement("canvas");
+ canvas.src = image.src;
+ canvas.width = image.width;
+ canvas.height = image.height;
+
+ var context = canvas.getContext("2d");
+ context.drawImage(image, 0, 0, image.width, image.height);
+ return canvas;
+ };
+
+ /**
+ * Returns object as an array
+ * @param {object} obj An array or object
+ * @returns {array} Either an array or the object as an array
+ * @example
+ *
+ * jaws.forceArray(1) // --> [1]
+ * jaws.forceArray([1,2]) // --> [1,2]
+ */
+ jaws.forceArray = function(obj) {
+ return Array.isArray(obj) ? obj : [obj];
+ };
+
+ /**
+ * Clears screen (the canvas-element) through context.clearRect()
+ */
+ jaws.clear = function() {
+ jaws.context.clearRect(0, 0, jaws.width, jaws.height);
+ };
+
+ /** Fills the screen with given fill_style */
+ jaws.fill = function(fill_style) {
+ jaws.context.fillStyle = fill_style;
+ jaws.context.fillRect(0, 0, jaws.width, jaws.height);
+ };
+
+
+ /**
+ * calls draw() on everything you throw on it. Give it arrays, argumentlists, arrays of arrays.
+ *
+ */
+ jaws.draw = function() {
+ var list = arguments;
+ if(list.length == 1 && jaws.isArray(list[0])) list = list[0];
+ for(var i=0; i < list.length; i++) {
+ if(jaws.isArray(list[i])) jaws.draw(list[i]);
+ else if(list[i].draw) list[i].draw();
+ }
+ }
+
+ /**
+ * calls update() on everything you throw on it. Give it arrays, argumentlists, arrays of arrays.
+ *
+ */
+ jaws.update = function() {
+ var list = arguments;
+ if(list.length == 1 && jaws.isArray(list[0])) list = list[0];
+ for(var i=0; i < list.length; i++) {
+ if(jaws.isArray(list[i])) jaws.update(list[i]);
+ else if(list[i].update) list[i].update();
+ }
+ }
+
+ /**
+ * Tests if object is an image or not
+ * @param {object} obj An Image or image-like object
+ * @returns {boolean} If object's prototype is "HTMLImageElement"
+ */
+ jaws.isImage = function(obj) {
+ return Object.prototype.toString.call(obj) === "[object HTMLImageElement]";
+ };
+
+ /**
+ * Tests if object is a Canvas object
+ * @param {type} obj A canvas or canvas-like object
+ * @returns {boolean} If object's prototype is "HTMLCanvasElement"
+ */
+ jaws.isCanvas = function(obj) {
+ return Object.prototype.toString.call(obj) === "[object HTMLCanvasElement]";
+ };
+
+ /**
+ * Tests if an object is either a canvas or an image object
+ * @param {object} obj A canvas or canva-like object
+ * @returns {boolean} If object isImage or isCanvas
+ */
+ jaws.isDrawable = function(obj) {
+ return jaws.isImage(obj) || jaws.isCanvas(obj);
+ };
+
+ /**
+ * Tests if an object is a string or not
+ * @param {object} obj A string or string-like object
+ * @returns {boolean} The result of typeof and constructor testing
+ */
+ jaws.isString = function(obj) {
+ return typeof obj === "string" || (typeof obj === "object" && obj.constructor === String);
+ };
+
+ /**
+ * Tests if an object is a number or not
+ * @param {number} n A number or number-like value
+ * @returns {boolean} If n passed isNaN() and isFinite()
+ */
+ jaws.isNumber = function(n) {
+ return !isNaN(parseFloat(n)) && isFinite(n);
+ };
+
+ /**
+ * Tests if an object is an Array or not
+ * @param {object} obj An array or array-like object
+ * @returns {boolean} If object's constructor is "Array"
+ */
+ jaws.isArray = function(obj) {
+ if (!obj)
+ return false;
+ return !(obj.constructor.toString().indexOf("Array") === -1);
+ };
+
+ /**
+ * Tests if an object is an Object or not
+ * @param {object} value An object or object-like enitity
+ * @returns {boolean} If object is not null and typeof 'object'
+ */
+ jaws.isObject = function(value) {
+ return value !== null && typeof value === 'object';
+ };
+
+ /**
+ * Tests if an object is a function or not
+ * @param {object} obj A function or function-like object
+ * @returns {boolean} If the prototype of the object is "Function"
+ */
+ jaws.isFunction = function(obj) {
+ return (Object.prototype.toString.call(obj) === "[object Function]");
+ };
+
+ /**
+ * Tests if an object is a regular expression or not
+ * @param {object} obj A /regexp/-object
+ * @returns {boolean} If the object is an instance of RegExp
+ */
+ jaws.isRegExp = function(obj) {
+ return (obj instanceof RegExp);
+ };
+
+
+ /**
+ * Tests if an object is within drawing canvas (jaws.width and jaws.height)
+ * @param {object} item An object with both x and y properties
+ * @returns {boolean} If the item's x and y are less than 0 or more than jaws.width or jaws.height
+ */
+ jaws.isOutsideCanvas = function(item) {
+ if (item.x && item.y) {
+ return (item.x < 0 || item.y < 0 || item.x > jaws.width || item.y > jaws.height);
+ }
+ };
+
+ /**
+ * Sets x and y properties to 0 (if less than), or jaws.width or jaws.height (if greater than)
+ * @param {object} item An object with x and y properties
+ */
+ jaws.forceInsideCanvas = function(item) {
+ if (item.x && item.y) {
+ if (item.x < 0) {
+ item.x = 0;
+ }
+ if (item.x > jaws.width) {
+ item.x = jaws.width;
+ }
+ if (item.y < 0) {
+ item.y = 0;
+ }
+ if (item.y > jaws.height) {
+ item.y = jaws.height;
+ }
+ }
+ };
+
+ /**
+ * Parses current window.location for URL parameters and values
+ * @returns {array} Hash of url-parameters and their values
+ * @example
+ * // Given the current URL is <b>http://test.com/?debug=1&foo=bar</b>
+ * jaws.getUrlParameters() // --> {debug: 1, foo: bar}
+ */
+ jaws.getUrlParameters = function() {
+ var vars = [], hash;
+ var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
+ for (var i = 0; i < hashes.length; i++) {
+ hash = hashes[i].split('=');
+ vars.push(hash[0]);
+ vars[hash[0]] = hash[1];
+ }
+ return vars;
+ };
+
+ /**
+ * Compares an object's default properties against those sent to its constructor
+ * @param {object} object The object to compare and assign new values
+ * @param {object} options Object-literal of constructor properties and new values
+ * @param {object} defaults Object-literal of properties and their default values
+ */
+ jaws.parseOptions = function(object, options, defaults) {
+ object["options"] = options;
+
+ for (var option in options) {
+ if (defaults[option] === undefined) {
+ jaws.log.warn("jaws.parseOptions: Unsupported property " + option + "for " + object.constructor);
+ }
+ }
+ for (var option in defaults) {
+ if( jaws.isFunction(defaults[option]) ) defaults[option] = defaults[option]();
+ object[option] = (options[option] !== undefined) ? options[option] : jaws.clone(defaults[option]);
+ }
+ };
+
+ /**
+ * Returns a shallow copy of an array or object
+ * @param {array|object} value The array or object to clone
+ * @returns {array|object} A copy of an array of object
+ */
+ jaws.clone = function(value) {
+ if (jaws.isArray(value))
+ return value.slice(0);
+ if (jaws.isObject(value))
+ return JSON.parse(JSON.stringify(value));
+ return value;
+ };
+
+ /*
+ * Converts image to canvas 2D context. Then you can draw on it :).
+ */
+ jaws.imageToCanvasContext = function(image) {
+ var canvas = document.createElement("canvas")
+ canvas.width = image.width
+ canvas.height = image.height
+
+ var context = canvas.getContext("2d")
+ if(jaws.context) {
+ context.imageSmoothingEnabled = jaws.context.mozImageSmoothingEnabled;
+ context.webkitImageSmoothingEnabled = jaws.context.mozImageSmoothingEnabled;
+ context.mozImageSmoothingEnabled = jaws.context.mozImageSmoothingEnabled;
+ }
+
+ context.drawImage(image, 0, 0, canvas.width, canvas.height)
+ return context
+ }
+
+ /**
+ * scale 'image' by factor 'factor'.
+ * Scaling is done using nearest-neighbor ( retro-blocky-style ).
+ * Returns a canvas.
+ */
+ jaws.retroScaleImage = function(image, factor) {
+ var canvas = jaws.isImage(image) ? jaws.imageToCanvas(image) : image
+ var context = canvas.getContext("2d")
+ var data = context.getImageData(0,0,canvas.width,canvas.height).data
+
+ // Create new canvas to return
+ var canvas2 = document.createElement("canvas")
+ canvas2.width = image.width * factor
+ canvas2.height = image.height * factor
+ var context2 = canvas2.getContext("2d")
+ var to_data = context2.createImageData(canvas2.width, canvas2.height)
+
+ var w2 = to_data.width
+ var h2 = to_data.height
+ for (var y=0; y < h2; y += 1) {
+ var y2 = Math.floor(y / factor)
+ var y_as_x = y * to_data.width
+ var y2_as_x = y2 * image.width
+
+ for (var x=0; x < w2; x += 1) {
+ var x2 = Math.floor(x / factor)
+ var y_dst = (y_as_x + x) * 4
+ var y_src = (y2_as_x + x2) * 4
+
+ to_data.data[y_dst] = data[y_src];
+ to_data.data[y_dst+1] = data[y_src+1];
+ to_data.data[y_dst+2] = data[y_src+2];
+ to_data.data[y_dst+3] = data[y_src+3];
+ }
+ }
+
+ context2.putImageData(to_data, 0, 0)
+
+ return canvas2
+ }
+
+ return jaws;
+})(jaws || {});
+
+// Support CommonJS require()
+if(typeof module !== "undefined" && ('exports' in module)) { module.exports = jaws }