123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928 |
- /*
- Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
- Available via Academic Free License >= 2.1 OR the modified BSD license.
- see: http://dojotoolkit.org/license for details
- */
- /*
- This is an optimized version of Dojo, built for deployment and not for
- development. To get sources and documentation, please visit:
- http://dojotoolkit.org
- */
- if(!dojo._hasResource["dojox.gfx.matrix"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
- dojo._hasResource["dojox.gfx.matrix"] = true;
- dojo.provide("dojox.gfx.matrix");
- (function(){
- var m = dojox.gfx.matrix;
- // candidates for dojox.math:
- var _degToRadCache = {};
- m._degToRad = function(degree){
- return _degToRadCache[degree] || (_degToRadCache[degree] = (Math.PI * degree / 180));
- };
- m._radToDeg = function(radian){ return radian / Math.PI * 180; };
- m.Matrix2D = function(arg){
- // summary: a 2D matrix object
- // description: Normalizes a 2D matrix-like object. If arrays is passed,
- // all objects of the array are normalized and multiplied sequentially.
- // arg: Object
- // a 2D matrix-like object, a number, or an array of such objects
- if(arg){
- if(typeof arg == "number"){
- this.xx = this.yy = arg;
- }else if(arg instanceof Array){
- if(arg.length > 0){
- var matrix = m.normalize(arg[0]);
- // combine matrices
- for(var i = 1; i < arg.length; ++i){
- var l = matrix, r = dojox.gfx.matrix.normalize(arg[i]);
- matrix = new m.Matrix2D();
- matrix.xx = l.xx * r.xx + l.xy * r.yx;
- matrix.xy = l.xx * r.xy + l.xy * r.yy;
- matrix.yx = l.yx * r.xx + l.yy * r.yx;
- matrix.yy = l.yx * r.xy + l.yy * r.yy;
- matrix.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
- matrix.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
- }
- dojo.mixin(this, matrix);
- }
- }else{
- dojo.mixin(this, arg);
- }
- }
- };
- // the default (identity) matrix, which is used to fill in missing values
- dojo.extend(m.Matrix2D, {xx: 1, xy: 0, yx: 0, yy: 1, dx: 0, dy: 0});
- dojo.mixin(m, {
- // summary: class constants, and methods of dojox.gfx.matrix
- // matrix constants
- // identity: dojox.gfx.matrix.Matrix2D
- // an identity matrix constant: identity * (x, y) == (x, y)
- identity: new m.Matrix2D(),
- // flipX: dojox.gfx.matrix.Matrix2D
- // a matrix, which reflects points at x = 0 line: flipX * (x, y) == (-x, y)
- flipX: new m.Matrix2D({xx: -1}),
- // flipY: dojox.gfx.matrix.Matrix2D
- // a matrix, which reflects points at y = 0 line: flipY * (x, y) == (x, -y)
- flipY: new m.Matrix2D({yy: -1}),
- // flipXY: dojox.gfx.matrix.Matrix2D
- // a matrix, which reflects points at the origin of coordinates: flipXY * (x, y) == (-x, -y)
- flipXY: new m.Matrix2D({xx: -1, yy: -1}),
- // matrix creators
- translate: function(a, b){
- // summary: forms a translation matrix
- // description: The resulting matrix is used to translate (move) points by specified offsets.
- // a: Number: an x coordinate value
- // b: Number: a y coordinate value
- if(arguments.length > 1){
- return new m.Matrix2D({dx: a, dy: b}); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // a: dojox.gfx.Point: a point-like object, which specifies offsets for both dimensions
- // b: null
- return new m.Matrix2D({dx: a.x, dy: a.y}); // dojox.gfx.matrix.Matrix2D
- },
- scale: function(a, b){
- // summary: forms a scaling matrix
- // description: The resulting matrix is used to scale (magnify) points by specified offsets.
- // a: Number: a scaling factor used for the x coordinate
- // b: Number: a scaling factor used for the y coordinate
- if(arguments.length > 1){
- return new m.Matrix2D({xx: a, yy: b}); // dojox.gfx.matrix.Matrix2D
- }
- if(typeof a == "number"){
- // branch
- // a: Number: a uniform scaling factor used for the both coordinates
- // b: null
- return new m.Matrix2D({xx: a, yy: a}); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // a: dojox.gfx.Point: a point-like object, which specifies scale factors for both dimensions
- // b: null
- return new m.Matrix2D({xx: a.x, yy: a.y}); // dojox.gfx.matrix.Matrix2D
- },
- rotate: function(angle){
- // summary: forms a rotating matrix
- // description: The resulting matrix is used to rotate points
- // around the origin of coordinates (0, 0) by specified angle.
- // angle: Number: an angle of rotation in radians (>0 for CW)
- var c = Math.cos(angle);
- var s = Math.sin(angle);
- return new m.Matrix2D({xx: c, xy: -s, yx: s, yy: c}); // dojox.gfx.matrix.Matrix2D
- },
- rotateg: function(degree){
- // summary: forms a rotating matrix
- // description: The resulting matrix is used to rotate points
- // around the origin of coordinates (0, 0) by specified degree.
- // See dojox.gfx.matrix.rotate() for comparison.
- // degree: Number: an angle of rotation in degrees (>0 for CW)
- return m.rotate(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
- },
- skewX: function(angle) {
- // summary: forms an x skewing matrix
- // description: The resulting matrix is used to skew points in the x dimension
- // around the origin of coordinates (0, 0) by specified angle.
- // angle: Number: an skewing angle in radians
- return new m.Matrix2D({xy: Math.tan(angle)}); // dojox.gfx.matrix.Matrix2D
- },
- skewXg: function(degree){
- // summary: forms an x skewing matrix
- // description: The resulting matrix is used to skew points in the x dimension
- // around the origin of coordinates (0, 0) by specified degree.
- // See dojox.gfx.matrix.skewX() for comparison.
- // degree: Number: an skewing angle in degrees
- return m.skewX(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
- },
- skewY: function(angle){
- // summary: forms a y skewing matrix
- // description: The resulting matrix is used to skew points in the y dimension
- // around the origin of coordinates (0, 0) by specified angle.
- // angle: Number: an skewing angle in radians
- return new m.Matrix2D({yx: Math.tan(angle)}); // dojox.gfx.matrix.Matrix2D
- },
- skewYg: function(degree){
- // summary: forms a y skewing matrix
- // description: The resulting matrix is used to skew points in the y dimension
- // around the origin of coordinates (0, 0) by specified degree.
- // See dojox.gfx.matrix.skewY() for comparison.
- // degree: Number: an skewing angle in degrees
- return m.skewY(m._degToRad(degree)); // dojox.gfx.matrix.Matrix2D
- },
- reflect: function(a, b){
- // summary: forms a reflection matrix
- // description: The resulting matrix is used to reflect points around a vector,
- // which goes through the origin.
- // a: dojox.gfx.Point: a point-like object, which specifies a vector of reflection
- // b: null
- if(arguments.length == 1){
- b = a.y;
- a = a.x;
- }
- // branch
- // a: Number: an x coordinate value
- // b: Number: a y coordinate value
- // make a unit vector
- var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = 2 * a * b / n2;
- return new m.Matrix2D({xx: 2 * a2 / n2 - 1, xy: xy, yx: xy, yy: 2 * b2 / n2 - 1}); // dojox.gfx.matrix.Matrix2D
- },
- project: function(a, b){
- // summary: forms an orthogonal projection matrix
- // description: The resulting matrix is used to project points orthogonally on a vector,
- // which goes through the origin.
- // a: dojox.gfx.Point: a point-like object, which specifies a vector of projection
- // b: null
- if(arguments.length == 1){
- b = a.y;
- a = a.x;
- }
- // branch
- // a: Number: an x coordinate value
- // b: Number: a y coordinate value
- // make a unit vector
- var a2 = a * a, b2 = b * b, n2 = a2 + b2, xy = a * b / n2;
- return new m.Matrix2D({xx: a2 / n2, xy: xy, yx: xy, yy: b2 / n2}); // dojox.gfx.matrix.Matrix2D
- },
- // ensure matrix 2D conformance
- normalize: function(matrix){
- // summary: converts an object to a matrix, if necessary
- // description: Converts any 2D matrix-like object or an array of
- // such objects to a valid dojox.gfx.matrix.Matrix2D object.
- // matrix: Object: an object, which is converted to a matrix, if necessary
- return (matrix instanceof m.Matrix2D) ? matrix : new m.Matrix2D(matrix); // dojox.gfx.matrix.Matrix2D
- },
- // common operations
- clone: function(matrix){
- // summary: creates a copy of a 2D matrix
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to be cloned
- var obj = new m.Matrix2D();
- for(var i in matrix){
- if(typeof(matrix[i]) == "number" && typeof(obj[i]) == "number" && obj[i] != matrix[i]) obj[i] = matrix[i];
- }
- return obj; // dojox.gfx.matrix.Matrix2D
- },
- invert: function(matrix){
- // summary: inverts a 2D matrix
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object to be inverted
- var M = m.normalize(matrix),
- D = M.xx * M.yy - M.xy * M.yx,
- M = new m.Matrix2D({
- xx: M.yy/D, xy: -M.xy/D,
- yx: -M.yx/D, yy: M.xx/D,
- dx: (M.xy * M.dy - M.yy * M.dx) / D,
- dy: (M.yx * M.dx - M.xx * M.dy) / D
- });
- return M; // dojox.gfx.matrix.Matrix2D
- },
- _multiplyPoint: function(matrix, x, y){
- // summary: applies a matrix to a point
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
- // x: Number: an x coordinate of a point
- // y: Number: a y coordinate of a point
- return {x: matrix.xx * x + matrix.xy * y + matrix.dx, y: matrix.yx * x + matrix.yy * y + matrix.dy}; // dojox.gfx.Point
- },
- multiplyPoint: function(matrix, /* Number||Point */ a, /* Number, optional */ b){
- // summary: applies a matrix to a point
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
- // a: Number: an x coordinate of a point
- // b: Number: a y coordinate of a point
- var M = m.normalize(matrix);
- if(typeof a == "number" && typeof b == "number"){
- return m._multiplyPoint(M, a, b); // dojox.gfx.Point
- }
- // branch
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix object to be applied
- // a: dojox.gfx.Point: a point
- // b: null
- return m._multiplyPoint(M, a.x, a.y); // dojox.gfx.Point
- },
- multiply: function(matrix){
- // summary: combines matrices by multiplying them sequentially in the given order
- // matrix: dojox.gfx.matrix.Matrix2D...: a 2D matrix-like object,
- // all subsequent arguments are matrix-like objects too
- var M = m.normalize(matrix);
- // combine matrices
- for(var i = 1; i < arguments.length; ++i){
- var l = M, r = m.normalize(arguments[i]);
- M = new m.Matrix2D();
- M.xx = l.xx * r.xx + l.xy * r.yx;
- M.xy = l.xx * r.xy + l.xy * r.yy;
- M.yx = l.yx * r.xx + l.yy * r.yx;
- M.yy = l.yx * r.xy + l.yy * r.yy;
- M.dx = l.xx * r.dx + l.xy * r.dy + l.dx;
- M.dy = l.yx * r.dx + l.yy * r.dy + l.dy;
- }
- return M; // dojox.gfx.matrix.Matrix2D
- },
- // high level operations
- _sandwich: function(matrix, x, y){
- // summary: applies a matrix at a centrtal point
- // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object, which is applied at a central point
- // x: Number: an x component of the central point
- // y: Number: a y component of the central point
- return m.multiply(m.translate(x, y), matrix, m.translate(-x, -y)); // dojox.gfx.matrix.Matrix2D
- },
- scaleAt: function(a, b, c, d){
- // summary: scales a picture using a specified point as a center of scaling
- // description: Compare with dojox.gfx.matrix.scale().
- // a: Number: a scaling factor used for the x coordinate
- // b: Number: a scaling factor used for the y coordinate
- // c: Number: an x component of a central point
- // d: Number: a y component of a central point
- // accepts several signatures:
- // 1) uniform scale factor, Point
- // 2) uniform scale factor, x, y
- // 3) x scale, y scale, Point
- // 4) x scale, y scale, x, y
- switch(arguments.length){
- case 4:
- // a and b are scale factor components, c and d are components of a point
- return m._sandwich(m.scale(a, b), c, d); // dojox.gfx.matrix.Matrix2D
- case 3:
- if(typeof c == "number"){
- // branch
- // a: Number: a uniform scaling factor used for both coordinates
- // b: Number: an x component of a central point
- // c: Number: a y component of a central point
- // d: null
- return m._sandwich(m.scale(a), b, c); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // a: Number: a scaling factor used for the x coordinate
- // b: Number: a scaling factor used for the y coordinate
- // c: dojox.gfx.Point: a central point
- // d: null
- return m._sandwich(m.scale(a, b), c.x, c.y); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // a: Number: a uniform scaling factor used for both coordinates
- // b: dojox.gfx.Point: a central point
- // c: null
- // d: null
- return m._sandwich(m.scale(a), b.x, b.y); // dojox.gfx.matrix.Matrix2D
- },
- rotateAt: function(angle, a, b){
- // summary: rotates a picture using a specified point as a center of rotation
- // description: Compare with dojox.gfx.matrix.rotate().
- // angle: Number: an angle of rotation in radians (>0 for CW)
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) rotation angle in radians, Point
- // 2) rotation angle in radians, x, y
- if(arguments.length > 2){
- return m._sandwich(m.rotate(angle), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // angle: Number: an angle of rotation in radians (>0 for CCW)
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.rotate(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- },
- rotategAt: function(degree, a, b){
- // summary: rotates a picture using a specified point as a center of rotation
- // description: Compare with dojox.gfx.matrix.rotateg().
- // degree: Number: an angle of rotation in degrees (>0 for CW)
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) rotation angle in degrees, Point
- // 2) rotation angle in degrees, x, y
- if(arguments.length > 2){
- return m._sandwich(m.rotateg(degree), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // degree: Number: an angle of rotation in degrees (>0 for CCW)
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.rotateg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- },
- skewXAt: function(angle, a, b){
- // summary: skews a picture along the x axis using a specified point as a center of skewing
- // description: Compare with dojox.gfx.matrix.skewX().
- // angle: Number: an skewing angle in radians
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) skew angle in radians, Point
- // 2) skew angle in radians, x, y
- if(arguments.length > 2){
- return m._sandwich(m.skewX(angle), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // angle: Number: an skewing angle in radians
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.skewX(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- },
- skewXgAt: function(degree, a, b){
- // summary: skews a picture along the x axis using a specified point as a center of skewing
- // description: Compare with dojox.gfx.matrix.skewXg().
- // degree: Number: an skewing angle in degrees
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) skew angle in degrees, Point
- // 2) skew angle in degrees, x, y
- if(arguments.length > 2){
- return m._sandwich(m.skewXg(degree), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // degree: Number: an skewing angle in degrees
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.skewXg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- },
- skewYAt: function(angle, a, b){
- // summary: skews a picture along the y axis using a specified point as a center of skewing
- // description: Compare with dojox.gfx.matrix.skewY().
- // angle: Number: an skewing angle in radians
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) skew angle in radians, Point
- // 2) skew angle in radians, x, y
- if(arguments.length > 2){
- return m._sandwich(m.skewY(angle), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // angle: Number: an skewing angle in radians
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.skewY(angle), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- },
- skewYgAt: function(/* Number */ degree, /* Number||Point */ a, /* Number, optional */ b){
- // summary: skews a picture along the y axis using a specified point as a center of skewing
- // description: Compare with dojox.gfx.matrix.skewYg().
- // degree: Number: an skewing angle in degrees
- // a: Number: an x component of a central point
- // b: Number: a y component of a central point
- // accepts several signatures:
- // 1) skew angle in degrees, Point
- // 2) skew angle in degrees, x, y
- if(arguments.length > 2){
- return m._sandwich(m.skewYg(degree), a, b); // dojox.gfx.matrix.Matrix2D
- }
- // branch
- // degree: Number: an skewing angle in degrees
- // a: dojox.gfx.Point: a central point
- // b: null
- return m._sandwich(m.skewYg(degree), a.x, a.y); // dojox.gfx.matrix.Matrix2D
- }
- //TODO: rect-to-rect mapping, scale-to-fit (isotropic and anisotropic versions)
- });
- })();
- // propagate Matrix2D up
- dojox.gfx.Matrix2D = dojox.gfx.matrix.Matrix2D;
- }
- if(!dojo._hasResource["dojox.gfx._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
- dojo._hasResource["dojox.gfx._base"] = true;
- dojo.provide("dojox.gfx._base");
- (function(){
- var g = dojox.gfx, b = g._base;
- // candidates for dojox.style (work on VML and SVG nodes)
- g._hasClass = function(/*DomNode*/node, /*String*/classStr){
- // summary:
- // Returns whether or not the specified classes are a portion of the
- // class list currently applied to the node.
- // return (new RegExp('(^|\\s+)'+classStr+'(\\s+|$)')).test(node.className) // Boolean
- var cls = node.getAttribute("className");
- return cls && (" " + cls + " ").indexOf(" " + classStr + " ") >= 0; // Boolean
- };
- g._addClass = function(/*DomNode*/node, /*String*/classStr){
- // summary:
- // Adds the specified classes to the end of the class list on the
- // passed node.
- var cls = node.getAttribute("className") || "";
- if(!cls || (" " + cls + " ").indexOf(" " + classStr + " ") < 0){
- node.setAttribute("className", cls + (cls ? " " : "") + classStr);
- }
- };
- g._removeClass = function(/*DomNode*/node, /*String*/classStr){
- // summary: Removes classes from node.
- var cls = node.getAttribute("className");
- if(cls){
- node.setAttribute(
- "className",
- cls.replace(new RegExp('(^|\\s+)' + classStr + '(\\s+|$)'), "$1$2")
- );
- }
- };
- // candidate for dojox.html.metrics (dynamic font resize handler is not implemented here)
- // derived from Morris John's emResized measurer
- b._getFontMeasurements = function(){
- // summary:
- // Returns an object that has pixel equivilents of standard font
- // size values.
- var heights = {
- '1em': 0, '1ex': 0, '100%': 0, '12pt': 0, '16px': 0, 'xx-small': 0,
- 'x-small': 0, 'small': 0, 'medium': 0, 'large': 0, 'x-large': 0,
- 'xx-large': 0
- };
- if(dojo.isIE){
- // we do a font-size fix if and only if one isn't applied already.
- // NOTE: If someone set the fontSize on the HTML Element, this will kill it.
- dojo.doc.documentElement.style.fontSize="100%";
- }
- // set up the measuring node.
- var div = dojo.create("div", {style: {
- position: "absolute",
- left: "0",
- top: "-100px",
- width: "30px",
- height: "1000em",
- borderWidth: "0",
- margin: "0",
- padding: "0",
- outline: "none",
- lineHeight: "1",
- overflow: "hidden"
- }}, dojo.body());
- // do the measurements.
- for(var p in heights){
- div.style.fontSize = p;
- heights[p] = Math.round(div.offsetHeight * 12/16) * 16/12 / 1000;
- }
- dojo.body().removeChild(div);
- return heights; // object
- };
- var fontMeasurements = null;
- b._getCachedFontMeasurements = function(recalculate){
- if(recalculate || !fontMeasurements){
- fontMeasurements = b._getFontMeasurements();
- }
- return fontMeasurements;
- };
- // candidate for dojox.html.metrics
- var measuringNode = null, empty = {};
- b._getTextBox = function( /*String*/ text,
- /*Object*/ style,
- /*String?*/ className){
- var m, s, al = arguments.length;
- if(!measuringNode){
- measuringNode = dojo.create("div", {style: {
- position: "absolute",
- top: "-10000px",
- left: "0"
- }}, dojo.body());
- }
- m = measuringNode;
- // reset styles
- m.className = "";
- s = m.style;
- s.borderWidth = "0";
- s.margin = "0";
- s.padding = "0";
- s.outline = "0";
- // set new style
- if(al > 1 && style){
- for(var i in style){
- if(i in empty){ continue; }
- s[i] = style[i];
- }
- }
- // set classes
- if(al > 2 && className){
- m.className = className;
- }
- // take a measure
- m.innerHTML = text;
- if(m["getBoundingClientRect"]){
- var bcr = m.getBoundingClientRect();
- return {l: bcr.left, t: bcr.top, w: bcr.width || (bcr.right - bcr.left), h: bcr.height || (bcr.bottom - bcr.top)};
- }else{
- return dojo.marginBox(m);
- }
- };
- // candidate for dojo.dom
- var uniqueId = 0;
- b._getUniqueId = function(){
- // summary: returns a unique string for use with any DOM element
- var id;
- do{
- id = dojo._scopeName + "Unique" + (++uniqueId);
- }while(dojo.byId(id));
- return id;
- };
- })();
- dojo.mixin(dojox.gfx, {
- // summary:
- // defines constants, prototypes, and utility functions
- // default shapes, which are used to fill in missing parameters
- defaultPath: {
- type: "path", path: ""
- },
- defaultPolyline: {
- type: "polyline", points: []
- },
- defaultRect: {
- type: "rect", x: 0, y: 0, width: 100, height: 100, r: 0
- },
- defaultEllipse: {
- type: "ellipse", cx: 0, cy: 0, rx: 200, ry: 100
- },
- defaultCircle: {
- type: "circle", cx: 0, cy: 0, r: 100
- },
- defaultLine: {
- type: "line", x1: 0, y1: 0, x2: 100, y2: 100
- },
- defaultImage: {
- type: "image", x: 0, y: 0, width: 0, height: 0, src: ""
- },
- defaultText: {
- type: "text", x: 0, y: 0, text: "", align: "start",
- decoration: "none", rotated: false, kerning: true
- },
- defaultTextPath: {
- type: "textpath", text: "", align: "start",
- decoration: "none", rotated: false, kerning: true
- },
- // default geometric attributes
- defaultStroke: {
- type: "stroke", color: "black", style: "solid", width: 1,
- cap: "butt", join: 4
- },
- defaultLinearGradient: {
- type: "linear", x1: 0, y1: 0, x2: 100, y2: 100,
- colors: [
- { offset: 0, color: "black" }, { offset: 1, color: "white" }
- ]
- },
- defaultRadialGradient: {
- type: "radial", cx: 0, cy: 0, r: 100,
- colors: [
- { offset: 0, color: "black" }, { offset: 1, color: "white" }
- ]
- },
- defaultPattern: {
- type: "pattern", x: 0, y: 0, width: 0, height: 0, src: ""
- },
- defaultFont: {
- type: "font", style: "normal", variant: "normal",
- weight: "normal", size: "10pt", family: "serif"
- },
- getDefault: (function(){
- var typeCtorCache = {};
- // a memoized delegate()
- return function(/*String*/ type){
- var t = typeCtorCache[type];
- if(t){
- return new t();
- }
- t = typeCtorCache[type] = new Function;
- t.prototype = dojox.gfx[ "default" + type ];
- return new t();
- }
- })(),
- normalizeColor: function(/*Color*/ color){
- // summary:
- // converts any legal color representation to normalized
- // dojo.Color object
- return (color instanceof dojo.Color) ? color : new dojo.Color(color); // dojo.Color
- },
- normalizeParameters: function(existed, update){
- // summary:
- // updates an existing object with properties from an "update"
- // object
- // existed: Object
- // the "target" object to be updated
- // update: Object
- // the "update" object, whose properties will be used to update
- // the existed object
- if(update){
- var empty = {};
- for(var x in existed){
- if(x in update && !(x in empty)){
- existed[x] = update[x];
- }
- }
- }
- return existed; // Object
- },
- makeParameters: function(defaults, update){
- // summary:
- // copies the original object, and all copied properties from the
- // "update" object
- // defaults: Object
- // the object to be cloned before updating
- // update: Object
- // the object, which properties are to be cloned during updating
- if(!update){
- // return dojo.clone(defaults);
- return dojo.delegate(defaults);
- }
- var result = {};
- for(var i in defaults){
- if(!(i in result)){
- result[i] = dojo.clone((i in update) ? update[i] : defaults[i]);
- }
- }
- return result; // Object
- },
- formatNumber: function(x, addSpace){
- // summary: converts a number to a string using a fixed notation
- // x: Number: number to be converted
- // addSpace: Boolean?: if it is true, add a space before a positive number
- var val = x.toString();
- if(val.indexOf("e") >= 0){
- val = x.toFixed(4);
- }else{
- var point = val.indexOf(".");
- if(point >= 0 && val.length - point > 5){
- val = x.toFixed(4);
- }
- }
- if(x < 0){
- return val; // String
- }
- return addSpace ? " " + val : val; // String
- },
- // font operations
- makeFontString: function(font){
- // summary: converts a font object to a CSS font string
- // font: Object: font object (see dojox.gfx.defaultFont)
- return font.style + " " + font.variant + " " + font.weight + " " + font.size + " " + font.family; // Object
- },
- splitFontString: function(str){
- // summary:
- // converts a CSS font string to a font object
- // description:
- // Converts a CSS font string to a gfx font object. The CSS font
- // string components should follow the W3C specified order
- // (see http://www.w3.org/TR/CSS2/fonts.html#font-shorthand):
- // style, variant, weight, size, optional line height (will be
- // ignored), and family.
- // str: String
- // a CSS font string
- var font = dojox.gfx.getDefault("Font");
- var t = str.split(/\s+/);
- do{
- if(t.length < 5){ break; }
- font.style = t[0];
- font.variant = t[1];
- font.weight = t[2];
- var i = t[3].indexOf("/");
- font.size = i < 0 ? t[3] : t[3].substring(0, i);
- var j = 4;
- if(i < 0){
- if(t[4] == "/"){
- j = 6;
- }else if(t[4].charAt(0) == "/"){
- j = 5;
- }
- }
- if(j < t.length){
- font.family = t.slice(j).join(" ");
- }
- }while(false);
- return font; // Object
- },
- // length operations
- cm_in_pt: 72 / 2.54, // Number: points per centimeter
- mm_in_pt: 7.2 / 2.54, // Number: points per millimeter
- px_in_pt: function(){
- // summary: returns a number of pixels per point
- return dojox.gfx._base._getCachedFontMeasurements()["12pt"] / 12; // Number
- },
- pt2px: function(len){
- // summary: converts points to pixels
- // len: Number: a value in points
- return len * dojox.gfx.px_in_pt(); // Number
- },
- px2pt: function(len){
- // summary: converts pixels to points
- // len: Number: a value in pixels
- return len / dojox.gfx.px_in_pt(); // Number
- },
- normalizedLength: function(len) {
- // summary: converts any length value to pixels
- // len: String: a length, e.g., "12pc"
- if(len.length == 0) return 0;
- if(len.length > 2){
- var px_in_pt = dojox.gfx.px_in_pt();
- var val = parseFloat(len);
- switch(len.slice(-2)){
- case "px": return val;
- case "pt": return val * px_in_pt;
- case "in": return val * 72 * px_in_pt;
- case "pc": return val * 12 * px_in_pt;
- case "mm": return val * dojox.gfx.mm_in_pt * px_in_pt;
- case "cm": return val * dojox.gfx.cm_in_pt * px_in_pt;
- }
- }
- return parseFloat(len); // Number
- },
- // a constant used to split a SVG/VML path into primitive components
- pathVmlRegExp: /([A-Za-z]+)|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
- pathSvgRegExp: /([A-Za-z])|(\d+(\.\d+)?)|(\.\d+)|(-\d+(\.\d+)?)|(-\.\d+)/g,
- equalSources: function(a, b){
- // summary: compares event sources, returns true if they are equal
- return a && b && a == b;
- },
-
- switchTo: function(renderer){
- var ns = dojox.gfx[renderer];
- if(ns){
- dojo.forEach(["Group", "Rect", "Ellipse", "Circle", "Line",
- "Polyline", "Image", "Text", "Path", "TextPath",
- "Surface", "createSurface"], function(name){
- dojox.gfx[name] = ns[name];
- });
- }
- }
- });
- }
- if(!dojo._hasResource["dojox.gfx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
- dojo._hasResource["dojox.gfx"] = true;
- dojo.provide("dojox.gfx");
- dojo.loadInit(function(){
- // Since loaderInit can be fired before any dojo.provide/require calls,
- // make sure the dojox.gfx object exists and only run this logic if dojox.gfx.renderer
- // has not been defined yet.
- var gfx = dojo.getObject("dojox.gfx", true), sl, flag, match;
- while(!gfx.renderer){
- // Have a way to force a GFX renderer, if so desired.
- // Useful for being able to serialize GFX data in a particular format.
- if(dojo.config.forceGfxRenderer){
- dojox.gfx.renderer = dojo.config.forceGfxRenderer;
- break;
- }
- var renderers = (typeof dojo.config.gfxRenderer == "string" ?
- dojo.config.gfxRenderer : "svg,vml,canvas,silverlight").split(",");
- for(var i = 0; i < renderers.length; ++i){
- switch(renderers[i]){
- case "svg":
- // the next test is from https://github.com/phiggins42/has.js
- if("SVGAngle" in dojo.global){
- dojox.gfx.renderer = "svg";
- }
- break;
- case "vml":
- if(dojo.isIE){
- dojox.gfx.renderer = "vml";
- }
- break;
- case "silverlight":
- try{
- if(dojo.isIE){
- sl = new ActiveXObject("AgControl.AgControl");
- if(sl && sl.IsVersionSupported("1.0")){
- flag = true;
- }
- }else{
- if(navigator.plugins["Silverlight Plug-In"]){
- flag = true;
- }
- }
- }catch(e){
- flag = false;
- }finally{
- sl = null;
- }
- if(flag){
- dojox.gfx.renderer = "silverlight";
- }
- break;
- case "canvas":
- if(dojo.global.CanvasRenderingContext2D){
- dojox.gfx.renderer = "canvas";
- }
- break;
- }
- if(gfx.renderer){
- break;
- }
- }
- break;
- }
-
- if(dojo.config.isDebug){
- console.log("gfx renderer = " + gfx.renderer);
- }
- // load & initialize renderer
- if(gfx[gfx.renderer]){
- // already loaded
- gfx.switchTo(gfx.renderer);
- }else{
- // load
- gfx.loadAndSwitch = gfx.renderer;
- dojo["require"]("dojox.gfx." + gfx.renderer);
- }
- });
- }
|