<commit_before>=================
sprite.js v1.1.0
=================

The sprite.js framework lets you create animations and games
using sprites in an efficient way. The goal is to have common
framework for Desktop and mobile browsers.

sprite.js has been tested on Chromium, Firefox, Android emulator, Opera and IE9.

For an example of the what the framework offers, have a look at the test files:

http://batiste.dosimple.ch/sprite.js/tests/

Example usage
=================

Example of a basic use::

    <script src="sprite.js"></script>

    <script>
    // set the Scene object
    var scene = sjs.Scene({w:640, h:480});

    // load the images in parallel. When all the images are
    // ready, the callback function is called.
    scene.loadImages(['character.png'], function() {

        // create the Sprite object;
        var sp = scene.Sprite('character.png');

        // change the visible size of the sprite
        sp.size(55, 30);

        // apply the latest visual changes to the sprite (draw if canvas, update attribute if DOM);
        sp.update();

        // change the offset of the image in the sprite (this works the opposite way of a CSS background)
        sp.offset(50, 50);

        // diverse transformations
        sp.move(100, 100);
        sp.rotate(3.14 / 4);
        sp.scale(2);
        sp.opacity = 0.8;

        sp.update();
    });
    </script>



Performance and different ways to draw
=======================================

This library provides 2 rendering backends: HTML and canvas.

By default the HTML backend is used. The HTML backend displays sprites using DOM elements when the canvas
backend draw the sprites on the canvas. Each layer of the application can have a different backend.
This enable you to mix the 2 technics if needed.

To use canvas with a layer you need to specify it in the options::

    var background = scene.Layer('background', {useCanvas:true});

The canvas will be automaticaly cleared by the game ticker. If you don't need it you can set the autoClear to false when building a layer::

    var background = scene.Layer('background', {useCanvas:true, autoClear:false});

Performances on particle test can be quite different depending on the device and browser and plateform:

+------------------------+---------------+-------------+---------------+---------------------+-------+
| Browsers               | Chrome linux  | Opera linux | Firefox linux | HTC Desire (webkit) | IE9   |
+========================+===============+=============+===============+=====================+=======+
| HTML backend           | 2000          | 60          | 500           | 120                 | 30    |
+------------------------+---------------+-------------+---------------+---------------------+-------+
| Canvas backend         | 1300          | 100         | 300           | 80                  | 600   |
+------------------------+---------------+-------------+---------------+---------------------+-------+


Scene object
==============

The scene object is where all the Sprites will be drawned. You always need to start by creating a scene::

    var scene = sjs.Scene({w:640, h:680});

A list of the different methods available on the Scene object::

    scene.loadImages(Arrar(<src>), callback)       // load the array of image source. When all is loaded, the callback is called.

    scene.Layer(<name>, <options>)                 // build a Layer object, see Layer section

    scene.Sprite(<src>, <layer>)                   // build a Sprite object, see Sprite section

    scene.Ticker(<tickDuration>, <paint function>) // build a Ticker object for this scene or reset the previous one

    scene.reset()                                  // Delete all layers present in this scene,
                                                   // delete dom from HTML Sprite in layers, pause the ticker.

    scene.Cycle(<triplets>)                        // alias for sjs.Cycle, look at Cycle section

    scene.Input()                                  // alias for sjs.Input, look at Input section


Sprite object public methods and attributes
===========================================


To create a sprite you should use the scene.Sprite constructor::

    var sprite = scene.Sprite(<src>, <layer>)

Both parameters are optionnal. If the layer is not specified, the default layer will be used. If you want to set the layer but not any image::

    var sprite = scene.Sprite(false, <layer>)

You can also init any Sprite properties by passing an object instead of the Layer object, eg::

    var sprite = scene.Sprite("mysprite.png", {layer:layer, x:10, size:[20, 20], y:15})

For technichal and performance reasons Sprite's attributes needs to be changed using a setters method. The following
attributes are *READ ONLY*::

    sprite.x        // position of the sprite from the left corner of the scene
    sprite.y        // position of the sprite from the top corner of the scene

    sprite.w        // controls the visible surface of the image. To have a repeating sprite background
                    // you can set the width or height value bigger than the size of the image.
    sprite.h

    sprite.xoffset  // horizontal offset in the image from where to start painting the sprite surface.
    sprite.yoffset  // verical offset
    sprite.xscale   // vertical and horizontal scaling
    sprite.yscale
    sprite.angle    // use radians
    sprite.opacity  // use float in the range 0-1
    sprite.color    // background color of the sprite. Use the rgb/hexadecimal CSS notation.

If you want to change any of those attributes use the following setters::

    sprite.setX(10);
    sprite.setY(12);
    sprite.setW(32);
    sprite.setH(32);
    sprite.setXOffset(10);
    sprite.setYOffset(5);
    sprite.setXScale(2);
    sprite.setYScale(3);
    sprite.setAngle(Math.PI / 2);
    sprite.setColor('#333');
    sprite.setOpacity(0.5);

Or one of those helper methods::

    sprite.rotate(radians)
    sprite.scale(x, y)      // if y is not defined, y take the same value as x
    sprite.move(x, y)       // move the sprite in the direction of the provided vector (x, y)
    sprite.position(x, y)   // set the position of the sprite (left, top)
    sprite.offset(x, y)
    sprite.size(w, h)       // set the width and height of the visible sprite

Sprites comes with methods that can help you implement a basic physic engine::

    sprite.xv                // horizontal velocity
    sprite.yv                // vertical velocity
    sprite.rv                // radial velocity
    sprite.applyVelocity()   // apply all velocities on the current Sprite
    sprite.reverseVelocity() // apply all the negative velocities on the current Sprite

    sprite.applyXVelocity()    // apply the horizontal xv velocity
    sprite.applyYVelocity()    // apply the vertical yv velocity
    sprite.reverseXVelocity()  // apply the horizontal xv velocity negatively
    sprite.reverseYVelocity()  // apply the vertical yv velocity negatively

    sprite.isPointIn(x, y)      // return true if the point (x, y) is within the sprite surface

    sprite.collidesWith(sprite) // return true if the sprite is in collision with the other sprite

    sprite.collidesWithArray([sprites]) // Search in  an array of sprite for a colliding sprite.
                                        // If found, a sprite is returned.

    sprite.distance(sprite)     // return the distance between 2 sprite center
    sprite.distance(x, y)       // return the distance between the sprite center and the point (x, y)

There is also 2 methods that can help to create special effects. You can use explode2 to separate the current sprite in 2 parts::

    // return 2 new sprites that are the 2 parts of the sprite according to the given position.
    // Default value for position is half the size of the sprite.
    [sprite1, sprite2] = sprite.explode2(<position>, <bool horizontal>, <layer>)

    // Return 4 new sprites that are the split from the center (x, y).
    // Default value for the center is the center of the sprite.
    [sprite1, sprite2, sprite3, sprite4] = sprite.explode4(<x>, <y>, <layer>)

Other important methods::

    sprite.loadImg(src, <bool resetSize>)    // change the image sprite. The size of the sprite will be reseted by
                                             // the new image if resetSize is true.

    sprite.remove // Remove the dom element if the HTML backend is used and facilite the garbage collection of the object.


    sprite.canvasUpdate(layer)  // draw the sprite on a given Canvas layer. This doesn't work with an HTML layer.


To update any visual changes to the view you should call the "update" method::

    Sprite.update()

With a canvas backend, the surface will be automaticaly cleared before each game tick. You will need to call update
to draw the sprite on the canvas again. If you don't want to do this you can set the layer autoClear attribute to false.

SpriteList object
==================

SpriteList is a convenience list type object that enable you to delete and add sprites without having to care
about indexes and for loop syntax::

    var sprite_list = sjs.SpriteList(<array of sprites>)

    sprite_list.add(sprite || array of sprite)  // add to the list
    sprite_list.remove(sprite)                  // delete from the list
    sprite_list.iterate()                       // iterate on the entire list then stops
    sprite_list.list.length                     // length of the list
    sprite_list.list                            // the actual list of sprite

Example of use::

    var crates = sjs.SpriteList([crate1, crate2]);

    var crate;
    while(crate = crates.iterate()) {
        crate.applyVelocity();
        if(crate.y > 200) {
            // remove it from the list
            crates.remove(crate);
            // remove it from the DOM
            crate.remove();
        }
    }


Ticker object
==============

Keeping track of time in javascript is tricky. Sprite.js provides a Ticker object to deal with
this issue.

A ticker is an object that keeps track of time properly, so it's straight
forward to render the changes in the scene. The ticker gives accurate ticks.
A game tick is the time between every Sprites/Physics update in your engine.
To setup a ticker::

    function paint() {

        myCycles.next(ticker.lastTicksElapsed);
        // do your animation and physic here

    }
    var ticker = scene.Ticker(35, paint); // we want a tick every 35ms
    ticker.run();

    ticker.pause();
    ticker.resume();

lastTicksElapsed is the number of ticks elapsed during 2 runs of the paint
function. If performances are good the value should be 1. If the number
is higher than 1, it means that there have been more game ticks than calls
to the paint function since the last time paint was called. In essence,
there were dropped frames. The game loop can use the tick count to make
sure it's physics end up in the right state, regardless of what has been
rendered.

Cycle object
============

A cycle object handles sprite animations by moving the offsets of the sprite.
A cycle is defined by list of tuples: (x offset, y offset, game tick duration), and the sprites the
cycle applies to. this is a cycle with 3 position, each lasting 5 game ticks::

    var cycle = scene.Cycle([[0, 2, 5],
                              [30, 2, 5],
                              [60, 2, 5]);
    var sprite = scene.Sprite("walk.png");
    cycle.addSprite(sprite);

    var sprites = [sprite1, sprite2];
    cycle.addSprites(sprites);  // add an Array of sprites to the cycle

    cycle.removeSprite(sprite); // remove the sprite from the cycle

    cycle.next()         // apply the next cycle to the sprite
    cycle.next(1, true)  // apply the next cycle *and* call update() on the sprites
    cycle.next(2)        // apply the second next cycle to the sprite
    cycle.goto(1)        // go to the second game tick in the triplet
    cycle.reset()        // reset the cycle to the original position
    cycle.repeat = false // if set to false, the animation will stop automaticaly after one run
    cycle.done           // can be used to check if the cycle has completed
                         // stays false if cycle is set to repeat = true

    cycle.update()       // calls update() on all the sprites in the cycle

Input object
=============

The input object deals with user input. There are a number of flags for keys
that will be true if the key is pressed::

    var input  = scene.Input();
    if(input.keyboard.right) {
        sprite.move(5, 0);
    }

Input.keyboard is a memory of which key is down and up. This is a list of the flags available in the keyboard object::

    keyboard.up
    keyboard.right
    keyboard.up
    keyboard.down
    keyboard.enter
    keyboard.space
    keyboard.ctrl

You also have access to those helpers on the input object::

    input.arrows() // arrows return true if any directionnal keyboard arrows are pressed
    input.keydown  // this is true if any key is down

If you need to know which key has just been pressed or released during the last game tick you can use those methods::

    input.keyPressed('up')
    input.keyReleased('up')



Layer object
=============

If you need to separate you sprites into logical layers, you can use the Layer
object::

    var background = scene.Layer('background', options);

You should then pass the layer as the second argument of the contructor of your sprites::

    var sprite = scene.Sprite('bg.png', background);

The layer object can take those options::

    var options = {
        useCanvas:true,   // force the use of the canvas on this layer, that enable you to mix HTML and canvas
        autoClear:false   // disable the automatic clearing of the canvas before every paint call.
    }


ScrollingSurface object
========================

This object provide a simple and efficent way to display a moving static background within a scene. The surface
only redraw the necessary parts instead of the whole scene at every frame.

A scrolling surface is build this way::

    var surface = sjs.SrollingSurface(scene, scene.w, scene.h, redrawCallback);

    function redrawCallback(layer, x, y) {
        // draw the necessary sprites on the layer
        sprite.updateCanvas(layer);
    })

    surface.move(x, y);       // move the surface in direction (x, y)
    surface.position(x, y);   // set the surface position to (x, y)
    surface.update();         // update the latest changes to the surface and call the redrawCallback

The redrawCallback is called everytime a part of the surface need to be updated. The absolute position on the surface
is provided for you to determine what to draw on this layer. The layer object has a width and height (layer.x, layer.y).


Troubleshooting
====================

When using canvas, I get an "Uncaught Error: INDEX_SIZE_ERR: DOM Exception 1" in updateCanvas
----------------------------------------------------------------------------------------------------

This error appears when canvas try to read an image out of the boundary of the image itself. Check that your cycle doesn't
go off the boundaries, and that the size and offset are correct.

<commit_msg>Add a link to the game "The invasion of the evil lords".<commit_after>=================
sprite.js v1.1.0
=================

The sprite.js framework lets you create animations and games
using sprites in an efficient way. The goal is to have common
framework for Desktop and mobile browsers.

sprite.js has been tested on Chromium, Firefox, Android emulator, Opera and IE9.

For an example of a game made with sprite.js there is an example game named "The invasion of the evil lords":

http://batiste.dosimple.ch/games/rpg/game.html

For an example of the what the framework offers, have a look at the test files:

http://batiste.dosimple.ch/sprite.js/tests/

Example usage
=================

Example of a basic use::

    <script src="sprite.js"></script>

    <script>
    // set the Scene object
    var scene = sjs.Scene({w:640, h:480});

    // load the images in parallel. When all the images are
    // ready, the callback function is called.
    scene.loadImages(['character.png'], function() {

        // create the Sprite object;
        var sp = scene.Sprite('character.png');

        // change the visible size of the sprite
        sp.size(55, 30);

        // apply the latest visual changes to the sprite (draw if canvas, update attribute if DOM);
        sp.update();

        // change the offset of the image in the sprite (this works the opposite way of a CSS background)
        sp.offset(50, 50);

        // diverse transformations
        sp.move(100, 100);
        sp.rotate(3.14 / 4);
        sp.scale(2);
        sp.opacity = 0.8;

        sp.update();
    });
    </script>



Performance and different ways to draw
=======================================

This library provides 2 rendering backends: HTML and canvas.

By default the HTML backend is used. The HTML backend displays sprites using DOM elements when the canvas
backend draw the sprites on the canvas. Each layer of the application can have a different backend.
This enable you to mix the 2 technics if needed.

To use canvas with a layer you need to specify it in the options::

    var background = scene.Layer('background', {useCanvas:true});

The canvas will be automaticaly cleared by the game ticker. If you don't need it you can set the autoClear to false when building a layer::

    var background = scene.Layer('background', {useCanvas:true, autoClear:false});

Performances on particle test can be quite different depending on the device and browser and plateform:

+------------------------+---------------+-------------+---------------+---------------------+-------+
| Browsers               | Chrome linux  | Opera linux | Firefox linux | HTC Desire (webkit) | IE9   |
+========================+===============+=============+===============+=====================+=======+
| HTML backend           | 2000          | 60          | 500           | 120                 | 30    |
+------------------------+---------------+-------------+---------------+---------------------+-------+
| Canvas backend         | 1300          | 100         | 300           | 80                  | 600   |
+------------------------+---------------+-------------+---------------+---------------------+-------+


Scene object
==============

The scene object is where all the Sprites will be drawned. You always need to start by creating a scene::

    var scene = sjs.Scene({w:640, h:680});

A list of the different methods available on the Scene object::

    scene.loadImages(Arrar(<src>), callback)       // load the array of image source. When all is loaded, the callback is called.

    scene.Layer(<name>, <options>)                 // build a Layer object, see Layer section

    scene.Sprite(<src>, <layer>)                   // build a Sprite object, see Sprite section

    scene.Ticker(<tickDuration>, <paint function>) // build a Ticker object for this scene or reset the previous one

    scene.reset()                                  // Delete all layers present in this scene,
                                                   // delete dom from HTML Sprite in layers, pause the ticker.

    scene.Cycle(<triplets>)                        // alias for sjs.Cycle, look at Cycle section

    scene.Input()                                  // alias for sjs.Input, look at Input section


Sprite object public methods and attributes
===========================================


To create a sprite you should use the scene.Sprite constructor::

    var sprite = scene.Sprite(<src>, <layer>)

Both parameters are optionnal. If the layer is not specified, the default layer will be used. If you want to set the layer but not any image::

    var sprite = scene.Sprite(false, <layer>)

You can also init any Sprite properties by passing an object instead of the Layer object, eg::

    var sprite = scene.Sprite("mysprite.png", {layer:layer, x:10, size:[20, 20], y:15})

For technichal and performance reasons Sprite's attributes needs to be changed using a setters method. The following
attributes are *READ ONLY*::

    sprite.x        // position of the sprite from the left corner of the scene
    sprite.y        // position of the sprite from the top corner of the scene

    sprite.w        // controls the visible surface of the image. To have a repeating sprite background
                    // you can set the width or height value bigger than the size of the image.
    sprite.h

    sprite.xoffset  // horizontal offset in the image from where to start painting the sprite surface.
    sprite.yoffset  // verical offset
    sprite.xscale   // vertical and horizontal scaling
    sprite.yscale
    sprite.angle    // use radians
    sprite.opacity  // use float in the range 0-1
    sprite.color    // background color of the sprite. Use the rgb/hexadecimal CSS notation.

If you want to change any of those attributes use the following setters::

    sprite.setX(10);
    sprite.setY(12);
    sprite.setW(32);
    sprite.setH(32);
    sprite.setXOffset(10);
    sprite.setYOffset(5);
    sprite.setXScale(2);
    sprite.setYScale(3);
    sprite.setAngle(Math.PI / 2);
    sprite.setColor('#333');
    sprite.setOpacity(0.5);

Or one of those helper methods::

    sprite.rotate(radians)
    sprite.scale(x, y)      // if y is not defined, y take the same value as x
    sprite.move(x, y)       // move the sprite in the direction of the provided vector (x, y)
    sprite.position(x, y)   // set the position of the sprite (left, top)
    sprite.offset(x, y)
    sprite.size(w, h)       // set the width and height of the visible sprite

Sprites comes with methods that can help you implement a basic physic engine::

    sprite.xv                // horizontal velocity
    sprite.yv                // vertical velocity
    sprite.rv                // radial velocity
    sprite.applyVelocity()   // apply all velocities on the current Sprite
    sprite.reverseVelocity() // apply all the negative velocities on the current Sprite

    sprite.applyXVelocity()    // apply the horizontal xv velocity
    sprite.applyYVelocity()    // apply the vertical yv velocity
    sprite.reverseXVelocity()  // apply the horizontal xv velocity negatively
    sprite.reverseYVelocity()  // apply the vertical yv velocity negatively

    sprite.isPointIn(x, y)      // return true if the point (x, y) is within the sprite surface

    sprite.collidesWith(sprite) // return true if the sprite is in collision with the other sprite

    sprite.collidesWithArray([sprites]) // Search in  an array of sprite for a colliding sprite.
                                        // If found, a sprite is returned.

    sprite.distance(sprite)     // return the distance between 2 sprite center
    sprite.distance(x, y)       // return the distance between the sprite center and the point (x, y)

There is also 2 methods that can help to create special effects. You can use explode2 to separate the current sprite in 2 parts::

    // return 2 new sprites that are the 2 parts of the sprite according to the given position.
    // Default value for position is half the size of the sprite.
    [sprite1, sprite2] = sprite.explode2(<position>, <bool horizontal>, <layer>)

    // Return 4 new sprites that are the split from the center (x, y).
    // Default value for the center is the center of the sprite.
    [sprite1, sprite2, sprite3, sprite4] = sprite.explode4(<x>, <y>, <layer>)

Other important methods::

    sprite.loadImg(src, <bool resetSize>)    // change the image sprite. The size of the sprite will be reseted by
                                             // the new image if resetSize is true.

    sprite.remove // Remove the dom element if the HTML backend is used and facilite the garbage collection of the object.


    sprite.canvasUpdate(layer)  // draw the sprite on a given Canvas layer. This doesn't work with an HTML layer.


To update any visual changes to the view you should call the "update" method::

    Sprite.update()

With a canvas backend, the surface will be automaticaly cleared before each game tick. You will need to call update
to draw the sprite on the canvas again. If you don't want to do this you can set the layer autoClear attribute to false.

SpriteList object
==================

SpriteList is a convenience list type object that enable you to delete and add sprites without having to care
about indexes and for loop syntax::

    var sprite_list = sjs.SpriteList(<array of sprites>)

    sprite_list.add(sprite || array of sprite)  // add to the list
    sprite_list.remove(sprite)                  // delete from the list
    sprite_list.iterate()                       // iterate on the entire list then stops
    sprite_list.list.length                     // length of the list
    sprite_list.list                            // the actual list of sprite

Example of use::

    var crates = sjs.SpriteList([crate1, crate2]);

    var crate;
    while(crate = crates.iterate()) {
        crate.applyVelocity();
        if(crate.y > 200) {
            // remove it from the list
            crates.remove(crate);
            // remove it from the DOM
            crate.remove();
        }
    }


Ticker object
==============

Keeping track of time in javascript is tricky. Sprite.js provides a Ticker object to deal with
this issue.

A ticker is an object that keeps track of time properly, so it's straight
forward to render the changes in the scene. The ticker gives accurate ticks.
A game tick is the time between every Sprites/Physics update in your engine.
To setup a ticker::

    function paint() {

        myCycles.next(ticker.lastTicksElapsed);
        // do your animation and physic here

    }
    var ticker = scene.Ticker(35, paint); // we want a tick every 35ms
    ticker.run();

    ticker.pause();
    ticker.resume();

lastTicksElapsed is the number of ticks elapsed during 2 runs of the paint
function. If performances are good the value should be 1. If the number
is higher than 1, it means that there have been more game ticks than calls
to the paint function since the last time paint was called. In essence,
there were dropped frames. The game loop can use the tick count to make
sure it's physics end up in the right state, regardless of what has been
rendered.

Cycle object
============

A cycle object handles sprite animations by moving the offsets of the sprite.
A cycle is defined by list of tuples: (x offset, y offset, game tick duration), and the sprites the
cycle applies to. this is a cycle with 3 position, each lasting 5 game ticks::

    var cycle = scene.Cycle([[0, 2, 5],
                              [30, 2, 5],
                              [60, 2, 5]);
    var sprite = scene.Sprite("walk.png");
    cycle.addSprite(sprite);

    var sprites = [sprite1, sprite2];
    cycle.addSprites(sprites);  // add an Array of sprites to the cycle

    cycle.removeSprite(sprite); // remove the sprite from the cycle

    cycle.next()         // apply the next cycle to the sprite
    cycle.next(1, true)  // apply the next cycle *and* call update() on the sprites
    cycle.next(2)        // apply the second next cycle to the sprite
    cycle.goto(1)        // go to the second game tick in the triplet
    cycle.reset()        // reset the cycle to the original position
    cycle.repeat = false // if set to false, the animation will stop automaticaly after one run
    cycle.done           // can be used to check if the cycle has completed
                         // stays false if cycle is set to repeat = true

    cycle.update()       // calls update() on all the sprites in the cycle

Input object
=============

The input object deals with user input. There are a number of flags for keys
that will be true if the key is pressed::

    var input  = scene.Input();
    if(input.keyboard.right) {
        sprite.move(5, 0);
    }

Input.keyboard is a memory of which key is down and up. This is a list of the flags available in the keyboard object::

    keyboard.up
    keyboard.right
    keyboard.up
    keyboard.down
    keyboard.enter
    keyboard.space
    keyboard.ctrl

You also have access to those helpers on the input object::

    input.arrows() // arrows return true if any directionnal keyboard arrows are pressed
    input.keydown  // this is true if any key is down

If you need to know which key has just been pressed or released during the last game tick you can use those methods::

    input.keyPressed('up')
    input.keyReleased('up')



Layer object
=============

If you need to separate you sprites into logical layers, you can use the Layer
object::

    var background = scene.Layer('background', options);

You should then pass the layer as the second argument of the contructor of your sprites::

    var sprite = scene.Sprite('bg.png', background);

The layer object can take those options::

    var options = {
        useCanvas:true,   // force the use of the canvas on this layer, that enable you to mix HTML and canvas
        autoClear:false   // disable the automatic clearing of the canvas before every paint call.
    }


ScrollingSurface object
========================

This object provide a simple and efficent way to display a moving static background within a scene. The surface
only redraw the necessary parts instead of the whole scene at every frame.

A scrolling surface is build this way::

    var surface = sjs.SrollingSurface(scene, scene.w, scene.h, redrawCallback);

    function redrawCallback(layer, x, y) {
        // draw the necessary sprites on the layer
        sprite.updateCanvas(layer);
    })

    surface.move(x, y);       // move the surface in direction (x, y)
    surface.position(x, y);   // set the surface position to (x, y)
    surface.update();         // update the latest changes to the surface and call the redrawCallback

The redrawCallback is called everytime a part of the surface need to be updated. The absolute position on the surface
is provided for you to determine what to draw on this layer. The layer object has a width and height (layer.x, layer.y).


Troubleshooting
====================

When using canvas, I get an "Uncaught Error: INDEX_SIZE_ERR: DOM Exception 1" in updateCanvas
----------------------------------------------------------------------------------------------------

This error appears when canvas try to read an image out of the boundary of the image itself. Check that your cycle doesn't
go off the boundaries, and that the size and offset are correct.


{'fraction_non_alphanumeric': 0.1174360980699009, 'fraction_numerical': 0.009520083463745435, 'mean_word_length': 2.4248548459133543, 'pattern_counts': {'":': 1, '<': 49, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5575284', 'n_tokens_mistral': 8331, 'n_tokens_neox': 7689, 'n_words': 3755}