| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873 |
- //MooCanvas, My Object Oriented Canvas Element. Copyright (c) 2007 Olmo Maldonado, <http://ibolmo.no-ip.info/sandbox/moocanvas/>, MIT Style License.
- /*
- Script: Canvas.js
- Contains the <Canvas> class.
- Dependencies:
- MooTools, <http://mootools.net/>
- Element, and its dependencies
- Author:
- Olmo Maldonado, <http://olmo-maldonado.com/>
-
- Credits:
- Lightly based from Ralph Sommerer's work: <http://blogs.msdn.com/sompost/archive/2006/02/22/536967.aspx>
- Moderately based from excanvas: <http://excanvas.sourceforge.net/>
- Great thanks to Inviz, <http://inviz.ru/>, for his optimizing help.
-
- License:
- MIT License, <http://en.wikipedia.org/wiki/MIT_License>
- */
- /*
- Class: Canvas
- Creates the element <canvas> and extends the element with getContext if not defined.
- Arguments:
- id - The ID of the canvas element
- props - Optional properties for the canvas element, which also gets passed to the new Element
-
- Example:
- > var cv = new Canvas('cv');
- > var ctx = cv.getContext('2d');
- >
- > $(document.body).adopt(cv);
- */
- var MooCanvas = new Class({
-
- initialize: function(id, props) {
- var el;
- if($type(id) == 'string') {
- props = $merge({width: 300, height: 150}, props, {'id': id});
- el = new Element('canvas', props);
- if(!el.getContext) {
- if(!CanvasRenderingContext2D.cssFixed) {
- document.createStyleSheet().cssText =
- 'canvas{display:inline-block;overflow:hidden;text-align:left;cursor:default;}' +
- 'v\\:*{behavior:url(#default#VML)}' +
- 'o\\:*{behavior:url(#default#VML)}';
- CanvasRenderingContext2D.cssFixed = true;
- }
-
- el.set({
- styles: {
- width: props.width,
- height: props.height,
- display: 'inline-block',
- overflow: 'hidden'
- },
-
- getContext: function() {
- this.context = this.context || new CanvasRenderingContext2D(el);
- return this.context;
- }
- });
-
- }
- }
-
- return el;
- }
-
- });
- /*
- Class: CanvasRenderingContext2D
- Context2D class with all the Context methods specified by the WHATWG, <http://www.whatwg.org/specs/web-apps/current-work/#the-canvas>
-
- Arguments:
- el - Element requesting the context2D
- */
- var CanvasRenderingContext2D = new Class({
- initialize: function(el) {
- this.parent = el;
- this.fragment = document.createDocumentFragment();
- this.element = new Element('div', {
- styles: {
- width: el.clientWidth || el.width,
- height: el.clientHeight || el.height,
- overflow: 'hidden',
- position: 'absolute'
- }
- });
- this.fragment.appendChild(this.element);
- this.m = [
- [1, 0, 0],
- [0, 1, 0],
- [0, 0, 1]
- ];
- this.rot = 0;
- this.state = [];
- this.path = [];
- this.delay = 30;
- this.max = 10;
- this.i = 0;
-
- // from excanvas, subpixel rendering.
- this.Z = 10;
- this.Z2 = this.Z / 2;
- this.arcScaleX = 1;
- this.arcScaleY = 1;
- this.currentX = 0;
- this.currentY = 0;
-
-
- this.miterLimit = this.Z * 1;
- },
-
- lineWidth: 1,
- strokeStyle: '#000',
- fillStyle: '#fff',
- globalAlpha: 1,
- globalCompositeOperation: 'source-over',
- lineCap: 'butt',
- lineJoin: 'miter',
- shadowBlur: 0,
- shadowColor: '#000',
- shadowOffsetX: 0,
- shadowOffsetY: 0
-
- });
- /*
- Script: Path.js
- Dependencies:
- Canvas.js
-
- Author:
- Olmo Maldonado, <http://olmo-maldonado.com/>
-
- Credits:
- Lightly based from Ralph Sommerer's work: <http://blogs.msdn.com/sompost/archive/2006/02/22/536967.aspx>
- Moderately based from excanvas: <http://excanvas.sourceforge.net/>
- Great thanks to Inviz, <http://inviz.ru/>, for his optimizing help.
-
- License:
- MIT License, <http://en.wikipedia.org/wiki/MIT_License>
- */
- CanvasRenderingContext2D.implement({
-
- /*
- A path has a list of zero or more subpaths.
- Each subpath consists of a list of one or more points,
- connected by straight or curved lines, and a flag indicating whether
- the subpath is closed or not. A closed subpath is one where the
- last point of the subpath is connected to the first point of
- the subpath by a straight line. Subpaths with fewer than two
- points are ignored when painting the path.
- */
- /*
- Property:
- Empties the list of subpaths so that the context once again has zero
- subpaths.
- */
- beginPath: function() {
- this.path = [];
- this.moved = false;
- },
-
- /*
- Property:
- Creates a new subpath with the specified point as its first
- (and only) point.
- */
- moveTo: function(x, y) {
- this.path.push('m', this.coord(x, y));
- this.currentX = x;
- this.currentY = y;
- this.moved = true;
- },
-
- /*
- Property:
- Does nothing if the context has no subpaths.
- Otherwise, marks the last subpath as closed, create a new
- subpath whose first point is the same as the previous
- subpath's first point, and finally add this new subpath to the
- path.
- */
- closePath: function() {
- this.path.push('x');
- },
-
- /*
- Property:
- Method must do nothing if the context has no subpaths. Otherwise,
- it must connect the last point in the subpath to the given point
- (x, y) using a straight line, and must then add the given point
- (x, y) to the subpath.
- */
- lineTo: function(x, y) {
- this.path.push((this.moved ? 'l' : ','), this.coord(x, y));
- this.currentX = x;
- this.currentY = y;
- this.moved = false;
- },
- /*
- Property:
- Method must do nothing if the context has no subpaths. Otherwise,
- it must connect the last point in the subpath to the given point
- (x, y) using a straight line, and must then add the given point
- (x, y) to the subpath.
- */
- quadraticCurveTo: function(cpx, cpy, x, y) {
- var cx = 2 * cpx,
- cy = 2 * cpy;
-
- this.bezierCurveTo(
- (cx + this.currentX) / 3,
- (cy + this.currentY) / 3,
- (cx + x) / 3,
- (cy + y) / 3,
- x,
- y
- );
- },
-
- /*
- Property:
- Method must do nothing if the context has no subpaths. Otherwise,
- it must connect the last point in the subpath to the given point
- (x, y) using a bezier curve with control points (cp1x, cp1y) and
- (cp2x, cp2y). Then, it must add the point (x, y) to the subpath.
- */
- bezierCurveTo: function(cp0x, cp0y, cp1x, cp1y, x, y) {
- this.path.push(' c ',
- this.coord(cp0x, cp0y), ",",
- this.coord(cp1x, cp1y), ",",
- this.coord(x, y)
- );
-
- this.currentX = x;
- this.currentY = y;
- },
-
- /*
- Property:
- Method must do nothing if the context has no subpaths. If the context
- does have a subpath, then the behaviour depends on the arguments and
- the last point in the subpath.
-
- Let the point (x0, y0) be the last point in the subpath. Let The Arc
- be the shortest arc given by circumference of the circle that has one
- point tangent to the line defined by the points (x0, y0) and (x1, y1),
- another point tangent to the line defined by the points (x1, y1) and
- (x2, y2), and that has radius radius. The points at which this circle
- touches these two lines are called the start and end tangent points
- respectively.
-
- If the point (x2, y2) is on the line defined by the points (x0, y0)
- and (x1, y1) then the method must do nothing, as no arc would satisfy
- the above constraints.
-
- Otherwise, the method must connect the point (x0, y0) to the start
- tangent point by a straight line, then connect the start tangent point
- to the end tangent point by The Arc, and finally add the start and end
- tangent points to the subpath.
-
- Negative or zero values for radius must cause the implementation to
- raise an INDEX_SIZE_ERR exception.
- */
- arcTo: function(x, y, w, h) {
- },
-
- /*
- Property:
- Method draws an arc. If the context has any subpaths, then the method
- must add a straight line from the last point in the subpath to the
- start point of the arc. In any case, it must draw the arc between the
- start point of the arc and the end point of the arc, and add the start
- and end points of the arc to the subpath. The arc and its start and
- end points are defined as follows:
-
- Consider a circle that has its origin at (x, y) and that has radius
- radius. The points at startAngle and endAngle along the circle's
- circumference, measured in radians clockwise from the positive x-axis,
- are the start and end points respectively. The arc is the path along
- the circumference of this circle from the start point to the end point,
- going anti-clockwise if the anticlockwise argument is true, and
- clockwise otherwise.
-
- Negative or zero values for radius must cause the implementation to
- raise an INDEX_SIZE_ERR exception.
- */
- arc: function(x, y, rad, a0, a1, cw) {
- if(this.rot === 0) rad *= this.Z;
-
- var x0 = Math.cos(a0) * rad,
- y0 = Math.sin(a0) * rad,
- x1 = Math.cos(a1) * rad,
- y1 = Math.sin(a1) * rad;
-
- if (this.rot !== 0) {
- var da = Math.PI / 24;
- this.lineTo(x0 + x, y0 + y);
- if(cw) {
- if (a0 < a1) a0 += 2 * Math.PI;
- while(a0 - da > a1) this.lineTo(x + Math.cos(a0 -= da) * rad, y + Math.sin(a0) * rad);
- } else {
- if (a1 < a0) a1 += 2 * Math.PI;
- while(a0 + da < a1) this.lineTo(x + Math.cos(a0 += da) * rad, y + Math.sin(a0) * rad);
- }
- this.lineTo(x1 + x, y1 + y);
- return;
- }
-
- if (x0 == x1 && !cw) x0 += 0.125;
-
- var c = this.getCoords(x, y);
- this.path.push(cw ? 'at ' : 'wa ',
- Math.round(c.x - this.arcScaleX * rad) + ',' + Math.round(c.y - this.arcScaleY * rad), ' ',
- Math.round(c.x + this.arcScaleX * rad) + ',' + Math.round(c.y + this.arcScaleY * rad), ' ',
- this.coord(x0 + x - this.Z2, y0 + y - this.Z2), ' ',
- this.coord(x1 + x - this.Z2, y1 + y - this.Z2)
- );
- },
- /*
- Property:
- method must create a new subpath containing just the four points
- (x, y), (x+w, y), (x+w, y+h), (x, y+h), with those four points
- connected by straight lines, and must then mark the subpath as
- closed. It must then create a new subpath with the point (x, y)
- as the only point in the subpath.
-
- Negative values for w and h must cause the implementation to raise
- an INDEX_SIZE_ERR exception.
- */
- rect: function(x, y, w, h) {
- this.moveTo(x, y);
- this.lineTo(x + w, y);
- this.lineTo(x + w, y + h);
- this.lineTo(x, y + h);
- this.closePath();
- },
-
- /*
- Property:
- Method must fill each subpath of the current path in turn, using
- fillStyle, and using the non-zero winding number rule. Open subpaths
- must be implicitly closed when being filled (without affecting the
- actual subpaths).
- */
- fill: function() {
- this.stroke(true);
- },
- /*
- Property:
- Method must stroke each subpath of the current path in turn, using
- the strokeStyle, lineWidth, lineJoin, and (if appropriate) miterLimit
- attributes.
-
- Paths, when filled or stroked, must be painted without affecting the
- current path, and must be subject to transformations, shadow effects,
- global alpha, clipping paths, and global composition operators.
-
- The transformation is applied to the path when it is drawn, not when
- the path is constructed. Thus, a single path can be constructed and
- then drawn according to different transformations without recreating
- the path.
- */
-
- stroke: function(fill) {
- if(!this.path.length) return;
- var a, color;
- if (fill) {
- a = [1000, '<v:fill ' + this.processColorObject(this.fillStyle) + '></v:fill>'];
- } else {
- color = this.processColor(this.strokeStyle);
- a = [10,
- '<v:stroke ' +
- 'endcap="' + ((this.lineCap == 'butt') ? 'flat' : this.lineCap) + '" ' +
- 'joinstyle="' + this.lineJoin + '" ' +
- 'color="' + color.color + '" ' +
- 'opacity="' + color.opacity + '"' +
- '/>'];
- }
- this.element.insertAdjacentHTML('beforeEnd',
- '<v:shape ' +
- 'path="' + this.path.join('') + 'e" ' +
- 'stroked="' + !fill + '" ' +
- (!fill ? ('strokeweight="' + 0.8 * this.lineWidth * this.m[0][0] + '" ') : '') +
- 'filled="' + !!fill + '" ' +
- 'coordsize="' + this.Z * a[0] + ',' + this.Z * a[0] + '" ' +
- 'style="width:' + a[0] + 'px; height:' + a[0] + 'px; position: absolute;">' +
- a[1] +
- '</v:shape>'
- );
-
- this.parent.appendChild(this.fragment);
-
- if(fill && this.fillStyle.img) this.element.getLast().fill.alignshape = false; // not sure why this has to be called explicitly
-
- this.path = [];
- },
- /*
- Property:
- Method must create a new clipping path by calculating the intersection
- of the current clipping path and the area described by the current path
- (after applying the current transformation), using the non-zero winding
- number rule. Open subpaths must be implicitly closed when computing the
- clipping path, without affecting the actual subpaths.
-
- When the context is created, the initial clipping path is the rectangle
- with the top left corner at (0,0) and the width and height of the
- coordinate space.
- */
- clip: function() {
- },
-
- /*
- Property:
- Method must return true if the point given by the x and y coordinates
- passed to the method, when treated as coordinates in the canvas'
- coordinate space unaffected by the current transformation, is within
- the area of the canvas that is inside the current path; and must
- return false otherwise.
- */
- isPointInPath: function(x, y) {
-
- },
-
- processColor: function(col) { //path
- var a = this.globalAlpha;
- if (col.substr(0, 3) == 'rgb') {
- if (col.charAt(3) == "a") {
- a*= col.match(/([\d.]*)\)$/)[1];
- }
-
- col = col.rgbToHex();
- }
- return {
- color: col,
- opacity: a
- };
- },
-
- /*
- If a gradient has no stops defined, then the gradient must be treated as a
- solid transparent black. Gradients are, naturally, only painted where the
- stroking or filling effect requires that they be drawn.
- */
- processColorObject: function(obj) {
- var ret = '', col;
- if(obj.addColorStop) {
- ret += ((obj.r0) ? (
- 'type="gradientradial" ' +
- 'focusposition="0.2, 0.2" ' +
- 'focussize="0.2, 0.2" '
- ) : (
- 'type="gradient" ' +
- 'focus="0" ' +
- 'angle="' + (180 + (180 * obj.angle(obj.x0, obj.y0, obj.x1, obj.y1) / Math.PI)) + '" '
- )) +
- 'color="' + obj.col0.color + '" ' +
- 'opacity="' + obj.col0.opacity * 100 + '%" ' +
- 'color2="' + obj.col1.color + '" ' +
- 'o:opacity2="' + obj.col1.opacity * 100 + '%" ' +
- 'colors="';
- if(obj.stops) {
- for (var i = 0, l = obj.stops.length; i < l; i++) {
- ret += Math.round(100 * obj.stops[i][0]) + '% ' + obj.stops[i][1];
- }
- }
- ret +=
- '" ';
- } else if(obj.img) { //pattern
- ret +=
- 'type="tile" ' +
- 'src="' + obj.img.src + '" ';
- } else {
- col = this.processColor(obj);
- ret +=
- 'color="' + col.color + '" ' +
- 'opacity="' + col.opacity + '" ';
- }
-
- return ret;
- },
-
- getCoords: function(x, y) {
- var m = this.m;
- return {
- x: this.Z * (x * m[0][0] + y * m[1][0] + m[2][0]) - this.Z2,
- y: this.Z * (x * m[0][1] + y * m[1][1] + m[2][1]) - this.Z2
- };
- },
- coord: function(x, y) {
- var m = this.m;
- return [
- Math.round(this.Z * (x * m[0][0] + y * m[1][0] + m[2][0]) - this.Z2), ',',
- Math.round(this.Z * (x * m[0][1] + y * m[1][1] + m[2][1]) - this.Z2)
- ].join('');
- }
- });
- /*
- Script: Rects.js
- Dependencies:
- Canvas.js, Path.js
- Author:
- Olmo Maldonado, <http://olmo-maldonado.com/>
-
- Credits:
- Lightly based from Ralph Sommerer's work: <http://blogs.msdn.com/sompost/archive/2006/02/22/536967.aspx>
- Moderately based from excanvas: <http://excanvas.sourceforge.net/>
- Great thanks to Inviz, <http://inviz.ru/>, for his optimizing help.
-
- License:
- MIT License, <http://en.wikipedia.org/wiki/MIT_License>
- */
- CanvasRenderingContext2D.implement({
-
- /*
- Property: clearRect
- Clears the pixels in the specified rectangle.
- If height or width are zero has no effect.
-
- If no arguments, clears all of the canvas
-
- Currently, clearRect clears all of the canvas.
- */
- clearRect: function(x, y, w, h) {
- //if((x <= 0) && (y <= 0) && ( x + w >= this.element.width) && (y + h >= this.element.height)){
- this.element.innerHTML = '';
- //} else {
- // var f0 = this.fillStyle;
- // this.fillStyle = '#fff';
- // this.fillRect(x, y, w, h);
- // this.fillStyle = f0;
- //}
- },
-
- /*
- Property: fillRect
- Paints the specified rectangle using fillStyle.
- If height or width are zero, this method has no effect.
- */
- fillRect: function(x, y, w, h) {
- this.rect(x, y, w, h);
- this.fill();
- },
-
- /*
- Draws a rectangular outline of the specified size.
- If width or height are zero: ??
- */
- strokeRect: function(x, y, w, h) {
- this.rect(x, y, w, h);
- this.stroke();
- }
-
- });
- /*
- Script: Transform.js
- Dependencies:
- Canvas.js
- Author:
- Olmo Maldonado, <http://olmo-maldonado.com/>
-
- Credits:
- Lightly based from Ralph Sommerer's work: <http://blogs.msdn.com/sompost/archive/2006/02/22/536967.aspx>
- Moderately based from excanvas: <http://excanvas.sourceforge.net/>
- Great thanks to Inviz, <http://inviz.ru/>, for his optimizing help.
-
- License:
- MIT License, <http://en.wikipedia.org/wiki/MIT_License>
- */
- CanvasRenderingContext2D.implement({
- /*
- The transformation matrix is applied to all drawing operations prior
- to their being rendered. It is also applied when creating the clip region.
- * The transformations must be performed in reverse order. For instance,
- if a scale transformation that doubles the width is applied, followed
- by a rotation transformation that rotates drawing operations by a
- quarter turn, and a rectangle twice as wide as it is tall is then
- drawn on the canvas, the actual result will be a square.
- */
- /*
- Property: scale
- Method must add the scaling transformation described by the arguments
- to the transformation matrix. The x argument represents the scale factor
- in the horizontal direction and the y argument represents the scale
- factor in the vertical direction. The factors are multiples.
- */
- scale: function(x, y) {
- this.arcScaleX *= x;
- this.arcScaleY *= y;
-
- this.matMult([
- [x, 0, 0],
- [0, y, 0],
- [0, 0, 1]
- ]);
- },
-
- /*
- Property: rotate
- Method must add the rotation transformation described by the argument
- to the transformation matrix. The angle argument represents a clockwise
- rotation angle expressed in radians.
- */
- rotate: function(ang) {
- this.rot += ang;
- var c = Math.cos(ang),
- s = Math.sin(ang);
-
- this.matMult([
- [ c, s, 0],
- [-s, c, 0],
- [ 0, 0, 1]
- ]);
- },
-
- /*
- Property: translate
- Method must add the translation transformation described by the arguments
- to the transformation matrix. The x argument represents the translation
- distance in the horizontal direction and the y argument represents the
- translation distance in the vertical direction. The arguments are in
- coordinate space units.
- */
- translate: function(x, y) {
- this.matMult([
- [1, 0, 0],
- [0, 1, 0],
- [x, y, 1]
- ]);
- },
-
- /*
- Property: transform
- Method must multiply the current transformation matrix with the matrix described
- by the inputs.
- */
- transform: function(m11, m12, m21, m22, dx, dy) {
- this.matMult([
- [m11, m21, dx],
- [m12, m22, dy],
- [ 0, 0, 1]
- ]);
- },
-
- /*
- Property: setTransform
- Method must reset the current transform to the identity matrix, and then invoke
- the transform method with the same arguments.
- */
- setTransform: function(m11, m12, m21, m22, dx, dy) {
- this.m = [
- [1, 0, 0],
- [0, 1, 0],
- [0, 0, 1]
- ];
-
- this.transform(m11, m12, m21, m22, dx, dy);
- },
-
- /*
- Property: matMult
- Method to multiply 3x3 matrice. Currently takes input and multiplies against
- the transform matrix and saves the result to the transform matrix.
-
- This is an optimized multiplication method. Will only multiply if the input
- value is not zero. Thus, minimizing multiplications and additions.
- */
- matMult: function(b) {
- var m = this.m,
- o = [
- [0, 0, 0],
- [0, 0, 0],
- [0, 0, 0]
- ];
-
- for(var i = 0; i < 3; i++) {
- if(b[0][i] !== 0) this.sum(o[0], this.mult(b[0][i], m[i]));
- if(b[1][i] !== 0) this.sum(o[1], this.mult(b[1][i], m[i]));
- if(b[2][i] !== 0) this.sum(o[2], this.mult(b[2][i], m[i]));
- }
-
- this.m = [o[0], o[1], o[2]];
- },
- mult: function(x, y) {
- return [x * y[0], x * y[1], x * y[2]];
- },
-
- sum: function(o, v) {
- o[0] += v[0];
- o[1] += v[1];
- o[2] += v[2];
- }
- });
- /*
- Script: Image.js
- Dependencies:
- Canvas.js
- Author:
- Olmo Maldonado, <http://olmo-maldonado.com/>
-
- Credits:
- Lightly based from Ralph Sommerer's work: <http://blogs.msdn.com/sompost/archive/2006/02/22/536967.aspx>
- Moderately based from excanvas: <http://excanvas.sourceforge.net/>
- Great thanks to Inviz, <http://inviz.ru/>, for his optimizing help.
-
- License:
- MIT License, <http://en.wikipedia.org/wiki/MIT_License>
- */
- CanvasRenderingContext2D.implement({
- /*
- Property: drawImage
- This method is overloaded with three variants: drawImage(image, dx, dy),
- drawImage(image, dx, dy, dw, dh), and drawImage(image, sx, sy, sw, sh,
- dx, dy, dw, dh). (Actually it is overloaded with six; each of those three
- can take either an HTMLImageElement or an HTMLCanvasElement for the image
- argument.) If not specified, the dw and dh arguments default to the values
- of sw and sh, interpreted such that one CSS pixel in the image is treated
- as one unit in the canvas coordinate space. If the sx, sy, sw, and sh
- arguments are omitted, they default to 0, 0, the image's intrinsic width
- in image pixels, and the image's intrinsic height in image pixels,
- respectively.
-
- If the image is of the wrong type, the implementation must raise a
- TYPE_MISMATCH_ERR exception. If one of the sy, sw, sw, and sh arguments
- is outside the size of the image, or if one of the dw and dh arguments
- is negative, the implementation must raise an INDEX_SIZE_ERR exception.
-
- The specified region of the image specified by the source rectangle
- (sx, sy, sw, sh) must be painted on the region of the canvas specified
- by the destination rectangle (dx, dy, dw, dh).
-
- Images are painted without affecting the current path, and are subject to
- transformations, shadow effects, global alpha, clipping paths, and global
- composition operators.
- */
- drawImage: function (image, var_args) {
- var args = arguments,
- length = args.length,
- off = (length == 9) ? 4 : 0;
-
- if(!((length + '').test(/3|5|9/))) throw 'Wrong number of arguments';
-
- var w0 = image.runtimeStyle.width,
- h0 = image.runtimeStyle.height;
- image.runtimeStyle.width = 'auto';
- image.runtimeStyle.height = 'auto';
-
- var w = image.width,
- h = image.height;
- image.runtimeStyle.width = w0;
- image.runtimeStyle.height = h0;
-
- var sx = 0,
- sy = 0,
- sw = w,
- sh = h,
- dx = args[1 + off],
- dy = args[2 + off],
- dw = args[3 + off] || w,
- dh = args[4 + off] || h;
-
- if (length == 9) {
- sx = args[1];
- sy = args[2];
- sw = args[3];
- sh = args[4];
- }
- var d = this.getCoords(dx, dy),
- vmlStr =
- '<v:group coordsize="' + this.Z * 10 + ',' + this.Z * 10 + '" ' +
- 'coordorigin="0,0" ' +
- 'style="width:10;height:10;position:absolute;';
-
- if (this.m[0][0] != 1 || this.m[0][1]) {
- var max = Math.max(
- this.getCoords(dx + dw, dy),
- this.getCoords(dx, dy + dh),
- this.getCoords(dx + dw, dy + dh)
- );
-
- vmlStr +=
- 'padding:0;' +
- 'padding-right:' + Math.round(Math.max(d.x, max) / this.Z) + 'px;' +
- 'padding-bottom:' + Math.round(Math.max(d.y, max) / this.Z) + 'px;' +
- 'filter:progid:DXImageTransform.Microsoft.Matrix(' +
- "M11='" + this.m[0][0] + "', M12='" + this.m[1][0] + "', " +
- "M21='" + this.m[0][1] + "', M22='" + this.m[1][1] + "', " +
- "Dx='" + Math.round(d.x / this.Z) + "', Dy='" + Math.round(d.y / this.Z) + "', " +
- "sizingmethod='clip'" +
- ');';
- } else {
- vmlStr +=
- 'top:' + Math.round(d.y / this.Z) + 'px;' +
- 'left:' + Math.round(d.x / this.Z) + 'px;';
- }
-
- this.element.insertAdjacentHTML('BeforeEnd', vmlStr +
- '"><v:image src="' + image.src + '" ' +
- 'style="width:' + this.Z * dw + ';height:' + this.Z * dh + ';" ' +
- 'cropleft="' + sx / w + '" ' +
- 'croptop="' + sy / h + '" ' +
- 'cropright="' + (w - sx - sw) / w + '" ' +
- 'cropbottom="' + (h - sy - sh) / h + '" ' +
- '/></v:group>'
- );
-
- this.parent.appendChild(this.fragment);
- },
- drawImageFromRect: Function.empty,
-
- /*
- Property: getImageData
- Method must return an ImageData object representing the underlying
- pixel data for the area of the canvas denoted by the rectangle which
- has one corner at the (sx, sy) coordinate, and that has width sw and
- height sh. Pixels outside the canvas must be returned as transparent
- black.
- */
- getImageData: function(sx, sy, sw, sh) {
- },
-
- /*
- Property: putImageData
- Method must take the given ImageData structure, and draw it at the
- specified location dx,dy in the canvas coordinate space, mapping each
- pixel represented by the ImageData structure into one device pixel.
- */
- putImageData: function(image, dx, dy) {
-
- },
- getCoords: function(x, y) {
- var m = this.m;
- return {
- x: this.Z * (x * m[0][0] + y * m[1][0] + m[2][0]) - this.Z2,
- y: this.Z * (x * m[0][1] + y * m[1][1] + m[2][1]) - this.Z2
- };
- }
-
- });
|