Blame | Last modification | View Log | RSS feed
if(!dojo._hasResource["dojox.gfx.vml"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojox.gfx.vml"] = true;dojo.provide("dojox.gfx.vml");dojo.require("dojox.gfx._base");dojo.require("dojox.gfx.shape");dojo.require("dojox.gfx.path");dojo.require("dojox.gfx.arc");// dojox.gfx.vml.xmlns: String: a VML's namespacedojox.gfx.vml.xmlns = "urn:schemas-microsoft-com:vml";// dojox.gfx.vml.text_alignment: Object: mapping from SVG alignment to VML alignmentdojox.gfx.vml.text_alignment = {start: "left", middle: "center", end: "right"};dojox.gfx.vml._parseFloat = function(str) {// summary: a helper function to parse VML-specific floating-point values// str: String: a representation of a floating-point numberreturn str.match(/^\d+f$/i) ? parseInt(str) / 65536 : parseFloat(str); // Number};dojox.gfx.vml._bool = {"t": 1, "true": 1};dojo.extend(dojox.gfx.Shape, {// summary: VML-specific implementation of dojox.gfx.Shape methodssetFill: function(fill){// summary: sets a fill object (VML)// fill: Object: a fill object// (see dojox.gfx.defaultLinearGradient,// dojox.gfx.defaultRadialGradient,// dojox.gfx.defaultPattern,// or dojo.Color)if(!fill){// don't fillthis.fillStyle = null;this.rawNode.filled = "f";return this;}if(typeof fill == "object" && "type" in fill){// gradientswitch(fill.type){case "linear":var f = dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient, fill),s = [], a = f.colors, matrix = this._getRealMatrix(), m = dojox.gfx.matrix;this.fillStyle = f;dojo.forEach(a, function(v, i, a){a[i].color = dojox.gfx.normalizeColor(v.color);});if(a[0].offset > 0){s.push("0 " + a[0].color.toHex());}for(var i = 0; i < a.length; ++i){s.push(a[i].offset.toFixed(8) + " " + a[i].color.toHex());}var i = a.length - 1;if(a[i].offset < 1){s.push("1 " + a[i].color.toHex());}var fo = this.rawNode.fill;fo.colors.value = s.join(";");fo.method = "sigma";fo.type = "gradient";var fc1 = matrix ? m.multiplyPoint(matrix, f.x1, f.y1) : {x: f.x1, y: f.y1},fc2 = matrix ? m.multiplyPoint(matrix, f.x2, f.y2) : {x: f.x2, y: f.y2};fo.angle = (m._radToDeg(Math.atan2(fc2.x - fc1.x, fc2.y - fc1.y)) + 180) % 360;fo.on = true;break;case "radial":var f = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);this.fillStyle = f;var l = parseFloat(this.rawNode.style.left),t = parseFloat(this.rawNode.style.top),w = parseFloat(this.rawNode.style.width),h = parseFloat(this.rawNode.style.height),c = isNaN(w) ? 1 : 2 * f.r / w,a = new Array(f.colors.length);// massage colorsdojo.forEach(f.colors, function(v, i){a[i] = {offset: 1 - v.offset * c, color: dojox.gfx.normalizeColor(v.color)};});var i = a.length - 1;while(i >= 0 && a[i].offset < 0){ --i; }if(i < a.length - 1){// correct excessive colorsvar q = a[i], p = a[i + 1];p.color = dojo.blendColors(q.color, p.color, q.offset / (q.offset - p.offset));p.offset = 0;while(a.length - i > 2) a.pop();}// set colorsvar i = a.length - 1, s = [];if(a[i].offset > 0){s.push("0 " + a[i].color.toHex());}for(; i >= 0; --i){s.push(a[i].offset.toFixed(8) + " " + a[i].color.toHex());}if(a[0].offset < 1){s.push("1 " + a[0].color.toHex());}var fo = this.rawNode.fill;fo.colors.value = s.join(";");fo.method = "sigma";fo.type = "gradientradial";if(isNaN(w) || isNaN(h) || isNaN(l) || isNaN(t)){fo.focusposition = "0.5 0.5";}else{fo.focusposition = ((f.cx - l) / w).toFixed(8) + " " + ((f.cy - t) / h).toFixed(8);}fo.focussize = "0 0";fo.on = true;break;case "pattern":var f = dojox.gfx.makeParameters(dojox.gfx.defaultPattern, fill);this.fillStyle = f;var fo = this.rawNode.fill;fo.type = "tile";fo.src = f.src;if(f.width && f.height){// in pointsfo.size.x = dojox.gfx.px2pt(f.width);fo.size.y = dojox.gfx.px2pt(f.height);}fo.alignShape = "f";fo.position.x = 0;fo.position.y = 0;fo.origin.x = f.width ? f.x / f.width : 0;fo.origin.y = f.height ? f.y / f.height : 0;fo.on = true;break;}this.rawNode.fill.opacity = 1;return this;}// color objectthis.fillStyle = dojox.gfx.normalizeColor(fill);this.rawNode.fillcolor = this.fillStyle.toHex();this.rawNode.fill.opacity = this.fillStyle.a;this.rawNode.filled = true;return this; // self},setStroke: function(stroke){// summary: sets a stroke object (VML)// stroke: Object: a stroke object// (see dojox.gfx.defaultStroke)if(!stroke){// don't strokethis.strokeStyle = null;this.rawNode.stroked = "f";return this;}// normalize the strokeif(typeof stroke == "string"){stroke = {color: stroke};}var s = this.strokeStyle = dojox.gfx.makeParameters(dojox.gfx.defaultStroke, stroke);s.color = dojox.gfx.normalizeColor(s.color);// generate attributesvar rn = this.rawNode;rn.stroked = true;rn.strokecolor = s.color.toCss();rn.strokeweight = s.width + "px"; // TODO: should we assume that the width is always in pixels?if(rn.stroke) {rn.stroke.opacity = s.color.a;rn.stroke.endcap = this._translate(this._capMap, s.cap);if(typeof s.join == "number") {rn.stroke.joinstyle = "miter";rn.stroke.miterlimit = s.join;}else{rn.stroke.joinstyle = s.join;// rn.stroke.miterlimit = s.width;}rn.stroke.dashstyle = s.style == "none" ? "Solid" : s.style;}return this; // self},_capMap: { butt: 'flat' },_capMapReversed: { flat: 'butt' },_translate: function(dict, value) {return (value in dict) ? dict[value] : value;},_applyTransform: function() {if(this.fillStyle && this.fillStyle.type == "linear"){this.setFill(this.fillStyle);}var matrix = this._getRealMatrix();if(!matrix) return this;var skew = this.rawNode.skew;if(typeof skew == "undefined"){for(var i = 0; i < this.rawNode.childNodes.length; ++i){if(this.rawNode.childNodes[i].tagName == "skew"){skew = this.rawNode.childNodes[i];break;}}}if(skew){skew.on = "f";var mt = matrix.xx.toFixed(8) + " " + matrix.xy.toFixed(8) + " " +matrix.yx.toFixed(8) + " " + matrix.yy.toFixed(8) + " 0 0",offset = Math.floor(matrix.dx).toFixed() + "px " + Math.floor(matrix.dy).toFixed() + "px",s = this.rawNode.style,l = parseFloat(s.left),t = parseFloat(s.top),w = parseFloat(s.width),h = parseFloat(s.height);if(isNaN(l)) l = 0;if(isNaN(t)) t = 0;if(isNaN(w)) w = 1;if(isNaN(h)) h = 1;var origin = (-l / w - 0.5).toFixed(8) + " " + (-t / h - 0.5).toFixed(8);skew.matrix = mt;skew.origin = origin;skew.offset = offset;skew.on = true;}return this;},setRawNode: function(rawNode){// summary:// assigns and clears the underlying node that will represent this// shape. Once set, transforms, gradients, etc, can be applied.// (no fill & stroke by default)rawNode.stroked = "f";rawNode.filled = "f";this.rawNode = rawNode;},// move family_moveToFront: function(){// summary: moves a shape to front of its parent's list of shapes (VML)this.rawNode.parentNode.appendChild(this.rawNode);return this;},_moveToBack: function(){// summary: moves a shape to back of its parent's list of shapes (VML)var r = this.rawNode, p = r.parentNode, n = p.firstChild;p.insertBefore(r, n);if(n.tagName == "rect"){// surface has a background rectangle, which position should be preservedn.swapNode(r);}return this;},_getRealMatrix: function(){// summary: returns the cumulative ("real") transformation matrix// by combining the shape's matrix with its parent's matrixreturn this.parentMatrix ? new dojox.gfx.Matrix2D([this.parentMatrix, this.matrix]) : this.matrix; // dojox.gfx.Matrix2D}});dojo.declare("dojox.gfx.Group", dojox.gfx.Shape, {// summary: a group shape (VML), which can be used// to logically group shapes (e.g, to propagate matricies)constructor: function(){dojox.gfx.vml.Container._init.call(this);},// apply transformation_applyTransform: function(){// summary: applies a transformation matrix to a groupvar matrix = this._getRealMatrix();for(var i = 0; i < this.children.length; ++i){this.children[i]._updateParentMatrix(matrix);}return this; // self}});dojox.gfx.Group.nodeType = "group";dojo.declare("dojox.gfx.Rect", dojox.gfx.shape.Rect, {// summary: a rectangle shape (VML)setShape: function(newShape){// summary: sets a rectangle shape object (VML)// newShape: Object: a rectangle shape objectvar shape = this.shape = dojox.gfx.makeParameters(this.shape, newShape);this.bbox = null;var style = this.rawNode.style;style.left = shape.x.toFixed();style.top = shape.y.toFixed();style.width = (typeof shape.width == "string" && shape.width.indexOf("%") >= 0) ? shape.width : shape.width.toFixed();style.height = (typeof shape.width == "string" && shape.height.indexOf("%") >= 0) ? shape.height : shape.height.toFixed();var r = Math.min(1, (shape.r / Math.min(parseFloat(shape.width), parseFloat(shape.height)))).toFixed(8);// a workaround for the VML's arcsize bug: cannot read arcsize of an instantiated nodevar parent = this.rawNode.parentNode, before = null;if(parent){if(parent.lastChild != this.rawNode){for(var i = 0; i < parent.childNodes.length; ++i){if(parent.childNodes[i] == this.rawNode){before = parent.childNodes[i+1];break;}}}parent.removeChild(this.rawNode);}this.rawNode.arcsize = r;if(parent){if(before){parent.insertBefore(this.rawNode, before);}else{parent.appendChild(this.rawNode);}}// set all necessary styles, which are lost by VML (yes, it's a VML's bug)return this.setTransform(this.matrix).setFill(this.fillStyle).setStroke(this.strokeStyle); // self}});dojox.gfx.Rect.nodeType = "roundrect"; // use a roundrect so the stroke join type is respecteddojo.declare("dojox.gfx.Ellipse", dojox.gfx.shape.Ellipse, {// summary: an ellipse shape (VML)setShape: function(newShape){// summary: sets an ellipse shape object (VML)// newShape: Object: an ellipse shape objectvar shape = this.shape = dojox.gfx.makeParameters(this.shape, newShape);this.bbox = null;var style = this.rawNode.style;style.left = (shape.cx - shape.rx).toFixed();style.top = (shape.cy - shape.ry).toFixed();style.width = (shape.rx * 2).toFixed();style.height = (shape.ry * 2).toFixed();return this.setTransform(this.matrix); // self}});dojox.gfx.Ellipse.nodeType = "oval";dojo.declare("dojox.gfx.Circle", dojox.gfx.shape.Circle, {// summary: a circle shape (VML)setShape: function(newShape){// summary: sets a circle shape object (VML)// newShape: Object: a circle shape objectvar shape = this.shape = dojox.gfx.makeParameters(this.shape, newShape);this.bbox = null;var style = this.rawNode.style;style.left = (shape.cx - shape.r).toFixed();style.top = (shape.cy - shape.r).toFixed();style.width = (shape.r * 2).toFixed();style.height = (shape.r * 2).toFixed();return this; // self}});dojox.gfx.Circle.nodeType = "oval";dojo.declare("dojox.gfx.Line", dojox.gfx.shape.Line, {// summary: a line shape (VML)constructor: function(rawNode){if(rawNode) rawNode.setAttribute("dojoGfxType", "line");},setShape: function(newShape){// summary: sets a line shape object (VML)// newShape: Object: a line shape objectvar shape = this.shape = dojox.gfx.makeParameters(this.shape, newShape);this.bbox = null;this.rawNode.path.v = "m" + shape.x1.toFixed() + " " + shape.y1.toFixed() +"l" + shape.x2.toFixed() + " " + shape.y2.toFixed() + "e";return this.setTransform(this.matrix); // self}});dojox.gfx.Line.nodeType = "shape";dojo.declare("dojox.gfx.Polyline", dojox.gfx.shape.Polyline, {// summary: a polyline/polygon shape (VML)constructor: function(rawNode){if(rawNode) rawNode.setAttribute("dojoGfxType", "polyline");},setShape: function(points, closed){// summary: sets a polyline/polygon shape object (VML)// points: Object: a polyline/polygon shape object// closed: Boolean?: if true, close the polyline explicitelyif(points && points instanceof Array){// branch// points: Array: an array of pointsthis.shape = dojox.gfx.makeParameters(this.shape, { points: points });if(closed && this.shape.points.length) this.shape.points.push(this.shape.points[0]);}else{this.shape = dojox.gfx.makeParameters(this.shape, points);}this.bbox = null;var attr = [], p = this.shape.points;if(p.length > 0){attr.push("m");var k = 1;if(typeof p[0] == "number"){attr.push(p[0].toFixed());attr.push(p[1].toFixed());k = 2;}else{attr.push(p[0].x.toFixed());attr.push(p[0].y.toFixed());}if(p.length > k){attr.push("l");for(var i = k; i < p.length; ++i){if(typeof p[i] == "number"){attr.push(p[i].toFixed());}else{attr.push(p[i].x.toFixed());attr.push(p[i].y.toFixed());}}}}attr.push("e");this.rawNode.path.v = attr.join(" ");return this.setTransform(this.matrix); // self}});dojox.gfx.Polyline.nodeType = "shape";dojo.declare("dojox.gfx.Image", dojox.gfx.shape.Image, {// summary: an image (VML)constructor: function(rawNode){if(rawNode) rawNode.setAttribute("dojoGfxType", "image");},getEventSource: function() {// summary: returns a Node, which is used as// a source of events for this shapereturn this.rawNode ? this.rawNode.firstChild : null; // Node},setShape: function(newShape){// summary: sets an image shape object (VML)// newShape: Object: an image shape objectvar shape = this.shape = dojox.gfx.makeParameters(this.shape, newShape);this.bbox = null;var firstChild = this.rawNode.firstChild;firstChild.src = shape.src;if(shape.width || shape.height){firstChild.style.width = shape.width;firstChild.style.height = shape.height;}return this.setTransform(this.matrix); // self},_applyTransform: function() {var matrix = this._getRealMatrix();if(!matrix) return this;matrix = dojox.gfx.matrix.multiply(matrix, {dx: this.shape.x, dy: this.shape.y});var f = this.rawNode.filters["DXImageTransform.Microsoft.Matrix"];f.M11 = matrix.xx;f.M12 = matrix.xy;f.M21 = matrix.yx;f.M22 = matrix.yy;f.Dx = matrix.dx;f.Dy = matrix.dy;return this;}});dojox.gfx.Image.nodeType = "div";dojo.declare("dojox.gfx.Text", dojox.gfx.shape.Text, {// summary: an anchored text (VML)constructor: function(rawNode){if(rawNode){rawNode.setAttribute("dojoGfxType", "text");}this.fontStyle = null;},_alignment: {start: "left", middle: "center", end: "right"},setShape: function(newShape){// summary: sets a text shape object (VML)// newShape: Object: a text shape objectthis.shape = dojox.gfx.makeParameters(this.shape, newShape);this.bbox = null;var r = this.rawNode, s = this.shape, x = s.x, y = s.y.toFixed();switch(s.align){case "middle":x -= 5;break;case "end":x -= 10;break;}this.rawNode.path.v = "m" + x.toFixed() + "," + y +"l" + (x + 10).toFixed() + "," + y + "e";// find path and text pathvar p = null, t = null, c = r.childNodes;for(var i = 0; i < c.length; ++i){var tag = c[i].tagName;if(tag == "path"){p = c[i];if(t) break;}else if(tag == "textpath"){t = c[i];if(p) break;}}if(!p){p = this.rawNode.ownerDocument.createElement("v:path");r.appendChild(p);}if(!t){t = this.rawNode.ownerDocument.createElement("v:textpath");r.appendChild(t);}p.textPathOk = true;t.on = true;var a = dojox.gfx.vml.text_alignment[s.align];t.style["v-text-align"] = a ? a : "left";t.style["text-decoration"] = s.decoration;t.style["v-rotate-letters"] = s.rotated;t.style["v-text-kern"] = s.kerning;t.string = s.text;return this.setTransform(this.matrix); // self},_setFont: function(){// summary: sets a font object (VML)var f = this.fontStyle, c = this.rawNode.childNodes;for(var i = 0; i < c.length; ++i){if(c[i].tagName == "textpath"){c[i].style.font = dojox.gfx.makeFontString(f);break;}}this.setTransform(this.matrix);},_getRealMatrix: function(){// summary: returns the cumulative ("real") transformation matrix// by combining the shape's matrix with its parent's matrix;// it makes a correction for a font sizevar matrix = dojox.gfx.Shape.prototype._getRealMatrix.call(this);// It appears that text is always aligned vertically at a middle of x-height (???).// It is impossible to obtain these metrics from VML => I try to approximate it with// more-or-less util value of 0.7 * FontSize, which is typical for European fonts.if(matrix){matrix = dojox.gfx.matrix.multiply(matrix,{dy: -dojox.gfx.normalizedLength(this.fontStyle ? this.fontStyle.size : "10pt") * 0.35});}return matrix; // dojox.gfx.Matrix2D},getTextWidth: function(){// summary: get the text width, in pxvar rawNode = this.rawNode, _display = rawNode.style.display;rawNode.style.display = "inline";var _width = dojox.gfx.pt2px(parseFloat(rawNode.currentStyle.width));rawNode.style.display = _display;return _width;}});dojox.gfx.Text.nodeType = "shape";dojox.gfx.path._calcArc = function(alpha){// return a start point, 1st and 2nd control points, and an end pointvar cosa = Math.cos(alpha), sina = Math.sin(alpha),p2 = {x: cosa + (4 / 3) * (1 - cosa), y: sina - (4 / 3) * cosa * (1 - cosa) / sina};return {s: {x: cosa, y: -sina},c1: {x: p2.x, y: -p2.y},c2: p2,e: {x: cosa, y: sina}};};dojo.declare("dojox.gfx.Path", dojox.gfx.path.Path, {// summary: a path shape (VML)constructor: function(rawNode){if(rawNode && !rawNode.getAttribute("dojoGfxType")){rawNode.setAttribute("dojoGfxType", "path");}this.vmlPath = "";this.lastControl = {};},_updateWithSegment: function(segment){// summary: updates the bounding box of path with new segment// segment: Object: a segmentvar last = dojo.clone(this.last);dojox.gfx.Path.superclass._updateWithSegment.apply(this, arguments);// add a VML path segmentvar path = this[this.renderers[segment.action]](segment, last);if(typeof this.vmlPath == "string"){this.vmlPath += path.join("");this.rawNode.path.v = this.vmlPath + " r0,0 e";}else{this.vmlPath = this.vmlPath.concat(path);}},setShape: function(newShape){// summary: forms a path using a shape (VML)// newShape: Object: an VML path string or a path object (see dojox.gfx.defaultPath)this.vmlPath = [];this.lastControl = {};dojox.gfx.Path.superclass.setShape.apply(this, arguments);this.vmlPath = this.vmlPath.join("");this.rawNode.path.v = this.vmlPath + " r0,0 e";return this;},_pathVmlToSvgMap: {m: "M", l: "L", t: "m", r: "l", c: "C", v: "c", qb: "Q", x: "z", e: ""},// VML-specific segment renderersrenderers: {M: "_moveToA", m: "_moveToR",L: "_lineToA", l: "_lineToR",H: "_hLineToA", h: "_hLineToR",V: "_vLineToA", v: "_vLineToR",C: "_curveToA", c: "_curveToR",S: "_smoothCurveToA", s: "_smoothCurveToR",Q: "_qCurveToA", q: "_qCurveToR",T: "_qSmoothCurveToA", t: "_qSmoothCurveToR",A: "_arcTo", a: "_arcTo",Z: "_closePath", z: "_closePath"},_addArgs: function(path, args, from, upto){if(typeof upto == "undefined"){upto = args.length;}if(typeof from == "undefined"){from = 0;}for(var i = from; i < upto; ++i){path.push(" ");path.push(args[i].toFixed());}},_addArgsAdjusted: function(path, last, args, from, upto){if(typeof upto == "undefined"){upto = args.length;}if(typeof from == "undefined"){from = 0;}for(var i = from; i < upto; i += 2){path.push(" ");path.push((last.x + args[i]).toFixed());path.push(" ");path.push((last.y + args[i + 1]).toFixed());}},_moveToA: function(segment){var p = [" m"], n = segment.args, l = n.length;if(l == 2){this._addArgs(p, n);}else{this._addArgs(p, n, 0, 2);p.push(" l");this._addArgs(p, n, 2);}this.lastControl = {};return p;},_moveToR: function(segment, last){var p = ["x" in last ? " t" : " m"], n = segment.args, l = n.length;if(l == 2){this._addArgs(p, n);}else{this._addArgs(p, n, 0, 2);p.push(" r");this._addArgs(p, n, 2);}this.lastControl = {};return p;},_lineToA: function(segment){var p = [" l"];this._addArgs(p, segment.args);this.lastControl = {};return p;},_lineToR: function(segment){var p = [" r"];this._addArgs(p, segment.args);this.lastControl = {};return p;},_hLineToA: function(segment, last){var p = [" l"], n = segment.args, l = n.length, y = " " + last.y.toFixed();for(var i = 0; i < l; ++i){p.push(" ");p.push(n[i].toFixed());p.push(y);}this.lastControl = {};return p;},_hLineToR: function(segment){var p = [" r"], n = segment.args, l = n.length;for(var i = 0; i < l; ++i){p.push(" ");p.push(n[i].toFixed());p.push(" 0");}this.lastControl = {};return p;},_vLineToA: function(segment, last){var p = [" l"], n = segment.args, l = n.length, x = " " + last.x.toFixed();for(var i = 0; i < l; ++i){p.push(x);p.push(" ");p.push(n[i].toFixed());}this.lastControl = {};return p;},_vLineToR: function(segment){var p = [" r"], n = segment.args, l = n.length;for(var i = 0; i < l; ++i){p.push(" 0 ");p.push(n[i].toFixed());}this.lastControl = {};return p;},_curveToA: function(segment){var p = [], n = segment.args, l = n.length;for(var i = 0; i < l; i += 6){p.push(" c");this._addArgs(p, n, i, i + 6);}this.lastControl = {x: n[l - 4], y: n[l - 3], type: "C"};return p;},_curveToR: function(segment, last){var p = [], n = segment.args, l = n.length;for(var i = 0; i < l; i += 6){p.push(" v");this._addArgs(p, n, i, i + 6);this.lastControl = {x: last.x + n[i + 2], y: last.y + n[i + 3]};last.x += n[i + 4];last.y += n[i + 5];}this.lastControl.type = "C";return p;},_smoothCurveToA: function(segment, last){var p = [], n = segment.args, l = n.length;for(var i = 0; i < l; i += 4){p.push(" c");if(this.lastControl.type == "C"){this._addArgs(p, [2 * last.x - this.lastControl.x,2 * last.y - this.lastControl.y]);}else{this._addArgs(p, [last.x, last.y]);}this._addArgs(p, n, i, i + 4);}this.lastControl = {x: n[l - 4], y: n[l - 3], type: "C"};return p;},_smoothCurveToR: function(segment, last){var p = [], n = segment.args, l = n.length;for(var i = 0; i < l; i += 4){p.push(" v");if(this.lastControl.type == "C"){this._addArgs(p, [last.x - this.lastControl.x,last.y - this.lastControl.y]);}else{this._addArgs(p, [0, 0]);}this._addArgs(p, n, i, i + 4);this.lastControl = {x: last.x + n[i], y: last.y + n[i + 1]};last.x += n[i + 2];last.y += n[i + 3];}this.lastControl.type = "C";return p;},_qCurveToA: function(segment){var p = [], n = segment.args, l = n.length;for(var i = 0; i < l; i += 4){p.push(" qb");this._addArgs(p, n, i, i + 4);}this.lastControl = {x: n[l - 4], y: n[l - 3], type: "Q"};return p;},_qCurveToR: function(segment, last){var p = [], n = segment.args, l = n.length;for(var i = 0; i < l; i += 4){p.push(" qb");this._addArgsAdjusted(p, last, n, i, i + 4);this.lastControl = {x: last.x + n[i], y: last.y + n[i + 1]};last.x += n[i + 2];last.y += n[i + 3];}this.lastControl.type = "Q";return p;},_qSmoothCurveToA: function(segment, last){var p = [], n = segment.args, l = n.length;for(var i = 0; i < l; i += 2){p.push(" qb");if(this.lastControl.type == "Q"){this._addArgs(p, [this.lastControl.x = 2 * last.x - this.lastControl.x,this.lastControl.y = 2 * last.y - this.lastControl.y]);}else{this._addArgs(p, [this.lastControl.x = last.x,this.lastControl.y = last.y]);}this._addArgs(p, n, i, i + 2);}this.lastControl.type = "Q";return p;},_qSmoothCurveToR: function(segment, last){var p = [], n = segment.args, l = n.length;for(var i = 0; i < l; i += 2){p.push(" qb");if(this.lastControl.type == "Q"){this._addArgs(p, [this.lastControl.x = 2 * last.x - this.lastControl.x,this.lastControl.y = 2 * last.y - this.lastControl.y]);}else{this._addArgs(p, [this.lastControl.x = last.x,this.lastControl.y = last.y]);}this._addArgsAdjusted(p, last, n, i, i + 2);}this.lastControl.type = "Q";return p;},_arcTo: function(segment, last){var p = [], n = segment.args, l = n.length, relative = segment.action == "a";for(var i = 0; i < l; i += 7){var x1 = n[i + 5], y1 = n[i + 6];if(relative){x1 += last.x;y1 += last.y;}var result = dojox.gfx.arc.arcAsBezier(last, n[i], n[i + 1], n[i + 2],n[i + 3] ? 1 : 0, n[i + 4] ? 1 : 0,x1, y1);for(var j = 0; j < result.length; ++j){p.push(" c");this._addArgs(p, result[j]);}last = {x: x1, y: y1};}this.lastControl = {};return p;},_closePath: function(){this.lastControl = {};return ["x"];}});dojox.gfx.Path.nodeType = "shape";dojo.declare("dojox.gfx.TextPath", dojox.gfx.Path, {// summary: a textpath shape (VML)constructor: function(rawNode){if(rawNode){rawNode.setAttribute("dojoGfxType", "textpath");}this.fontStyle = null;if(!("text" in this)){this.text = dojo.clone(dojox.gfx.defaultTextPath);}if(!("fontStyle" in this)){this.fontStyle = dojo.clone(dojox.gfx.defaultFont);}},setText: function(newText){// summary: sets a text to be drawn along the paththis.text = dojox.gfx.makeParameters(this.text,typeof newText == "string" ? {text: newText} : newText);this._setText();return this; // self},setFont: function(newFont){// summary: sets a font for textthis.fontStyle = typeof newFont == "string" ?dojox.gfx.splitFontString(newFont) :dojox.gfx.makeParameters(dojox.gfx.defaultFont, newFont);this._setFont();return this; // self},_setText: function(){// summary: sets a text shape object (VML)this.bbox = null;var r = this.rawNode, s = this.text,// find path and text pathp = null, t = null, c = r.childNodes;for(var i = 0; i < c.length; ++i){var tag = c[i].tagName;if(tag == "path"){p = c[i];if(t) break;}else if(tag == "textpath"){t = c[i];if(p) break;}}if(!p){p = this.rawNode.ownerDocument.createElement("v:path");r.appendChild(p);}if(!t){t = this.rawNode.ownerDocument.createElement("v:textpath");r.appendChild(t);}p.textPathOk = true;t.on = true;var a = dojox.gfx.vml.text_alignment[s.align];t.style["v-text-align"] = a ? a : "left";t.style["text-decoration"] = s.decoration;t.style["v-rotate-letters"] = s.rotated;t.style["v-text-kern"] = s.kerning;t.string = s.text;},_setFont: function(){// summary: sets a font object (VML)var f = this.fontStyle, c = this.rawNode.childNodes;for(var i = 0; i < c.length; ++i){if(c[i].tagName == "textpath"){c[i].style.font = dojox.gfx.makeFontString(f);break;}}}});dojox.gfx.TextPath.nodeType = "shape";dojo.declare("dojox.gfx.Surface", dojox.gfx.shape.Surface, {// summary: a surface object to be used for drawings (VML)constructor: function(){dojox.gfx.vml.Container._init.call(this);},setDimensions: function(width, height){// summary: sets the width and height of the rawNode// width: String: width of surface, e.g., "100px"// height: String: height of surface, e.g., "100px"this.width = dojox.gfx.normalizedLength(width); // in pixelsthis.height = dojox.gfx.normalizedLength(height); // in pixelsif(!this.rawNode) return this;var cs = this.clipNode.style,r = this.rawNode, rs = r.style,bs = this.bgNode.style;cs.width = width;cs.height = height;cs.clip = "rect(0 " + width + " " + height + " 0)";rs.width = width;rs.height = height;r.coordsize = width + " " + height;bs.width = width;bs.height = height;return this; // self},getDimensions: function(){// summary: returns an object with properties "width" and "height"var t = this.rawNode ? {width: dojox.gfx.normalizedLength(this.rawNode.style.width),height: dojox.gfx.normalizedLength(this.rawNode.style.height)} : null;if(t.width <= 0){ t.width = this.width; }if(t.height <= 0){ t.height = this.height; }return t; // Object}});dojox.gfx.createSurface = function(parentNode, width, height){// summary: creates a surface (VML)// parentNode: Node: a parent node// width: String: width of surface, e.g., "100px"// height: String: height of surface, e.g., "100px"if(!width){ width = "100%"; }if(!height){ height = "100%"; }var s = new dojox.gfx.Surface(), p = dojo.byId(parentNode),c = s.clipNode = p.ownerDocument.createElement("div"),r = s.rawNode = p.ownerDocument.createElement("v:group"),cs = c.style, rs = r.style;p.style.width = width;p.style.height = height;cs.width = width;cs.height = height;cs.clip = "rect(0 " + width + " " + height + " 0)";cs.position = "absolute";rs.width = width;rs.height = height;r.coordsize = (width == "100%" ? width : parseFloat(width)) + " " +(height == "100%" ? height : parseFloat(height));r.coordorigin = "0 0";// create a background rectangle, which is required to show all other shapesvar b = s.bgNode = r.ownerDocument.createElement("v:rect"), bs = b.style;bs.left = bs.top = 0;bs.width = rs.width;bs.height = rs.height;b.filled = b.stroked = "f";r.appendChild(b);c.appendChild(r);p.appendChild(c);s.width = dojox.gfx.normalizedLength(width); // in pixelss.height = dojox.gfx.normalizedLength(height); // in pixelsreturn s; // dojox.gfx.Surface};// Extendersdojox.gfx.vml.Container = {_init: function(){dojox.gfx.shape.Container._init.call(this);},add: function(shape){// summary: adds a shape to a group/surface// shape: dojox.gfx.Shape: an VML shape objectif(this != shape.getParent()){this.rawNode.appendChild(shape.rawNode);//dojox.gfx.Group.superclass.add.apply(this, arguments);//this.inherited(arguments);dojox.gfx.shape.Container.add.apply(this, arguments);}return this; // self},remove: function(shape, silently){// summary: remove a shape from a group/surface// shape: dojox.gfx.Shape: an VML shape object// silently: Boolean?: if true, regenerate a pictureif(this == shape.getParent()){if(this.rawNode == shape.rawNode.parentNode){this.rawNode.removeChild(shape.rawNode);}//dojox.gfx.Group.superclass.remove.apply(this, arguments);//this.inherited(arguments);dojox.gfx.shape.Container.remove.apply(this, arguments);}return this; // self},clear: function(){// summary: removes all shapes from a group/surfacevar r = this.rawNode;while(r.firstChild != r.lastChild){if(r.firstChild != this.bgNode){r.removeChild(r.firstChild);}if(r.lastChild != this.bgNode){r.removeChild(r.lastChild);}}//return this.inherited(arguments); // selfreturn dojox.gfx.shape.Container.clear.apply(this, arguments);},_moveChildToFront: dojox.gfx.shape.Container._moveChildToFront,_moveChildToBack: dojox.gfx.shape.Container._moveChildToBack};dojo.mixin(dojox.gfx.shape.Creator, {// summary: VML shape creatorscreateGroup: function(){// summary: creates a VML group shapevar g = this.createObject(dojox.gfx.Group, null); // dojox.gfx.Group// create a background rectangle, which is required to show all other shapesvar r = g.rawNode.ownerDocument.createElement("v:rect");r.style.left = r.style.top = 0;r.style.width = g.rawNode.style.width;r.style.height = g.rawNode.style.height;r.filled = r.stroked = "f";g.rawNode.appendChild(r);g.bgNode = r;return g; // dojox.gfx.Group},createImage: function(image){// summary: creates a VML image shape// image: Object: an image object (see dojox.gfx.defaultImage)if(!this.rawNode) return null;var shape = new dojox.gfx.Image(), node = this.rawNode.ownerDocument.createElement('div');node.style.position = "absolute";node.style.width = this.rawNode.style.width;node.style.height = this.rawNode.style.height;node.style.filter = "progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22=1, Dx=0, Dy=0)";var img = this.rawNode.ownerDocument.createElement('img');node.appendChild(img);shape.setRawNode(node);this.rawNode.appendChild(node);shape.setShape(image);this.add(shape);return shape; // dojox.gfx.Image},createObject: function(shapeType, rawShape) {// summary: creates an instance of the passed shapeType class// shapeType: Function: a class constructor to create an instance of// rawShape: Object: properties to be passed in to the classes "setShape" method// overrideSize: Boolean: set the size explicitly, if trueif(!this.rawNode) return null;var shape = new shapeType(),node = this.rawNode.ownerDocument.createElement('v:' + shapeType.nodeType);shape.setRawNode(node);this.rawNode.appendChild(node);switch(shapeType){case dojox.gfx.Group:case dojox.gfx.Line:case dojox.gfx.Polyline:case dojox.gfx.Text:case dojox.gfx.Path:case dojox.gfx.TextPath:this._overrideSize(node);}shape.setShape(rawShape);this.add(shape);return shape; // dojox.gfx.Shape},_overrideSize: function(node){var p = this;for(; p && !(p instanceof dojox.gfx.Surface); p = p.parent);node.style.width = p.width;node.style.height = p.height;node.coordsize = p.width + " " + p.height;}});dojo.extend(dojox.gfx.Group, dojox.gfx.vml.Container);dojo.extend(dojox.gfx.Group, dojox.gfx.shape.Creator);dojo.extend(dojox.gfx.Surface, dojox.gfx.vml.Container);dojo.extend(dojox.gfx.Surface, dojox.gfx.shape.Creator);}