diff options
Diffstat (limited to 'js/dojo-1.6/dojox/gfx')
53 files changed, 19722 insertions, 0 deletions
diff --git a/js/dojo-1.6/dojox/gfx/Moveable.js b/js/dojo-1.6/dojox/gfx/Moveable.js new file mode 100644 index 0000000..65f876f --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/Moveable.js @@ -0,0 +1,109 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.Moveable"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.Moveable"] = true;
+dojo.provide("dojox.gfx.Moveable");
+
+dojo.require("dojox.gfx.Mover");
+
+dojo.declare("dojox.gfx.Moveable", null, {
+ constructor: function(shape, params){
+ // summary: an object, which makes a shape moveable
+ // shape: dojox.gfx.Shape: a shape object to be moved
+ // params: Object: an optional object with additional parameters;
+ // following parameters are recognized:
+ // delay: Number: delay move by this number of pixels
+ // mover: Object: a constructor of custom Mover
+ this.shape = shape;
+ this.delay = (params && params.delay > 0) ? params.delay : 0;
+ this.mover = (params && params.mover) ? params.mover : dojox.gfx.Mover;
+ this.events = [
+ this.shape.connect("onmousedown", this, "onMouseDown")
+ // cancel text selection and text dragging
+ //, dojo.connect(this.handle, "ondragstart", dojo, "stopEvent")
+ //, dojo.connect(this.handle, "onselectstart", dojo, "stopEvent")
+ ];
+ },
+
+ // methods
+ destroy: function(){
+ // summary: stops watching for possible move, deletes all references, so the object can be garbage-collected
+ dojo.forEach(this.events, this.shape.disconnect, this.shape);
+ this.events = this.shape = null;
+ },
+
+ // mouse event processors
+ onMouseDown: function(e){
+ // summary: event processor for onmousedown, creates a Mover for the shape
+ // e: Event: mouse event
+ if(this.delay){
+ this.events.push(
+ this.shape.connect("onmousemove", this, "onMouseMove"),
+ this.shape.connect("onmouseup", this, "onMouseUp"));
+ this._lastX = e.clientX;
+ this._lastY = e.clientY;
+ }else{
+ new this.mover(this.shape, e, this);
+ }
+ dojo.stopEvent(e);
+ },
+ onMouseMove: function(e){
+ // summary: event processor for onmousemove, used only for delayed drags
+ // e: Event: mouse event
+ if(Math.abs(e.clientX - this._lastX) > this.delay || Math.abs(e.clientY - this._lastY) > this.delay){
+ this.onMouseUp(e);
+ new this.mover(this.shape, e, this);
+ }
+ dojo.stopEvent(e);
+ },
+ onMouseUp: function(e){
+ // summary: event processor for onmouseup, used only for delayed delayed drags
+ // e: Event: mouse event
+ this.shape.disconnect(this.events.pop());
+ this.shape.disconnect(this.events.pop());
+ },
+
+ // local events
+ onMoveStart: function(/* dojox.gfx.Mover */ mover){
+ // summary: called before every move operation
+ dojo.publish("/gfx/move/start", [mover]);
+ dojo.addClass(dojo.body(), "dojoMove");
+ },
+ onMoveStop: function(/* dojox.gfx.Mover */ mover){
+ // summary: called after every move operation
+ dojo.publish("/gfx/move/stop", [mover]);
+ dojo.removeClass(dojo.body(), "dojoMove");
+ },
+ onFirstMove: function(/* dojox.gfx.Mover */ mover){
+ // summary: called during the very first move notification,
+ // can be used to initialize coordinates, can be overwritten.
+
+ // default implementation does nothing
+ },
+ onMove: function(/* dojox.gfx.Mover */ mover, /* Object */ shift){
+ // summary: called during every move notification,
+ // should actually move the node, can be overwritten.
+ this.onMoving(mover, shift);
+ this.shape.applyLeftTransform(shift);
+ this.onMoved(mover, shift);
+ },
+ onMoving: function(/* dojox.gfx.Mover */ mover, /* Object */ shift){
+ // summary: called before every incremental move,
+ // can be overwritten.
+
+ // default implementation does nothing
+ },
+ onMoved: function(/* dojox.gfx.Mover */ mover, /* Object */ shift){
+ // summary: called after every incremental move,
+ // can be overwritten.
+
+ // default implementation does nothing
+ }
+});
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/Moveable.xd.js b/js/dojo-1.6/dojox/gfx/Moveable.xd.js new file mode 100644 index 0000000..058593e --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/Moveable.xd.js @@ -0,0 +1,114 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.Moveable"],
+["require", "dojox.gfx.Mover"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.Moveable"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.Moveable"] = true;
+dojo.provide("dojox.gfx.Moveable");
+
+dojo.require("dojox.gfx.Mover");
+
+dojo.declare("dojox.gfx.Moveable", null, {
+ constructor: function(shape, params){
+ // summary: an object, which makes a shape moveable
+ // shape: dojox.gfx.Shape: a shape object to be moved
+ // params: Object: an optional object with additional parameters;
+ // following parameters are recognized:
+ // delay: Number: delay move by this number of pixels
+ // mover: Object: a constructor of custom Mover
+ this.shape = shape;
+ this.delay = (params && params.delay > 0) ? params.delay : 0;
+ this.mover = (params && params.mover) ? params.mover : dojox.gfx.Mover;
+ this.events = [
+ this.shape.connect("onmousedown", this, "onMouseDown")
+ // cancel text selection and text dragging
+ //, dojo.connect(this.handle, "ondragstart", dojo, "stopEvent")
+ //, dojo.connect(this.handle, "onselectstart", dojo, "stopEvent")
+ ];
+ },
+
+ // methods
+ destroy: function(){
+ // summary: stops watching for possible move, deletes all references, so the object can be garbage-collected
+ dojo.forEach(this.events, this.shape.disconnect, this.shape);
+ this.events = this.shape = null;
+ },
+
+ // mouse event processors
+ onMouseDown: function(e){
+ // summary: event processor for onmousedown, creates a Mover for the shape
+ // e: Event: mouse event
+ if(this.delay){
+ this.events.push(
+ this.shape.connect("onmousemove", this, "onMouseMove"),
+ this.shape.connect("onmouseup", this, "onMouseUp"));
+ this._lastX = e.clientX;
+ this._lastY = e.clientY;
+ }else{
+ new this.mover(this.shape, e, this);
+ }
+ dojo.stopEvent(e);
+ },
+ onMouseMove: function(e){
+ // summary: event processor for onmousemove, used only for delayed drags
+ // e: Event: mouse event
+ if(Math.abs(e.clientX - this._lastX) > this.delay || Math.abs(e.clientY - this._lastY) > this.delay){
+ this.onMouseUp(e);
+ new this.mover(this.shape, e, this);
+ }
+ dojo.stopEvent(e);
+ },
+ onMouseUp: function(e){
+ // summary: event processor for onmouseup, used only for delayed delayed drags
+ // e: Event: mouse event
+ this.shape.disconnect(this.events.pop());
+ this.shape.disconnect(this.events.pop());
+ },
+
+ // local events
+ onMoveStart: function(/* dojox.gfx.Mover */ mover){
+ // summary: called before every move operation
+ dojo.publish("/gfx/move/start", [mover]);
+ dojo.addClass(dojo.body(), "dojoMove");
+ },
+ onMoveStop: function(/* dojox.gfx.Mover */ mover){
+ // summary: called after every move operation
+ dojo.publish("/gfx/move/stop", [mover]);
+ dojo.removeClass(dojo.body(), "dojoMove");
+ },
+ onFirstMove: function(/* dojox.gfx.Mover */ mover){
+ // summary: called during the very first move notification,
+ // can be used to initialize coordinates, can be overwritten.
+
+ // default implementation does nothing
+ },
+ onMove: function(/* dojox.gfx.Mover */ mover, /* Object */ shift){
+ // summary: called during every move notification,
+ // should actually move the node, can be overwritten.
+ this.onMoving(mover, shift);
+ this.shape.applyLeftTransform(shift);
+ this.onMoved(mover, shift);
+ },
+ onMoving: function(/* dojox.gfx.Mover */ mover, /* Object */ shift){
+ // summary: called before every incremental move,
+ // can be overwritten.
+
+ // default implementation does nothing
+ },
+ onMoved: function(/* dojox.gfx.Mover */ mover, /* Object */ shift){
+ // summary: called after every incremental move,
+ // can be overwritten.
+
+ // default implementation does nothing
+ }
+});
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/Mover.js b/js/dojo-1.6/dojox/gfx/Mover.js new file mode 100644 index 0000000..aee67c0 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/Mover.js @@ -0,0 +1,69 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.Mover"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.Mover"] = true;
+dojo.provide("dojox.gfx.Mover");
+
+dojo.declare("dojox.gfx.Mover", null, {
+ constructor: function(shape, e, host){
+ // summary: an object, which makes a shape follow the mouse,
+ // used as a default mover, and as a base class for custom movers
+ // shape: dojox.gfx.Shape: a shape object to be moved
+ // e: Event: a mouse event, which started the move;
+ // only clientX and clientY properties are used
+ // host: Object?: object which implements the functionality of the move,
+ // and defines proper events (onMoveStart and onMoveStop)
+ this.shape = shape;
+ this.lastX = e.clientX
+ this.lastY = e.clientY;
+ var h = this.host = host, d = document,
+ firstEvent = dojo.connect(d, "onmousemove", this, "onFirstMove");
+ this.events = [
+ dojo.connect(d, "onmousemove", this, "onMouseMove"),
+ dojo.connect(d, "onmouseup", this, "destroy"),
+ // cancel text selection and text dragging
+ dojo.connect(d, "ondragstart", dojo, "stopEvent"),
+ dojo.connect(d, "onselectstart", dojo, "stopEvent"),
+ firstEvent
+ ];
+ // notify that the move has started
+ if(h && h.onMoveStart){
+ h.onMoveStart(this);
+ }
+ },
+ // mouse event processors
+ onMouseMove: function(e){
+ // summary: event processor for onmousemove
+ // e: Event: mouse event
+ var x = e.clientX;
+ var y = e.clientY;
+ this.host.onMove(this, {dx: x - this.lastX, dy: y - this.lastY});
+ this.lastX = x;
+ this.lastY = y;
+ dojo.stopEvent(e);
+ },
+ // utilities
+ onFirstMove: function(){
+ // summary: it is meant to be called only once
+ this.host.onFirstMove(this);
+ dojo.disconnect(this.events.pop());
+ },
+ destroy: function(){
+ // summary: stops the move, deletes all references, so the object can be garbage-collected
+ dojo.forEach(this.events, dojo.disconnect);
+ // undo global settings
+ var h = this.host;
+ if(h && h.onMoveStop){
+ h.onMoveStop(this);
+ }
+ // destroy objects
+ this.events = this.shape = null;
+ }
+});
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/Mover.xd.js b/js/dojo-1.6/dojox/gfx/Mover.xd.js new file mode 100644 index 0000000..101fa7d --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/Mover.xd.js @@ -0,0 +1,73 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.Mover"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.Mover"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.Mover"] = true;
+dojo.provide("dojox.gfx.Mover");
+
+dojo.declare("dojox.gfx.Mover", null, {
+ constructor: function(shape, e, host){
+ // summary: an object, which makes a shape follow the mouse,
+ // used as a default mover, and as a base class for custom movers
+ // shape: dojox.gfx.Shape: a shape object to be moved
+ // e: Event: a mouse event, which started the move;
+ // only clientX and clientY properties are used
+ // host: Object?: object which implements the functionality of the move,
+ // and defines proper events (onMoveStart and onMoveStop)
+ this.shape = shape;
+ this.lastX = e.clientX
+ this.lastY = e.clientY;
+ var h = this.host = host, d = document,
+ firstEvent = dojo.connect(d, "onmousemove", this, "onFirstMove");
+ this.events = [
+ dojo.connect(d, "onmousemove", this, "onMouseMove"),
+ dojo.connect(d, "onmouseup", this, "destroy"),
+ // cancel text selection and text dragging
+ dojo.connect(d, "ondragstart", dojo, "stopEvent"),
+ dojo.connect(d, "onselectstart", dojo, "stopEvent"),
+ firstEvent
+ ];
+ // notify that the move has started
+ if(h && h.onMoveStart){
+ h.onMoveStart(this);
+ }
+ },
+ // mouse event processors
+ onMouseMove: function(e){
+ // summary: event processor for onmousemove
+ // e: Event: mouse event
+ var x = e.clientX;
+ var y = e.clientY;
+ this.host.onMove(this, {dx: x - this.lastX, dy: y - this.lastY});
+ this.lastX = x;
+ this.lastY = y;
+ dojo.stopEvent(e);
+ },
+ // utilities
+ onFirstMove: function(){
+ // summary: it is meant to be called only once
+ this.host.onFirstMove(this);
+ dojo.disconnect(this.events.pop());
+ },
+ destroy: function(){
+ // summary: stops the move, deletes all references, so the object can be garbage-collected
+ dojo.forEach(this.events, dojo.disconnect);
+ // undo global settings
+ var h = this.host;
+ if(h && h.onMoveStop){
+ h.onMoveStop(this);
+ }
+ // destroy objects
+ this.events = this.shape = null;
+ }
+});
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/README b/js/dojo-1.6/dojox/gfx/README new file mode 100644 index 0000000..485f628 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/README @@ -0,0 +1,109 @@ +------------------------------------------------------------------------------- +dojox.gfx +------------------------------------------------------------------------------- +Version 1.100 +Release date: 08/01/2006 +------------------------------------------------------------------------------- +Project state: +SVG renderer: production +VML renderer: production +Silverlight renderer: beta +HTMLCanvas renderer: beta +SVGWeb integration: experimental +------------------------------------------------------------------------------- +Credits + Eugene Lazutkin (eugene.lazutkin@gmail.com) + Kun Xi (bookstack@gmail.com) + Chris Mitchell (ccmitchellusa@gmail.com) HTML Canvas + Yang Li () SVGWeb integration +------------------------------------------------------------------------------- +Project description + +Implementation of simple portable 2D graphics library. +------------------------------------------------------------------------------- +Dependencies: + +Dojo Core +------------------------------------------------------------------------------- +Documentation + +Currently it can be found here: http://docs.google.com/Doc?id=d764479_1hnb2tn + +HTMLCanvas Renderer Status + +To use canvas rendering, insert 'canvas' at the beginning of the gfxRenderers list in your +djConfig, for example: +<script type="text/javascript" src="../../../dojo/dojo.js" + djConfig="parseOnLoad: true, gfxRenderer: 'canvas,svg,silverlight,vml'"></script> +canvas currently will only render on non-IE browsers (see dojox/gfx.js for where the renderer is loaded); +although it should be possible to use an IE canvas implementation (like Google's); however, it will be very slow. + +The following tests can be made to work with HTML Canvas with minor testcase modification: +dojox/gfx/tests + test_gfx.html-Bugs #1 + test_arc.html + test_bezier.html + test_pattern.html + test_gradient.html + test_linearGradient.html + test_image1.html - Limitation #3 + test_transform.html - Bug #1 + test_poly.html - Bug #1 +dojox/gfx/demos + butterfly.html - Bug #1 + lion.html - Bug #1 + tiger.html - Bug #1 + circles.html - No event processing yet :( + creator.html +dojox/chart + test_pie2d.html - Dojo Charts on iPhone anyone? :) + test_chart2d.html - + + // To make charts work, the following line needs to be added to the end of the + // Chart2D.js render() method (prior to return) + if(this.surface.render){this.surface.render()}; + +Known Limitations: +1) event handling- plan is to capture all events at canvas, perform intersect/hit + tests (not implemented) against scene graph, then propogate event to top-most + intersected shape. HtmlCanvas shape need intersectsStroke and intersectsBounds, + and intersects (region). +2) SVG and VML are "live" scene graphs; eg. any state change to objects in the + scene automatically get rendered in next engine render pass. For canvas, it's + procedural, and current implementation requires application to call surface.render() + whenever scene needs to be updated. Plan is to do dirty region checking based + on bounding boxes (currently not properly computed), and track dirty areas anytime + state changes (invalidate) separate from render phase. + Add the following call where changes to the scene graph are complete and you want to + render: + + if (surface.render){surface.render();} + +4) Text/Text Paths - Text shape is implemented using DIV overlays. Many text styles are not + applied, and outline/fills are not possible. This is due to limitations in Canvas spec. + Firefox 3.0 has proprietary text functions that we could test for and use once FF3 is out. + No luck on Safari. +3) No Image skewing - Limitation of Canvas + +Known Bugs: +1) Matrix xformations (applied from root to shape leaf nodes) not quite right--but very close. + Canvas does not have a built in transformation function that allows skewing. Need to + track skew matrix with Shape, and perform other trans/rot/scale transformations without + using canvas transform functions. + +SVGWeb Integration Status + +See README-svgweb. + +------------------------------------------------------------------------------- +Installation instructions + +Grab the following from the Dojo SVN Repository: +http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/gfx.js +http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/gfx/* + +Install into the following directory structure: +/dojox/gfx/ + +...which should be at the same level as your Dojo checkout. +------------------------------------------------------------------------------- diff --git a/js/dojo-1.6/dojox/gfx/README-svgweb b/js/dojo-1.6/dojox/gfx/README-svgweb new file mode 100644 index 0000000..f701bb3 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/README-svgweb @@ -0,0 +1,98 @@ +NOTICE of 3rd party code included +================================= +For ease of testing, latest SVGWeb release is included, see +dojox/gfx/tests/svgweb/README for details. + + +============================================================ +Enable or disable the SVGWeb with dojo gfx +------------------------------------------------------------ + +The function is only enabled when SVGWeb JS is included and the gfx renderer is +'svg'. If either SVGWeb is not available or the renderer is not 'svg', dojox.gfx +works as usual. + +To enable SVGWeb with dojo gfx: + +1. Include SVGWeb JS at the FIRST of all your javascripts + + <meta name="svg.render.forceflash" content="true"/> + <script src="<path>/svgweb/src/svg.js" data-path="<path>/svgweb/src"></script> + +2. Force 'svg' renderer with the 'forceGfxRenderer' config + + <script src="<path>/dojo/dojo.js" djConfig="forceGfxRenderer:'svg'"></script> + + +============================================================ +Test dojo gfx + SVGWeb +------------------------------------------------------------ + +All SVGWeb-specific tests are in dojox/gfx/tests/svgweb. + +============================================================ +GFX Performance Test Status +------------------------------------------------------------ + +Runs dojo gfx performance tests on IE7 with different renderers, compare their +performance. The result so far is + + * Silverlight is the fastest: 27,546 ms; + * Tuned SVGWeb is the 2nd place: 38,690 ms, almost 3 times faster than + before + * VML is the slowest: 50,250 ms + + +============================================================ +GFX Functional Test Status +------------------------------------------------------------ + +Summary / General findings + + * Pass rate 83%, 25 out of 30 pass + * The behavior is very consistent on IE & FF + * Transformation of Text is not working + * Line style is not working + * getTextWidth() does not work, see svgweb bug 417 + * IE7 has memory issue, see svgweb bug 418 (IE8 seems fine) + +PASS test.roundrect.html +PASS test_arc.html +PASS test_bezier.html +PASS test_decompose.html +PASS test_destroy.html +PASS test_fill.html + +FAIL test_fx.html: mostly works, except for the transformation of text (svgweb bug 158) + +PASS test_fx_shapes.html +PASS test_gfx.html +PASS test_gradient.html: works, but performance is slow due to the creation of a lot of shapes; using suspendRedraw() helps, but not much; current time is 8.5 seconds on IE7, 3 seconds on FF 3.5 +PASS test_group1.html: partly works, but rect highlight change has problem (svgweb bug 296) +PASS test_group2.html: works, with source changed from 'dijit.byId()' to 'dojo.byId()' +PASS test_image1.html +PASS test_image2.html: picture shows, but move and transform has serious problem (svgweb bug 296) + +FAIL test_image3.html: picture shows, but move and transform has serious problem (svgweb bug 427, 436) + +PASS test_image4.html +PASS test_image5.html: still image gets cropped after dragging, but mostly it's working (svgweb bug 244) +PASS test_linearGradient.html + +FAIL test_linestyle.html: not work (svgweb bug 65) + +PASS test_pattern.html +PASS test_poly.html +PASS test_resize.html +PASS test_setPath.html +PASS test_tbbox.html: output drawing is incorrect (svgweb bug 296) + +FAIL test_text.html: text shows, but the rotation still fails (svgweb bug 158) + +FAIL test_textpath.html: not work (svgweb bug 169) + +PASS test_transform.html: output drawing is incorrect (svgweb bug 296) +PASS test_utils.html +PASS test_vectortext_draw.html +PASS test_vectortext_load.html: functionally, this works, but very very slow; Reduced the test case to print just 26 chars, in FF it takes 30+ seconds, in IE7 it's more than a minute... + diff --git a/js/dojo-1.6/dojox/gfx/VectorText.js b/js/dojo-1.6/dojox/gfx/VectorText.js new file mode 100644 index 0000000..2f472a4 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/VectorText.js @@ -0,0 +1,788 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.VectorText"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.VectorText"] = true;
+dojo.provide("dojox.gfx.VectorText");
+dojo.require("dojox.gfx");
+dojo.require("dojox.xml.DomParser");
+dojo.require("dojox.html.metrics");
+
+(function(){
+ /*
+ dojox.gfx.VectorText
+ An implementation of the SVG Font 1.1 spec, using dojox.gfx.
+
+ Basic interface:
+ var f = new dojox.gfx.Font(url|string);
+ surface||group.createVectorText(text)
+ .setFill(fill)
+ .setStroke(stroke)
+ .setFont(fontStyleObject);
+
+ The arguments passed to createVectorText are the same as you would
+ pass to surface||group.createText; the difference is that this
+ is entirely renderer-agnostic, and the return value is a subclass
+ of dojox.gfx.Group.
+
+ Note also that the "defaultText" object is slightly different:
+ { type:"vectortext", x:0, y:0, width:null, height: null,
+ text: "", align: "start", decoration: "none" }
+
+ ...as well as the "defaultVectorFont" object:
+ { type:"vectorfont", size:"10pt" }
+
+ The reason for this should be obvious: most of the style for the font is defined
+ by the font object itself.
+
+ Note that this will only render IF and WHEN you set the font.
+ */
+ dojo.mixin(dojox.gfx, {
+ vectorFontFitting: {
+ NONE: 0, // render text according to passed size.
+ FLOW: 1, // render text based on the passed width and size
+ FIT: 2 // render text based on a passed viewbox.
+ },
+ defaultVectorText: {
+ type:"vectortext", x:0, y:0, width: null, height: null,
+ text: "", align: "start", decoration: "none", fitting: 0, // vectorFontFitting.NONE
+ leading: 1.5 // in ems.
+ },
+ defaultVectorFont: {
+ type:"vectorfont", size: "10pt", family: null
+ },
+ _vectorFontCache: {},
+ _svgFontCache: {},
+ getVectorFont: function(/* String */url){
+ if(dojox.gfx._vectorFontCache[url]){
+ return dojox.gfx._vectorFontCache[url];
+ }
+ return new dojox.gfx.VectorFont(url);
+ }
+ });
+
+ dojo.declare("dojox.gfx.VectorFont", null, {
+ _entityRe: /&(quot|apos|lt|gt|amp|#x[^;]+|#\d+);/g,
+ _decodeEntitySequence: function(str){
+ // unescape the unicode sequences
+
+ // nothing to decode
+ if(!str.match(this._entityRe)){ return; } // undefined
+ var xmlEntityMap = {
+ amp:"&", apos:"'", quot:'"', lt:"<", gt:">"
+ };
+
+ // we have at least one encoded entity.
+ var r, tmp="";
+ while((r=this._entityRe.exec(str))!==null){
+ if(r[1].charAt(1)=="x"){
+ tmp += String.fromCharCode(parseInt(r[1].slice(2), 16));
+ }
+ else if(!isNaN(parseInt(r[1].slice(1),10))){
+ tmp += String.fromCharCode(parseInt(r[1].slice(1), 10));
+ }
+ else {
+ tmp += xmlEntityMap[r[1]] || "";
+ }
+ }
+ return tmp; // String
+ },
+ _parse: function(/* String */svg, /* String */url){
+ // summary:
+ // Take the loaded SVG Font definition file and convert the info
+ // into things we can use. The SVG Font definition must follow
+ // the SVG 1.1 Font specification.
+ var doc = dojox.gfx._svgFontCache[url]||dojox.xml.DomParser.parse(svg);
+
+ // font information
+ var f = doc.documentElement.byName("font")[0], face = doc.documentElement.byName("font-face")[0];
+ var unitsPerEm = parseFloat(face.getAttribute("units-per-em")||1000, 10);
+ var advance = {
+ x: parseFloat(f.getAttribute("horiz-adv-x"), 10),
+ y: parseFloat(f.getAttribute("vert-adv-y")||0, 10)
+ };
+ if(!advance.y){
+ advance.y = unitsPerEm;
+ }
+
+ var origin = {
+ horiz: {
+ x: parseFloat(f.getAttribute("horiz-origin-x")||0, 10),
+ y: parseFloat(f.getAttribute("horiz-origin-y")||0, 10)
+ },
+ vert: {
+ x: parseFloat(f.getAttribute("vert-origin-x")||0, 10),
+ y: parseFloat(f.getAttribute("vert-origin-y")||0, 10)
+ }
+ };
+
+ // face information
+ var family = face.getAttribute("font-family"),
+ style = face.getAttribute("font-style")||"all",
+ variant = face.getAttribute("font-variant")||"normal",
+ weight = face.getAttribute("font-weight")||"all",
+ stretch = face.getAttribute("font-stretch")||"normal",
+
+ // additional info, may not be needed
+ range = face.getAttribute("unicode-range")||"U+0-10FFFF",
+ panose = face.getAttribute("panose-1") || "0 0 0 0 0 0 0 0 0 0",
+ capHeight = face.getAttribute("cap-height"),
+ ascent = parseFloat(face.getAttribute("ascent")||(unitsPerEm-origin.vert.y), 10),
+ descent = parseFloat(face.getAttribute("descent")||origin.vert.y, 10),
+ baseline = {};
+
+ // check for font-face-src/font-face-name
+ var name = family;
+ if(face.byName("font-face-name")[0]){
+ name = face.byName("font-face-name")[0].getAttribute("name");
+ }
+
+ // see if this is cached already, and if so, forget the rest of the parsing.
+ if(dojox.gfx._vectorFontCache[name]){ return; }
+
+ // get any provided baseline alignment offsets.
+ dojo.forEach(["alphabetic", "ideographic", "mathematical", "hanging" ], function(attr){
+ var a = face.getAttribute(attr);
+ if(a !== null /* be explicit, might be 0 */){
+ baseline[attr] = parseFloat(a, 10);
+ }
+ });
+
+ /*
+ // TODO: decoration hinting.
+ var decoration = { };
+ dojo.forEach(["underline", "strikethrough", "overline"], function(type){
+ if(face.getAttribute(type+"-position")!=null){
+ decoration[type]={ };
+ }
+ });
+ */
+
+ // missing glyph info
+ var missing = parseFloat(doc.documentElement.byName("missing-glyph")[0].getAttribute("horiz-adv-x")||advance.x, 10);
+
+ // glyph information
+ var glyphs = {}, glyphsByName={}, g=doc.documentElement.byName("glyph");
+ dojo.forEach(g, function(node){
+ // we are going to assume the following:
+ // 1) we have the unicode attribute
+ // 2) we have the name attribute
+ // 3) we have the horiz-adv-x and d attributes.
+ var code = node.getAttribute("unicode"),
+ name = node.getAttribute("glyph-name"),
+ xAdv = parseFloat(node.getAttribute("horiz-adv-x")||advance.x, 10),
+ path = node.getAttribute("d");
+
+ // unescape the unicode sequences
+ if(code.match(this._entityRe)){
+ code = this._decodeEntitySequence(code);
+ }
+
+ // build our glyph objects
+ var o = { code: code, name: name, xAdvance: xAdv, path: path };
+ glyphs[code]=o;
+ glyphsByName[name]=o;
+ }, this);
+
+ // now the fun part: look for kerning pairs.
+ var hkern=doc.documentElement.byName("hkern");
+ dojo.forEach(hkern, function(node, i){
+ var k = -parseInt(node.getAttribute("k"),10);
+ // look for either a code or a name
+ var u1=node.getAttribute("u1"),
+ g1=node.getAttribute("g1"),
+ u2=node.getAttribute("u2"),
+ g2=node.getAttribute("g2"),
+ gl;
+
+ if(u1){
+ // the first of the pair is a sequence of unicode characters.
+ // TODO: deal with unicode ranges and mulitple characters.
+ u1 = this._decodeEntitySequence(u1);
+ if(glyphs[u1]){
+ gl = glyphs[u1];
+ }
+ } else {
+ // we are referring to a name.
+ // TODO: deal with multiple names
+ if(glyphsByName[g1]){
+ gl = glyphsByName[g1];
+ }
+ }
+
+ if(gl){
+ if(!gl.kern){ gl.kern = {}; }
+ if(u2){
+ // see the notes above.
+ u2 = this._decodeEntitySequence(u2);
+ gl.kern[u2] = { x: k };
+ } else {
+ if(glyphsByName[g2]){
+ gl.kern[glyphsByName[g2].code] = { x: k };
+ }
+ }
+ }
+ }, this);
+
+ // pop the final definition in the font cache.
+ dojo.mixin(this, {
+ family: family,
+ name: name,
+ style: style,
+ variant: variant,
+ weight: weight,
+ stretch: stretch,
+ range: range,
+ viewbox: { width: unitsPerEm, height: unitsPerEm },
+ origin: origin,
+ advance: dojo.mixin(advance, {
+ missing:{ x: missing, y: missing }
+ }),
+ ascent: ascent,
+ descent: descent,
+ baseline: baseline,
+ glyphs: glyphs
+ });
+
+ // cache the parsed font
+ dojox.gfx._vectorFontCache[name] = this;
+ dojox.gfx._vectorFontCache[url] = this;
+ if(name!=family && !dojox.gfx._vectorFontCache[family]){
+ dojox.gfx._vectorFontCache[family] = this;
+ }
+
+ // cache the doc
+ if(!dojox.gfx._svgFontCache[url]){
+ dojox.gfx._svgFontCache[url]=doc;
+ }
+ },
+ _clean: function(){
+ // summary:
+ // Clean off all of the given mixin parameters.
+ var name = this.name, family = this.family;
+ dojo.forEach(["family","name","style","variant",
+ "weight","stretch","range","viewbox",
+ "origin","advance","ascent","descent",
+ "baseline","glyphs"], function(prop){
+ try{ delete this[prop]; } catch(e) { }
+ }, this);
+
+ // try to pull out of the font cache.
+ if(dojox.gfx._vectorFontCache[name]){
+ delete dojox.gfx._vectorFontCache[name];
+ }
+ if(dojox.gfx._vectorFontCache[family]){
+ delete dojox.gfx._vectorFontCache[family];
+ }
+ return this;
+ },
+
+ constructor: function(/* String|dojo._Url */url){
+ // summary::
+ // Create this font object based on the SVG Font definition at url.
+ this._defaultLeading = 1.5;
+ if(url!==undefined){
+ this.load(url);
+ }
+ },
+ load: function(/* String|dojo._Url */url){
+ // summary::
+ // Load the passed SVG and send it to the parser for parsing.
+ this.onLoadBegin(url.toString());
+ this._parse(
+ dojox.gfx._svgFontCache[url.toString()]||dojo._getText(url.toString()),
+ url.toString()
+ );
+ this.onLoad(this);
+ return this; // dojox.gfx.VectorFont
+ },
+ initialized: function(){
+ // summary::
+ // Return if we've loaded a font def, and the parsing was successful.
+ return (this.glyphs!==null); // Boolean
+ },
+
+ // preset round to 3 places.
+ _round: function(n){ return Math.round(1000*n)/1000; },
+ _leading: function(unit){ return this.viewbox.height * (unit||this._defaultLeading); },
+ _normalize: function(str){
+ return str.replace(/\s+/g, String.fromCharCode(0x20));
+ },
+
+ _getWidth: function(glyphs){
+ var w=0, last=0, lastGlyph=null;
+ dojo.forEach(glyphs, function(glyph, i){
+ last=glyph.xAdvance;
+ if(glyphs[i] && glyph.kern && glyph.kern[glyphs[i].code]){
+ last += glyph.kern[glyphs[i].code].x;
+ }
+ w += last;
+ lastGlyph = glyph;
+ });
+
+ // if the last glyph was a space, pull it off.
+ if(lastGlyph && lastGlyph.code == " "){
+ w -= lastGlyph.xAdvance;
+ }
+
+ return this._round(w/*-last*/);
+ },
+
+ _getLongestLine: function(lines){
+ var maxw=0, idx=0;
+ dojo.forEach(lines, function(line, i){
+ var max = Math.max(maxw, this._getWidth(line));
+ if(max > maxw){
+ maxw = max;
+ idx=i;
+ }
+ }, this);
+ return { width: maxw, index: idx, line: lines[idx] };
+ },
+
+ _trim: function(lines){
+ var fn = function(arr){
+ // check if the first or last character is a space and if so, remove it.
+ if(!arr.length){ return; }
+ if(arr[arr.length-1].code == " "){ arr.splice(arr.length-1, 1); }
+ if(!arr.length){ return; }
+ if(arr[0].code == " "){ arr.splice(0, 1); }
+ };
+
+ if(dojo.isArray(lines[0])){
+ // more than one line.
+ dojo.forEach(lines, fn);
+ } else {
+ fn(lines);
+ }
+ return lines;
+ },
+
+ _split: function(chars, nLines){
+ // summary:
+ // split passed chars into nLines by finding the closest whitespace.
+ var w = this._getWidth(chars),
+ limit = Math.floor(w/nLines),
+ lines = [],
+ cw = 0,
+ c = [],
+ found = false;
+
+ for(var i=0, l=chars.length; i<l; i++){
+ if(chars[i].code == " "){ found = true; }
+ cw += chars[i].xAdvance;
+ if(i+1<l && chars[i].kern && chars[i].kern[chars[i+1].code]){
+ cw += chars[i].kern[chars[i+1].code].x;
+ }
+
+ if(cw>=limit){
+ var chr=chars[i];
+ while(found && chr.code != " " && i>=0){
+ chr = c.pop(); i--;
+ }
+ lines.push(c);
+ c=[];
+ cw=0;
+ found=false;
+ }
+ c.push(chars[i]);
+ }
+ if(c.length){ lines.push(c); }
+ // "trim" it
+ return this._trim(lines);
+ },
+
+ _getSizeFactor: function(size){
+ // given the size, return a scaling factor based on the height of the
+ // font as defined in the font definition file.
+ size += ""; // force the string cast.
+ var metrics = dojox.html.metrics.getCachedFontMeasurements(),
+ height=this.viewbox.height,
+ f=metrics["1em"],
+ unit=parseFloat(size, 10); // the default.
+ if(size.indexOf("em")>-1){
+ return this._round((metrics["1em"]*unit)/height);
+ }
+ else if(size.indexOf("ex")>-1){
+ return this._round((metrics["1ex"]*unit)/height);
+ }
+ else if(size.indexOf("pt")>-1){
+ return this._round(((metrics["12pt"] / 12)*unit) / height);
+ }
+ else if(size.indexOf("px")>-1){
+ return this._round(((metrics["16px"] / 16)*unit) / height);
+ }
+ else if(size.indexOf("%")>-1){
+ return this._round((metrics["1em"]*(unit / 100)) / height);
+ }
+ else {
+ f=metrics[size]||metrics.medium;
+ return this._round(f/height);
+ }
+ },
+
+ _getFitFactor: function(lines, w, h, l){
+ // summary:
+ // Find the scaling factor for the given phrase set.
+ if(!h){
+ // if no height was passed, we assume an array of glyphs instead of lines.
+ return this._round(w/this._getWidth(lines));
+ } else {
+ var maxw = this._getLongestLine(lines).width,
+ maxh = (lines.length*(this.viewbox.height*l))-((this.viewbox.height*l)-this.viewbox.height);
+ return this._round(Math.min(w/maxw, h/maxh));
+ }
+ },
+ _getBestFit: function(chars, w, h, ldng){
+ // summary:
+ // Get the best number of lines to return given w and h.
+ var limit=32,
+ factor=0,
+ lines=limit;
+ while(limit>0){
+ var f=this._getFitFactor(this._split(chars, limit), w, h, ldng);
+ if(f>factor){
+ factor = f;
+ lines=limit;
+ }
+ limit--;
+ }
+ return { scale: factor, lines: this._split(chars, lines) };
+ },
+
+ _getBestFlow: function(chars, w, scale){
+ // summary:
+ // Based on the given scale, do the best line splitting possible.
+ var lines = [],
+ cw = 0,
+ c = [],
+ found = false;
+ for(var i=0, l=chars.length; i<l; i++){
+ if(chars[i].code == " "){ found = true; }
+ var tw = chars[i].xAdvance;
+ if(i+1<l && chars[i].kern && chars[i].kern[chars[i+1].code]){
+ tw += chars[i].kern[chars[i+1].code].x;
+ }
+ cw += scale*tw;
+
+ if(cw>=w){
+ var chr=chars[i];
+ while(found && chr.code != " " && i>=0){
+ chr = c.pop(); i--;
+ }
+ lines.push(c);
+ c=[];
+ cw=0;
+ found=false;
+ }
+ c.push(chars[i]);
+ }
+ if(c.length){ lines.push(c); }
+ return this._trim(lines);
+ },
+
+ // public functions
+ getWidth: function(/* String */text, /* Float? */scale){
+ // summary:
+ // Get the width of the rendered text without actually rendering it.
+ return this._getWidth(dojo.map(this._normalize(text).split(""), function(chr){
+ return this.glyphs[chr] || { xAdvance: this.advance.missing.x };
+ }, this)) * (scale || 1); // Float
+ },
+ getLineHeight: function(/* Float? */scale){
+ // summary:
+ // return the height of a single line, sans leading, based on scale.
+ return this.viewbox.height * (scale || 1); // Float
+ },
+
+ // A note:
+ // Many SVG exports do not include information such as x-height, caps-height
+ // and other coords that may help alignment. We can calc the baseline and
+ // we can get a mean line (i.e. center alignment) but that's about all, reliably.
+ getCenterline: function(/* Float? */scale){
+ // summary:
+ // return the y coordinate that is the center of the viewbox.
+ return (scale||1) * (this.viewbox.height/2);
+ },
+ getBaseline: function(/* Float? */scale){
+ // summary:
+ // Find the baseline coord for alignment; adjust for scale if passed.
+ return (scale||1) * (this.viewbox.height+this.descent); // Float
+ },
+
+ draw: function(/* dojox.gfx.Container */group, /* dojox.gfx.__TextArgs */textArgs, /* dojox.gfx.__FontArgs */fontArgs, /* dojox.gfx.__FillArgs */fillArgs, /* dojox.gfx.__StrokeArgs? */strokeArgs){
+ // summary:
+ // based on the passed parameters, draw the given text using paths
+ // defined by this font.
+ //
+ // description:
+ // The main method of a VectorFont, draw() will take a text fragment
+ // and render it in a set of groups and paths based on the parameters
+ // passed.
+ //
+ // The basics of drawing text are simple enough: pass it your text as
+ // part of the textArgs object, pass size and family info as part of
+ // the fontArgs object, pass at least a color as the fillArgs object,
+ // and if you are looking to create an outline, pass the strokeArgs
+ // object as well. fillArgs and strokeArgs are the same as any other
+ // gfx fill and stroke arguments; they are simply applied to any path
+ // object generated by this method.
+ //
+ // Resulting GFX structure
+ // -----------------------
+ //
+ // The result of this function is a set of gfx objects in the following
+ // structure:
+ //
+ // | dojox.gfx.Group // the parent group generated by this function
+ // | + dojox.gfx.Group[] // a group generated for each line of text
+ // | + dojox.gfx.Path[] // each glyph/character in the text
+ //
+ // Scaling transformations (i.e. making the generated text the correct size)
+ // are always applied to the parent Group that is generated (i.e. the top
+ // node in the above example). In theory, if you are looking to do any kind
+ // of other transformations (such as a translation), you should apply it to
+ // the group reference you pass to this method. If you find that you need
+ // to apply transformations to the group that is returned by this method,
+ // you will need to reapply the scaling transformation as the *last* transform,
+ // like so:
+ //
+ // | textGroup.setTransform(new dojox.gfx.Matrix2D([
+ // | dojox.gfx.matrix.translate({ dx: dx, dy: dy }),
+ // | textGroup.getTransform()
+ // | ]));
+ //
+ // In general, this should never be necessary unless you are doing advanced
+ // placement of your text.
+ //
+ // Advanced Layout Functionality
+ // -----------------------------
+ //
+ // In addition to straight text fragments, draw() supports a few advanced
+ // operations not normally available with vector graphics:
+ //
+ // * Flow operations (i.e. wrap to a given width)
+ // * Fitting operations (i.e. find a best fit to a given rectangle)
+ //
+ // To enable either, pass a `fitting` property along with the textArgs object.
+ // The possible values are contained in the dojox.gfx.vectorFontFitting enum
+ // (NONE, FLOW, FIT).
+ //
+ // `Flow fitting`
+ // Flow fitting requires both a passed size (in the fontArgs object) and a
+ // width (passed with the textArgs object). draw() will attempt to split the
+ // passed text up into lines, at the closest whitespace according to the
+ // passed width. If a width is missing, it will revert to NONE.
+ //
+ // `Best fit fitting`
+ // Doing a "best fit" means taking the passed text, and finding the largest
+ // size and line breaks so that it is the closest fit possible. With best
+ // fit, any size arguments are ignored; if a height is missing, it will revert
+ // to NONE.
+ //
+ // Other notes
+ // -----------
+ //
+ // `a11y`
+ // Since the results of this method are rendering using pure paths (think
+ // "convert to outlines" in Adobe Illustrator), any text rendered by this
+ // code is NOT considered a11y-friendly. If a11y is a requirement, we
+ // suggest using other, more a11y-friendly methods.
+ //
+ // `Font sources`
+ // Always make sure that you are legally allowed to use any fonts that you
+ // convert to SVG format; we claim no responsibility for any licensing
+ // infractions that may be caused by the use of this code.
+ if(!this.initialized()){
+ throw new Error("dojox.gfx.VectorFont.draw(): we have not been initialized yet.");
+ }
+ // TODO: BIDI handling. Deal with layout/alignments based on font parameters.
+
+ // start by creating the overall group. This is the INNER group (the caller
+ // should be the outer).
+ var g = group.createGroup();
+
+ // do the x/y translation on the parent group
+ // FIXME: this is probably not the best way of doing this.
+ if(textArgs.x || textArgs.y){
+ group.applyTransform({ dx: textArgs.x||0, dy: textArgs.y||0 });
+ }
+
+ // go get the glyph array.
+ var text = dojo.map(this._normalize(textArgs.text).split(""), function(chr){
+ return this.glyphs[chr] || { path:null, xAdvance: this.advance.missing.x };
+ }, this);
+
+ // determine the font style info, ignore decoration.
+ var size = fontArgs.size,
+ fitting = textArgs.fitting,
+ width = textArgs.width,
+ height = textArgs.height,
+ align = textArgs.align,
+ leading = textArgs.leading||this._defaultLeading;
+
+ // figure out if we have to do fitting at all.
+ if(fitting){
+ // more than zero.
+ if((fitting==dojox.gfx.vectorFontFitting.FLOW && !width) || (fitting==dojox.gfx.vectorFontFitting.FIT && (!width || !height))){
+ // reset the fitting if we don't have everything we need.
+ fitting = dojox.gfx.vectorFontFitting.NONE;
+ }
+ }
+
+ // set up the lines array and the scaling factor.
+ var lines, scale;
+ switch(fitting){
+ case dojox.gfx.vectorFontFitting.FIT:
+ var o=this._getBestFit(text, width, height, leading);
+ scale = o.scale;
+ lines = o.lines;
+ break;
+
+ case dojox.gfx.vectorFontFitting.FLOW:
+ scale = this._getSizeFactor(size);
+ lines = this._getBestFlow(text, width, scale);
+ break;
+
+ default:
+ scale = this._getSizeFactor(size);
+ lines = [ text ];
+
+ }
+
+ // make sure lines doesn't have any empty lines.
+ lines = dojo.filter(lines, function(item){
+ return item.length>0;
+ });
+
+ // let's start drawing.
+ var cy = 0,
+ maxw = this._getLongestLine(lines).width;
+
+ for(var i=0, l=lines.length; i<l; i++){
+ var cx = 0,
+ line=lines[i],
+ linew = this._getWidth(line),
+ lg=g.createGroup();
+
+ // loop through the glyphs and add them to the line group (lg)
+ for (var j=0; j<line.length; j++){
+ var glyph=line[j];
+ if(glyph.path!==null){
+ var p = lg.createPath(glyph.path).setFill(fillArgs);
+ if(strokeArgs){ p.setStroke(strokeArgs); }
+ p.setTransform([
+ dojox.gfx.matrix.flipY,
+ dojox.gfx.matrix.translate(cx, -this.viewbox.height-this.descent)
+ ]);
+ }
+ cx += glyph.xAdvance;
+ if(j+1<line.length && glyph.kern && glyph.kern[line[j+1].code]){
+ cx += glyph.kern[line[j+1].code].x;
+ }
+ }
+
+ // transform the line group.
+ var dx = 0;
+ if(align=="middle"){ dx = maxw/2 - linew/2; }
+ else if(align=="end"){ dx = maxw - linew; }
+ lg.setTransform({ dx: dx, dy: cy });
+ cy += this.viewbox.height * leading;
+ }
+
+ // scale the group
+ g.setTransform(dojox.gfx.matrix.scale(scale));
+
+ // return the overall group
+ return g; // dojox.gfx.Group
+ },
+
+ // events
+ onLoadBegin: function(/* String */url){ },
+ onLoad: function(/* dojox.gfx.VectorFont */font){ }
+ });
+
+ // TODO: dojox.gfx integration
+/*
+
+ // Inherit from Group but attach Text properties to it.
+ dojo.declare("dojox.gfx.VectorText", dojox.gfx.Group, {
+ constructor: function(rawNode){
+ dojox.gfx.Group._init.call(this);
+ this.fontStyle = null;
+ },
+
+ // private methods.
+ _setFont: function(){
+ // render this using the font code.
+ var f = this.fontStyle;
+ var font = dojox.gfx._vectorFontCache[f.family];
+ if(!font){
+ throw new Error("dojox.gfx.VectorText._setFont: the passed font family '" + f.family + "' was not found.");
+ }
+
+ // the actual rendering belongs to the font itself.
+ font.draw(this, this.shape, this.fontStyle, this.fillStyle, this.strokeStyle);
+ },
+
+ getFont: function(){ return this.fontStyle; },
+
+ // overridden public methods.
+ setShape: function(newShape){
+ dojox.gfx.Group.setShape.call(this);
+ this.shape = dojox.gfx.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ this._setFont();
+ return this;
+ },
+
+ // if we've been drawing, we should have exactly one child, and that
+ // child will contain the real children.
+ setFill: function(fill){
+ this.fillStyle = fill;
+ if(this.children[0]){
+ dojo.forEach(this.children[0].children, function(group){
+ dojo.forEach(group.children, function(path){
+ path.setFill(fill);
+ });
+ }, this);
+ }
+ return this;
+ },
+ setStroke: function(stroke){
+ this.strokeStyle = stroke;
+ if(this.children[0]){
+ dojo.forEach(this.children[0].children, function(group){
+ dojo.forEach(group.children, function(path){
+ path.setStroke(stroke);
+ });
+ }, this);
+ }
+ return this;
+ },
+
+ setFont: function(newFont){
+ // this will do the real rendering.
+ this.fontStyle = typeof newFont == "string" ? dojox.gfx.splitFontString(newFont)
+ : dojox.gfx.makeParameters(dojox.gfx.defaultFont, newFont);
+ this._setFont();
+ return this;
+ },
+
+ getBoundingBox: function(){
+ return this.bbox;
+ }
+ });
+
+ // TODO: figure out how to add this to container objects!
+ dojox.gfx.shape.Creator.createVectorText = function(text){
+ return this.createObject(dojox.gfx.VectorText, text);
+ }
+*/
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/VectorText.xd.js b/js/dojo-1.6/dojox/gfx/VectorText.xd.js new file mode 100644 index 0000000..5654ba2 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/VectorText.xd.js @@ -0,0 +1,795 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.VectorText"],
+["require", "dojox.gfx"],
+["require", "dojox.xml.DomParser"],
+["require", "dojox.html.metrics"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.VectorText"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.VectorText"] = true;
+dojo.provide("dojox.gfx.VectorText");
+dojo.require("dojox.gfx");
+dojo.require("dojox.xml.DomParser");
+dojo.require("dojox.html.metrics");
+
+(function(){
+ /*
+ dojox.gfx.VectorText
+ An implementation of the SVG Font 1.1 spec, using dojox.gfx.
+
+ Basic interface:
+ var f = new dojox.gfx.Font(url|string);
+ surface||group.createVectorText(text)
+ .setFill(fill)
+ .setStroke(stroke)
+ .setFont(fontStyleObject);
+
+ The arguments passed to createVectorText are the same as you would
+ pass to surface||group.createText; the difference is that this
+ is entirely renderer-agnostic, and the return value is a subclass
+ of dojox.gfx.Group.
+
+ Note also that the "defaultText" object is slightly different:
+ { type:"vectortext", x:0, y:0, width:null, height: null,
+ text: "", align: "start", decoration: "none" }
+
+ ...as well as the "defaultVectorFont" object:
+ { type:"vectorfont", size:"10pt" }
+
+ The reason for this should be obvious: most of the style for the font is defined
+ by the font object itself.
+
+ Note that this will only render IF and WHEN you set the font.
+ */
+ dojo.mixin(dojox.gfx, {
+ vectorFontFitting: {
+ NONE: 0, // render text according to passed size.
+ FLOW: 1, // render text based on the passed width and size
+ FIT: 2 // render text based on a passed viewbox.
+ },
+ defaultVectorText: {
+ type:"vectortext", x:0, y:0, width: null, height: null,
+ text: "", align: "start", decoration: "none", fitting: 0, // vectorFontFitting.NONE
+ leading: 1.5 // in ems.
+ },
+ defaultVectorFont: {
+ type:"vectorfont", size: "10pt", family: null
+ },
+ _vectorFontCache: {},
+ _svgFontCache: {},
+ getVectorFont: function(/* String */url){
+ if(dojox.gfx._vectorFontCache[url]){
+ return dojox.gfx._vectorFontCache[url];
+ }
+ return new dojox.gfx.VectorFont(url);
+ }
+ });
+
+ dojo.declare("dojox.gfx.VectorFont", null, {
+ _entityRe: /&(quot|apos|lt|gt|amp|#x[^;]+|#\d+);/g,
+ _decodeEntitySequence: function(str){
+ // unescape the unicode sequences
+
+ // nothing to decode
+ if(!str.match(this._entityRe)){ return; } // undefined
+ var xmlEntityMap = {
+ amp:"&", apos:"'", quot:'"', lt:"<", gt:">"
+ };
+
+ // we have at least one encoded entity.
+ var r, tmp="";
+ while((r=this._entityRe.exec(str))!==null){
+ if(r[1].charAt(1)=="x"){
+ tmp += String.fromCharCode(parseInt(r[1].slice(2), 16));
+ }
+ else if(!isNaN(parseInt(r[1].slice(1),10))){
+ tmp += String.fromCharCode(parseInt(r[1].slice(1), 10));
+ }
+ else {
+ tmp += xmlEntityMap[r[1]] || "";
+ }
+ }
+ return tmp; // String
+ },
+ _parse: function(/* String */svg, /* String */url){
+ // summary:
+ // Take the loaded SVG Font definition file and convert the info
+ // into things we can use. The SVG Font definition must follow
+ // the SVG 1.1 Font specification.
+ var doc = dojox.gfx._svgFontCache[url]||dojox.xml.DomParser.parse(svg);
+
+ // font information
+ var f = doc.documentElement.byName("font")[0], face = doc.documentElement.byName("font-face")[0];
+ var unitsPerEm = parseFloat(face.getAttribute("units-per-em")||1000, 10);
+ var advance = {
+ x: parseFloat(f.getAttribute("horiz-adv-x"), 10),
+ y: parseFloat(f.getAttribute("vert-adv-y")||0, 10)
+ };
+ if(!advance.y){
+ advance.y = unitsPerEm;
+ }
+
+ var origin = {
+ horiz: {
+ x: parseFloat(f.getAttribute("horiz-origin-x")||0, 10),
+ y: parseFloat(f.getAttribute("horiz-origin-y")||0, 10)
+ },
+ vert: {
+ x: parseFloat(f.getAttribute("vert-origin-x")||0, 10),
+ y: parseFloat(f.getAttribute("vert-origin-y")||0, 10)
+ }
+ };
+
+ // face information
+ var family = face.getAttribute("font-family"),
+ style = face.getAttribute("font-style")||"all",
+ variant = face.getAttribute("font-variant")||"normal",
+ weight = face.getAttribute("font-weight")||"all",
+ stretch = face.getAttribute("font-stretch")||"normal",
+
+ // additional info, may not be needed
+ range = face.getAttribute("unicode-range")||"U+0-10FFFF",
+ panose = face.getAttribute("panose-1") || "0 0 0 0 0 0 0 0 0 0",
+ capHeight = face.getAttribute("cap-height"),
+ ascent = parseFloat(face.getAttribute("ascent")||(unitsPerEm-origin.vert.y), 10),
+ descent = parseFloat(face.getAttribute("descent")||origin.vert.y, 10),
+ baseline = {};
+
+ // check for font-face-src/font-face-name
+ var name = family;
+ if(face.byName("font-face-name")[0]){
+ name = face.byName("font-face-name")[0].getAttribute("name");
+ }
+
+ // see if this is cached already, and if so, forget the rest of the parsing.
+ if(dojox.gfx._vectorFontCache[name]){ return; }
+
+ // get any provided baseline alignment offsets.
+ dojo.forEach(["alphabetic", "ideographic", "mathematical", "hanging" ], function(attr){
+ var a = face.getAttribute(attr);
+ if(a !== null /* be explicit, might be 0 */){
+ baseline[attr] = parseFloat(a, 10);
+ }
+ });
+
+ /*
+ // TODO: decoration hinting.
+ var decoration = { };
+ dojo.forEach(["underline", "strikethrough", "overline"], function(type){
+ if(face.getAttribute(type+"-position")!=null){
+ decoration[type]={ };
+ }
+ });
+ */
+
+ // missing glyph info
+ var missing = parseFloat(doc.documentElement.byName("missing-glyph")[0].getAttribute("horiz-adv-x")||advance.x, 10);
+
+ // glyph information
+ var glyphs = {}, glyphsByName={}, g=doc.documentElement.byName("glyph");
+ dojo.forEach(g, function(node){
+ // we are going to assume the following:
+ // 1) we have the unicode attribute
+ // 2) we have the name attribute
+ // 3) we have the horiz-adv-x and d attributes.
+ var code = node.getAttribute("unicode"),
+ name = node.getAttribute("glyph-name"),
+ xAdv = parseFloat(node.getAttribute("horiz-adv-x")||advance.x, 10),
+ path = node.getAttribute("d");
+
+ // unescape the unicode sequences
+ if(code.match(this._entityRe)){
+ code = this._decodeEntitySequence(code);
+ }
+
+ // build our glyph objects
+ var o = { code: code, name: name, xAdvance: xAdv, path: path };
+ glyphs[code]=o;
+ glyphsByName[name]=o;
+ }, this);
+
+ // now the fun part: look for kerning pairs.
+ var hkern=doc.documentElement.byName("hkern");
+ dojo.forEach(hkern, function(node, i){
+ var k = -parseInt(node.getAttribute("k"),10);
+ // look for either a code or a name
+ var u1=node.getAttribute("u1"),
+ g1=node.getAttribute("g1"),
+ u2=node.getAttribute("u2"),
+ g2=node.getAttribute("g2"),
+ gl;
+
+ if(u1){
+ // the first of the pair is a sequence of unicode characters.
+ // TODO: deal with unicode ranges and mulitple characters.
+ u1 = this._decodeEntitySequence(u1);
+ if(glyphs[u1]){
+ gl = glyphs[u1];
+ }
+ } else {
+ // we are referring to a name.
+ // TODO: deal with multiple names
+ if(glyphsByName[g1]){
+ gl = glyphsByName[g1];
+ }
+ }
+
+ if(gl){
+ if(!gl.kern){ gl.kern = {}; }
+ if(u2){
+ // see the notes above.
+ u2 = this._decodeEntitySequence(u2);
+ gl.kern[u2] = { x: k };
+ } else {
+ if(glyphsByName[g2]){
+ gl.kern[glyphsByName[g2].code] = { x: k };
+ }
+ }
+ }
+ }, this);
+
+ // pop the final definition in the font cache.
+ dojo.mixin(this, {
+ family: family,
+ name: name,
+ style: style,
+ variant: variant,
+ weight: weight,
+ stretch: stretch,
+ range: range,
+ viewbox: { width: unitsPerEm, height: unitsPerEm },
+ origin: origin,
+ advance: dojo.mixin(advance, {
+ missing:{ x: missing, y: missing }
+ }),
+ ascent: ascent,
+ descent: descent,
+ baseline: baseline,
+ glyphs: glyphs
+ });
+
+ // cache the parsed font
+ dojox.gfx._vectorFontCache[name] = this;
+ dojox.gfx._vectorFontCache[url] = this;
+ if(name!=family && !dojox.gfx._vectorFontCache[family]){
+ dojox.gfx._vectorFontCache[family] = this;
+ }
+
+ // cache the doc
+ if(!dojox.gfx._svgFontCache[url]){
+ dojox.gfx._svgFontCache[url]=doc;
+ }
+ },
+ _clean: function(){
+ // summary:
+ // Clean off all of the given mixin parameters.
+ var name = this.name, family = this.family;
+ dojo.forEach(["family","name","style","variant",
+ "weight","stretch","range","viewbox",
+ "origin","advance","ascent","descent",
+ "baseline","glyphs"], function(prop){
+ try{ delete this[prop]; } catch(e) { }
+ }, this);
+
+ // try to pull out of the font cache.
+ if(dojox.gfx._vectorFontCache[name]){
+ delete dojox.gfx._vectorFontCache[name];
+ }
+ if(dojox.gfx._vectorFontCache[family]){
+ delete dojox.gfx._vectorFontCache[family];
+ }
+ return this;
+ },
+
+ constructor: function(/* String|dojo._Url */url){
+ // summary::
+ // Create this font object based on the SVG Font definition at url.
+ this._defaultLeading = 1.5;
+ if(url!==undefined){
+ this.load(url);
+ }
+ },
+ load: function(/* String|dojo._Url */url){
+ // summary::
+ // Load the passed SVG and send it to the parser for parsing.
+ this.onLoadBegin(url.toString());
+ this._parse(
+ dojox.gfx._svgFontCache[url.toString()]||dojo._getText(url.toString()),
+ url.toString()
+ );
+ this.onLoad(this);
+ return this; // dojox.gfx.VectorFont
+ },
+ initialized: function(){
+ // summary::
+ // Return if we've loaded a font def, and the parsing was successful.
+ return (this.glyphs!==null); // Boolean
+ },
+
+ // preset round to 3 places.
+ _round: function(n){ return Math.round(1000*n)/1000; },
+ _leading: function(unit){ return this.viewbox.height * (unit||this._defaultLeading); },
+ _normalize: function(str){
+ return str.replace(/\s+/g, String.fromCharCode(0x20));
+ },
+
+ _getWidth: function(glyphs){
+ var w=0, last=0, lastGlyph=null;
+ dojo.forEach(glyphs, function(glyph, i){
+ last=glyph.xAdvance;
+ if(glyphs[i] && glyph.kern && glyph.kern[glyphs[i].code]){
+ last += glyph.kern[glyphs[i].code].x;
+ }
+ w += last;
+ lastGlyph = glyph;
+ });
+
+ // if the last glyph was a space, pull it off.
+ if(lastGlyph && lastGlyph.code == " "){
+ w -= lastGlyph.xAdvance;
+ }
+
+ return this._round(w/*-last*/);
+ },
+
+ _getLongestLine: function(lines){
+ var maxw=0, idx=0;
+ dojo.forEach(lines, function(line, i){
+ var max = Math.max(maxw, this._getWidth(line));
+ if(max > maxw){
+ maxw = max;
+ idx=i;
+ }
+ }, this);
+ return { width: maxw, index: idx, line: lines[idx] };
+ },
+
+ _trim: function(lines){
+ var fn = function(arr){
+ // check if the first or last character is a space and if so, remove it.
+ if(!arr.length){ return; }
+ if(arr[arr.length-1].code == " "){ arr.splice(arr.length-1, 1); }
+ if(!arr.length){ return; }
+ if(arr[0].code == " "){ arr.splice(0, 1); }
+ };
+
+ if(dojo.isArray(lines[0])){
+ // more than one line.
+ dojo.forEach(lines, fn);
+ } else {
+ fn(lines);
+ }
+ return lines;
+ },
+
+ _split: function(chars, nLines){
+ // summary:
+ // split passed chars into nLines by finding the closest whitespace.
+ var w = this._getWidth(chars),
+ limit = Math.floor(w/nLines),
+ lines = [],
+ cw = 0,
+ c = [],
+ found = false;
+
+ for(var i=0, l=chars.length; i<l; i++){
+ if(chars[i].code == " "){ found = true; }
+ cw += chars[i].xAdvance;
+ if(i+1<l && chars[i].kern && chars[i].kern[chars[i+1].code]){
+ cw += chars[i].kern[chars[i+1].code].x;
+ }
+
+ if(cw>=limit){
+ var chr=chars[i];
+ while(found && chr.code != " " && i>=0){
+ chr = c.pop(); i--;
+ }
+ lines.push(c);
+ c=[];
+ cw=0;
+ found=false;
+ }
+ c.push(chars[i]);
+ }
+ if(c.length){ lines.push(c); }
+ // "trim" it
+ return this._trim(lines);
+ },
+
+ _getSizeFactor: function(size){
+ // given the size, return a scaling factor based on the height of the
+ // font as defined in the font definition file.
+ size += ""; // force the string cast.
+ var metrics = dojox.html.metrics.getCachedFontMeasurements(),
+ height=this.viewbox.height,
+ f=metrics["1em"],
+ unit=parseFloat(size, 10); // the default.
+ if(size.indexOf("em")>-1){
+ return this._round((metrics["1em"]*unit)/height);
+ }
+ else if(size.indexOf("ex")>-1){
+ return this._round((metrics["1ex"]*unit)/height);
+ }
+ else if(size.indexOf("pt")>-1){
+ return this._round(((metrics["12pt"] / 12)*unit) / height);
+ }
+ else if(size.indexOf("px")>-1){
+ return this._round(((metrics["16px"] / 16)*unit) / height);
+ }
+ else if(size.indexOf("%")>-1){
+ return this._round((metrics["1em"]*(unit / 100)) / height);
+ }
+ else {
+ f=metrics[size]||metrics.medium;
+ return this._round(f/height);
+ }
+ },
+
+ _getFitFactor: function(lines, w, h, l){
+ // summary:
+ // Find the scaling factor for the given phrase set.
+ if(!h){
+ // if no height was passed, we assume an array of glyphs instead of lines.
+ return this._round(w/this._getWidth(lines));
+ } else {
+ var maxw = this._getLongestLine(lines).width,
+ maxh = (lines.length*(this.viewbox.height*l))-((this.viewbox.height*l)-this.viewbox.height);
+ return this._round(Math.min(w/maxw, h/maxh));
+ }
+ },
+ _getBestFit: function(chars, w, h, ldng){
+ // summary:
+ // Get the best number of lines to return given w and h.
+ var limit=32,
+ factor=0,
+ lines=limit;
+ while(limit>0){
+ var f=this._getFitFactor(this._split(chars, limit), w, h, ldng);
+ if(f>factor){
+ factor = f;
+ lines=limit;
+ }
+ limit--;
+ }
+ return { scale: factor, lines: this._split(chars, lines) };
+ },
+
+ _getBestFlow: function(chars, w, scale){
+ // summary:
+ // Based on the given scale, do the best line splitting possible.
+ var lines = [],
+ cw = 0,
+ c = [],
+ found = false;
+ for(var i=0, l=chars.length; i<l; i++){
+ if(chars[i].code == " "){ found = true; }
+ var tw = chars[i].xAdvance;
+ if(i+1<l && chars[i].kern && chars[i].kern[chars[i+1].code]){
+ tw += chars[i].kern[chars[i+1].code].x;
+ }
+ cw += scale*tw;
+
+ if(cw>=w){
+ var chr=chars[i];
+ while(found && chr.code != " " && i>=0){
+ chr = c.pop(); i--;
+ }
+ lines.push(c);
+ c=[];
+ cw=0;
+ found=false;
+ }
+ c.push(chars[i]);
+ }
+ if(c.length){ lines.push(c); }
+ return this._trim(lines);
+ },
+
+ // public functions
+ getWidth: function(/* String */text, /* Float? */scale){
+ // summary:
+ // Get the width of the rendered text without actually rendering it.
+ return this._getWidth(dojo.map(this._normalize(text).split(""), function(chr){
+ return this.glyphs[chr] || { xAdvance: this.advance.missing.x };
+ }, this)) * (scale || 1); // Float
+ },
+ getLineHeight: function(/* Float? */scale){
+ // summary:
+ // return the height of a single line, sans leading, based on scale.
+ return this.viewbox.height * (scale || 1); // Float
+ },
+
+ // A note:
+ // Many SVG exports do not include information such as x-height, caps-height
+ // and other coords that may help alignment. We can calc the baseline and
+ // we can get a mean line (i.e. center alignment) but that's about all, reliably.
+ getCenterline: function(/* Float? */scale){
+ // summary:
+ // return the y coordinate that is the center of the viewbox.
+ return (scale||1) * (this.viewbox.height/2);
+ },
+ getBaseline: function(/* Float? */scale){
+ // summary:
+ // Find the baseline coord for alignment; adjust for scale if passed.
+ return (scale||1) * (this.viewbox.height+this.descent); // Float
+ },
+
+ draw: function(/* dojox.gfx.Container */group, /* dojox.gfx.__TextArgs */textArgs, /* dojox.gfx.__FontArgs */fontArgs, /* dojox.gfx.__FillArgs */fillArgs, /* dojox.gfx.__StrokeArgs? */strokeArgs){
+ // summary:
+ // based on the passed parameters, draw the given text using paths
+ // defined by this font.
+ //
+ // description:
+ // The main method of a VectorFont, draw() will take a text fragment
+ // and render it in a set of groups and paths based on the parameters
+ // passed.
+ //
+ // The basics of drawing text are simple enough: pass it your text as
+ // part of the textArgs object, pass size and family info as part of
+ // the fontArgs object, pass at least a color as the fillArgs object,
+ // and if you are looking to create an outline, pass the strokeArgs
+ // object as well. fillArgs and strokeArgs are the same as any other
+ // gfx fill and stroke arguments; they are simply applied to any path
+ // object generated by this method.
+ //
+ // Resulting GFX structure
+ // -----------------------
+ //
+ // The result of this function is a set of gfx objects in the following
+ // structure:
+ //
+ // | dojox.gfx.Group // the parent group generated by this function
+ // | + dojox.gfx.Group[] // a group generated for each line of text
+ // | + dojox.gfx.Path[] // each glyph/character in the text
+ //
+ // Scaling transformations (i.e. making the generated text the correct size)
+ // are always applied to the parent Group that is generated (i.e. the top
+ // node in the above example). In theory, if you are looking to do any kind
+ // of other transformations (such as a translation), you should apply it to
+ // the group reference you pass to this method. If you find that you need
+ // to apply transformations to the group that is returned by this method,
+ // you will need to reapply the scaling transformation as the *last* transform,
+ // like so:
+ //
+ // | textGroup.setTransform(new dojox.gfx.Matrix2D([
+ // | dojox.gfx.matrix.translate({ dx: dx, dy: dy }),
+ // | textGroup.getTransform()
+ // | ]));
+ //
+ // In general, this should never be necessary unless you are doing advanced
+ // placement of your text.
+ //
+ // Advanced Layout Functionality
+ // -----------------------------
+ //
+ // In addition to straight text fragments, draw() supports a few advanced
+ // operations not normally available with vector graphics:
+ //
+ // * Flow operations (i.e. wrap to a given width)
+ // * Fitting operations (i.e. find a best fit to a given rectangle)
+ //
+ // To enable either, pass a `fitting` property along with the textArgs object.
+ // The possible values are contained in the dojox.gfx.vectorFontFitting enum
+ // (NONE, FLOW, FIT).
+ //
+ // `Flow fitting`
+ // Flow fitting requires both a passed size (in the fontArgs object) and a
+ // width (passed with the textArgs object). draw() will attempt to split the
+ // passed text up into lines, at the closest whitespace according to the
+ // passed width. If a width is missing, it will revert to NONE.
+ //
+ // `Best fit fitting`
+ // Doing a "best fit" means taking the passed text, and finding the largest
+ // size and line breaks so that it is the closest fit possible. With best
+ // fit, any size arguments are ignored; if a height is missing, it will revert
+ // to NONE.
+ //
+ // Other notes
+ // -----------
+ //
+ // `a11y`
+ // Since the results of this method are rendering using pure paths (think
+ // "convert to outlines" in Adobe Illustrator), any text rendered by this
+ // code is NOT considered a11y-friendly. If a11y is a requirement, we
+ // suggest using other, more a11y-friendly methods.
+ //
+ // `Font sources`
+ // Always make sure that you are legally allowed to use any fonts that you
+ // convert to SVG format; we claim no responsibility for any licensing
+ // infractions that may be caused by the use of this code.
+ if(!this.initialized()){
+ throw new Error("dojox.gfx.VectorFont.draw(): we have not been initialized yet.");
+ }
+ // TODO: BIDI handling. Deal with layout/alignments based on font parameters.
+
+ // start by creating the overall group. This is the INNER group (the caller
+ // should be the outer).
+ var g = group.createGroup();
+
+ // do the x/y translation on the parent group
+ // FIXME: this is probably not the best way of doing this.
+ if(textArgs.x || textArgs.y){
+ group.applyTransform({ dx: textArgs.x||0, dy: textArgs.y||0 });
+ }
+
+ // go get the glyph array.
+ var text = dojo.map(this._normalize(textArgs.text).split(""), function(chr){
+ return this.glyphs[chr] || { path:null, xAdvance: this.advance.missing.x };
+ }, this);
+
+ // determine the font style info, ignore decoration.
+ var size = fontArgs.size,
+ fitting = textArgs.fitting,
+ width = textArgs.width,
+ height = textArgs.height,
+ align = textArgs.align,
+ leading = textArgs.leading||this._defaultLeading;
+
+ // figure out if we have to do fitting at all.
+ if(fitting){
+ // more than zero.
+ if((fitting==dojox.gfx.vectorFontFitting.FLOW && !width) || (fitting==dojox.gfx.vectorFontFitting.FIT && (!width || !height))){
+ // reset the fitting if we don't have everything we need.
+ fitting = dojox.gfx.vectorFontFitting.NONE;
+ }
+ }
+
+ // set up the lines array and the scaling factor.
+ var lines, scale;
+ switch(fitting){
+ case dojox.gfx.vectorFontFitting.FIT:
+ var o=this._getBestFit(text, width, height, leading);
+ scale = o.scale;
+ lines = o.lines;
+ break;
+
+ case dojox.gfx.vectorFontFitting.FLOW:
+ scale = this._getSizeFactor(size);
+ lines = this._getBestFlow(text, width, scale);
+ break;
+
+ default:
+ scale = this._getSizeFactor(size);
+ lines = [ text ];
+
+ }
+
+ // make sure lines doesn't have any empty lines.
+ lines = dojo.filter(lines, function(item){
+ return item.length>0;
+ });
+
+ // let's start drawing.
+ var cy = 0,
+ maxw = this._getLongestLine(lines).width;
+
+ for(var i=0, l=lines.length; i<l; i++){
+ var cx = 0,
+ line=lines[i],
+ linew = this._getWidth(line),
+ lg=g.createGroup();
+
+ // loop through the glyphs and add them to the line group (lg)
+ for (var j=0; j<line.length; j++){
+ var glyph=line[j];
+ if(glyph.path!==null){
+ var p = lg.createPath(glyph.path).setFill(fillArgs);
+ if(strokeArgs){ p.setStroke(strokeArgs); }
+ p.setTransform([
+ dojox.gfx.matrix.flipY,
+ dojox.gfx.matrix.translate(cx, -this.viewbox.height-this.descent)
+ ]);
+ }
+ cx += glyph.xAdvance;
+ if(j+1<line.length && glyph.kern && glyph.kern[line[j+1].code]){
+ cx += glyph.kern[line[j+1].code].x;
+ }
+ }
+
+ // transform the line group.
+ var dx = 0;
+ if(align=="middle"){ dx = maxw/2 - linew/2; }
+ else if(align=="end"){ dx = maxw - linew; }
+ lg.setTransform({ dx: dx, dy: cy });
+ cy += this.viewbox.height * leading;
+ }
+
+ // scale the group
+ g.setTransform(dojox.gfx.matrix.scale(scale));
+
+ // return the overall group
+ return g; // dojox.gfx.Group
+ },
+
+ // events
+ onLoadBegin: function(/* String */url){ },
+ onLoad: function(/* dojox.gfx.VectorFont */font){ }
+ });
+
+ // TODO: dojox.gfx integration
+/*
+
+ // Inherit from Group but attach Text properties to it.
+ dojo.declare("dojox.gfx.VectorText", dojox.gfx.Group, {
+ constructor: function(rawNode){
+ dojox.gfx.Group._init.call(this);
+ this.fontStyle = null;
+ },
+
+ // private methods.
+ _setFont: function(){
+ // render this using the font code.
+ var f = this.fontStyle;
+ var font = dojox.gfx._vectorFontCache[f.family];
+ if(!font){
+ throw new Error("dojox.gfx.VectorText._setFont: the passed font family '" + f.family + "' was not found.");
+ }
+
+ // the actual rendering belongs to the font itself.
+ font.draw(this, this.shape, this.fontStyle, this.fillStyle, this.strokeStyle);
+ },
+
+ getFont: function(){ return this.fontStyle; },
+
+ // overridden public methods.
+ setShape: function(newShape){
+ dojox.gfx.Group.setShape.call(this);
+ this.shape = dojox.gfx.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ this._setFont();
+ return this;
+ },
+
+ // if we've been drawing, we should have exactly one child, and that
+ // child will contain the real children.
+ setFill: function(fill){
+ this.fillStyle = fill;
+ if(this.children[0]){
+ dojo.forEach(this.children[0].children, function(group){
+ dojo.forEach(group.children, function(path){
+ path.setFill(fill);
+ });
+ }, this);
+ }
+ return this;
+ },
+ setStroke: function(stroke){
+ this.strokeStyle = stroke;
+ if(this.children[0]){
+ dojo.forEach(this.children[0].children, function(group){
+ dojo.forEach(group.children, function(path){
+ path.setStroke(stroke);
+ });
+ }, this);
+ }
+ return this;
+ },
+
+ setFont: function(newFont){
+ // this will do the real rendering.
+ this.fontStyle = typeof newFont == "string" ? dojox.gfx.splitFontString(newFont)
+ : dojox.gfx.makeParameters(dojox.gfx.defaultFont, newFont);
+ this._setFont();
+ return this;
+ },
+
+ getBoundingBox: function(){
+ return this.bbox;
+ }
+ });
+
+ // TODO: figure out how to add this to container objects!
+ dojox.gfx.shape.Creator.createVectorText = function(text){
+ return this.createObject(dojox.gfx.VectorText, text);
+ }
+*/
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/_base.js b/js/dojo-1.6/dojox/gfx/_base.js new file mode 100644 index 0000000..1ad8a19 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/_base.js @@ -0,0 +1,388 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+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];
+ });
+ }
+ }
+});
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/_base.xd.js b/js/dojo-1.6/dojox/gfx/_base.xd.js new file mode 100644 index 0000000..9d70c65 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/_base.xd.js @@ -0,0 +1,392 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx._base"]],
+defineResource: function(dojo, dijit, dojox){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];
+ });
+ }
+ }
+});
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/arc.js b/js/dojo-1.6/dojox/gfx/arc.js new file mode 100644 index 0000000..739ce9c --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/arc.js @@ -0,0 +1,130 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.arc"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.arc"] = true;
+dojo.provide("dojox.gfx.arc");
+
+dojo.require("dojox.gfx.matrix");
+
+(function(){
+ var m = dojox.gfx.matrix,
+ twoPI = 2 * Math.PI, pi4 = Math.PI / 4, pi8 = Math.PI / 8,
+ pi48 = pi4 + pi8, curvePI4 = unitArcAsBezier(pi8);
+
+ function unitArcAsBezier(alpha){
+ // summary: return a start point, 1st and 2nd control points, and an end point of
+ // a an arc, which is reflected on the x axis
+ // alpha: Number: angle in radians, the arc will be 2 * angle size
+ var cosa = Math.cos(alpha), sina = Math.sin(alpha),
+ p2 = {x: cosa + (4 / 3) * (1 - cosa), y: sina - (4 / 3) * cosa * (1 - cosa) / sina};
+ return { // Object
+ s: {x: cosa, y: -sina},
+ c1: {x: p2.x, y: -p2.y},
+ c2: p2,
+ e: {x: cosa, y: sina}
+ };
+ }
+
+ dojox.gfx.arc = {
+ unitArcAsBezier: unitArcAsBezier,
+ curvePI4: curvePI4,
+ arcAsBezier: function(last, rx, ry, xRotg, large, sweep, x, y){
+ // summary: calculates an arc as a series of Bezier curves
+ // given the last point and a standard set of SVG arc parameters,
+ // it returns an array of arrays of parameters to form a series of
+ // absolute Bezier curves.
+ // last: Object: a point-like object as a start of the arc
+ // rx: Number: a horizontal radius for the virtual ellipse
+ // ry: Number: a vertical radius for the virtual ellipse
+ // xRotg: Number: a rotation of an x axis of the virtual ellipse in degrees
+ // large: Boolean: which part of the ellipse will be used (the larger arc if true)
+ // sweep: Boolean: direction of the arc (CW if true)
+ // x: Number: the x coordinate of the end point of the arc
+ // y: Number: the y coordinate of the end point of the arc
+
+ // calculate parameters
+ large = Boolean(large);
+ sweep = Boolean(sweep);
+ var xRot = m._degToRad(xRotg),
+ rx2 = rx * rx, ry2 = ry * ry,
+ pa = m.multiplyPoint(
+ m.rotate(-xRot),
+ {x: (last.x - x) / 2, y: (last.y - y) / 2}
+ ),
+ pax2 = pa.x * pa.x, pay2 = pa.y * pa.y,
+ c1 = Math.sqrt((rx2 * ry2 - rx2 * pay2 - ry2 * pax2) / (rx2 * pay2 + ry2 * pax2));
+ if(isNaN(c1)){ c1 = 0; }
+ var ca = {
+ x: c1 * rx * pa.y / ry,
+ y: -c1 * ry * pa.x / rx
+ };
+ if(large == sweep){
+ ca = {x: -ca.x, y: -ca.y};
+ }
+ // the center
+ var c = m.multiplyPoint(
+ [
+ m.translate(
+ (last.x + x) / 2,
+ (last.y + y) / 2
+ ),
+ m.rotate(xRot)
+ ],
+ ca
+ );
+ // calculate the elliptic transformation
+ var elliptic_transform = m.normalize([
+ m.translate(c.x, c.y),
+ m.rotate(xRot),
+ m.scale(rx, ry)
+ ]);
+ // start, end, and size of our arc
+ var inversed = m.invert(elliptic_transform),
+ sp = m.multiplyPoint(inversed, last),
+ ep = m.multiplyPoint(inversed, x, y),
+ startAngle = Math.atan2(sp.y, sp.x),
+ endAngle = Math.atan2(ep.y, ep.x),
+ theta = startAngle - endAngle; // size of our arc in radians
+ if(sweep){ theta = -theta; }
+ if(theta < 0){
+ theta += twoPI;
+ }else if(theta > twoPI){
+ theta -= twoPI;
+ }
+
+ // draw curve chunks
+ var alpha = pi8, curve = curvePI4, step = sweep ? alpha : -alpha,
+ result = [];
+ for(var angle = theta; angle > 0; angle -= pi4){
+ if(angle < pi48){
+ alpha = angle / 2;
+ curve = unitArcAsBezier(alpha);
+ step = sweep ? alpha : -alpha;
+ angle = 0; // stop the loop
+ }
+ var c1, c2, e,
+ M = m.normalize([elliptic_transform, m.rotate(startAngle + step)]);
+ if(sweep){
+ c1 = m.multiplyPoint(M, curve.c1);
+ c2 = m.multiplyPoint(M, curve.c2);
+ e = m.multiplyPoint(M, curve.e );
+ }else{
+ c1 = m.multiplyPoint(M, curve.c2);
+ c2 = m.multiplyPoint(M, curve.c1);
+ e = m.multiplyPoint(M, curve.s );
+ }
+ // draw the curve
+ result.push([c1.x, c1.y, c2.x, c2.y, e.x, e.y]);
+ startAngle += 2 * step;
+ }
+ return result; // Array
+ }
+ };
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/arc.xd.js b/js/dojo-1.6/dojox/gfx/arc.xd.js new file mode 100644 index 0000000..686f6a6 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/arc.xd.js @@ -0,0 +1,135 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.arc"],
+["require", "dojox.gfx.matrix"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.arc"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.arc"] = true;
+dojo.provide("dojox.gfx.arc");
+
+dojo.require("dojox.gfx.matrix");
+
+(function(){
+ var m = dojox.gfx.matrix,
+ twoPI = 2 * Math.PI, pi4 = Math.PI / 4, pi8 = Math.PI / 8,
+ pi48 = pi4 + pi8, curvePI4 = unitArcAsBezier(pi8);
+
+ function unitArcAsBezier(alpha){
+ // summary: return a start point, 1st and 2nd control points, and an end point of
+ // a an arc, which is reflected on the x axis
+ // alpha: Number: angle in radians, the arc will be 2 * angle size
+ var cosa = Math.cos(alpha), sina = Math.sin(alpha),
+ p2 = {x: cosa + (4 / 3) * (1 - cosa), y: sina - (4 / 3) * cosa * (1 - cosa) / sina};
+ return { // Object
+ s: {x: cosa, y: -sina},
+ c1: {x: p2.x, y: -p2.y},
+ c2: p2,
+ e: {x: cosa, y: sina}
+ };
+ }
+
+ dojox.gfx.arc = {
+ unitArcAsBezier: unitArcAsBezier,
+ curvePI4: curvePI4,
+ arcAsBezier: function(last, rx, ry, xRotg, large, sweep, x, y){
+ // summary: calculates an arc as a series of Bezier curves
+ // given the last point and a standard set of SVG arc parameters,
+ // it returns an array of arrays of parameters to form a series of
+ // absolute Bezier curves.
+ // last: Object: a point-like object as a start of the arc
+ // rx: Number: a horizontal radius for the virtual ellipse
+ // ry: Number: a vertical radius for the virtual ellipse
+ // xRotg: Number: a rotation of an x axis of the virtual ellipse in degrees
+ // large: Boolean: which part of the ellipse will be used (the larger arc if true)
+ // sweep: Boolean: direction of the arc (CW if true)
+ // x: Number: the x coordinate of the end point of the arc
+ // y: Number: the y coordinate of the end point of the arc
+
+ // calculate parameters
+ large = Boolean(large);
+ sweep = Boolean(sweep);
+ var xRot = m._degToRad(xRotg),
+ rx2 = rx * rx, ry2 = ry * ry,
+ pa = m.multiplyPoint(
+ m.rotate(-xRot),
+ {x: (last.x - x) / 2, y: (last.y - y) / 2}
+ ),
+ pax2 = pa.x * pa.x, pay2 = pa.y * pa.y,
+ c1 = Math.sqrt((rx2 * ry2 - rx2 * pay2 - ry2 * pax2) / (rx2 * pay2 + ry2 * pax2));
+ if(isNaN(c1)){ c1 = 0; }
+ var ca = {
+ x: c1 * rx * pa.y / ry,
+ y: -c1 * ry * pa.x / rx
+ };
+ if(large == sweep){
+ ca = {x: -ca.x, y: -ca.y};
+ }
+ // the center
+ var c = m.multiplyPoint(
+ [
+ m.translate(
+ (last.x + x) / 2,
+ (last.y + y) / 2
+ ),
+ m.rotate(xRot)
+ ],
+ ca
+ );
+ // calculate the elliptic transformation
+ var elliptic_transform = m.normalize([
+ m.translate(c.x, c.y),
+ m.rotate(xRot),
+ m.scale(rx, ry)
+ ]);
+ // start, end, and size of our arc
+ var inversed = m.invert(elliptic_transform),
+ sp = m.multiplyPoint(inversed, last),
+ ep = m.multiplyPoint(inversed, x, y),
+ startAngle = Math.atan2(sp.y, sp.x),
+ endAngle = Math.atan2(ep.y, ep.x),
+ theta = startAngle - endAngle; // size of our arc in radians
+ if(sweep){ theta = -theta; }
+ if(theta < 0){
+ theta += twoPI;
+ }else if(theta > twoPI){
+ theta -= twoPI;
+ }
+
+ // draw curve chunks
+ var alpha = pi8, curve = curvePI4, step = sweep ? alpha : -alpha,
+ result = [];
+ for(var angle = theta; angle > 0; angle -= pi4){
+ if(angle < pi48){
+ alpha = angle / 2;
+ curve = unitArcAsBezier(alpha);
+ step = sweep ? alpha : -alpha;
+ angle = 0; // stop the loop
+ }
+ var c1, c2, e,
+ M = m.normalize([elliptic_transform, m.rotate(startAngle + step)]);
+ if(sweep){
+ c1 = m.multiplyPoint(M, curve.c1);
+ c2 = m.multiplyPoint(M, curve.c2);
+ e = m.multiplyPoint(M, curve.e );
+ }else{
+ c1 = m.multiplyPoint(M, curve.c2);
+ c2 = m.multiplyPoint(M, curve.c1);
+ e = m.multiplyPoint(M, curve.s );
+ }
+ // draw the curve
+ result.push([c1.x, c1.y, c2.x, c2.y, e.x, e.y]);
+ startAngle += 2 * step;
+ }
+ return result; // Array
+ }
+ };
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/attach.js b/js/dojo-1.6/dojox/gfx/attach.js new file mode 100644 index 0000000..2bbc69b --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/attach.js @@ -0,0 +1,22 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.attach"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.attach"] = true;
+dojo.provide("dojox.gfx.attach");
+
+dojo.require("dojox.gfx");
+
+// rename an attacher conditionally
+
+(function(){
+ var r = dojox.gfx.svg.attach[dojox.gfx.renderer];
+ dojo.gfx.attachSurface = r.attachSurface;
+ dojo.gfx.attachNode = r.attachNode;
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/attach.xd.js b/js/dojo-1.6/dojox/gfx/attach.xd.js new file mode 100644 index 0000000..9df290f --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/attach.xd.js @@ -0,0 +1,27 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.attach"],
+["require", "dojox.gfx"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.attach"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.attach"] = true;
+dojo.provide("dojox.gfx.attach");
+
+dojo.require("dojox.gfx");
+
+// rename an attacher conditionally
+
+(function(){
+ var r = dojox.gfx.svg.attach[dojox.gfx.renderer];
+ dojo.gfx.attachSurface = r.attachSurface;
+ dojo.gfx.attachNode = r.attachNode;
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/canvas.js b/js/dojo-1.6/dojox/gfx/canvas.js new file mode 100644 index 0000000..57b6ee1 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/canvas.js @@ -0,0 +1,810 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.canvas"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.canvas"] = true;
+dojo.provide("dojox.gfx.canvas");
+
+dojo.require("dojox.gfx._base");
+dojo.require("dojox.gfx.shape");
+dojo.require("dojox.gfx.path");
+dojo.require("dojox.gfx.arc");
+dojo.require("dojox.gfx.decompose");
+
+dojo.experimental("dojox.gfx.canvas");
+
+(function(){
+ var d = dojo, g = dojox.gfx, gs = g.shape, ga = g.arc, canvas = g.canvas,
+ m = g.matrix, mp = m.multiplyPoint, pi = Math.PI, twoPI = 2 * pi, halfPI = pi /2,
+ pattrnbuffer = null;
+
+ d.declare("dojox.gfx.canvas.Shape", gs.Shape, {
+ _render: function(/* Object */ ctx){
+ // summary: render the shape
+ ctx.save();
+ this._renderTransform(ctx);
+ this._renderShape(ctx);
+ this._renderFill(ctx, true);
+ this._renderStroke(ctx, true);
+ ctx.restore();
+ },
+ _renderTransform: function(/* Object */ ctx){
+ if("canvasTransform" in this){
+ var t = this.canvasTransform;
+ ctx.translate(t.dx, t.dy);
+ ctx.rotate(t.angle2);
+ ctx.scale(t.sx, t.sy);
+ ctx.rotate(t.angle1);
+ // The future implementation when vendors catch up with the spec:
+ // var t = this.matrix;
+ // ctx.transform(t.xx, t.yx, t.xy, t.yy, t.dx, t.dy);
+ }
+ },
+ _renderShape: function(/* Object */ ctx){
+ // nothing
+ },
+ _renderFill: function(/* Object */ ctx, /* Boolean */ apply){
+ if("canvasFill" in this){
+ var fs = this.fillStyle;
+ if("canvasFillImage" in this){
+ var w = fs.width, h = fs.height,
+ iw = this.canvasFillImage.width, ih = this.canvasFillImage.height,
+ // let's match the svg default behavior wrt. aspect ratio: xMidYMid meet
+ sx = w == iw ? 1 : w / iw,
+ sy = h == ih ? 1 : h / ih,
+ s = Math.min(sx,sy), //meet->math.min , slice->math.max
+ dx = (w - s * iw)/2,
+ dy = (h - s * ih)/2;
+ // the buffer used to scaled the image
+ pattrnbuffer.width = w; pattrnbuffer.height = h;
+ var copyctx = pattrnbuffer.getContext("2d");
+ copyctx.clearRect(0, 0, w, h);
+ copyctx.drawImage(this.canvasFillImage, 0, 0, iw, ih, dx, dy, s*iw, s*ih);
+ this.canvasFill = ctx.createPattern(pattrnbuffer, "repeat");
+ delete this.canvasFillImage;
+ }
+ ctx.fillStyle = this.canvasFill;
+ if(apply){
+ // offset the pattern
+ if (fs.type==="pattern" && (fs.x !== 0 || fs.y !== 0)) {
+ ctx.translate(fs.x,fs.y);
+ }
+ ctx.fill();
+ }
+ }else{
+ ctx.fillStyle = "rgba(0,0,0,0.0)";
+ }
+ },
+ _renderStroke: function(/* Object */ ctx, /* Boolean */ apply){
+ var s = this.strokeStyle;
+ if(s){
+ ctx.strokeStyle = s.color.toString();
+ ctx.lineWidth = s.width;
+ ctx.lineCap = s.cap;
+ if(typeof s.join == "number"){
+ ctx.lineJoin = "miter";
+ ctx.miterLimit = s.join;
+ }else{
+ ctx.lineJoin = s.join;
+ }
+ if(apply){ ctx.stroke(); }
+ }else if(!apply){
+ ctx.strokeStyle = "rgba(0,0,0,0.0)";
+ }
+ },
+
+ // events are not implemented
+ getEventSource: function(){ return null; },
+ connect: function(){},
+ disconnect: function(){}
+ });
+
+ var modifyMethod = function(shape, method, extra){
+ var old = shape.prototype[method];
+ shape.prototype[method] = extra ?
+ function(){
+ this.surface.makeDirty();
+ old.apply(this, arguments);
+ extra.call(this);
+ return this;
+ } :
+ function(){
+ this.surface.makeDirty();
+ return old.apply(this, arguments);
+ };
+ };
+
+ modifyMethod(canvas.Shape, "setTransform",
+ function(){
+ // prepare Canvas-specific structures
+ if(this.matrix){
+ this.canvasTransform = g.decompose(this.matrix);
+ }else{
+ delete this.canvasTransform;
+ }
+ });
+
+ modifyMethod(canvas.Shape, "setFill",
+ function(){
+ // prepare Canvas-specific structures
+ var fs = this.fillStyle, f;
+ if(fs){
+ if(typeof(fs) == "object" && "type" in fs){
+ var ctx = this.surface.rawNode.getContext("2d");
+ switch(fs.type){
+ case "linear":
+ case "radial":
+ f = fs.type == "linear" ?
+ ctx.createLinearGradient(fs.x1, fs.y1, fs.x2, fs.y2) :
+ ctx.createRadialGradient(fs.cx, fs.cy, 0, fs.cx, fs.cy, fs.r);
+ d.forEach(fs.colors, function(step){
+ f.addColorStop(step.offset, g.normalizeColor(step.color).toString());
+ });
+ break;
+ case "pattern":
+ if (!pattrnbuffer) {
+ pattrnbuffer = document.createElement("canvas");
+ }
+ // no need to scale the image since the canvas.createPattern uses
+ // the original image data and not the scaled ones (see spec.)
+ // the scaling needs to be done at rendering time in a context buffer
+ var img =new Image();
+ this.surface.downloadImage(img, fs.src);
+ this.canvasFillImage = img;
+ }
+ }else{
+ // Set fill color using CSS RGBA func style
+ f = fs.toString();
+ }
+ this.canvasFill = f;
+ }else{
+ delete this.canvasFill;
+ }
+ });
+
+ modifyMethod(canvas.Shape, "setStroke");
+ modifyMethod(canvas.Shape, "setShape");
+
+ dojo.declare("dojox.gfx.canvas.Group", canvas.Shape, {
+ // summary: a group shape (Canvas), which can be used
+ // to logically group shapes (e.g, to propagate matricies)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ _render: function(/* Object */ ctx){
+ // summary: render the group
+ ctx.save();
+ this._renderTransform(ctx);
+ for(var i = 0; i < this.children.length; ++i){
+ this.children[i]._render(ctx);
+ }
+ ctx.restore();
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Rect", [canvas.Shape, gs.Rect], {
+ // summary: a rectangle shape (Canvas)
+ _renderShape: function(/* Object */ ctx){
+ var s = this.shape, r = Math.min(s.r, s.height / 2, s.width / 2),
+ xl = s.x, xr = xl + s.width, yt = s.y, yb = yt + s.height,
+ xl2 = xl + r, xr2 = xr - r, yt2 = yt + r, yb2 = yb - r;
+ ctx.beginPath();
+ ctx.moveTo(xl2, yt);
+ if(r){
+ ctx.arc(xr2, yt2, r, -halfPI, 0, false);
+ ctx.arc(xr2, yb2, r, 0, halfPI, false);
+ ctx.arc(xl2, yb2, r, halfPI, pi, false);
+ ctx.arc(xl2, yt2, r, pi, pi + halfPI, false);
+ }else{
+ ctx.lineTo(xr2, yt);
+ ctx.lineTo(xr, yb2);
+ ctx.lineTo(xl2, yb);
+ ctx.lineTo(xl, yt2);
+ }
+ ctx.closePath();
+ }
+ });
+
+ var bezierCircle = [];
+ (function(){
+ var u = ga.curvePI4;
+ bezierCircle.push(u.s, u.c1, u.c2, u.e);
+ for(var a = 45; a < 360; a += 45){
+ var r = m.rotateg(a);
+ bezierCircle.push(mp(r, u.c1), mp(r, u.c2), mp(r, u.e));
+ }
+ })();
+
+ dojo.declare("dojox.gfx.canvas.Ellipse", [canvas.Shape, gs.Ellipse], {
+ // summary: an ellipse shape (Canvas)
+ setShape: function(){
+ this.inherited(arguments);
+ // prepare Canvas-specific structures
+ var s = this.shape, t, c1, c2, r = [],
+ M = m.normalize([m.translate(s.cx, s.cy), m.scale(s.rx, s.ry)]);
+ t = mp(M, bezierCircle[0]);
+ r.push([t.x, t.y]);
+ for(var i = 1; i < bezierCircle.length; i += 3){
+ c1 = mp(M, bezierCircle[i]);
+ c2 = mp(M, bezierCircle[i + 1]);
+ t = mp(M, bezierCircle[i + 2]);
+ r.push([c1.x, c1.y, c2.x, c2.y, t.x, t.y]);
+ }
+ this.canvasEllipse = r;
+ return this;
+ },
+ _renderShape: function(/* Object */ ctx){
+ var r = this.canvasEllipse;
+ ctx.beginPath();
+ ctx.moveTo.apply(ctx, r[0]);
+ for(var i = 1; i < r.length; ++i){
+ ctx.bezierCurveTo.apply(ctx, r[i]);
+ }
+ ctx.closePath();
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Circle", [canvas.Shape, gs.Circle], {
+ // summary: a circle shape (Canvas)
+ _renderShape: function(/* Object */ ctx){
+ var s = this.shape;
+ ctx.beginPath();
+ ctx.arc(s.cx, s.cy, s.r, 0, twoPI, 1);
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Line", [canvas.Shape, gs.Line], {
+ // summary: a line shape (Canvas)
+ _renderShape: function(/* Object */ ctx){
+ var s = this.shape;
+ ctx.beginPath();
+ ctx.moveTo(s.x1, s.y1);
+ ctx.lineTo(s.x2, s.y2);
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Polyline", [canvas.Shape, gs.Polyline], {
+ // summary: a polyline/polygon shape (Canvas)
+ setShape: function(){
+ this.inherited(arguments);
+ // prepare Canvas-specific structures
+ var p = this.shape.points, f = p[0], r = [], c, i;
+ if(p.length){
+ if(typeof f == "number"){
+ r.push(f, p[1]);
+ i = 2;
+ }else{
+ r.push(f.x, f.y);
+ i = 1;
+ }
+ for(; i < p.length; ++i){
+ c = p[i];
+ if(typeof c == "number"){
+ r.push(c, p[++i]);
+ }else{
+ r.push(c.x, c.y);
+ }
+ }
+ }
+ this.canvasPolyline = r;
+ return this;
+ },
+ _renderShape: function(/* Object */ ctx){
+ var p = this.canvasPolyline;
+ if(p.length){
+ ctx.beginPath();
+ ctx.moveTo(p[0], p[1]);
+ for(var i = 2; i < p.length; i += 2){
+ ctx.lineTo(p[i], p[i + 1]);
+ }
+ }
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Image", [canvas.Shape, gs.Image], {
+ // summary: an image shape (Canvas)
+ setShape: function(){
+ this.inherited(arguments);
+ // prepare Canvas-specific structures
+ var img = new Image();
+ this.surface.downloadImage(img, this.shape.src);
+ this.canvasImage = img;
+ return this;
+ },
+ _renderShape: function(/* Object */ ctx){
+ var s = this.shape;
+ ctx.drawImage(this.canvasImage, s.x, s.y, s.width, s.height);
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Text", [canvas.Shape, gs.Text], {
+ _setFont:function(){
+ if (this.fontStyle){
+ this.canvasFont = g.makeFontString(this.fontStyle);
+ } else {
+ delete this.canvasFont;
+ }
+ },
+
+ getTextWidth: function(){
+ // summary: get the text width in pixels
+ var s = this.shape, w = 0, ctx;
+ if(s.text && s.text.length > 0){
+ ctx = this.surface.rawNode.getContext("2d");
+ ctx.save();
+ this._renderTransform(ctx);
+ this._renderFill(ctx, false);
+ this._renderStroke(ctx, false);
+ if (this.canvasFont)
+ ctx.font = this.canvasFont;
+ w = ctx.measureText(s.text).width;
+ ctx.restore();
+ }
+ return w;
+ },
+
+ // override to apply first fill and stroke (
+ // the base implementation is for path-based shape that needs to first define the path then to fill/stroke it.
+ // Here, we need the fillstyle or strokestyle to be set before calling fillText/strokeText.
+ _render: function(/* Object */ctx){
+ // summary: render the shape
+ // ctx : Object: the drawing context.
+ ctx.save();
+ this._renderTransform(ctx);
+ this._renderFill(ctx, false);
+ this._renderStroke(ctx, false);
+ this._renderShape(ctx);
+ ctx.restore();
+ },
+
+ _renderShape: function(ctx){
+ // summary: a text shape (Canvas)
+ // ctx : Object: the drawing context.
+ var ta, s = this.shape;
+ if(!s.text || s.text.length == 0){
+ return;
+ }
+ // text align
+ ta = s.align === 'middle' ? 'center' : s.align;
+ ctx.textAlign = ta;
+ if(this.canvasFont){
+ ctx.font = this.canvasFont;
+ }
+ if(this.canvasFill){
+ ctx.fillText(s.text, s.x, s.y);
+ }
+ if(this.strokeStyle){
+ ctx.beginPath(); // fix bug in FF3.6. Fixed in FF4b8
+ ctx.strokeText(s.text, s.x, s.y);
+ ctx.closePath();
+ }
+ }
+ });
+ modifyMethod(canvas.Text, "setFont");
+
+ // the next test is from https://github.com/phiggins42/has.js
+ if(typeof dojo.doc.createElement("canvas").getContext("2d").fillText != "function"){
+ canvas.Text.extend({
+ getTextWidth: function(){
+ return 0;
+ },
+ _renderShape: function(){}
+ });
+ }
+
+
+ var pathRenderers = {
+ 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"
+ };
+
+ dojo.declare("dojox.gfx.canvas.Path", [canvas.Shape, g.path.Path], {
+ // summary: a path shape (Canvas)
+ constructor: function(){
+ this.lastControl = {};
+ },
+ setShape: function(){
+ this.canvasPath = [];
+ return this.inherited(arguments);
+ },
+ _updateWithSegment: function(segment){
+ var last = d.clone(this.last);
+ this[pathRenderers[segment.action]](this.canvasPath, segment.action, segment.args);
+ this.last = last;
+ this.inherited(arguments);
+ },
+ _renderShape: function(/* Object */ ctx){
+ var r = this.canvasPath;
+ ctx.beginPath();
+ for(var i = 0; i < r.length; i += 2){
+ ctx[r[i]].apply(ctx, r[i + 1]);
+ }
+ },
+ _moveToA: function(result, action, args){
+ result.push("moveTo", [args[0], args[1]]);
+ for(var i = 2; i < args.length; i += 2){
+ result.push("lineTo", [args[i], args[i + 1]]);
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ this.lastControl = {};
+ },
+ _moveToR: function(result, action, args){
+ if("x" in this.last){
+ result.push("moveTo", [this.last.x += args[0], this.last.y += args[1]]);
+ }else{
+ result.push("moveTo", [this.last.x = args[0], this.last.y = args[1]]);
+ }
+ for(var i = 2; i < args.length; i += 2){
+ result.push("lineTo", [this.last.x += args[i], this.last.y += args[i + 1]]);
+ }
+ this.lastControl = {};
+ },
+ _lineToA: function(result, action, args){
+ for(var i = 0; i < args.length; i += 2){
+ result.push("lineTo", [args[i], args[i + 1]]);
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ this.lastControl = {};
+ },
+ _lineToR: function(result, action, args){
+ for(var i = 0; i < args.length; i += 2){
+ result.push("lineTo", [this.last.x += args[i], this.last.y += args[i + 1]]);
+ }
+ this.lastControl = {};
+ },
+ _hLineToA: function(result, action, args){
+ for(var i = 0; i < args.length; ++i){
+ result.push("lineTo", [args[i], this.last.y]);
+ }
+ this.last.x = args[args.length - 1];
+ this.lastControl = {};
+ },
+ _hLineToR: function(result, action, args){
+ for(var i = 0; i < args.length; ++i){
+ result.push("lineTo", [this.last.x += args[i], this.last.y]);
+ }
+ this.lastControl = {};
+ },
+ _vLineToA: function(result, action, args){
+ for(var i = 0; i < args.length; ++i){
+ result.push("lineTo", [this.last.x, args[i]]);
+ }
+ this.last.y = args[args.length - 1];
+ this.lastControl = {};
+ },
+ _vLineToR: function(result, action, args){
+ for(var i = 0; i < args.length; ++i){
+ result.push("lineTo", [this.last.x, this.last.y += args[i]]);
+ }
+ this.lastControl = {};
+ },
+ _curveToA: function(result, action, args){
+ for(var i = 0; i < args.length; i += 6){
+ result.push("bezierCurveTo", args.slice(i, i + 6));
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ this.lastControl.x = args[args.length - 4];
+ this.lastControl.y = args[args.length - 3];
+ this.lastControl.type = "C";
+ },
+ _curveToR: function(result, action, args){
+ for(var i = 0; i < args.length; i += 6){
+ result.push("bezierCurveTo", [
+ this.last.x + args[i],
+ this.last.y + args[i + 1],
+ this.lastControl.x = this.last.x + args[i + 2],
+ this.lastControl.y = this.last.y + args[i + 3],
+ this.last.x + args[i + 4],
+ this.last.y + args[i + 5]
+ ]);
+ this.last.x += args[i + 4];
+ this.last.y += args[i + 5];
+ }
+ this.lastControl.type = "C";
+ },
+ _smoothCurveToA: function(result, action, args){
+ for(var i = 0; i < args.length; i += 4){
+ var valid = this.lastControl.type == "C";
+ result.push("bezierCurveTo", [
+ valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+ valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+ args[i],
+ args[i + 1],
+ args[i + 2],
+ args[i + 3]
+ ]);
+ this.lastControl.x = args[i];
+ this.lastControl.y = args[i + 1];
+ this.lastControl.type = "C";
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ },
+ _smoothCurveToR: function(result, action, args){
+ for(var i = 0; i < args.length; i += 4){
+ var valid = this.lastControl.type == "C";
+ result.push("bezierCurveTo", [
+ valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+ valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+ this.last.x + args[i],
+ this.last.y + args[i + 1],
+ this.last.x + args[i + 2],
+ this.last.y + args[i + 3]
+ ]);
+ this.lastControl.x = this.last.x + args[i];
+ this.lastControl.y = this.last.y + args[i + 1];
+ this.lastControl.type = "C";
+ this.last.x += args[i + 2];
+ this.last.y += args[i + 3];
+ }
+ },
+ _qCurveToA: function(result, action, args){
+ for(var i = 0; i < args.length; i += 4){
+ result.push("quadraticCurveTo", args.slice(i, i + 4));
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ this.lastControl.x = args[args.length - 4];
+ this.lastControl.y = args[args.length - 3];
+ this.lastControl.type = "Q";
+ },
+ _qCurveToR: function(result, action, args){
+ for(var i = 0; i < args.length; i += 4){
+ result.push("quadraticCurveTo", [
+ this.lastControl.x = this.last.x + args[i],
+ this.lastControl.y = this.last.y + args[i + 1],
+ this.last.x + args[i + 2],
+ this.last.y + args[i + 3]
+ ]);
+ this.last.x += args[i + 2];
+ this.last.y += args[i + 3];
+ }
+ this.lastControl.type = "Q";
+ },
+ _qSmoothCurveToA: function(result, action, args){
+ for(var i = 0; i < args.length; i += 2){
+ var valid = this.lastControl.type == "Q";
+ result.push("quadraticCurveTo", [
+ this.lastControl.x = valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+ this.lastControl.y = valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+ args[i],
+ args[i + 1]
+ ]);
+ this.lastControl.type = "Q";
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ },
+ _qSmoothCurveToR: function(result, action, args){
+ for(var i = 0; i < args.length; i += 2){
+ var valid = this.lastControl.type == "Q";
+ result.push("quadraticCurveTo", [
+ this.lastControl.x = valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+ this.lastControl.y = valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+ this.last.x + args[i],
+ this.last.y + args[i + 1]
+ ]);
+ this.lastControl.type = "Q";
+ this.last.x += args[i];
+ this.last.y += args[i + 1];
+ }
+ },
+ _arcTo: function(result, action, args){
+ var relative = action == "a";
+ for(var i = 0; i < args.length; i += 7){
+ var x1 = args[i + 5], y1 = args[i + 6];
+ if(relative){
+ x1 += this.last.x;
+ y1 += this.last.y;
+ }
+ var arcs = ga.arcAsBezier(
+ this.last, args[i], args[i + 1], args[i + 2],
+ args[i + 3] ? 1 : 0, args[i + 4] ? 1 : 0,
+ x1, y1
+ );
+ d.forEach(arcs, function(p){
+ result.push("bezierCurveTo", p);
+ });
+ this.last.x = x1;
+ this.last.y = y1;
+ }
+ this.lastControl = {};
+ },
+ _closePath: function(result, action, args){
+ result.push("closePath", []);
+ this.lastControl = {};
+ }
+ });
+ d.forEach(["moveTo", "lineTo", "hLineTo", "vLineTo", "curveTo",
+ "smoothCurveTo", "qCurveTo", "qSmoothCurveTo", "arcTo", "closePath"],
+ function(method){ modifyMethod(canvas.Path, method); }
+ );
+
+ dojo.declare("dojox.gfx.canvas.TextPath", [canvas.Shape, g.path.TextPath], {
+ // summary: a text shape (Canvas)
+ _renderShape: function(/* Object */ ctx){
+ var s = this.shape;
+ // nothing for the moment
+ },
+ _setText: function(){
+ // not implemented
+ },
+ _setFont: function(){
+ // not implemented
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Surface", gs.Surface, {
+ // summary: a surface object to be used for drawings (Canvas)
+ constructor: function(){
+ gs.Container._init.call(this);
+ this.pendingImageCount = 0;
+ this.makeDirty();
+ },
+ 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 = g.normalizedLength(width); // in pixels
+ this.height = g.normalizedLength(height); // in pixels
+ if(!this.rawNode) return this;
+ this.rawNode.width = width;
+ this.rawNode.height = height;
+ this.makeDirty();
+ return this; // self
+ },
+ getDimensions: function(){
+ // summary: returns an object with properties "width" and "height"
+ return this.rawNode ? {width: this.rawNode.width, height: this.rawNode.height} : null; // Object
+ },
+ _render: function(){
+ // summary: render the all shapes
+ if(this.pendingImageCount){ return; }
+ var ctx = this.rawNode.getContext("2d");
+ ctx.save();
+ ctx.clearRect(0, 0, this.rawNode.width, this.rawNode.height);
+ for(var i = 0; i < this.children.length; ++i){
+ this.children[i]._render(ctx);
+ }
+ ctx.restore();
+ if("pendingRender" in this){
+ clearTimeout(this.pendingRender);
+ delete this.pendingRender;
+ }
+ },
+ makeDirty: function(){
+ // summary: internal method, which is called when we may need to redraw
+ if(!this.pendingImagesCount && !("pendingRender" in this)){
+ this.pendingRender = setTimeout(d.hitch(this, this._render), 0);
+ }
+ },
+ downloadImage: function(img, url){
+ // summary:
+ // internal method, which starts an image download and renders, when it is ready
+ // img: Image:
+ // the image object
+ // url: String:
+ // the url of the image
+ var handler = d.hitch(this, this.onImageLoad);
+ if(!this.pendingImageCount++ && "pendingRender" in this){
+ clearTimeout(this.pendingRender);
+ delete this.pendingRender;
+ }
+ img.onload = handler;
+ img.onerror = handler;
+ img.onabort = handler;
+ img.src = url;
+ },
+ onImageLoad: function(){
+ if(!--this.pendingImageCount){ this._render(); }
+ },
+
+ // events are not implemented
+ getEventSource: function(){ return null; },
+ connect: function(){},
+ disconnect: function(){}
+ });
+
+ canvas.createSurface = function(parentNode, width, height){
+ // summary: creates a surface (Canvas)
+ // parentNode: Node: a parent node
+ // width: String: width of surface, e.g., "100px"
+ // height: String: height of surface, e.g., "100px"
+
+ if(!width && !height){
+ var pos = d.position(parentNode);
+ width = width || pos.w;
+ height = height || pos.h;
+ }
+ if(typeof width == "number"){
+ width = width + "px";
+ }
+ if(typeof height == "number"){
+ height = height + "px";
+ }
+
+ var s = new canvas.Surface(),
+ p = d.byId(parentNode),
+ c = p.ownerDocument.createElement("canvas");
+
+ c.width = g.normalizedLength(width); // in pixels
+ c.height = g.normalizedLength(height); // in pixels
+
+ p.appendChild(c);
+ s.rawNode = c;
+ s._parent = p;
+ s.surface = s;
+ return s; // dojox.gfx.Surface
+ };
+
+ // Extenders
+
+ var C = gs.Container, Container = {
+ add: function(shape){
+ this.surface.makeDirty();
+ return C.add.apply(this, arguments);
+ },
+ remove: function(shape, silently){
+ this.surface.makeDirty();
+ return C.remove.apply(this, arguments);
+ },
+ clear: function(){
+ this.surface.makeDirty();
+ return C.clear.apply(this, arguments);
+ },
+ _moveChildToFront: function(shape){
+ this.surface.makeDirty();
+ return C._moveChildToFront.apply(this, arguments);
+ },
+ _moveChildToBack: function(shape){
+ this.surface.makeDirty();
+ return C._moveChildToBack.apply(this, arguments);
+ }
+ };
+
+ var Creator = {
+ // summary: Canvas shape creators
+ 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 true
+ var shape = new shapeType();
+ shape.surface = this.surface;
+ shape.setShape(rawShape);
+ this.add(shape);
+ return shape; // dojox.gfx.Shape
+ }
+ };
+
+ d.extend(canvas.Group, Container);
+ d.extend(canvas.Group, gs.Creator);
+ d.extend(canvas.Group, Creator);
+
+ d.extend(canvas.Surface, Container);
+ d.extend(canvas.Surface, gs.Creator);
+ d.extend(canvas.Surface, Creator);
+
+ // see if we are required to initilize
+ if(g.loadAndSwitch === "canvas"){
+ g.switchTo("canvas");
+ delete g.loadAndSwitch;
+ }
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/canvas.xd.js b/js/dojo-1.6/dojox/gfx/canvas.xd.js new file mode 100644 index 0000000..7c78aae --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/canvas.xd.js @@ -0,0 +1,819 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.canvas"],
+["require", "dojox.gfx._base"],
+["require", "dojox.gfx.shape"],
+["require", "dojox.gfx.path"],
+["require", "dojox.gfx.arc"],
+["require", "dojox.gfx.decompose"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.canvas"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.canvas"] = true;
+dojo.provide("dojox.gfx.canvas");
+
+dojo.require("dojox.gfx._base");
+dojo.require("dojox.gfx.shape");
+dojo.require("dojox.gfx.path");
+dojo.require("dojox.gfx.arc");
+dojo.require("dojox.gfx.decompose");
+
+dojo.experimental("dojox.gfx.canvas");
+
+(function(){
+ var d = dojo, g = dojox.gfx, gs = g.shape, ga = g.arc, canvas = g.canvas,
+ m = g.matrix, mp = m.multiplyPoint, pi = Math.PI, twoPI = 2 * pi, halfPI = pi /2,
+ pattrnbuffer = null;
+
+ d.declare("dojox.gfx.canvas.Shape", gs.Shape, {
+ _render: function(/* Object */ ctx){
+ // summary: render the shape
+ ctx.save();
+ this._renderTransform(ctx);
+ this._renderShape(ctx);
+ this._renderFill(ctx, true);
+ this._renderStroke(ctx, true);
+ ctx.restore();
+ },
+ _renderTransform: function(/* Object */ ctx){
+ if("canvasTransform" in this){
+ var t = this.canvasTransform;
+ ctx.translate(t.dx, t.dy);
+ ctx.rotate(t.angle2);
+ ctx.scale(t.sx, t.sy);
+ ctx.rotate(t.angle1);
+ // The future implementation when vendors catch up with the spec:
+ // var t = this.matrix;
+ // ctx.transform(t.xx, t.yx, t.xy, t.yy, t.dx, t.dy);
+ }
+ },
+ _renderShape: function(/* Object */ ctx){
+ // nothing
+ },
+ _renderFill: function(/* Object */ ctx, /* Boolean */ apply){
+ if("canvasFill" in this){
+ var fs = this.fillStyle;
+ if("canvasFillImage" in this){
+ var w = fs.width, h = fs.height,
+ iw = this.canvasFillImage.width, ih = this.canvasFillImage.height,
+ // let's match the svg default behavior wrt. aspect ratio: xMidYMid meet
+ sx = w == iw ? 1 : w / iw,
+ sy = h == ih ? 1 : h / ih,
+ s = Math.min(sx,sy), //meet->math.min , slice->math.max
+ dx = (w - s * iw)/2,
+ dy = (h - s * ih)/2;
+ // the buffer used to scaled the image
+ pattrnbuffer.width = w; pattrnbuffer.height = h;
+ var copyctx = pattrnbuffer.getContext("2d");
+ copyctx.clearRect(0, 0, w, h);
+ copyctx.drawImage(this.canvasFillImage, 0, 0, iw, ih, dx, dy, s*iw, s*ih);
+ this.canvasFill = ctx.createPattern(pattrnbuffer, "repeat");
+ delete this.canvasFillImage;
+ }
+ ctx.fillStyle = this.canvasFill;
+ if(apply){
+ // offset the pattern
+ if (fs.type==="pattern" && (fs.x !== 0 || fs.y !== 0)) {
+ ctx.translate(fs.x,fs.y);
+ }
+ ctx.fill();
+ }
+ }else{
+ ctx.fillStyle = "rgba(0,0,0,0.0)";
+ }
+ },
+ _renderStroke: function(/* Object */ ctx, /* Boolean */ apply){
+ var s = this.strokeStyle;
+ if(s){
+ ctx.strokeStyle = s.color.toString();
+ ctx.lineWidth = s.width;
+ ctx.lineCap = s.cap;
+ if(typeof s.join == "number"){
+ ctx.lineJoin = "miter";
+ ctx.miterLimit = s.join;
+ }else{
+ ctx.lineJoin = s.join;
+ }
+ if(apply){ ctx.stroke(); }
+ }else if(!apply){
+ ctx.strokeStyle = "rgba(0,0,0,0.0)";
+ }
+ },
+
+ // events are not implemented
+ getEventSource: function(){ return null; },
+ connect: function(){},
+ disconnect: function(){}
+ });
+
+ var modifyMethod = function(shape, method, extra){
+ var old = shape.prototype[method];
+ shape.prototype[method] = extra ?
+ function(){
+ this.surface.makeDirty();
+ old.apply(this, arguments);
+ extra.call(this);
+ return this;
+ } :
+ function(){
+ this.surface.makeDirty();
+ return old.apply(this, arguments);
+ };
+ };
+
+ modifyMethod(canvas.Shape, "setTransform",
+ function(){
+ // prepare Canvas-specific structures
+ if(this.matrix){
+ this.canvasTransform = g.decompose(this.matrix);
+ }else{
+ delete this.canvasTransform;
+ }
+ });
+
+ modifyMethod(canvas.Shape, "setFill",
+ function(){
+ // prepare Canvas-specific structures
+ var fs = this.fillStyle, f;
+ if(fs){
+ if(typeof(fs) == "object" && "type" in fs){
+ var ctx = this.surface.rawNode.getContext("2d");
+ switch(fs.type){
+ case "linear":
+ case "radial":
+ f = fs.type == "linear" ?
+ ctx.createLinearGradient(fs.x1, fs.y1, fs.x2, fs.y2) :
+ ctx.createRadialGradient(fs.cx, fs.cy, 0, fs.cx, fs.cy, fs.r);
+ d.forEach(fs.colors, function(step){
+ f.addColorStop(step.offset, g.normalizeColor(step.color).toString());
+ });
+ break;
+ case "pattern":
+ if (!pattrnbuffer) {
+ pattrnbuffer = document.createElement("canvas");
+ }
+ // no need to scale the image since the canvas.createPattern uses
+ // the original image data and not the scaled ones (see spec.)
+ // the scaling needs to be done at rendering time in a context buffer
+ var img =new Image();
+ this.surface.downloadImage(img, fs.src);
+ this.canvasFillImage = img;
+ }
+ }else{
+ // Set fill color using CSS RGBA func style
+ f = fs.toString();
+ }
+ this.canvasFill = f;
+ }else{
+ delete this.canvasFill;
+ }
+ });
+
+ modifyMethod(canvas.Shape, "setStroke");
+ modifyMethod(canvas.Shape, "setShape");
+
+ dojo.declare("dojox.gfx.canvas.Group", canvas.Shape, {
+ // summary: a group shape (Canvas), which can be used
+ // to logically group shapes (e.g, to propagate matricies)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ _render: function(/* Object */ ctx){
+ // summary: render the group
+ ctx.save();
+ this._renderTransform(ctx);
+ for(var i = 0; i < this.children.length; ++i){
+ this.children[i]._render(ctx);
+ }
+ ctx.restore();
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Rect", [canvas.Shape, gs.Rect], {
+ // summary: a rectangle shape (Canvas)
+ _renderShape: function(/* Object */ ctx){
+ var s = this.shape, r = Math.min(s.r, s.height / 2, s.width / 2),
+ xl = s.x, xr = xl + s.width, yt = s.y, yb = yt + s.height,
+ xl2 = xl + r, xr2 = xr - r, yt2 = yt + r, yb2 = yb - r;
+ ctx.beginPath();
+ ctx.moveTo(xl2, yt);
+ if(r){
+ ctx.arc(xr2, yt2, r, -halfPI, 0, false);
+ ctx.arc(xr2, yb2, r, 0, halfPI, false);
+ ctx.arc(xl2, yb2, r, halfPI, pi, false);
+ ctx.arc(xl2, yt2, r, pi, pi + halfPI, false);
+ }else{
+ ctx.lineTo(xr2, yt);
+ ctx.lineTo(xr, yb2);
+ ctx.lineTo(xl2, yb);
+ ctx.lineTo(xl, yt2);
+ }
+ ctx.closePath();
+ }
+ });
+
+ var bezierCircle = [];
+ (function(){
+ var u = ga.curvePI4;
+ bezierCircle.push(u.s, u.c1, u.c2, u.e);
+ for(var a = 45; a < 360; a += 45){
+ var r = m.rotateg(a);
+ bezierCircle.push(mp(r, u.c1), mp(r, u.c2), mp(r, u.e));
+ }
+ })();
+
+ dojo.declare("dojox.gfx.canvas.Ellipse", [canvas.Shape, gs.Ellipse], {
+ // summary: an ellipse shape (Canvas)
+ setShape: function(){
+ this.inherited(arguments);
+ // prepare Canvas-specific structures
+ var s = this.shape, t, c1, c2, r = [],
+ M = m.normalize([m.translate(s.cx, s.cy), m.scale(s.rx, s.ry)]);
+ t = mp(M, bezierCircle[0]);
+ r.push([t.x, t.y]);
+ for(var i = 1; i < bezierCircle.length; i += 3){
+ c1 = mp(M, bezierCircle[i]);
+ c2 = mp(M, bezierCircle[i + 1]);
+ t = mp(M, bezierCircle[i + 2]);
+ r.push([c1.x, c1.y, c2.x, c2.y, t.x, t.y]);
+ }
+ this.canvasEllipse = r;
+ return this;
+ },
+ _renderShape: function(/* Object */ ctx){
+ var r = this.canvasEllipse;
+ ctx.beginPath();
+ ctx.moveTo.apply(ctx, r[0]);
+ for(var i = 1; i < r.length; ++i){
+ ctx.bezierCurveTo.apply(ctx, r[i]);
+ }
+ ctx.closePath();
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Circle", [canvas.Shape, gs.Circle], {
+ // summary: a circle shape (Canvas)
+ _renderShape: function(/* Object */ ctx){
+ var s = this.shape;
+ ctx.beginPath();
+ ctx.arc(s.cx, s.cy, s.r, 0, twoPI, 1);
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Line", [canvas.Shape, gs.Line], {
+ // summary: a line shape (Canvas)
+ _renderShape: function(/* Object */ ctx){
+ var s = this.shape;
+ ctx.beginPath();
+ ctx.moveTo(s.x1, s.y1);
+ ctx.lineTo(s.x2, s.y2);
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Polyline", [canvas.Shape, gs.Polyline], {
+ // summary: a polyline/polygon shape (Canvas)
+ setShape: function(){
+ this.inherited(arguments);
+ // prepare Canvas-specific structures
+ var p = this.shape.points, f = p[0], r = [], c, i;
+ if(p.length){
+ if(typeof f == "number"){
+ r.push(f, p[1]);
+ i = 2;
+ }else{
+ r.push(f.x, f.y);
+ i = 1;
+ }
+ for(; i < p.length; ++i){
+ c = p[i];
+ if(typeof c == "number"){
+ r.push(c, p[++i]);
+ }else{
+ r.push(c.x, c.y);
+ }
+ }
+ }
+ this.canvasPolyline = r;
+ return this;
+ },
+ _renderShape: function(/* Object */ ctx){
+ var p = this.canvasPolyline;
+ if(p.length){
+ ctx.beginPath();
+ ctx.moveTo(p[0], p[1]);
+ for(var i = 2; i < p.length; i += 2){
+ ctx.lineTo(p[i], p[i + 1]);
+ }
+ }
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Image", [canvas.Shape, gs.Image], {
+ // summary: an image shape (Canvas)
+ setShape: function(){
+ this.inherited(arguments);
+ // prepare Canvas-specific structures
+ var img = new Image();
+ this.surface.downloadImage(img, this.shape.src);
+ this.canvasImage = img;
+ return this;
+ },
+ _renderShape: function(/* Object */ ctx){
+ var s = this.shape;
+ ctx.drawImage(this.canvasImage, s.x, s.y, s.width, s.height);
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Text", [canvas.Shape, gs.Text], {
+ _setFont:function(){
+ if (this.fontStyle){
+ this.canvasFont = g.makeFontString(this.fontStyle);
+ } else {
+ delete this.canvasFont;
+ }
+ },
+
+ getTextWidth: function(){
+ // summary: get the text width in pixels
+ var s = this.shape, w = 0, ctx;
+ if(s.text && s.text.length > 0){
+ ctx = this.surface.rawNode.getContext("2d");
+ ctx.save();
+ this._renderTransform(ctx);
+ this._renderFill(ctx, false);
+ this._renderStroke(ctx, false);
+ if (this.canvasFont)
+ ctx.font = this.canvasFont;
+ w = ctx.measureText(s.text).width;
+ ctx.restore();
+ }
+ return w;
+ },
+
+ // override to apply first fill and stroke (
+ // the base implementation is for path-based shape that needs to first define the path then to fill/stroke it.
+ // Here, we need the fillstyle or strokestyle to be set before calling fillText/strokeText.
+ _render: function(/* Object */ctx){
+ // summary: render the shape
+ // ctx : Object: the drawing context.
+ ctx.save();
+ this._renderTransform(ctx);
+ this._renderFill(ctx, false);
+ this._renderStroke(ctx, false);
+ this._renderShape(ctx);
+ ctx.restore();
+ },
+
+ _renderShape: function(ctx){
+ // summary: a text shape (Canvas)
+ // ctx : Object: the drawing context.
+ var ta, s = this.shape;
+ if(!s.text || s.text.length == 0){
+ return;
+ }
+ // text align
+ ta = s.align === 'middle' ? 'center' : s.align;
+ ctx.textAlign = ta;
+ if(this.canvasFont){
+ ctx.font = this.canvasFont;
+ }
+ if(this.canvasFill){
+ ctx.fillText(s.text, s.x, s.y);
+ }
+ if(this.strokeStyle){
+ ctx.beginPath(); // fix bug in FF3.6. Fixed in FF4b8
+ ctx.strokeText(s.text, s.x, s.y);
+ ctx.closePath();
+ }
+ }
+ });
+ modifyMethod(canvas.Text, "setFont");
+
+ // the next test is from https://github.com/phiggins42/has.js
+ if(typeof dojo.doc.createElement("canvas").getContext("2d").fillText != "function"){
+ canvas.Text.extend({
+ getTextWidth: function(){
+ return 0;
+ },
+ _renderShape: function(){}
+ });
+ }
+
+
+ var pathRenderers = {
+ 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"
+ };
+
+ dojo.declare("dojox.gfx.canvas.Path", [canvas.Shape, g.path.Path], {
+ // summary: a path shape (Canvas)
+ constructor: function(){
+ this.lastControl = {};
+ },
+ setShape: function(){
+ this.canvasPath = [];
+ return this.inherited(arguments);
+ },
+ _updateWithSegment: function(segment){
+ var last = d.clone(this.last);
+ this[pathRenderers[segment.action]](this.canvasPath, segment.action, segment.args);
+ this.last = last;
+ this.inherited(arguments);
+ },
+ _renderShape: function(/* Object */ ctx){
+ var r = this.canvasPath;
+ ctx.beginPath();
+ for(var i = 0; i < r.length; i += 2){
+ ctx[r[i]].apply(ctx, r[i + 1]);
+ }
+ },
+ _moveToA: function(result, action, args){
+ result.push("moveTo", [args[0], args[1]]);
+ for(var i = 2; i < args.length; i += 2){
+ result.push("lineTo", [args[i], args[i + 1]]);
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ this.lastControl = {};
+ },
+ _moveToR: function(result, action, args){
+ if("x" in this.last){
+ result.push("moveTo", [this.last.x += args[0], this.last.y += args[1]]);
+ }else{
+ result.push("moveTo", [this.last.x = args[0], this.last.y = args[1]]);
+ }
+ for(var i = 2; i < args.length; i += 2){
+ result.push("lineTo", [this.last.x += args[i], this.last.y += args[i + 1]]);
+ }
+ this.lastControl = {};
+ },
+ _lineToA: function(result, action, args){
+ for(var i = 0; i < args.length; i += 2){
+ result.push("lineTo", [args[i], args[i + 1]]);
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ this.lastControl = {};
+ },
+ _lineToR: function(result, action, args){
+ for(var i = 0; i < args.length; i += 2){
+ result.push("lineTo", [this.last.x += args[i], this.last.y += args[i + 1]]);
+ }
+ this.lastControl = {};
+ },
+ _hLineToA: function(result, action, args){
+ for(var i = 0; i < args.length; ++i){
+ result.push("lineTo", [args[i], this.last.y]);
+ }
+ this.last.x = args[args.length - 1];
+ this.lastControl = {};
+ },
+ _hLineToR: function(result, action, args){
+ for(var i = 0; i < args.length; ++i){
+ result.push("lineTo", [this.last.x += args[i], this.last.y]);
+ }
+ this.lastControl = {};
+ },
+ _vLineToA: function(result, action, args){
+ for(var i = 0; i < args.length; ++i){
+ result.push("lineTo", [this.last.x, args[i]]);
+ }
+ this.last.y = args[args.length - 1];
+ this.lastControl = {};
+ },
+ _vLineToR: function(result, action, args){
+ for(var i = 0; i < args.length; ++i){
+ result.push("lineTo", [this.last.x, this.last.y += args[i]]);
+ }
+ this.lastControl = {};
+ },
+ _curveToA: function(result, action, args){
+ for(var i = 0; i < args.length; i += 6){
+ result.push("bezierCurveTo", args.slice(i, i + 6));
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ this.lastControl.x = args[args.length - 4];
+ this.lastControl.y = args[args.length - 3];
+ this.lastControl.type = "C";
+ },
+ _curveToR: function(result, action, args){
+ for(var i = 0; i < args.length; i += 6){
+ result.push("bezierCurveTo", [
+ this.last.x + args[i],
+ this.last.y + args[i + 1],
+ this.lastControl.x = this.last.x + args[i + 2],
+ this.lastControl.y = this.last.y + args[i + 3],
+ this.last.x + args[i + 4],
+ this.last.y + args[i + 5]
+ ]);
+ this.last.x += args[i + 4];
+ this.last.y += args[i + 5];
+ }
+ this.lastControl.type = "C";
+ },
+ _smoothCurveToA: function(result, action, args){
+ for(var i = 0; i < args.length; i += 4){
+ var valid = this.lastControl.type == "C";
+ result.push("bezierCurveTo", [
+ valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+ valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+ args[i],
+ args[i + 1],
+ args[i + 2],
+ args[i + 3]
+ ]);
+ this.lastControl.x = args[i];
+ this.lastControl.y = args[i + 1];
+ this.lastControl.type = "C";
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ },
+ _smoothCurveToR: function(result, action, args){
+ for(var i = 0; i < args.length; i += 4){
+ var valid = this.lastControl.type == "C";
+ result.push("bezierCurveTo", [
+ valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+ valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+ this.last.x + args[i],
+ this.last.y + args[i + 1],
+ this.last.x + args[i + 2],
+ this.last.y + args[i + 3]
+ ]);
+ this.lastControl.x = this.last.x + args[i];
+ this.lastControl.y = this.last.y + args[i + 1];
+ this.lastControl.type = "C";
+ this.last.x += args[i + 2];
+ this.last.y += args[i + 3];
+ }
+ },
+ _qCurveToA: function(result, action, args){
+ for(var i = 0; i < args.length; i += 4){
+ result.push("quadraticCurveTo", args.slice(i, i + 4));
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ this.lastControl.x = args[args.length - 4];
+ this.lastControl.y = args[args.length - 3];
+ this.lastControl.type = "Q";
+ },
+ _qCurveToR: function(result, action, args){
+ for(var i = 0; i < args.length; i += 4){
+ result.push("quadraticCurveTo", [
+ this.lastControl.x = this.last.x + args[i],
+ this.lastControl.y = this.last.y + args[i + 1],
+ this.last.x + args[i + 2],
+ this.last.y + args[i + 3]
+ ]);
+ this.last.x += args[i + 2];
+ this.last.y += args[i + 3];
+ }
+ this.lastControl.type = "Q";
+ },
+ _qSmoothCurveToA: function(result, action, args){
+ for(var i = 0; i < args.length; i += 2){
+ var valid = this.lastControl.type == "Q";
+ result.push("quadraticCurveTo", [
+ this.lastControl.x = valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+ this.lastControl.y = valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+ args[i],
+ args[i + 1]
+ ]);
+ this.lastControl.type = "Q";
+ }
+ this.last.x = args[args.length - 2];
+ this.last.y = args[args.length - 1];
+ },
+ _qSmoothCurveToR: function(result, action, args){
+ for(var i = 0; i < args.length; i += 2){
+ var valid = this.lastControl.type == "Q";
+ result.push("quadraticCurveTo", [
+ this.lastControl.x = valid ? 2 * this.last.x - this.lastControl.x : this.last.x,
+ this.lastControl.y = valid ? 2 * this.last.y - this.lastControl.y : this.last.y,
+ this.last.x + args[i],
+ this.last.y + args[i + 1]
+ ]);
+ this.lastControl.type = "Q";
+ this.last.x += args[i];
+ this.last.y += args[i + 1];
+ }
+ },
+ _arcTo: function(result, action, args){
+ var relative = action == "a";
+ for(var i = 0; i < args.length; i += 7){
+ var x1 = args[i + 5], y1 = args[i + 6];
+ if(relative){
+ x1 += this.last.x;
+ y1 += this.last.y;
+ }
+ var arcs = ga.arcAsBezier(
+ this.last, args[i], args[i + 1], args[i + 2],
+ args[i + 3] ? 1 : 0, args[i + 4] ? 1 : 0,
+ x1, y1
+ );
+ d.forEach(arcs, function(p){
+ result.push("bezierCurveTo", p);
+ });
+ this.last.x = x1;
+ this.last.y = y1;
+ }
+ this.lastControl = {};
+ },
+ _closePath: function(result, action, args){
+ result.push("closePath", []);
+ this.lastControl = {};
+ }
+ });
+ d.forEach(["moveTo", "lineTo", "hLineTo", "vLineTo", "curveTo",
+ "smoothCurveTo", "qCurveTo", "qSmoothCurveTo", "arcTo", "closePath"],
+ function(method){ modifyMethod(canvas.Path, method); }
+ );
+
+ dojo.declare("dojox.gfx.canvas.TextPath", [canvas.Shape, g.path.TextPath], {
+ // summary: a text shape (Canvas)
+ _renderShape: function(/* Object */ ctx){
+ var s = this.shape;
+ // nothing for the moment
+ },
+ _setText: function(){
+ // not implemented
+ },
+ _setFont: function(){
+ // not implemented
+ }
+ });
+
+ dojo.declare("dojox.gfx.canvas.Surface", gs.Surface, {
+ // summary: a surface object to be used for drawings (Canvas)
+ constructor: function(){
+ gs.Container._init.call(this);
+ this.pendingImageCount = 0;
+ this.makeDirty();
+ },
+ 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 = g.normalizedLength(width); // in pixels
+ this.height = g.normalizedLength(height); // in pixels
+ if(!this.rawNode) return this;
+ this.rawNode.width = width;
+ this.rawNode.height = height;
+ this.makeDirty();
+ return this; // self
+ },
+ getDimensions: function(){
+ // summary: returns an object with properties "width" and "height"
+ return this.rawNode ? {width: this.rawNode.width, height: this.rawNode.height} : null; // Object
+ },
+ _render: function(){
+ // summary: render the all shapes
+ if(this.pendingImageCount){ return; }
+ var ctx = this.rawNode.getContext("2d");
+ ctx.save();
+ ctx.clearRect(0, 0, this.rawNode.width, this.rawNode.height);
+ for(var i = 0; i < this.children.length; ++i){
+ this.children[i]._render(ctx);
+ }
+ ctx.restore();
+ if("pendingRender" in this){
+ clearTimeout(this.pendingRender);
+ delete this.pendingRender;
+ }
+ },
+ makeDirty: function(){
+ // summary: internal method, which is called when we may need to redraw
+ if(!this.pendingImagesCount && !("pendingRender" in this)){
+ this.pendingRender = setTimeout(d.hitch(this, this._render), 0);
+ }
+ },
+ downloadImage: function(img, url){
+ // summary:
+ // internal method, which starts an image download and renders, when it is ready
+ // img: Image:
+ // the image object
+ // url: String:
+ // the url of the image
+ var handler = d.hitch(this, this.onImageLoad);
+ if(!this.pendingImageCount++ && "pendingRender" in this){
+ clearTimeout(this.pendingRender);
+ delete this.pendingRender;
+ }
+ img.onload = handler;
+ img.onerror = handler;
+ img.onabort = handler;
+ img.src = url;
+ },
+ onImageLoad: function(){
+ if(!--this.pendingImageCount){ this._render(); }
+ },
+
+ // events are not implemented
+ getEventSource: function(){ return null; },
+ connect: function(){},
+ disconnect: function(){}
+ });
+
+ canvas.createSurface = function(parentNode, width, height){
+ // summary: creates a surface (Canvas)
+ // parentNode: Node: a parent node
+ // width: String: width of surface, e.g., "100px"
+ // height: String: height of surface, e.g., "100px"
+
+ if(!width && !height){
+ var pos = d.position(parentNode);
+ width = width || pos.w;
+ height = height || pos.h;
+ }
+ if(typeof width == "number"){
+ width = width + "px";
+ }
+ if(typeof height == "number"){
+ height = height + "px";
+ }
+
+ var s = new canvas.Surface(),
+ p = d.byId(parentNode),
+ c = p.ownerDocument.createElement("canvas");
+
+ c.width = g.normalizedLength(width); // in pixels
+ c.height = g.normalizedLength(height); // in pixels
+
+ p.appendChild(c);
+ s.rawNode = c;
+ s._parent = p;
+ s.surface = s;
+ return s; // dojox.gfx.Surface
+ };
+
+ // Extenders
+
+ var C = gs.Container, Container = {
+ add: function(shape){
+ this.surface.makeDirty();
+ return C.add.apply(this, arguments);
+ },
+ remove: function(shape, silently){
+ this.surface.makeDirty();
+ return C.remove.apply(this, arguments);
+ },
+ clear: function(){
+ this.surface.makeDirty();
+ return C.clear.apply(this, arguments);
+ },
+ _moveChildToFront: function(shape){
+ this.surface.makeDirty();
+ return C._moveChildToFront.apply(this, arguments);
+ },
+ _moveChildToBack: function(shape){
+ this.surface.makeDirty();
+ return C._moveChildToBack.apply(this, arguments);
+ }
+ };
+
+ var Creator = {
+ // summary: Canvas shape creators
+ 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 true
+ var shape = new shapeType();
+ shape.surface = this.surface;
+ shape.setShape(rawShape);
+ this.add(shape);
+ return shape; // dojox.gfx.Shape
+ }
+ };
+
+ d.extend(canvas.Group, Container);
+ d.extend(canvas.Group, gs.Creator);
+ d.extend(canvas.Group, Creator);
+
+ d.extend(canvas.Surface, Container);
+ d.extend(canvas.Surface, gs.Creator);
+ d.extend(canvas.Surface, Creator);
+
+ // see if we are required to initilize
+ if(g.loadAndSwitch === "canvas"){
+ g.switchTo("canvas");
+ delete g.loadAndSwitch;
+ }
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/canvas_attach.js b/js/dojo-1.6/dojox/gfx/canvas_attach.js new file mode 100644 index 0000000..3d008be --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/canvas_attach.js @@ -0,0 +1,21 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.canvas_attach"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.canvas_attach"] = true;
+dojo.provide("dojox.gfx.canvas_attach");
+
+dojo.require("dojox.gfx.canvas");
+
+dojo.experimental("dojox.gfx.canvas_attach");
+
+// not implemented
+dojox.gfx.canvas.attachSurface = dojox.gfx.canvas.attachNode = function(){
+ return null; // for now
+};
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/canvas_attach.xd.js b/js/dojo-1.6/dojox/gfx/canvas_attach.xd.js new file mode 100644 index 0000000..8bd48a3 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/canvas_attach.xd.js @@ -0,0 +1,26 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.canvas_attach"],
+["require", "dojox.gfx.canvas"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.canvas_attach"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.canvas_attach"] = true;
+dojo.provide("dojox.gfx.canvas_attach");
+
+dojo.require("dojox.gfx.canvas");
+
+dojo.experimental("dojox.gfx.canvas_attach");
+
+// not implemented
+dojox.gfx.canvas.attachSurface = dojox.gfx.canvas.attachNode = function(){
+ return null; // for now
+};
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/decompose.js b/js/dojo-1.6/dojox/gfx/decompose.js new file mode 100644 index 0000000..be3c15b --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/decompose.js @@ -0,0 +1,146 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.decompose"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.decompose"] = true;
+dojo.provide("dojox.gfx.decompose");
+
+dojo.require("dojox.gfx.matrix");
+
+(function(){
+ var m = dojox.gfx.matrix;
+
+ function eq(/* Number */ a, /* Number */ b){
+ // summary: compare two FP numbers for equality
+ return Math.abs(a - b) <= 1e-6 * (Math.abs(a) + Math.abs(b)); // Boolean
+ }
+
+ function calcFromValues(/* Number */ r1, /* Number */ m1, /* Number */ r2, /* Number */ m2){
+ // summary: uses two close FP ration and their original magnitudes to approximate the result
+ if(!isFinite(r1)){
+ return r2; // Number
+ }else if(!isFinite(r2)){
+ return r1; // Number
+ }
+ m1 = Math.abs(m1), m2 = Math.abs(m2);
+ return (m1 * r1 + m2 * r2) / (m1 + m2); // Number
+ }
+
+ function transpose(/* dojox.gfx.matrix.Matrix2D */ matrix){
+ // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object
+ var M = new m.Matrix2D(matrix);
+ return dojo.mixin(M, {dx: 0, dy: 0, xy: M.yx, yx: M.xy}); // dojox.gfx.matrix.Matrix2D
+ }
+
+ function scaleSign(/* dojox.gfx.matrix.Matrix2D */ matrix){
+ return (matrix.xx * matrix.yy < 0 || matrix.xy * matrix.yx > 0) ? -1 : 1; // Number
+ }
+
+ function eigenvalueDecomposition(/* dojox.gfx.matrix.Matrix2D */ matrix){
+ // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object
+ var M = m.normalize(matrix),
+ b = -M.xx - M.yy,
+ c = M.xx * M.yy - M.xy * M.yx,
+ d = Math.sqrt(b * b - 4 * c),
+ l1 = -(b + (b < 0 ? -d : d)) / 2,
+ l2 = c / l1,
+ vx1 = M.xy / (l1 - M.xx), vy1 = 1,
+ vx2 = M.xy / (l2 - M.xx), vy2 = 1;
+ if(eq(l1, l2)){
+ vx1 = 1, vy1 = 0, vx2 = 0, vy2 = 1;
+ }
+ if(!isFinite(vx1)){
+ vx1 = 1, vy1 = (l1 - M.xx) / M.xy;
+ if(!isFinite(vy1)){
+ vx1 = (l1 - M.yy) / M.yx, vy1 = 1;
+ if(!isFinite(vx1)){
+ vx1 = 1, vy1 = M.yx / (l1 - M.yy);
+ }
+ }
+ }
+ if(!isFinite(vx2)){
+ vx2 = 1, vy2 = (l2 - M.xx) / M.xy;
+ if(!isFinite(vy2)){
+ vx2 = (l2 - M.yy) / M.yx, vy2 = 1;
+ if(!isFinite(vx2)){
+ vx2 = 1, vy2 = M.yx / (l2 - M.yy);
+ }
+ }
+ }
+ var d1 = Math.sqrt(vx1 * vx1 + vy1 * vy1),
+ d2 = Math.sqrt(vx2 * vx2 + vy2 * vy2);
+ if(!isFinite(vx1 /= d1)){ vx1 = 0; }
+ if(!isFinite(vy1 /= d1)){ vy1 = 0; }
+ if(!isFinite(vx2 /= d2)){ vx2 = 0; }
+ if(!isFinite(vy2 /= d2)){ vy2 = 0; }
+ return { // Object
+ value1: l1,
+ value2: l2,
+ vector1: {x: vx1, y: vy1},
+ vector2: {x: vx2, y: vy2}
+ };
+ }
+
+ function decomposeSR(/* dojox.gfx.matrix.Matrix2D */ M, /* Object */ result){
+ // summary: decomposes a matrix into [scale, rotate]; no checks are done.
+ var sign = scaleSign(M),
+ a = result.angle1 = (Math.atan2(M.yx, M.yy) + Math.atan2(-sign * M.xy, sign * M.xx)) / 2,
+ cos = Math.cos(a), sin = Math.sin(a);
+ result.sx = calcFromValues(M.xx / cos, cos, -M.xy / sin, sin);
+ result.sy = calcFromValues(M.yy / cos, cos, M.yx / sin, sin);
+ return result; // Object
+ }
+
+ function decomposeRS(/* dojox.gfx.matrix.Matrix2D */ M, /* Object */ result){
+ // summary: decomposes a matrix into [rotate, scale]; no checks are done
+ var sign = scaleSign(M),
+ a = result.angle2 = (Math.atan2(sign * M.yx, sign * M.xx) + Math.atan2(-M.xy, M.yy)) / 2,
+ cos = Math.cos(a), sin = Math.sin(a);
+ result.sx = calcFromValues(M.xx / cos, cos, M.yx / sin, sin);
+ result.sy = calcFromValues(M.yy / cos, cos, -M.xy / sin, sin);
+ return result; // Object
+ }
+
+ dojox.gfx.decompose = function(matrix){
+ // summary: decompose a 2D matrix into translation, scaling, and rotation components
+ // description: this function decompose a matrix into four logical components:
+ // translation, rotation, scaling, and one more rotation using SVD.
+ // The components should be applied in following order:
+ // | [translate, rotate(angle2), scale, rotate(angle1)]
+ // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object
+ var M = m.normalize(matrix),
+ result = {dx: M.dx, dy: M.dy, sx: 1, sy: 1, angle1: 0, angle2: 0};
+ // detect case: [scale]
+ if(eq(M.xy, 0) && eq(M.yx, 0)){
+ return dojo.mixin(result, {sx: M.xx, sy: M.yy}); // Object
+ }
+ // detect case: [scale, rotate]
+ if(eq(M.xx * M.yx, -M.xy * M.yy)){
+ return decomposeSR(M, result); // Object
+ }
+ // detect case: [rotate, scale]
+ if(eq(M.xx * M.xy, -M.yx * M.yy)){
+ return decomposeRS(M, result); // Object
+ }
+ // do SVD
+ var MT = transpose(M),
+ u = eigenvalueDecomposition([M, MT]),
+ v = eigenvalueDecomposition([MT, M]),
+ U = new m.Matrix2D({xx: u.vector1.x, xy: u.vector2.x, yx: u.vector1.y, yy: u.vector2.y}),
+ VT = new m.Matrix2D({xx: v.vector1.x, xy: v.vector1.y, yx: v.vector2.x, yy: v.vector2.y}),
+ S = new m.Matrix2D([m.invert(U), M, m.invert(VT)]);
+ decomposeSR(VT, result);
+ S.xx *= result.sx;
+ S.yy *= result.sy;
+ decomposeRS(U, result);
+ S.xx *= result.sx;
+ S.yy *= result.sy;
+ return dojo.mixin(result, {sx: S.xx, sy: S.yy}); // Object
+ };
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/decompose.xd.js b/js/dojo-1.6/dojox/gfx/decompose.xd.js new file mode 100644 index 0000000..843b302 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/decompose.xd.js @@ -0,0 +1,151 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.decompose"],
+["require", "dojox.gfx.matrix"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.decompose"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.decompose"] = true;
+dojo.provide("dojox.gfx.decompose");
+
+dojo.require("dojox.gfx.matrix");
+
+(function(){
+ var m = dojox.gfx.matrix;
+
+ function eq(/* Number */ a, /* Number */ b){
+ // summary: compare two FP numbers for equality
+ return Math.abs(a - b) <= 1e-6 * (Math.abs(a) + Math.abs(b)); // Boolean
+ }
+
+ function calcFromValues(/* Number */ r1, /* Number */ m1, /* Number */ r2, /* Number */ m2){
+ // summary: uses two close FP ration and their original magnitudes to approximate the result
+ if(!isFinite(r1)){
+ return r2; // Number
+ }else if(!isFinite(r2)){
+ return r1; // Number
+ }
+ m1 = Math.abs(m1), m2 = Math.abs(m2);
+ return (m1 * r1 + m2 * r2) / (m1 + m2); // Number
+ }
+
+ function transpose(/* dojox.gfx.matrix.Matrix2D */ matrix){
+ // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object
+ var M = new m.Matrix2D(matrix);
+ return dojo.mixin(M, {dx: 0, dy: 0, xy: M.yx, yx: M.xy}); // dojox.gfx.matrix.Matrix2D
+ }
+
+ function scaleSign(/* dojox.gfx.matrix.Matrix2D */ matrix){
+ return (matrix.xx * matrix.yy < 0 || matrix.xy * matrix.yx > 0) ? -1 : 1; // Number
+ }
+
+ function eigenvalueDecomposition(/* dojox.gfx.matrix.Matrix2D */ matrix){
+ // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object
+ var M = m.normalize(matrix),
+ b = -M.xx - M.yy,
+ c = M.xx * M.yy - M.xy * M.yx,
+ d = Math.sqrt(b * b - 4 * c),
+ l1 = -(b + (b < 0 ? -d : d)) / 2,
+ l2 = c / l1,
+ vx1 = M.xy / (l1 - M.xx), vy1 = 1,
+ vx2 = M.xy / (l2 - M.xx), vy2 = 1;
+ if(eq(l1, l2)){
+ vx1 = 1, vy1 = 0, vx2 = 0, vy2 = 1;
+ }
+ if(!isFinite(vx1)){
+ vx1 = 1, vy1 = (l1 - M.xx) / M.xy;
+ if(!isFinite(vy1)){
+ vx1 = (l1 - M.yy) / M.yx, vy1 = 1;
+ if(!isFinite(vx1)){
+ vx1 = 1, vy1 = M.yx / (l1 - M.yy);
+ }
+ }
+ }
+ if(!isFinite(vx2)){
+ vx2 = 1, vy2 = (l2 - M.xx) / M.xy;
+ if(!isFinite(vy2)){
+ vx2 = (l2 - M.yy) / M.yx, vy2 = 1;
+ if(!isFinite(vx2)){
+ vx2 = 1, vy2 = M.yx / (l2 - M.yy);
+ }
+ }
+ }
+ var d1 = Math.sqrt(vx1 * vx1 + vy1 * vy1),
+ d2 = Math.sqrt(vx2 * vx2 + vy2 * vy2);
+ if(!isFinite(vx1 /= d1)){ vx1 = 0; }
+ if(!isFinite(vy1 /= d1)){ vy1 = 0; }
+ if(!isFinite(vx2 /= d2)){ vx2 = 0; }
+ if(!isFinite(vy2 /= d2)){ vy2 = 0; }
+ return { // Object
+ value1: l1,
+ value2: l2,
+ vector1: {x: vx1, y: vy1},
+ vector2: {x: vx2, y: vy2}
+ };
+ }
+
+ function decomposeSR(/* dojox.gfx.matrix.Matrix2D */ M, /* Object */ result){
+ // summary: decomposes a matrix into [scale, rotate]; no checks are done.
+ var sign = scaleSign(M),
+ a = result.angle1 = (Math.atan2(M.yx, M.yy) + Math.atan2(-sign * M.xy, sign * M.xx)) / 2,
+ cos = Math.cos(a), sin = Math.sin(a);
+ result.sx = calcFromValues(M.xx / cos, cos, -M.xy / sin, sin);
+ result.sy = calcFromValues(M.yy / cos, cos, M.yx / sin, sin);
+ return result; // Object
+ }
+
+ function decomposeRS(/* dojox.gfx.matrix.Matrix2D */ M, /* Object */ result){
+ // summary: decomposes a matrix into [rotate, scale]; no checks are done
+ var sign = scaleSign(M),
+ a = result.angle2 = (Math.atan2(sign * M.yx, sign * M.xx) + Math.atan2(-M.xy, M.yy)) / 2,
+ cos = Math.cos(a), sin = Math.sin(a);
+ result.sx = calcFromValues(M.xx / cos, cos, M.yx / sin, sin);
+ result.sy = calcFromValues(M.yy / cos, cos, -M.xy / sin, sin);
+ return result; // Object
+ }
+
+ dojox.gfx.decompose = function(matrix){
+ // summary: decompose a 2D matrix into translation, scaling, and rotation components
+ // description: this function decompose a matrix into four logical components:
+ // translation, rotation, scaling, and one more rotation using SVD.
+ // The components should be applied in following order:
+ // | [translate, rotate(angle2), scale, rotate(angle1)]
+ // matrix: dojox.gfx.matrix.Matrix2D: a 2D matrix-like object
+ var M = m.normalize(matrix),
+ result = {dx: M.dx, dy: M.dy, sx: 1, sy: 1, angle1: 0, angle2: 0};
+ // detect case: [scale]
+ if(eq(M.xy, 0) && eq(M.yx, 0)){
+ return dojo.mixin(result, {sx: M.xx, sy: M.yy}); // Object
+ }
+ // detect case: [scale, rotate]
+ if(eq(M.xx * M.yx, -M.xy * M.yy)){
+ return decomposeSR(M, result); // Object
+ }
+ // detect case: [rotate, scale]
+ if(eq(M.xx * M.xy, -M.yx * M.yy)){
+ return decomposeRS(M, result); // Object
+ }
+ // do SVD
+ var MT = transpose(M),
+ u = eigenvalueDecomposition([M, MT]),
+ v = eigenvalueDecomposition([MT, M]),
+ U = new m.Matrix2D({xx: u.vector1.x, xy: u.vector2.x, yx: u.vector1.y, yy: u.vector2.y}),
+ VT = new m.Matrix2D({xx: v.vector1.x, xy: v.vector1.y, yx: v.vector2.x, yy: v.vector2.y}),
+ S = new m.Matrix2D([m.invert(U), M, m.invert(VT)]);
+ decomposeSR(VT, result);
+ S.xx *= result.sx;
+ S.yy *= result.sy;
+ decomposeRS(U, result);
+ S.xx *= result.sx;
+ S.yy *= result.sy;
+ return dojo.mixin(result, {sx: S.xx, sy: S.yy}); // Object
+ };
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/fx.js b/js/dojo-1.6/dojox/gfx/fx.js new file mode 100644 index 0000000..c4baadf --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/fx.js @@ -0,0 +1,276 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.fx"] = true;
+dojo.provide("dojox.gfx.fx");
+
+dojo.require("dojox.gfx.matrix");
+
+(function(){
+ var d = dojo, g = dojox.gfx, m = g.matrix;
+
+ // Generic interpolators. Should they be moved to dojox.fx?
+
+ function InterpolNumber(start, end){
+ this.start = start, this.end = end;
+ }
+ InterpolNumber.prototype.getValue = function(r){
+ return (this.end - this.start) * r + this.start;
+ };
+
+ function InterpolUnit(start, end, units){
+ this.start = start, this.end = end;
+ this.units = units;
+ }
+ InterpolUnit.prototype.getValue = function(r){
+ return (this.end - this.start) * r + this.start + this.units;
+ };
+
+ function InterpolColor(start, end){
+ this.start = start, this.end = end;
+ this.temp = new dojo.Color();
+ }
+ InterpolColor.prototype.getValue = function(r){
+ return d.blendColors(this.start, this.end, r, this.temp);
+ };
+
+ function InterpolValues(values){
+ this.values = values;
+ this.length = values.length;
+ }
+ InterpolValues.prototype.getValue = function(r){
+ return this.values[Math.min(Math.floor(r * this.length), this.length - 1)];
+ };
+
+ function InterpolObject(values, def){
+ this.values = values;
+ this.def = def ? def : {};
+ }
+ InterpolObject.prototype.getValue = function(r){
+ var ret = dojo.clone(this.def);
+ for(var i in this.values){
+ ret[i] = this.values[i].getValue(r);
+ }
+ return ret;
+ };
+
+ function InterpolTransform(stack, original){
+ this.stack = stack;
+ this.original = original;
+ }
+ InterpolTransform.prototype.getValue = function(r){
+ var ret = [];
+ dojo.forEach(this.stack, function(t){
+ if(t instanceof m.Matrix2D){
+ ret.push(t);
+ return;
+ }
+ if(t.name == "original" && this.original){
+ ret.push(this.original);
+ return;
+ }
+ if(!(t.name in m)){ return; }
+ var f = m[t.name];
+ if(typeof f != "function"){
+ // constant
+ ret.push(f);
+ return;
+ }
+ var val = dojo.map(t.start, function(v, i){
+ return (t.end[i] - v) * r + v;
+ }),
+ matrix = f.apply(m, val);
+ if(matrix instanceof m.Matrix2D){
+ ret.push(matrix);
+ }
+ }, this);
+ return ret;
+ };
+
+ var transparent = new d.Color(0, 0, 0, 0);
+
+ function getColorInterpol(prop, obj, name, def){
+ if(prop.values){
+ return new InterpolValues(prop.values);
+ }
+ var value, start, end;
+ if(prop.start){
+ start = g.normalizeColor(prop.start);
+ }else{
+ start = value = obj ? (name ? obj[name] : obj) : def;
+ }
+ if(prop.end){
+ end = g.normalizeColor(prop.end);
+ }else{
+ if(!value){
+ value = obj ? (name ? obj[name] : obj) : def;
+ }
+ end = value;
+ }
+ return new InterpolColor(start, end);
+ }
+
+ function getNumberInterpol(prop, obj, name, def){
+ if(prop.values){
+ return new InterpolValues(prop.values);
+ }
+ var value, start, end;
+ if(prop.start){
+ start = prop.start;
+ }else{
+ start = value = obj ? obj[name] : def;
+ }
+ if(prop.end){
+ end = prop.end;
+ }else{
+ if(typeof value != "number"){
+ value = obj ? obj[name] : def;
+ }
+ end = value;
+ }
+ return new InterpolNumber(start, end);
+ }
+
+ g.fx.animateStroke = function(/*Object*/ args){
+ // summary:
+ // Returns an animation which will change stroke properties over time
+ // example:
+ // | dojox.gfx.fx.animateStroke{{
+ // | shape: shape,
+ // | duration: 500,
+ // | color: {start: "red", end: "green"},
+ // | width: {end: 15},
+ // | join: {values: ["miter", "bevel", "round"]}
+ // | }).play();
+ if(!args.easing){ args.easing = d._defaultEasing; }
+ var anim = new d.Animation(args), shape = args.shape, stroke;
+ d.connect(anim, "beforeBegin", anim, function(){
+ stroke = shape.getStroke();
+ var prop = args.color, values = {}, value, start, end;
+ if(prop){
+ values.color = getColorInterpol(prop, stroke, "color", transparent);
+ }
+ prop = args.style;
+ if(prop && prop.values){
+ values.style = new InterpolValues(prop.values);
+ }
+ prop = args.width;
+ if(prop){
+ values.width = getNumberInterpol(prop, stroke, "width", 1);
+ }
+ prop = args.cap;
+ if(prop && prop.values){
+ values.cap = new InterpolValues(prop.values);
+ }
+ prop = args.join;
+ if(prop){
+ if(prop.values){
+ values.join = new InterpolValues(prop.values);
+ }else{
+ start = prop.start ? prop.start : (stroke && stroke.join || 0);
+ end = prop.end ? prop.end : (stroke && stroke.join || 0);
+ if(typeof start == "number" && typeof end == "number"){
+ values.join = new InterpolNumber(start, end);
+ }
+ }
+ }
+ this.curve = new InterpolObject(values, stroke);
+ });
+ d.connect(anim, "onAnimate", shape, "setStroke");
+ return anim; // dojo.Animation
+ };
+
+ g.fx.animateFill = function(/*Object*/ args){
+ // summary:
+ // Returns an animation which will change fill color over time.
+ // Only solid fill color is supported at the moment
+ // example:
+ // | dojox.gfx.fx.animateFill{{
+ // | shape: shape,
+ // | duration: 500,
+ // | color: {start: "red", end: "green"}
+ // | }).play();
+ if(!args.easing){ args.easing = d._defaultEasing; }
+ var anim = new d.Animation(args), shape = args.shape, fill;
+ d.connect(anim, "beforeBegin", anim, function(){
+ fill = shape.getFill();
+ var prop = args.color, values = {};
+ if(prop){
+ this.curve = getColorInterpol(prop, fill, "", transparent);
+ }
+ });
+ d.connect(anim, "onAnimate", shape, "setFill");
+ return anim; // dojo.Animation
+ };
+
+ g.fx.animateFont = function(/*Object*/ args){
+ // summary:
+ // Returns an animation which will change font properties over time
+ // example:
+ // | dojox.gfx.fx.animateFont{{
+ // | shape: shape,
+ // | duration: 500,
+ // | variant: {values: ["normal", "small-caps"]},
+ // | size: {end: 10, units: "pt"}
+ // | }).play();
+ if(!args.easing){ args.easing = d._defaultEasing; }
+ var anim = new d.Animation(args), shape = args.shape, font;
+ d.connect(anim, "beforeBegin", anim, function(){
+ font = shape.getFont();
+ var prop = args.style, values = {}, value, start, end;
+ if(prop && prop.values){
+ values.style = new InterpolValues(prop.values);
+ }
+ prop = args.variant;
+ if(prop && prop.values){
+ values.variant = new InterpolValues(prop.values);
+ }
+ prop = args.weight;
+ if(prop && prop.values){
+ values.weight = new InterpolValues(prop.values);
+ }
+ prop = args.family;
+ if(prop && prop.values){
+ values.family = new InterpolValues(prop.values);
+ }
+ prop = args.size;
+ if(prop && prop.units){
+ start = parseFloat(prop.start ? prop.start : (shape.font && shape.font.size || "0"));
+ end = parseFloat(prop.end ? prop.end : (shape.font && shape.font.size || "0"));
+ values.size = new InterpolUnit(start, end, prop.units);
+ }
+ this.curve = new InterpolObject(values, font);
+ });
+ d.connect(anim, "onAnimate", shape, "setFont");
+ return anim; // dojo.Animation
+ };
+
+ g.fx.animateTransform = function(/*Object*/ args){
+ // summary:
+ // Returns an animation which will change transformation over time
+ // example:
+ // | dojox.gfx.fx.animateTransform{{
+ // | shape: shape,
+ // | duration: 500,
+ // | transform: [
+ // | {name: "translate", start: [0, 0], end: [200, 200]},
+ // | {name: "original"}
+ // | ]
+ // | }).play();
+ if(!args.easing){ args.easing = d._defaultEasing; }
+ var anim = new d.Animation(args), shape = args.shape, original;
+ d.connect(anim, "beforeBegin", anim, function(){
+ original = shape.getTransform();
+ this.curve = new InterpolTransform(args.transform, original);
+ });
+ d.connect(anim, "onAnimate", shape, "setTransform");
+ return anim; // dojo.Animation
+ };
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/fx.xd.js b/js/dojo-1.6/dojox/gfx/fx.xd.js new file mode 100644 index 0000000..f95dc57 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/fx.xd.js @@ -0,0 +1,281 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.fx"],
+["require", "dojox.gfx.matrix"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.fx"] = true;
+dojo.provide("dojox.gfx.fx");
+
+dojo.require("dojox.gfx.matrix");
+
+(function(){
+ var d = dojo, g = dojox.gfx, m = g.matrix;
+
+ // Generic interpolators. Should they be moved to dojox.fx?
+
+ function InterpolNumber(start, end){
+ this.start = start, this.end = end;
+ }
+ InterpolNumber.prototype.getValue = function(r){
+ return (this.end - this.start) * r + this.start;
+ };
+
+ function InterpolUnit(start, end, units){
+ this.start = start, this.end = end;
+ this.units = units;
+ }
+ InterpolUnit.prototype.getValue = function(r){
+ return (this.end - this.start) * r + this.start + this.units;
+ };
+
+ function InterpolColor(start, end){
+ this.start = start, this.end = end;
+ this.temp = new dojo.Color();
+ }
+ InterpolColor.prototype.getValue = function(r){
+ return d.blendColors(this.start, this.end, r, this.temp);
+ };
+
+ function InterpolValues(values){
+ this.values = values;
+ this.length = values.length;
+ }
+ InterpolValues.prototype.getValue = function(r){
+ return this.values[Math.min(Math.floor(r * this.length), this.length - 1)];
+ };
+
+ function InterpolObject(values, def){
+ this.values = values;
+ this.def = def ? def : {};
+ }
+ InterpolObject.prototype.getValue = function(r){
+ var ret = dojo.clone(this.def);
+ for(var i in this.values){
+ ret[i] = this.values[i].getValue(r);
+ }
+ return ret;
+ };
+
+ function InterpolTransform(stack, original){
+ this.stack = stack;
+ this.original = original;
+ }
+ InterpolTransform.prototype.getValue = function(r){
+ var ret = [];
+ dojo.forEach(this.stack, function(t){
+ if(t instanceof m.Matrix2D){
+ ret.push(t);
+ return;
+ }
+ if(t.name == "original" && this.original){
+ ret.push(this.original);
+ return;
+ }
+ if(!(t.name in m)){ return; }
+ var f = m[t.name];
+ if(typeof f != "function"){
+ // constant
+ ret.push(f);
+ return;
+ }
+ var val = dojo.map(t.start, function(v, i){
+ return (t.end[i] - v) * r + v;
+ }),
+ matrix = f.apply(m, val);
+ if(matrix instanceof m.Matrix2D){
+ ret.push(matrix);
+ }
+ }, this);
+ return ret;
+ };
+
+ var transparent = new d.Color(0, 0, 0, 0);
+
+ function getColorInterpol(prop, obj, name, def){
+ if(prop.values){
+ return new InterpolValues(prop.values);
+ }
+ var value, start, end;
+ if(prop.start){
+ start = g.normalizeColor(prop.start);
+ }else{
+ start = value = obj ? (name ? obj[name] : obj) : def;
+ }
+ if(prop.end){
+ end = g.normalizeColor(prop.end);
+ }else{
+ if(!value){
+ value = obj ? (name ? obj[name] : obj) : def;
+ }
+ end = value;
+ }
+ return new InterpolColor(start, end);
+ }
+
+ function getNumberInterpol(prop, obj, name, def){
+ if(prop.values){
+ return new InterpolValues(prop.values);
+ }
+ var value, start, end;
+ if(prop.start){
+ start = prop.start;
+ }else{
+ start = value = obj ? obj[name] : def;
+ }
+ if(prop.end){
+ end = prop.end;
+ }else{
+ if(typeof value != "number"){
+ value = obj ? obj[name] : def;
+ }
+ end = value;
+ }
+ return new InterpolNumber(start, end);
+ }
+
+ g.fx.animateStroke = function(/*Object*/ args){
+ // summary:
+ // Returns an animation which will change stroke properties over time
+ // example:
+ // | dojox.gfx.fx.animateStroke{{
+ // | shape: shape,
+ // | duration: 500,
+ // | color: {start: "red", end: "green"},
+ // | width: {end: 15},
+ // | join: {values: ["miter", "bevel", "round"]}
+ // | }).play();
+ if(!args.easing){ args.easing = d._defaultEasing; }
+ var anim = new d.Animation(args), shape = args.shape, stroke;
+ d.connect(anim, "beforeBegin", anim, function(){
+ stroke = shape.getStroke();
+ var prop = args.color, values = {}, value, start, end;
+ if(prop){
+ values.color = getColorInterpol(prop, stroke, "color", transparent);
+ }
+ prop = args.style;
+ if(prop && prop.values){
+ values.style = new InterpolValues(prop.values);
+ }
+ prop = args.width;
+ if(prop){
+ values.width = getNumberInterpol(prop, stroke, "width", 1);
+ }
+ prop = args.cap;
+ if(prop && prop.values){
+ values.cap = new InterpolValues(prop.values);
+ }
+ prop = args.join;
+ if(prop){
+ if(prop.values){
+ values.join = new InterpolValues(prop.values);
+ }else{
+ start = prop.start ? prop.start : (stroke && stroke.join || 0);
+ end = prop.end ? prop.end : (stroke && stroke.join || 0);
+ if(typeof start == "number" && typeof end == "number"){
+ values.join = new InterpolNumber(start, end);
+ }
+ }
+ }
+ this.curve = new InterpolObject(values, stroke);
+ });
+ d.connect(anim, "onAnimate", shape, "setStroke");
+ return anim; // dojo.Animation
+ };
+
+ g.fx.animateFill = function(/*Object*/ args){
+ // summary:
+ // Returns an animation which will change fill color over time.
+ // Only solid fill color is supported at the moment
+ // example:
+ // | dojox.gfx.fx.animateFill{{
+ // | shape: shape,
+ // | duration: 500,
+ // | color: {start: "red", end: "green"}
+ // | }).play();
+ if(!args.easing){ args.easing = d._defaultEasing; }
+ var anim = new d.Animation(args), shape = args.shape, fill;
+ d.connect(anim, "beforeBegin", anim, function(){
+ fill = shape.getFill();
+ var prop = args.color, values = {};
+ if(prop){
+ this.curve = getColorInterpol(prop, fill, "", transparent);
+ }
+ });
+ d.connect(anim, "onAnimate", shape, "setFill");
+ return anim; // dojo.Animation
+ };
+
+ g.fx.animateFont = function(/*Object*/ args){
+ // summary:
+ // Returns an animation which will change font properties over time
+ // example:
+ // | dojox.gfx.fx.animateFont{{
+ // | shape: shape,
+ // | duration: 500,
+ // | variant: {values: ["normal", "small-caps"]},
+ // | size: {end: 10, units: "pt"}
+ // | }).play();
+ if(!args.easing){ args.easing = d._defaultEasing; }
+ var anim = new d.Animation(args), shape = args.shape, font;
+ d.connect(anim, "beforeBegin", anim, function(){
+ font = shape.getFont();
+ var prop = args.style, values = {}, value, start, end;
+ if(prop && prop.values){
+ values.style = new InterpolValues(prop.values);
+ }
+ prop = args.variant;
+ if(prop && prop.values){
+ values.variant = new InterpolValues(prop.values);
+ }
+ prop = args.weight;
+ if(prop && prop.values){
+ values.weight = new InterpolValues(prop.values);
+ }
+ prop = args.family;
+ if(prop && prop.values){
+ values.family = new InterpolValues(prop.values);
+ }
+ prop = args.size;
+ if(prop && prop.units){
+ start = parseFloat(prop.start ? prop.start : (shape.font && shape.font.size || "0"));
+ end = parseFloat(prop.end ? prop.end : (shape.font && shape.font.size || "0"));
+ values.size = new InterpolUnit(start, end, prop.units);
+ }
+ this.curve = new InterpolObject(values, font);
+ });
+ d.connect(anim, "onAnimate", shape, "setFont");
+ return anim; // dojo.Animation
+ };
+
+ g.fx.animateTransform = function(/*Object*/ args){
+ // summary:
+ // Returns an animation which will change transformation over time
+ // example:
+ // | dojox.gfx.fx.animateTransform{{
+ // | shape: shape,
+ // | duration: 500,
+ // | transform: [
+ // | {name: "translate", start: [0, 0], end: [200, 200]},
+ // | {name: "original"}
+ // | ]
+ // | }).play();
+ if(!args.easing){ args.easing = d._defaultEasing; }
+ var anim = new d.Animation(args), shape = args.shape, original;
+ d.connect(anim, "beforeBegin", anim, function(){
+ original = shape.getTransform();
+ this.curve = new InterpolTransform(args.transform, original);
+ });
+ d.connect(anim, "onAnimate", shape, "setTransform");
+ return anim; // dojo.Animation
+ };
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/gradient.js b/js/dojo-1.6/dojox/gfx/gradient.js new file mode 100644 index 0000000..173a7e7 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/gradient.js @@ -0,0 +1,171 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.gradient"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.gradient"] = true;
+dojo.provide("dojox.gfx.gradient");
+
+dojo.require("dojox.gfx.matrix");
+
+// Various utilities to deal with a linear gradient (mostly VML-specific)
+
+(function(){
+ var d = dojo, m = dojox.gfx.matrix, C = d.Color;
+
+ dojox.gfx.gradient.rescale = function(stops, from, to){
+ // summary:
+ // recalculates a gradient from 0-1 window to
+ // "from"-"to" window blending and replicating colors,
+ // if necessary
+ // stops: Array:
+ // input gradient as a list of colors with offsets
+ // (see dojox.gfx.defaultLinearGradient and dojox.gfx.defaultRadialGradient)
+ // from: Number:
+ // the beginning of the window, should be less than "to"
+ // to: Number:
+ // the end of the window, should be more than "from"
+
+ var len = stops.length, reverseFlag = (to < from), newStops;
+
+ // do we need to reverse the color table?
+ if(reverseFlag){
+ var tmp = from;
+ from = to;
+ to = tmp;
+ }
+
+ // various edge cases
+ if(!len){
+ // no colors
+ return [];
+ }
+ if(to <= stops[0].offset){
+ // all colors are before the color table
+ newStops = [
+ {offset: 0, color: stops[0].color},
+ {offset: 1, color: stops[0].color}
+ ];
+ }else if(from >= stops[len - 1].offset){
+ // all colors are after the color table
+ newStops = [
+ {offset: 0, color: stops[len - 1].color},
+ {offset: 1, color: stops[len - 1].color}
+ ];
+ }else{
+ // main scanning algorithm
+ var span = to - from, stop, prev, i;
+ newStops = [];
+ if(from < 0){
+ newStops.push({offset: 0, color: new C(stops[0].color)});
+ }
+ for(i = 0; i < len; ++i){
+ stop = stops[i];
+ if(stop.offset >= from){
+ break;
+ }
+ // skip this color
+ }
+ if(i){
+ prev = stops[i - 1];
+ newStops.push({
+ offset: 0,
+ color: d.blendColors(new C(prev.color), new C(stop.color), (from - prev.offset) / (stop.offset - prev.offset))
+ });
+ }else{
+ newStops.push({offset: 0, color: new C(stop.color)});
+ }
+ for(; i < len; ++i){
+ stop = stops[i];
+ if(stop.offset >= to){
+ break;
+ }
+ newStops.push({offset: (stop.offset - from) / span, color: new C(stop.color)});
+ }
+ if(i < len){
+ prev = stops[i - 1];
+ newStops.push({
+ offset: 1,
+ color: d.blendColors(new C(prev.color), new C(stop.color), (to - prev.offset) / (stop.offset - prev.offset))
+ });
+ }else{
+ newStops.push({offset: 1, color: new C(stops[len - 1].color)});
+ }
+ }
+
+ // reverse the color table, if needed
+ if(reverseFlag){
+ newStops.reverse();
+ for(i = 0, len = newStops.length; i < len; ++i){
+ stop = newStops[i];
+ stop.offset = 1 - stop.offset;
+ }
+ }
+
+ return newStops;
+ };
+
+ function getPoint(x, y, matrix, project, shiftAndRotate, scale){
+ var r = m.multiplyPoint(matrix, x, y),
+ p = m.multiplyPoint(project, r);
+ return {r: r, p: p, o: m.multiplyPoint(shiftAndRotate, p).x / scale};
+ }
+
+ function sortPoints(a, b){
+ return a.o - b.o;
+ }
+
+ dojox.gfx.gradient.project = function(matrix, grad, tl, rb, ttl, trb){
+ // summary:
+ // return a new gradient using the "VML algorithm" and suitable for VML
+ // matrix: dojox.gfx.Matrix2D|Null:
+ // matrix to apply to a shape and its gradient
+ // grad: Object:
+ // a linear gradient object to be transformed
+ // tl: dojox.gfx.Point:
+ // top-left corner of shape's bounding box
+ // rb: dojox.gfx.Point:
+ // right-bottom corner of shape's bounding box
+ // ttl: dojox.gfx.Point:
+ // top-left corner of shape's transformed bounding box
+ // trb: dojox.gfx.Point:
+ // right-bottom corner of shape's transformed bounding box
+
+ matrix = matrix || m.identity;
+
+ var f1 = m.multiplyPoint(matrix, grad.x1, grad.y1),
+ f2 = m.multiplyPoint(matrix, grad.x2, grad.y2),
+ angle = Math.atan2(f2.y - f1.y, f2.x - f1.x),
+ project = m.project(f2.x - f1.x, f2.y - f1.y),
+ pf1 = m.multiplyPoint(project, f1),
+ pf2 = m.multiplyPoint(project, f2),
+ shiftAndRotate = new m.Matrix2D([m.rotate(-angle), {dx: -pf1.x, dy: -pf1.y}]),
+ scale = m.multiplyPoint(shiftAndRotate, pf2).x,
+ //comboMatrix = new m.Matrix2D([shiftAndRotate, project, matrix]),
+ // bbox-specific calculations
+ points = [
+ getPoint(tl.x, tl.y, matrix, project, shiftAndRotate, scale),
+ getPoint(rb.x, rb.y, matrix, project, shiftAndRotate, scale),
+ getPoint(tl.x, rb.y, matrix, project, shiftAndRotate, scale),
+ getPoint(rb.x, tl.y, matrix, project, shiftAndRotate, scale)
+ ].sort(sortPoints),
+ from = points[0].o,
+ to = points[3].o,
+ stops = dojox.gfx.gradient.rescale(grad.colors, from, to),
+ //angle2 = Math.atan2(Math.abs(points[3].r.y - points[0].r.y) * (f2.y - f1.y), Math.abs(points[3].r.x - points[0].r.x) * (f2.x - f1.x));
+ angle2 = Math.atan2(points[3].r.y - points[0].r.y, points[3].r.x - points[0].r.x);
+
+ return {
+ type: "linear",
+ x1: points[0].p.x, y1: points[0].p.y, x2: points[3].p.x, y2: points[3].p.y,
+ colors: stops,
+ // additional helpers (for VML)
+ angle: angle
+ };
+ };
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/gradient.xd.js b/js/dojo-1.6/dojox/gfx/gradient.xd.js new file mode 100644 index 0000000..8d198f0 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/gradient.xd.js @@ -0,0 +1,176 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.gradient"],
+["require", "dojox.gfx.matrix"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.gradient"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.gradient"] = true;
+dojo.provide("dojox.gfx.gradient");
+
+dojo.require("dojox.gfx.matrix");
+
+// Various utilities to deal with a linear gradient (mostly VML-specific)
+
+(function(){
+ var d = dojo, m = dojox.gfx.matrix, C = d.Color;
+
+ dojox.gfx.gradient.rescale = function(stops, from, to){
+ // summary:
+ // recalculates a gradient from 0-1 window to
+ // "from"-"to" window blending and replicating colors,
+ // if necessary
+ // stops: Array:
+ // input gradient as a list of colors with offsets
+ // (see dojox.gfx.defaultLinearGradient and dojox.gfx.defaultRadialGradient)
+ // from: Number:
+ // the beginning of the window, should be less than "to"
+ // to: Number:
+ // the end of the window, should be more than "from"
+
+ var len = stops.length, reverseFlag = (to < from), newStops;
+
+ // do we need to reverse the color table?
+ if(reverseFlag){
+ var tmp = from;
+ from = to;
+ to = tmp;
+ }
+
+ // various edge cases
+ if(!len){
+ // no colors
+ return [];
+ }
+ if(to <= stops[0].offset){
+ // all colors are before the color table
+ newStops = [
+ {offset: 0, color: stops[0].color},
+ {offset: 1, color: stops[0].color}
+ ];
+ }else if(from >= stops[len - 1].offset){
+ // all colors are after the color table
+ newStops = [
+ {offset: 0, color: stops[len - 1].color},
+ {offset: 1, color: stops[len - 1].color}
+ ];
+ }else{
+ // main scanning algorithm
+ var span = to - from, stop, prev, i;
+ newStops = [];
+ if(from < 0){
+ newStops.push({offset: 0, color: new C(stops[0].color)});
+ }
+ for(i = 0; i < len; ++i){
+ stop = stops[i];
+ if(stop.offset >= from){
+ break;
+ }
+ // skip this color
+ }
+ if(i){
+ prev = stops[i - 1];
+ newStops.push({
+ offset: 0,
+ color: d.blendColors(new C(prev.color), new C(stop.color), (from - prev.offset) / (stop.offset - prev.offset))
+ });
+ }else{
+ newStops.push({offset: 0, color: new C(stop.color)});
+ }
+ for(; i < len; ++i){
+ stop = stops[i];
+ if(stop.offset >= to){
+ break;
+ }
+ newStops.push({offset: (stop.offset - from) / span, color: new C(stop.color)});
+ }
+ if(i < len){
+ prev = stops[i - 1];
+ newStops.push({
+ offset: 1,
+ color: d.blendColors(new C(prev.color), new C(stop.color), (to - prev.offset) / (stop.offset - prev.offset))
+ });
+ }else{
+ newStops.push({offset: 1, color: new C(stops[len - 1].color)});
+ }
+ }
+
+ // reverse the color table, if needed
+ if(reverseFlag){
+ newStops.reverse();
+ for(i = 0, len = newStops.length; i < len; ++i){
+ stop = newStops[i];
+ stop.offset = 1 - stop.offset;
+ }
+ }
+
+ return newStops;
+ };
+
+ function getPoint(x, y, matrix, project, shiftAndRotate, scale){
+ var r = m.multiplyPoint(matrix, x, y),
+ p = m.multiplyPoint(project, r);
+ return {r: r, p: p, o: m.multiplyPoint(shiftAndRotate, p).x / scale};
+ }
+
+ function sortPoints(a, b){
+ return a.o - b.o;
+ }
+
+ dojox.gfx.gradient.project = function(matrix, grad, tl, rb, ttl, trb){
+ // summary:
+ // return a new gradient using the "VML algorithm" and suitable for VML
+ // matrix: dojox.gfx.Matrix2D|Null:
+ // matrix to apply to a shape and its gradient
+ // grad: Object:
+ // a linear gradient object to be transformed
+ // tl: dojox.gfx.Point:
+ // top-left corner of shape's bounding box
+ // rb: dojox.gfx.Point:
+ // right-bottom corner of shape's bounding box
+ // ttl: dojox.gfx.Point:
+ // top-left corner of shape's transformed bounding box
+ // trb: dojox.gfx.Point:
+ // right-bottom corner of shape's transformed bounding box
+
+ matrix = matrix || m.identity;
+
+ var f1 = m.multiplyPoint(matrix, grad.x1, grad.y1),
+ f2 = m.multiplyPoint(matrix, grad.x2, grad.y2),
+ angle = Math.atan2(f2.y - f1.y, f2.x - f1.x),
+ project = m.project(f2.x - f1.x, f2.y - f1.y),
+ pf1 = m.multiplyPoint(project, f1),
+ pf2 = m.multiplyPoint(project, f2),
+ shiftAndRotate = new m.Matrix2D([m.rotate(-angle), {dx: -pf1.x, dy: -pf1.y}]),
+ scale = m.multiplyPoint(shiftAndRotate, pf2).x,
+ //comboMatrix = new m.Matrix2D([shiftAndRotate, project, matrix]),
+ // bbox-specific calculations
+ points = [
+ getPoint(tl.x, tl.y, matrix, project, shiftAndRotate, scale),
+ getPoint(rb.x, rb.y, matrix, project, shiftAndRotate, scale),
+ getPoint(tl.x, rb.y, matrix, project, shiftAndRotate, scale),
+ getPoint(rb.x, tl.y, matrix, project, shiftAndRotate, scale)
+ ].sort(sortPoints),
+ from = points[0].o,
+ to = points[3].o,
+ stops = dojox.gfx.gradient.rescale(grad.colors, from, to),
+ //angle2 = Math.atan2(Math.abs(points[3].r.y - points[0].r.y) * (f2.y - f1.y), Math.abs(points[3].r.x - points[0].r.x) * (f2.x - f1.x));
+ angle2 = Math.atan2(points[3].r.y - points[0].r.y, points[3].r.x - points[0].r.x);
+
+ return {
+ type: "linear",
+ x1: points[0].p.x, y1: points[0].p.y, x2: points[3].p.x, y2: points[3].p.y,
+ colors: stops,
+ // additional helpers (for VML)
+ angle: angle
+ };
+ };
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/gradutils.js b/js/dojo-1.6/dojox/gfx/gradutils.js new file mode 100644 index 0000000..590d2aa --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/gradutils.js @@ -0,0 +1,102 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.gradutils"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.gradutils"] = true;
+dojo.provide("dojox.gfx.gradutils");
+
+dojo.require("dojox.gfx.matrix");
+
+// Various generic utilities to deal with a linear gradient
+
+(function(){
+ var d = dojo, m = dojox.gfx.matrix, C = d.Color;
+
+ function findColor(o, c){
+ if(o <= 0){
+ return c[0].color;
+ }
+ var len = c.length;
+ if(o >= 1){
+ return c[len - 1].color;
+ }
+ //TODO: use binary search
+ for(var i = 0; i < len; ++i){
+ var stop = c[i];
+ if(stop.offset >= o){
+ if(i){
+ var prev = c[i - 1];
+ return d.blendColors(new C(prev.color), new C(stop.color),
+ (o - prev.offset) / (stop.offset - prev.offset));
+ }
+ return stop.color;
+ }
+ }
+ return c[len - 1].color;
+ }
+
+ dojox.gfx.gradutils.getColor = function(fill, pt){
+ // summary:
+ // sample a color from a gradient using a point
+ // fill: Object:
+ // fill object
+ // pt: dojox.gfx.Point:
+ // point where to sample a color
+ var o;
+ if(fill){
+ switch(fill.type){
+ case "linear":
+ var angle = Math.atan2(fill.y2 - fill.y1, fill.x2 - fill.x1),
+ rotation = m.rotate(-angle),
+ projection = m.project(fill.x2 - fill.x1, fill.y2 - fill.y1),
+ p = m.multiplyPoint(projection, pt),
+ pf1 = m.multiplyPoint(projection, fill.x1, fill.y1),
+ pf2 = m.multiplyPoint(projection, fill.x2, fill.y2),
+ scale = m.multiplyPoint(rotation, pf2.x - pf1.x, pf2.y - pf1.y).x,
+ o = m.multiplyPoint(rotation, p.x - pf1.x, p.y - pf1.y).x / scale;
+ break;
+ case "radial":
+ var dx = pt.x - fill.cx, dy = pt.y - fill.cy,
+ o = Math.sqrt(dx * dx + dy * dy) / fill.r;
+ break;
+ }
+ return findColor(o, fill.colors); // dojo.Color
+ }
+ // simple color
+ return new C(fill || [0, 0, 0, 0]); // dojo.Color
+ };
+
+ dojox.gfx.gradutils.reverse = function(fill){
+ // summary:
+ // reverses a gradient
+ // fill: Object:
+ // fill object
+ if(fill){
+ switch(fill.type){
+ case "linear":
+ case "radial":
+ fill = dojo.delegate(fill);
+ if(fill.colors){
+ var c = fill.colors, l = c.length, i = 0, stop,
+ n = fill.colors = new Array(c.length);
+ for(; i < l; ++i){
+ stop = c[i];
+ n[i] = {
+ offset: 1 - stop.offset,
+ color: stop.color
+ };
+ }
+ n.sort(function(a, b){ return a.offset - b.offset; });
+ }
+ break;
+ }
+ }
+ return fill; // Object
+ };
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/gradutils.xd.js b/js/dojo-1.6/dojox/gfx/gradutils.xd.js new file mode 100644 index 0000000..c054a7f --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/gradutils.xd.js @@ -0,0 +1,107 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.gradutils"],
+["require", "dojox.gfx.matrix"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.gradutils"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.gradutils"] = true;
+dojo.provide("dojox.gfx.gradutils");
+
+dojo.require("dojox.gfx.matrix");
+
+// Various generic utilities to deal with a linear gradient
+
+(function(){
+ var d = dojo, m = dojox.gfx.matrix, C = d.Color;
+
+ function findColor(o, c){
+ if(o <= 0){
+ return c[0].color;
+ }
+ var len = c.length;
+ if(o >= 1){
+ return c[len - 1].color;
+ }
+ //TODO: use binary search
+ for(var i = 0; i < len; ++i){
+ var stop = c[i];
+ if(stop.offset >= o){
+ if(i){
+ var prev = c[i - 1];
+ return d.blendColors(new C(prev.color), new C(stop.color),
+ (o - prev.offset) / (stop.offset - prev.offset));
+ }
+ return stop.color;
+ }
+ }
+ return c[len - 1].color;
+ }
+
+ dojox.gfx.gradutils.getColor = function(fill, pt){
+ // summary:
+ // sample a color from a gradient using a point
+ // fill: Object:
+ // fill object
+ // pt: dojox.gfx.Point:
+ // point where to sample a color
+ var o;
+ if(fill){
+ switch(fill.type){
+ case "linear":
+ var angle = Math.atan2(fill.y2 - fill.y1, fill.x2 - fill.x1),
+ rotation = m.rotate(-angle),
+ projection = m.project(fill.x2 - fill.x1, fill.y2 - fill.y1),
+ p = m.multiplyPoint(projection, pt),
+ pf1 = m.multiplyPoint(projection, fill.x1, fill.y1),
+ pf2 = m.multiplyPoint(projection, fill.x2, fill.y2),
+ scale = m.multiplyPoint(rotation, pf2.x - pf1.x, pf2.y - pf1.y).x,
+ o = m.multiplyPoint(rotation, p.x - pf1.x, p.y - pf1.y).x / scale;
+ break;
+ case "radial":
+ var dx = pt.x - fill.cx, dy = pt.y - fill.cy,
+ o = Math.sqrt(dx * dx + dy * dy) / fill.r;
+ break;
+ }
+ return findColor(o, fill.colors); // dojo.Color
+ }
+ // simple color
+ return new C(fill || [0, 0, 0, 0]); // dojo.Color
+ };
+
+ dojox.gfx.gradutils.reverse = function(fill){
+ // summary:
+ // reverses a gradient
+ // fill: Object:
+ // fill object
+ if(fill){
+ switch(fill.type){
+ case "linear":
+ case "radial":
+ fill = dojo.delegate(fill);
+ if(fill.colors){
+ var c = fill.colors, l = c.length, i = 0, stop,
+ n = fill.colors = new Array(c.length);
+ for(; i < l; ++i){
+ stop = c[i];
+ n[i] = {
+ offset: 1 - stop.offset,
+ color: stop.color
+ };
+ }
+ n.sort(function(a, b){ return a.offset - b.offset; });
+ }
+ break;
+ }
+ }
+ return fill; // Object
+ };
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/matrix.js b/js/dojo-1.6/dojox/gfx/matrix.js new file mode 100644 index 0000000..142915f --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/matrix.js @@ -0,0 +1,454 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+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;
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/matrix.xd.js b/js/dojo-1.6/dojox/gfx/matrix.xd.js new file mode 100644 index 0000000..19818fb --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/matrix.xd.js @@ -0,0 +1,458 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.matrix"]],
+defineResource: function(dojo, dijit, dojox){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;
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/move.js b/js/dojo-1.6/dojox/gfx/move.js new file mode 100644 index 0000000..98aee43 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/move.js @@ -0,0 +1,15 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.move"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.move"] = true;
+dojo.provide("dojox.gfx.move");
+
+dojo.require("dojox.gfx.Mover");
+dojo.require("dojox.gfx.Moveable");
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/move.xd.js b/js/dojo-1.6/dojox/gfx/move.xd.js new file mode 100644 index 0000000..b2138aa --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/move.xd.js @@ -0,0 +1,21 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.move"],
+["require", "dojox.gfx.Mover"],
+["require", "dojox.gfx.Moveable"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.move"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.move"] = true;
+dojo.provide("dojox.gfx.move");
+
+dojo.require("dojox.gfx.Mover");
+dojo.require("dojox.gfx.Moveable");
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/path.js b/js/dojo-1.6/dojox/gfx/path.js new file mode 100644 index 0000000..62cc837 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/path.js @@ -0,0 +1,430 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.path"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.path"] = true;
+dojo.provide("dojox.gfx.path");
+
+dojo.require("dojox.gfx.matrix");
+dojo.require("dojox.gfx.shape");
+
+dojo.declare("dojox.gfx.path.Path", dojox.gfx.shape.Shape, {
+ // summary: a generalized path shape
+
+ constructor: function(rawNode){
+ // summary: a path constructor
+ // rawNode: Node: a DOM node to be used by this path object
+ this.shape = dojo.clone(dojox.gfx.defaultPath);
+ this.segments = [];
+ this.tbbox = null;
+ this.absolute = true;
+ this.last = {};
+ this.rawNode = rawNode;
+ this.segmented = false;
+ },
+
+ // mode manipulations
+ setAbsoluteMode: function(mode){
+ // summary: sets an absolute or relative mode for path points
+ // mode: Boolean: true/false or "absolute"/"relative" to specify the mode
+ this._confirmSegmented();
+ this.absolute = typeof mode == "string" ? (mode == "absolute") : mode;
+ return this; // self
+ },
+ getAbsoluteMode: function(){
+ // summary: returns a current value of the absolute mode
+ this._confirmSegmented();
+ return this.absolute; // Boolean
+ },
+
+ getBoundingBox: function(){
+ // summary: returns the bounding box {x, y, width, height} or null
+ this._confirmSegmented();
+ return (this.bbox && ("l" in this.bbox)) ? {x: this.bbox.l, y: this.bbox.t, width: this.bbox.r - this.bbox.l, height: this.bbox.b - this.bbox.t} : null; // dojox.gfx.Rectangle
+ },
+
+ _getRealBBox: function(){
+ // summary: returns an array of four points or null
+ // four points represent four corners of the untransformed bounding box
+ this._confirmSegmented();
+ if(this.tbbox){
+ return this.tbbox; // Array
+ }
+ var bbox = this.bbox, matrix = this._getRealMatrix();
+ this.bbox = null;
+ for(var i = 0, len = this.segments.length; i < len; ++i){
+ this._updateWithSegment(this.segments[i], matrix);
+ }
+ var t = this.bbox;
+ this.bbox = bbox;
+ this.tbbox = t ? [
+ {x: t.l, y: t.t},
+ {x: t.r, y: t.t},
+ {x: t.r, y: t.b},
+ {x: t.l, y: t.b}
+ ] : null;
+ return this.tbbox; // Array
+ },
+
+ getLastPosition: function(){
+ // summary: returns the last point in the path, or null
+ this._confirmSegmented();
+ return "x" in this.last ? this.last : null; // Object
+ },
+
+ _applyTransform: function(){
+ this.tbbox = null;
+ return this.inherited(arguments);
+ },
+
+ // segment interpretation
+ _updateBBox: function(x, y, matrix){
+ // summary: updates the bounding box of path with new point
+ // x: Number: an x coordinate
+ // y: Number: a y coordinate
+
+ if(matrix){
+ var t = dojox.gfx.matrix.multiplyPoint(matrix, x, y);
+ x = t.x;
+ y = t.y;
+ }
+
+ // we use {l, b, r, t} representation of a bbox
+ if(this.bbox && ("l" in this.bbox)){
+ if(this.bbox.l > x) this.bbox.l = x;
+ if(this.bbox.r < x) this.bbox.r = x;
+ if(this.bbox.t > y) this.bbox.t = y;
+ if(this.bbox.b < y) this.bbox.b = y;
+ }else{
+ this.bbox = {l: x, b: y, r: x, t: y};
+ }
+ },
+ _updateWithSegment: function(segment, matrix){
+ // summary: updates the bounding box of path with new segment
+ // segment: Object: a segment
+ var n = segment.args, l = n.length;
+ // update internal variables: bbox, absolute, last
+ switch(segment.action){
+ case "M":
+ case "L":
+ case "C":
+ case "S":
+ case "Q":
+ case "T":
+ for(var i = 0; i < l; i += 2){
+ this._updateBBox(n[i], n[i + 1], matrix);
+ }
+ this.last.x = n[l - 2];
+ this.last.y = n[l - 1];
+ this.absolute = true;
+ break;
+ case "H":
+ for(var i = 0; i < l; ++i){
+ this._updateBBox(n[i], this.last.y, matrix);
+ }
+ this.last.x = n[l - 1];
+ this.absolute = true;
+ break;
+ case "V":
+ for(var i = 0; i < l; ++i){
+ this._updateBBox(this.last.x, n[i], matrix);
+ }
+ this.last.y = n[l - 1];
+ this.absolute = true;
+ break;
+ case "m":
+ var start = 0;
+ if(!("x" in this.last)){
+ this._updateBBox(this.last.x = n[0], this.last.y = n[1], matrix);
+ start = 2;
+ }
+ for(var i = start; i < l; i += 2){
+ this._updateBBox(this.last.x += n[i], this.last.y += n[i + 1], matrix);
+ }
+ this.absolute = false;
+ break;
+ case "l":
+ case "t":
+ for(var i = 0; i < l; i += 2){
+ this._updateBBox(this.last.x += n[i], this.last.y += n[i + 1], matrix);
+ }
+ this.absolute = false;
+ break;
+ case "h":
+ for(var i = 0; i < l; ++i){
+ this._updateBBox(this.last.x += n[i], this.last.y, matrix);
+ }
+ this.absolute = false;
+ break;
+ case "v":
+ for(var i = 0; i < l; ++i){
+ this._updateBBox(this.last.x, this.last.y += n[i], matrix);
+ }
+ this.absolute = false;
+ break;
+ case "c":
+ for(var i = 0; i < l; i += 6){
+ this._updateBBox(this.last.x + n[i], this.last.y + n[i + 1], matrix);
+ this._updateBBox(this.last.x + n[i + 2], this.last.y + n[i + 3], matrix);
+ this._updateBBox(this.last.x += n[i + 4], this.last.y += n[i + 5], matrix);
+ }
+ this.absolute = false;
+ break;
+ case "s":
+ case "q":
+ for(var i = 0; i < l; i += 4){
+ this._updateBBox(this.last.x + n[i], this.last.y + n[i + 1], matrix);
+ this._updateBBox(this.last.x += n[i + 2], this.last.y += n[i + 3], matrix);
+ }
+ this.absolute = false;
+ break;
+ case "A":
+ for(var i = 0; i < l; i += 7){
+ this._updateBBox(n[i + 5], n[i + 6], matrix);
+ }
+ this.last.x = n[l - 2];
+ this.last.y = n[l - 1];
+ this.absolute = true;
+ break;
+ case "a":
+ for(var i = 0; i < l; i += 7){
+ this._updateBBox(this.last.x += n[i + 5], this.last.y += n[i + 6], matrix);
+ }
+ this.absolute = false;
+ break;
+ }
+ // add an SVG path segment
+ var path = [segment.action];
+ for(var i = 0; i < l; ++i){
+ path.push(dojox.gfx.formatNumber(n[i], true));
+ }
+ if(typeof this.shape.path == "string"){
+ this.shape.path += path.join("");
+ }else{
+ Array.prototype.push.apply(this.shape.path, path); //FIXME: why not simple push()?
+ }
+ },
+
+ // a dictionary, which maps segment type codes to a number of their arguments
+ _validSegments: {m: 2, l: 2, h: 1, v: 1, c: 6, s: 4, q: 4, t: 2, a: 7, z: 0},
+
+ _pushSegment: function(action, args){
+ // summary: adds a segment
+ // action: String: valid SVG code for a segment's type
+ // args: Array: a list of parameters for this segment
+ this.tbbox = null;
+ var group = this._validSegments[action.toLowerCase()];
+ if(typeof group == "number"){
+ if(group){
+ if(args.length >= group){
+ var segment = {action: action, args: args.slice(0, args.length - args.length % group)};
+ this.segments.push(segment);
+ this._updateWithSegment(segment);
+ }
+ }else{
+ var segment = {action: action, args: []};
+ this.segments.push(segment);
+ this._updateWithSegment(segment);
+ }
+ }
+ },
+
+ _collectArgs: function(array, args){
+ // summary: converts an array of arguments to plain numeric values
+ // array: Array: an output argument (array of numbers)
+ // args: Array: an input argument (can be values of Boolean, Number, dojox.gfx.Point, or an embedded array of them)
+ for(var i = 0; i < args.length; ++i){
+ var t = args[i];
+ if(typeof t == "boolean"){
+ array.push(t ? 1 : 0);
+ }else if(typeof t == "number"){
+ array.push(t);
+ }else if(t instanceof Array){
+ this._collectArgs(array, t);
+ }else if("x" in t && "y" in t){
+ array.push(t.x, t.y);
+ }
+ }
+ },
+
+ // segments
+ moveTo: function(){
+ // summary: formes a move segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "M" : "m", args);
+ return this; // self
+ },
+ lineTo: function(){
+ // summary: formes a line segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "L" : "l", args);
+ return this; // self
+ },
+ hLineTo: function(){
+ // summary: formes a horizontal line segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "H" : "h", args);
+ return this; // self
+ },
+ vLineTo: function(){
+ // summary: formes a vertical line segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "V" : "v", args);
+ return this; // self
+ },
+ curveTo: function(){
+ // summary: formes a curve segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "C" : "c", args);
+ return this; // self
+ },
+ smoothCurveTo: function(){
+ // summary: formes a smooth curve segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "S" : "s", args);
+ return this; // self
+ },
+ qCurveTo: function(){
+ // summary: formes a quadratic curve segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "Q" : "q", args);
+ return this; // self
+ },
+ qSmoothCurveTo: function(){
+ // summary: formes a quadratic smooth curve segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "T" : "t", args);
+ return this; // self
+ },
+ arcTo: function(){
+ // summary: formes an elliptic arc segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "A" : "a", args);
+ return this; // self
+ },
+ closePath: function(){
+ // summary: closes a path
+ this._confirmSegmented();
+ this._pushSegment("Z", []);
+ return this; // self
+ },
+
+ _confirmSegmented: function() {
+ if (!this.segmented) {
+ var path = this.shape.path;
+ // switch to non-updating version of path building
+ this.shape.path = [];
+ this._setPath(path);
+ // switch back to the string path
+ this.shape.path = this.shape.path.join("");
+ // become segmented
+ this.segmented = true;
+ }
+ },
+
+ // setShape
+ _setPath: function(path){
+ // summary: forms a path using an SVG path string
+ // path: String: an SVG path string
+ var p = dojo.isArray(path) ? path : path.match(dojox.gfx.pathSvgRegExp);
+ this.segments = [];
+ this.absolute = true;
+ this.bbox = {};
+ this.last = {};
+ if(!p) return;
+ // create segments
+ var action = "", // current action
+ args = [], // current arguments
+ l = p.length;
+ for(var i = 0; i < l; ++i){
+ var t = p[i], x = parseFloat(t);
+ if(isNaN(x)){
+ if(action){
+ this._pushSegment(action, args);
+ }
+ args = [];
+ action = t;
+ }else{
+ args.push(x);
+ }
+ }
+ this._pushSegment(action, args);
+ },
+ setShape: function(newShape){
+ // summary: forms a path using a shape
+ // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+ this.inherited(arguments, [typeof newShape == "string" ? {path: newShape} : newShape]);
+
+ this.segmented = false;
+ this.segments = [];
+ if(!dojox.gfx.lazyPathSegmentation){
+ this._confirmSegmented();
+ }
+ return this; // self
+ },
+
+ // useful constant for descendants
+ _2PI: Math.PI * 2
+});
+
+dojo.declare("dojox.gfx.path.TextPath", dojox.gfx.path.Path, {
+ // summary: a generalized TextPath shape
+
+ constructor: function(rawNode){
+ // summary: a TextPath shape constructor
+ // rawNode: Node: a DOM node to be used by this TextPath object
+ if(!("text" in this)){
+ this.text = dojo.clone(dojox.gfx.defaultTextPath);
+ }
+ if(!("fontStyle" in this)){
+ this.fontStyle = dojo.clone(dojox.gfx.defaultFont);
+ }
+ },
+ getText: function(){
+ // summary: returns the current text object or null
+ return this.text; // Object
+ },
+ setText: function(newText){
+ // summary: sets a text to be drawn along the path
+ this.text = dojox.gfx.makeParameters(this.text,
+ typeof newText == "string" ? {text: newText} : newText);
+ this._setText();
+ return this; // self
+ },
+ getFont: function(){
+ // summary: returns the current font object or null
+ return this.fontStyle; // Object
+ },
+ setFont: function(newFont){
+ // summary: sets a font for text
+ this.fontStyle = typeof newFont == "string" ?
+ dojox.gfx.splitFontString(newFont) :
+ dojox.gfx.makeParameters(dojox.gfx.defaultFont, newFont);
+ this._setFont();
+ return this; // self
+ }
+});
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/path.xd.js b/js/dojo-1.6/dojox/gfx/path.xd.js new file mode 100644 index 0000000..02ecbea --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/path.xd.js @@ -0,0 +1,436 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.path"],
+["require", "dojox.gfx.matrix"],
+["require", "dojox.gfx.shape"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.path"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.path"] = true;
+dojo.provide("dojox.gfx.path");
+
+dojo.require("dojox.gfx.matrix");
+dojo.require("dojox.gfx.shape");
+
+dojo.declare("dojox.gfx.path.Path", dojox.gfx.shape.Shape, {
+ // summary: a generalized path shape
+
+ constructor: function(rawNode){
+ // summary: a path constructor
+ // rawNode: Node: a DOM node to be used by this path object
+ this.shape = dojo.clone(dojox.gfx.defaultPath);
+ this.segments = [];
+ this.tbbox = null;
+ this.absolute = true;
+ this.last = {};
+ this.rawNode = rawNode;
+ this.segmented = false;
+ },
+
+ // mode manipulations
+ setAbsoluteMode: function(mode){
+ // summary: sets an absolute or relative mode for path points
+ // mode: Boolean: true/false or "absolute"/"relative" to specify the mode
+ this._confirmSegmented();
+ this.absolute = typeof mode == "string" ? (mode == "absolute") : mode;
+ return this; // self
+ },
+ getAbsoluteMode: function(){
+ // summary: returns a current value of the absolute mode
+ this._confirmSegmented();
+ return this.absolute; // Boolean
+ },
+
+ getBoundingBox: function(){
+ // summary: returns the bounding box {x, y, width, height} or null
+ this._confirmSegmented();
+ return (this.bbox && ("l" in this.bbox)) ? {x: this.bbox.l, y: this.bbox.t, width: this.bbox.r - this.bbox.l, height: this.bbox.b - this.bbox.t} : null; // dojox.gfx.Rectangle
+ },
+
+ _getRealBBox: function(){
+ // summary: returns an array of four points or null
+ // four points represent four corners of the untransformed bounding box
+ this._confirmSegmented();
+ if(this.tbbox){
+ return this.tbbox; // Array
+ }
+ var bbox = this.bbox, matrix = this._getRealMatrix();
+ this.bbox = null;
+ for(var i = 0, len = this.segments.length; i < len; ++i){
+ this._updateWithSegment(this.segments[i], matrix);
+ }
+ var t = this.bbox;
+ this.bbox = bbox;
+ this.tbbox = t ? [
+ {x: t.l, y: t.t},
+ {x: t.r, y: t.t},
+ {x: t.r, y: t.b},
+ {x: t.l, y: t.b}
+ ] : null;
+ return this.tbbox; // Array
+ },
+
+ getLastPosition: function(){
+ // summary: returns the last point in the path, or null
+ this._confirmSegmented();
+ return "x" in this.last ? this.last : null; // Object
+ },
+
+ _applyTransform: function(){
+ this.tbbox = null;
+ return this.inherited(arguments);
+ },
+
+ // segment interpretation
+ _updateBBox: function(x, y, matrix){
+ // summary: updates the bounding box of path with new point
+ // x: Number: an x coordinate
+ // y: Number: a y coordinate
+
+ if(matrix){
+ var t = dojox.gfx.matrix.multiplyPoint(matrix, x, y);
+ x = t.x;
+ y = t.y;
+ }
+
+ // we use {l, b, r, t} representation of a bbox
+ if(this.bbox && ("l" in this.bbox)){
+ if(this.bbox.l > x) this.bbox.l = x;
+ if(this.bbox.r < x) this.bbox.r = x;
+ if(this.bbox.t > y) this.bbox.t = y;
+ if(this.bbox.b < y) this.bbox.b = y;
+ }else{
+ this.bbox = {l: x, b: y, r: x, t: y};
+ }
+ },
+ _updateWithSegment: function(segment, matrix){
+ // summary: updates the bounding box of path with new segment
+ // segment: Object: a segment
+ var n = segment.args, l = n.length;
+ // update internal variables: bbox, absolute, last
+ switch(segment.action){
+ case "M":
+ case "L":
+ case "C":
+ case "S":
+ case "Q":
+ case "T":
+ for(var i = 0; i < l; i += 2){
+ this._updateBBox(n[i], n[i + 1], matrix);
+ }
+ this.last.x = n[l - 2];
+ this.last.y = n[l - 1];
+ this.absolute = true;
+ break;
+ case "H":
+ for(var i = 0; i < l; ++i){
+ this._updateBBox(n[i], this.last.y, matrix);
+ }
+ this.last.x = n[l - 1];
+ this.absolute = true;
+ break;
+ case "V":
+ for(var i = 0; i < l; ++i){
+ this._updateBBox(this.last.x, n[i], matrix);
+ }
+ this.last.y = n[l - 1];
+ this.absolute = true;
+ break;
+ case "m":
+ var start = 0;
+ if(!("x" in this.last)){
+ this._updateBBox(this.last.x = n[0], this.last.y = n[1], matrix);
+ start = 2;
+ }
+ for(var i = start; i < l; i += 2){
+ this._updateBBox(this.last.x += n[i], this.last.y += n[i + 1], matrix);
+ }
+ this.absolute = false;
+ break;
+ case "l":
+ case "t":
+ for(var i = 0; i < l; i += 2){
+ this._updateBBox(this.last.x += n[i], this.last.y += n[i + 1], matrix);
+ }
+ this.absolute = false;
+ break;
+ case "h":
+ for(var i = 0; i < l; ++i){
+ this._updateBBox(this.last.x += n[i], this.last.y, matrix);
+ }
+ this.absolute = false;
+ break;
+ case "v":
+ for(var i = 0; i < l; ++i){
+ this._updateBBox(this.last.x, this.last.y += n[i], matrix);
+ }
+ this.absolute = false;
+ break;
+ case "c":
+ for(var i = 0; i < l; i += 6){
+ this._updateBBox(this.last.x + n[i], this.last.y + n[i + 1], matrix);
+ this._updateBBox(this.last.x + n[i + 2], this.last.y + n[i + 3], matrix);
+ this._updateBBox(this.last.x += n[i + 4], this.last.y += n[i + 5], matrix);
+ }
+ this.absolute = false;
+ break;
+ case "s":
+ case "q":
+ for(var i = 0; i < l; i += 4){
+ this._updateBBox(this.last.x + n[i], this.last.y + n[i + 1], matrix);
+ this._updateBBox(this.last.x += n[i + 2], this.last.y += n[i + 3], matrix);
+ }
+ this.absolute = false;
+ break;
+ case "A":
+ for(var i = 0; i < l; i += 7){
+ this._updateBBox(n[i + 5], n[i + 6], matrix);
+ }
+ this.last.x = n[l - 2];
+ this.last.y = n[l - 1];
+ this.absolute = true;
+ break;
+ case "a":
+ for(var i = 0; i < l; i += 7){
+ this._updateBBox(this.last.x += n[i + 5], this.last.y += n[i + 6], matrix);
+ }
+ this.absolute = false;
+ break;
+ }
+ // add an SVG path segment
+ var path = [segment.action];
+ for(var i = 0; i < l; ++i){
+ path.push(dojox.gfx.formatNumber(n[i], true));
+ }
+ if(typeof this.shape.path == "string"){
+ this.shape.path += path.join("");
+ }else{
+ Array.prototype.push.apply(this.shape.path, path); //FIXME: why not simple push()?
+ }
+ },
+
+ // a dictionary, which maps segment type codes to a number of their arguments
+ _validSegments: {m: 2, l: 2, h: 1, v: 1, c: 6, s: 4, q: 4, t: 2, a: 7, z: 0},
+
+ _pushSegment: function(action, args){
+ // summary: adds a segment
+ // action: String: valid SVG code for a segment's type
+ // args: Array: a list of parameters for this segment
+ this.tbbox = null;
+ var group = this._validSegments[action.toLowerCase()];
+ if(typeof group == "number"){
+ if(group){
+ if(args.length >= group){
+ var segment = {action: action, args: args.slice(0, args.length - args.length % group)};
+ this.segments.push(segment);
+ this._updateWithSegment(segment);
+ }
+ }else{
+ var segment = {action: action, args: []};
+ this.segments.push(segment);
+ this._updateWithSegment(segment);
+ }
+ }
+ },
+
+ _collectArgs: function(array, args){
+ // summary: converts an array of arguments to plain numeric values
+ // array: Array: an output argument (array of numbers)
+ // args: Array: an input argument (can be values of Boolean, Number, dojox.gfx.Point, or an embedded array of them)
+ for(var i = 0; i < args.length; ++i){
+ var t = args[i];
+ if(typeof t == "boolean"){
+ array.push(t ? 1 : 0);
+ }else if(typeof t == "number"){
+ array.push(t);
+ }else if(t instanceof Array){
+ this._collectArgs(array, t);
+ }else if("x" in t && "y" in t){
+ array.push(t.x, t.y);
+ }
+ }
+ },
+
+ // segments
+ moveTo: function(){
+ // summary: formes a move segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "M" : "m", args);
+ return this; // self
+ },
+ lineTo: function(){
+ // summary: formes a line segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "L" : "l", args);
+ return this; // self
+ },
+ hLineTo: function(){
+ // summary: formes a horizontal line segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "H" : "h", args);
+ return this; // self
+ },
+ vLineTo: function(){
+ // summary: formes a vertical line segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "V" : "v", args);
+ return this; // self
+ },
+ curveTo: function(){
+ // summary: formes a curve segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "C" : "c", args);
+ return this; // self
+ },
+ smoothCurveTo: function(){
+ // summary: formes a smooth curve segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "S" : "s", args);
+ return this; // self
+ },
+ qCurveTo: function(){
+ // summary: formes a quadratic curve segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "Q" : "q", args);
+ return this; // self
+ },
+ qSmoothCurveTo: function(){
+ // summary: formes a quadratic smooth curve segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "T" : "t", args);
+ return this; // self
+ },
+ arcTo: function(){
+ // summary: formes an elliptic arc segment
+ this._confirmSegmented();
+ var args = [];
+ this._collectArgs(args, arguments);
+ this._pushSegment(this.absolute ? "A" : "a", args);
+ return this; // self
+ },
+ closePath: function(){
+ // summary: closes a path
+ this._confirmSegmented();
+ this._pushSegment("Z", []);
+ return this; // self
+ },
+
+ _confirmSegmented: function() {
+ if (!this.segmented) {
+ var path = this.shape.path;
+ // switch to non-updating version of path building
+ this.shape.path = [];
+ this._setPath(path);
+ // switch back to the string path
+ this.shape.path = this.shape.path.join("");
+ // become segmented
+ this.segmented = true;
+ }
+ },
+
+ // setShape
+ _setPath: function(path){
+ // summary: forms a path using an SVG path string
+ // path: String: an SVG path string
+ var p = dojo.isArray(path) ? path : path.match(dojox.gfx.pathSvgRegExp);
+ this.segments = [];
+ this.absolute = true;
+ this.bbox = {};
+ this.last = {};
+ if(!p) return;
+ // create segments
+ var action = "", // current action
+ args = [], // current arguments
+ l = p.length;
+ for(var i = 0; i < l; ++i){
+ var t = p[i], x = parseFloat(t);
+ if(isNaN(x)){
+ if(action){
+ this._pushSegment(action, args);
+ }
+ args = [];
+ action = t;
+ }else{
+ args.push(x);
+ }
+ }
+ this._pushSegment(action, args);
+ },
+ setShape: function(newShape){
+ // summary: forms a path using a shape
+ // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+ this.inherited(arguments, [typeof newShape == "string" ? {path: newShape} : newShape]);
+
+ this.segmented = false;
+ this.segments = [];
+ if(!dojox.gfx.lazyPathSegmentation){
+ this._confirmSegmented();
+ }
+ return this; // self
+ },
+
+ // useful constant for descendants
+ _2PI: Math.PI * 2
+});
+
+dojo.declare("dojox.gfx.path.TextPath", dojox.gfx.path.Path, {
+ // summary: a generalized TextPath shape
+
+ constructor: function(rawNode){
+ // summary: a TextPath shape constructor
+ // rawNode: Node: a DOM node to be used by this TextPath object
+ if(!("text" in this)){
+ this.text = dojo.clone(dojox.gfx.defaultTextPath);
+ }
+ if(!("fontStyle" in this)){
+ this.fontStyle = dojo.clone(dojox.gfx.defaultFont);
+ }
+ },
+ getText: function(){
+ // summary: returns the current text object or null
+ return this.text; // Object
+ },
+ setText: function(newText){
+ // summary: sets a text to be drawn along the path
+ this.text = dojox.gfx.makeParameters(this.text,
+ typeof newText == "string" ? {text: newText} : newText);
+ this._setText();
+ return this; // self
+ },
+ getFont: function(){
+ // summary: returns the current font object or null
+ return this.fontStyle; // Object
+ },
+ setFont: function(newFont){
+ // summary: sets a font for text
+ this.fontStyle = typeof newFont == "string" ?
+ dojox.gfx.splitFontString(newFont) :
+ dojox.gfx.makeParameters(dojox.gfx.defaultFont, newFont);
+ this._setFont();
+ return this; // self
+ }
+});
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/resources/Gillius.svg b/js/dojo-1.6/dojox/gfx/resources/Gillius.svg new file mode 100644 index 0000000..a93cdab --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/resources/Gillius.svg @@ -0,0 +1,1272 @@ +<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" > +<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"> +<defs> + <font horiz-adv-x="985"> + <font-face + font-family="Gillius ADF No2" + units-per-em="2048" + panose-1="2 11 5 3 5 0 0 2 0 3" + ascent="1536" + descent="-512" + alphabetic="0" /> +<missing-glyph horiz-adv-x="573" /> +<glyph unicode=" " glyph-name="space" horiz-adv-x="614" /> +<glyph unicode="!" glyph-name="exclam" horiz-adv-x="444" d="M185 176T221 176T284 147T311 80T284 14T221 -16T158 13T131 80T158 146ZM307 797L289 461H156L133 797V1417H307V797Z" /> +<glyph unicode=""" glyph-name="quotedbl" horiz-adv-x="737" d="M264 772H141V1231H264V772ZM596 772H473V1231H596V772Z" /> +<glyph unicode="#" glyph-name="numbersign" horiz-adv-x="1265" d="M815 862H530L451 530H737L815 862ZM1241 862H928L854 530H1137V395H825L731 0H614L705 395H432L328 0H211L303 395H23V530H332L412 862H123V995H432L532 1393H651L555 995H844L938 1393H1053L963 +995H1241V862Z" /> +<glyph unicode="$" glyph-name="dollar" horiz-adv-x="954" d="M774 342Q774 367 769 389T757 427T736 459T710 484T677 504T641 520T599 533T557 544T512 555V125Q644 147 707 193T774 342ZM449 721V1130Q328 1117 266 1072T203 926Q203 884 215 853T248 801T301 +764T368 739T449 721ZM905 360Q905 38 512 2V-287H449V2Q367 2 255 28T66 88V246Q164 174 236 151T449 123V573Q66 641 66 909Q66 991 95 1055T177 1159T298 1222T449 1251V1477H512V1251Q618 1251 686 1233Q758 1216 829 1194V1044Q746 1093 690 1110Q588 1125 +512 1130V705Q583 694 638 679T745 637T831 574T885 484T905 360Z" /> +<glyph unicode="%" glyph-name="percent" horiz-adv-x="1613" d="M532 1061Q532 1116 523 1163T493 1250T435 1314T346 1337Q299 1337 263 1313T205 1248T173 1160T162 1061Q162 991 178 931T238 826T346 778Q398 778 436 802T493 869T522 959T532 1061ZM1450 +354Q1450 404 1441 450T1411 539T1354 606T1268 631Q1085 631 1081 354Q1081 302 1090 256T1119 168T1177 101T1268 76Q1316 76 1352 100T1408 165T1438 253T1450 354ZM635 1061Q635 987 619 921T569 801T478 714T346 682Q269 682 213 713T124 799T77 919T59 1061Q59 +1132 76 1198T126 1319T216 1408T346 1442Q404 1442 453 1420T535 1361T591 1274T624 1171T635 1061ZM1278 1442L453 -29H336L1161 1442H1278ZM1554 354Q1554 283 1538 218T1489 96T1399 5T1268 -29T1136 4T1044 93T993 215T975 354Q975 425 993 491T1046 611T1138 +698T1268 733Q1340 733 1396 699T1486 609T1537 488T1554 354Z" /> +<glyph unicode="&" glyph-name="ampersand" horiz-adv-x="1306" d="M877 240L379 772Q290 696 246 621T201 444Q201 290 301 200T555 109Q649 109 723 140T877 240ZM1288 -4H1085L954 141Q753 -29 539 -29Q333 -29 201 98T68 432Q68 662 307 868Q269 919 240 +991Q219 1054 219 1118Q219 1260 311 1348Q406 1442 561 1442Q632 1442 712 1423T850 1374V1212Q713 1311 580 1311Q477 1311 416 1253Q348 1199 348 1118Q348 1063 379 1004Q413 946 492 864L963 362Q1031 458 1056 541T1087 752H1229Q1207 526 1040 266L1288 +-4Z" /> +<glyph unicode="'" glyph-name="quotesingle" horiz-adv-x="409" d="M276 1417Q274 1330 274 1259T268 1107T244 958H166L135 1169V1417H276Z" /> +<glyph unicode="(" glyph-name="parenleft" horiz-adv-x="507" d="M477 -256H358Q82 197 82 610Q82 1013 358 1475H477Q347 1239 289 1047T227 610Q227 371 287 174T477 -256Z" /> +<glyph unicode=")" glyph-name="parenright" horiz-adv-x="509" d="M426 610Q426 402 349 171T150 -256H31Q161 -26 221 173T281 610Q281 847 220 1047T29 1475H150Q274 1271 350 1046T426 610Z" /> +<glyph unicode="*" glyph-name="asterisk" horiz-adv-x="913" d="M848 811L811 727L498 918V555H416V918L104 727L66 811L387 1001L66 1188L104 1276L416 1077V1442H498V1077L811 1276L848 1188L520 999L848 811Z" /> +<glyph unicode="+" glyph-name="plus" horiz-adv-x="1107" d="M1083 467H614V0H496V467H23V594H496V1059H614V594H1083V467Z" /> +<glyph unicode="," glyph-name="comma" horiz-adv-x="454" d="M338 209V66Q336 -11 245 -102T74 -197Q116 -169 142 -118T168 -10Q168 33 154 68V209H338Z" /> +<glyph unicode="-" glyph-name="hyphen" horiz-adv-x="749" d="M608 395H141V530H608V395Z" /> +<glyph unicode="." glyph-name="period" horiz-adv-x="477" d="M336 0H141V209H336V0Z" /> +<glyph unicode="/" glyph-name="slash" horiz-adv-x="643" d="M623 1417L150 -180H23L494 1417H623Z" /> +<glyph unicode="0" glyph-name="zero" horiz-adv-x="1126" d="M866 705Q866 1309 561 1309Q501 1309 453 1285T373 1224T320 1131T286 1025T269 908T261 800T260 705T261 610T268 503T286 388T320 282T374 190T453 130T561 106Q866 106 866 705ZM1012 705Q1012 +636 1007 570T989 429T954 290T898 166T817 64T706 -3T561 -29T417 -4T307 64T226 166T170 290T136 429T118 569T113 705Q113 774 117 839T135 979T168 1119T224 1244T304 1347T416 1416T561 1442T705 1417T816 1349T897 1246T954 1121T988 982T1007 841T1012 705Z" +/> +<glyph unicode="1" glyph-name="one" horiz-adv-x="585" d="M426 0H268V1264L55 1092V1251L256 1417H426V0Z" /> +<glyph unicode="2" glyph-name="two" d="M899 0H74V147Q110 185 335 433T578 702Q642 772 691 863T741 1030Q741 1153 660 1225T455 1298Q356 1298 268 1265T82 1169V1352Q155 1381 202 1397T317 1428T451 1442Q642 1442 764 1337T887 1040Q887 987 878 942T846 +851T804 776T748 692L262 147H899V0Z" /> +<glyph unicode="3" glyph-name="three" horiz-adv-x="1015" d="M911 410Q911 319 885 246T814 122T704 37T564 -13T401 -29Q250 -29 57 39V213Q134 159 210 138T397 117Q481 117 544 130T660 176T739 267T766 410Q766 481 741 535T669 622T564 670T434 686H289V825H440Q570 +825 651 882T735 1057Q735 1183 653 1240T434 1298Q371 1298 309 1287T208 1264T98 1227V1382Q285 1442 451 1442Q568 1442 663 1405T819 1284T881 1081Q881 971 817 889T635 764Q767 727 839 631T911 410Z" /> +<glyph unicode="4" glyph-name="four" horiz-adv-x="1040" d="M651 483V1264L166 483H651ZM997 338H805V0H651V338H51V516L600 1417H805V483H997V338Z" /> +<glyph unicode="5" glyph-name="five" horiz-adv-x="997" d="M911 451Q911 220 778 96T412 -29Q241 -29 70 31V209Q148 160 226 139T408 117Q571 117 667 202T764 451Q764 610 667 696T408 782Q304 782 260 771T127 715L213 1417H815V1268H315L264 895Q331 922 +440 928Q655 928 781 799T911 451Z" /> +<glyph unicode="6" glyph-name="six" horiz-adv-x="1075" d="M260 424Q260 276 341 191T565 106Q707 106 778 191T850 424Q850 574 777 671T565 768Q422 768 343 672T260 424ZM98 535Q98 685 136 833T236 1097T382 1298T555 1417H737Q654 1365 576 1293T433 1135T328 +954T287 768Q379 892 575 901Q712 901 809 838T951 668T997 424Q997 225 874 100T565 -29Q461 -29 380 1T247 83T160 208T112 362T98 535Z" /> +<glyph unicode="7" glyph-name="seven" horiz-adv-x="915" d="M866 1346L381 0H219L678 1266H33V1417H866V1346Z" /> +<glyph unicode="8" glyph-name="eight" horiz-adv-x="1097" d="M846 395Q846 531 766 606T547 682Q407 682 328 609T248 395Q248 253 327 180T547 106Q684 106 765 181T846 395ZM815 1061Q809 1193 736 1251T547 1309Q422 1309 353 1251T274 1061Q278 961 356 +889T543 817H547Q659 817 737 885T815 1061ZM989 395Q989 186 873 79T547 -29Q336 -29 218 78T100 395Q100 524 173 617T383 754Q252 801 192 869T131 1061Q131 1180 188 1268T339 1399T547 1442Q723 1442 841 1341T963 1061Q963 858 733 754Q982 665 989 395Z" +/> +<glyph unicode="9" glyph-name="nine" horiz-adv-x="1077" d="M813 965Q813 1113 732 1197T508 1282Q366 1282 295 1197T223 965Q223 893 240 832T292 723T381 648T508 621Q652 621 731 716T813 965ZM975 854Q975 703 937 556T837 292T691 90T518 -29H336Q505 +76 640 258T782 590Q723 534 663 514T498 487Q394 487 313 523T181 624T103 775T76 965Q76 1164 199 1289T508 1417Q612 1417 693 1387T826 1305T913 1180T961 1027T975 854Z" /> +<glyph unicode=":" glyph-name="colon" horiz-adv-x="477" d="M336 0H141V215H336V0ZM336 657H141V872H336V657Z" /> +<glyph unicode=";" glyph-name="semicolon" horiz-adv-x="460" d="M334 209V66Q332 -11 241 -102T70 -197Q112 -169 138 -118T164 -10Q164 33 150 68V209H334ZM336 657H147V872H336V657Z" /> +<glyph unicode="<" glyph-name="less" horiz-adv-x="1177" d="M1100 78L39 465V592L1100 981V842L217 528L1100 217V78Z" /> +<glyph unicode="=" glyph-name="equal" horiz-adv-x="1345" d="M1204 291H141V420H1204V291ZM1204 639H141V766H1204V639Z" /> +<glyph unicode=">" glyph-name="greater" horiz-adv-x="1179" d="M1141 465L78 78V217L961 528L78 842V981L1141 592V465Z" /> +<glyph unicode="?" glyph-name="question" horiz-adv-x="784" d="M302 176T338 176T401 147T428 80T401 14T338 -16T275 13T248 80T275 146ZM727 1112Q727 1067 718 1030T686 958T645 900T588 838L506 754Q471 714 460 700T433 663T414 619T409 571T406 496V375H264V524Q264 +622 293 683T395 823L475 907Q511 941 544 994T582 1102Q582 1200 514 1251T344 1303Q255 1303 185 1271T37 1171V1339Q126 1393 202 1417T377 1442Q535 1442 629 1356T727 1112Z" /> +<glyph unicode="@" glyph-name="at" horiz-adv-x="1689" d="M1098 508Q1098 640 1032 721Q959 797 852 797Q734 797 674 716T610 508Q610 384 674 302T854 219Q972 219 1033 300T1098 508ZM1628 625Q1628 375 1488 230T1100 82V209Q1056 154 980 120T819 86Q752 +86 696 110T601 174T535 269T494 383T481 508Q481 590 501 664T562 800T668 898T819 936Q1038 936 1100 811V920H1229V221Q1304 233 1360 269T1448 359T1497 478T1516 621Q1516 741 1470 857T1342 1065T1140 1213T881 1270H866Q714 1270 583 1209T364 1044T226 +803T176 514Q176 352 232 216T383 -11T603 -151T866 -201Q1095 -201 1294 -39L1370 -150Q1241 -245 1127 -290T866 -338Q703 -338 557 -277T304 -106T133 165T70 514Q70 645 101 768T199 1000T359 1190T587 1318T879 1366Q1049 1366 1192 1305T1429 1140T1576 904T1628 +625Z" /> +<glyph unicode="A" glyph-name="A" horiz-adv-x="1222" d="M872 516L614 1245L350 516H872ZM1206 0H1042L924 371H299L178 0H16L518 1417H702L1206 0Z" /> +<glyph unicode="B" glyph-name="B" horiz-adv-x="1146" d="M909 416Q909 563 832 623T602 684H297V141H602Q753 141 831 205T909 416ZM866 1051Q866 1269 580 1276H297V821H580Q707 821 785 878T866 1051ZM1063 395Q1063 292 1031 215T938 92T797 23T614 0H141V1417H594Q993 +1417 1008 1071Q1008 960 962 879T823 774V754Q936 720 999 622T1063 395Z" /> +<glyph unicode="C" glyph-name="C" horiz-adv-x="1196" d="M1130 104Q1050 42 939 7T719 -29Q562 -29 440 27T241 184T125 417T86 705Q86 829 110 938T184 1141T308 1300T487 1404T719 1442Q946 1442 1130 1311V1118Q1047 1214 953 1258T729 1303Q598 1303 502 +1257T350 1127T267 939T238 705Q238 602 255 515T309 352T403 224T542 141T729 111Q858 111 951 153T1130 291V104Z" /> +<glyph unicode="D" glyph-name="D" horiz-adv-x="1320" d="M1081 711Q1081 1005 949 1139T528 1276H295V141H528Q812 141 946 281T1081 711ZM1231 1085T1231 711T1053 169T500 0H141V1417H500Q875 1417 1053 1251Z" /> +<glyph unicode="E" glyph-name="E" horiz-adv-x="1030" d="M979 0H141V1417H963V1268H295V827H932V682H295V147H979V0Z" /> +<glyph unicode="F" glyph-name="F" horiz-adv-x="921" d="M889 1268H297V831H831V684H297V0H141V1417H889V1268Z" /> +<glyph unicode="G" glyph-name="G" horiz-adv-x="1316" d="M1221 127Q1014 -29 735 -29Q573 -29 448 25T245 178T126 410T86 705T125 1000T243 1232T446 1387T735 1442Q855 1442 973 1408T1186 1311V1120Q1083 1219 987 1261T750 1303Q613 1303 514 1260T356 1134T269 +947T238 705Q238 570 267 464T356 277T516 154T750 111Q919 111 1071 182V590H770V731H1221V127Z" /> +<glyph unicode="H" glyph-name="H" horiz-adv-x="1271" d="M1130 0H975V682H295V0H141V1417H295V827H975V1417H1130V0Z" /> +<glyph unicode="I" glyph-name="I" horiz-adv-x="436" d="M295 0H141V1417H295V0Z" /> +<glyph unicode="J" glyph-name="J" horiz-adv-x="428" d="M287 94Q287 -152 193 -276Q105 -387 -98 -387H-156V-244H-113Q30 -244 84 -172Q135 -96 135 94V1417H287V94Z" /> +<glyph unicode="K" glyph-name="K" horiz-adv-x="1171" d="M1174 0H961L297 692V0H141V1417H297V809L913 1417H1128L463 760L1174 0Z" /> +<glyph unicode="L" glyph-name="L" horiz-adv-x="962" d="M952 0H141V1417H297V147H952V0Z" /> +<glyph unicode="M" glyph-name="M" horiz-adv-x="1470" d="M1329 0H1176V1135L739 276L295 1135V0H141V1417H295L739 578L1176 1417H1329V0Z" /> +<glyph unicode="N" glyph-name="N" horiz-adv-x="1265" d="M1124 0H971L293 1141V0H141V1417H287L971 274V1417H1124V0Z" /> +<glyph unicode="O" glyph-name="O" horiz-adv-x="1374" d="M1133 705Q1133 797 1119 880T1070 1042T985 1177T856 1269T682 1303Q587 1303 510 1269T383 1177T299 1041T251 879T236 705Q236 617 251 534T300 373T384 237T511 144T682 109Q777 109 854 143T982 +235T1068 370T1118 531T1133 705ZM1284 824T1284 705T1262 479T1193 279T1076 117T906 10T682 -29Q532 -29 415 31T227 196T120 429T84 705Q84 820 106 926T175 1126T291 1291T460 1401T682 1442Q805 1442 906 1403T1076 1295T1193 1132T1262 931Z" /> +<glyph unicode="P" glyph-name="P" horiz-adv-x="1040" d="M825 995Q825 1133 751 1203T541 1276H295V719H541Q677 719 749 790T825 995ZM979 995Q979 783 866 679T541 575H295V0H141V1417H541Q753 1417 866 1312T979 995Z" /> +<glyph unicode="Q" glyph-name="Q" horiz-adv-x="1372" d="M1133 707Q1133 798 1119 881T1070 1043T985 1178T856 1269T682 1303Q587 1303 510 1269T383 1177T299 1041T251 880T236 707Q236 620 251 538T301 378T386 242T513 148T682 113T852 147T980 239T1066 +374T1117 534T1133 707ZM1284 707Q1284 192 928 20Q928 -17 985 -68T1075 -119Q1083 -121 1100 -121Q1144 -121 1197 -97T1282 -37Q1285 -105 1214 -175T1055 -246Q961 -246 873 -175T766 -20Q730 -20 713 -21T682 -23Q561 -23 461 16T292 124T176 285T106 484T84 +707Q84 822 106 927T175 1127T291 1291T460 1401T682 1442Q805 1442 906 1403T1076 1295T1193 1132T1262 932T1284 707Z" /> +<glyph unicode="R" glyph-name="R" horiz-adv-x="1112" d="M821 1016Q821 1269 539 1276H295V748H539Q672 748 746 816T821 1016ZM1092 0H930Q886 40 859 99T808 243T770 365Q656 606 520 606H506H295V0H141V1417H539Q973 1417 973 1016Q973 947 963 899T926 805T845 +727T709 672Q731 659 751 641T787 604T818 562T846 517T871 471T893 425T913 381T952 276T1015 120T1092 0Z" /> +<glyph unicode="S" glyph-name="S" horiz-adv-x="1067" d="M999 385Q999 295 974 224T904 106T796 28T659 -16T500 -29Q433 -29 354 -15T222 15T84 59V246Q293 109 500 109Q566 109 625 123T735 167T816 249T846 371Q846 436 827 481T766 557T682 604T569 639L461 +659Q387 676 333 695T230 744T151 814T104 910T86 1040Q86 1142 120 1220T215 1346T359 1418T541 1442Q631 1442 738 1422T922 1368V1200Q841 1241 801 1258T698 1289T559 1303Q490 1303 435 1291T333 1250T260 1173T231 1055Q231 1007 245 971T282 912T342 871T415 +844T502 823L616 803Q801 760 900 663T999 385Z" /> +<glyph unicode="T" glyph-name="T" horiz-adv-x="1142" d="M1122 1268H649V0H496V1268H20V1417H1122V1268Z" /> +<glyph unicode="U" glyph-name="U" horiz-adv-x="1253" d="M1124 528Q1124 265 1005 118T631 -29Q376 -29 253 117T129 528V1417H283V553Q283 468 291 404T323 282T385 188T485 130T631 109Q733 109 802 140T907 234T958 372T973 553V1417H1124V528Z" /> +<glyph unicode="V" glyph-name="V" horiz-adv-x="1226" d="M1206 1417L616 -29L20 1417H178L616 369L1044 1417H1206Z" /> +<glyph unicode="W" glyph-name="W" horiz-adv-x="1726" d="M1686 1417L1255 -29L860 1044L477 -29L43 1417H197L498 451L860 1450L1235 451L1532 1417H1686Z" /> +<glyph unicode="X" glyph-name="X" horiz-adv-x="1140" d="M1120 0H952L571 614L178 0H10L492 760L72 1417H240L582 881L926 1417H1094L666 737L1120 0Z" /> +<glyph unicode="Y" glyph-name="Y" horiz-adv-x="1091" d="M1094 1417L623 676V0H469V676L0 1417H168L547 821L926 1417H1094Z" /> +<glyph unicode="Z" glyph-name="Z" horiz-adv-x="1155" d="M1112 0H51V137L895 1266H70V1417H1090L1087 1282L244 147H1112V0Z" /> +<glyph unicode="[" glyph-name="bracketleft" horiz-adv-x="542" d="M508 -256H141V1477H508V1354H287V-137H508V-256Z" /> +<glyph unicode="\" glyph-name="backslash" horiz-adv-x="647" d="M623 -180H494L23 1417H150L623 -180Z" /> +<glyph unicode="]" glyph-name="bracketright" horiz-adv-x="542" d="M401 -256H35V-137H256V1354H35V1477H401V-256Z" /> +<glyph unicode="^" glyph-name="asciicircum" horiz-adv-x="1234" d="M1198 887L1016 889L616 1260L217 889L37 887L530 1417H702L1198 887Z" /> +<glyph unicode="_" glyph-name="underscore" horiz-adv-x="921" d="M926 -459H-20V-322H926V-459Z" /> +<glyph unicode="`" glyph-name="grave" horiz-adv-x="573" d="M510 1040H375L72 1352H250L510 1040Z" /> +<glyph unicode="a" glyph-name="a" horiz-adv-x="1024" d="M709 365V381Q693 416 636 443T516 471Q478 471 444 468T368 452T297 420T247 364T225 281Q225 193 282 149T430 104Q557 106 633 168T709 365ZM967 139Q964 75 924 29T819 -25Q769 -21 739 17T709 121Q655 +52 570 14T387 -25Q246 -25 168 52T86 270Q86 357 119 420T210 517T339 568T496 584Q544 584 604 567T709 522V582Q706 711 639 765T446 819Q352 819 283 791T150 700V852Q208 894 296 920T461 946Q850 946 850 584V176Q847 116 897 104H903Q936 104 967 139Z" +/> +<glyph unicode="b" glyph-name="b" horiz-adv-x="1062" d="M295 778V141Q376 106 479 106Q644 110 727 201T811 461Q811 626 726 720T479 815Q368 810 295 778ZM141 1417H295V920Q391 946 487 946Q711 946 838 815T965 461Q962 240 840 108T498 -25Q302 -25 141 51V1417Z" /> +<glyph unicode="c" glyph-name="c" horiz-adv-x="925" d="M852 33Q692 -25 561 -25Q342 -25 220 107T94 461Q94 684 220 815T571 946Q693 946 852 891V737Q763 780 715 795T580 815Q418 815 333 721T248 461Q248 293 331 202T580 106Q618 106 648 109T702 118T750 +134T798 156T852 184V33Z" /> +<glyph unicode="d" glyph-name="d" horiz-adv-x="1056" d="M764 778Q691 810 580 815Q418 815 333 721T248 461Q248 293 331 202T580 106Q683 106 764 141V778ZM918 1417V51Q757 -25 561 -25Q342 -25 220 107T94 461Q94 684 220 815T571 946Q668 946 764 920V1417H918Z" /> +<glyph unicode="e" glyph-name="e" horiz-adv-x="1015" d="M784 588Q784 685 711 750T520 815Q409 815 341 751T258 588H784ZM934 463H252V446Q252 284 332 199T557 113Q682 113 733 127T901 199V45Q722 -25 547 -25Q338 -25 216 107T94 453Q94 550 122 638T203 +795T338 905T520 946Q632 944 713 909T841 809T911 663T934 477V463Z" /> +<glyph unicode="f" glyph-name="f" horiz-adv-x="657" d="M610 1286H459Q420 1286 389 1237T358 1067V924H621V801H358V0H205V801H55V924H205V1051Q213 1414 461 1417H610V1286Z" /> +<glyph unicode="g" glyph-name="g" horiz-adv-x="927" d="M461 811Q378 811 320 752T262 610T320 469T461 410Q543 410 601 468T659 610T601 752T461 811ZM436 154Q548 154 652 118T828 6T901 -172Q901 -298 764 -395T436 -492Q250 -492 131 -396T12 -170Q12 -89 +62 -19T201 96Q90 158 90 244Q90 303 135 340T229 379Q141 467 141 606Q145 744 242 842T471 942Q534 942 602 922H862V807H713Q780 714 780 606Q780 467 687 369T461 270Q429 270 377 279T303 307Q231 307 231 246Q231 215 274 184T385 152Q403 154 436 154ZM434 +23Q307 23 236 -31T164 -172T235 -312T434 -365Q564 -365 645 -311T727 -172T646 -32T434 23Z" /> +<glyph unicode="h" glyph-name="h" horiz-adv-x="1067" d="M938 0H788V553Q788 682 739 746T571 813Q452 811 374 732T293 522V0H141V1417H293V797Q385 946 608 946Q720 946 796 894T905 757T938 561V0Z" /> +<glyph unicode="i" glyph-name="i" horiz-adv-x="436" d="M183 1417T219 1417T282 1388T309 1321T282 1255T219 1225T156 1254T129 1321T156 1387ZM295 0H141V924H295V0Z" /> +<glyph unicode="j" glyph-name="j" horiz-adv-x="440" d="M183 1417T219 1417T282 1388T309 1321T282 1255T219 1225T156 1254T129 1321T156 1387ZM299 -172Q299 -347 223 -426Q182 -472 121 -492L57 -377Q84 -367 113 -336Q141 -297 141 -172V924H299V-172Z" /> +<glyph unicode="k" glyph-name="k" horiz-adv-x="1024" d="M1001 0H788L297 440V0H141V1417H297V541L772 924H981L461 496L1001 0Z" /> +<glyph unicode="l" glyph-name="l" horiz-adv-x="409" d="M270 1417V0H119V1417H270Z" /> +<glyph unicode="m" glyph-name="m" horiz-adv-x="1646" d="M1516 0H1372V553Q1372 678 1327 744T1171 811Q1040 811 972 734T901 522V0H756V553Q756 682 712 746T555 811H547Q437 811 367 730T293 522V0H141V926H293V801Q345 865 428 905T600 946Q697 946 771 +895T883 760Q939 846 1025 896T1214 946Q1296 946 1356 914T1450 826T1500 703T1516 557V0Z" /> +<glyph unicode="n" glyph-name="n" horiz-adv-x="1067" d="M938 0H788V553Q788 682 738 746T571 811Q448 811 372 733T293 522V0H141V926H293V799Q346 873 429 909T608 946Q776 946 857 840T938 557V0Z" /> +<glyph unicode="o" glyph-name="o" horiz-adv-x="1062" d="M813 461Q812 552 780 629T681 757T528 809Q436 808 372 760T278 637T248 467Q248 421 255 377T281 284T330 200T411 140T528 115Q653 115 732 217T813 461ZM965 461Q964 329 914 221T764 45T528 -25Q333 +-21 214 121T92 461Q94 672 210 809T528 946Q618 946 692 918T816 843T900 733T949 602T965 461Z" /> +<glyph unicode="p" glyph-name="p" horiz-adv-x="1056" d="M289 145Q363 114 473 109Q634 109 719 203T805 463Q805 631 722 722T473 817Q367 817 289 782V145ZM135 -494V872Q293 948 492 948Q710 948 832 816T958 463Q958 240 832 109T481 -23Q389 -23 289 4V-494H135Z" /> +<glyph unicode="q" glyph-name="q" horiz-adv-x="1054" d="M762 145V782Q684 817 578 817Q412 814 329 723T246 463Q246 298 331 204T578 109Q688 114 762 145ZM915 -494H762V4Q661 -23 569 -23Q345 -23 219 108T92 463Q95 684 217 816T559 948Q758 948 915 872V-494Z" /> +<glyph unicode="r" glyph-name="r" horiz-adv-x="757" d="M664 700L659 702Q633 735 568 771T467 807H463Q411 803 375 773T323 700T301 624T295 563V0H141V926H295V801Q327 864 383 899T512 938Q565 938 626 911T729 840L664 700Z" /> +<glyph unicode="s" glyph-name="s" horiz-adv-x="903" d="M817 256Q817 194 794 145T732 64T642 13T537 -16T426 -25Q297 -25 88 31V199Q164 162 182 154T246 130T329 111T430 104Q473 104 510 110T585 130T645 174T670 244Q670 286 649 314T593 357T515 382T430 +401L373 414Q244 439 175 497T102 674Q102 749 132 803T216 888T331 932T465 946Q644 946 772 897V743Q710 772 674 787T602 808T485 817Q442 817 404 812T328 792T266 750T240 680Q240 656 250 637T278 605T317 582T364 565T414 553T461 543L512 528Q582 515 631 +498T726 450T794 371T817 256Z" /> +<glyph unicode="t" glyph-name="t" horiz-adv-x="706" d="M659 10Q580 -25 498 -29Q327 -29 252 50T176 303V803H68V924H176L262 1188H328V924H600V803H328V303Q328 192 361 147T498 102Q574 102 659 141V10Z" /> +<glyph unicode="u" glyph-name="u" horiz-adv-x="1073" d="M932 0H774V121Q721 58 637 17T465 -25Q299 -25 215 83T131 365V924H281V369Q281 243 331 177T500 111Q636 111 705 188T774 401V924H932V0Z" /> +<glyph unicode="v" glyph-name="v" d="M944 924L494 -29L43 924H184L494 276L803 924H944Z" /> +<glyph unicode="w" glyph-name="w" horiz-adv-x="1363" d="M1305 924L975 -29L684 659L385 -29L61 924H193L410 297L684 946L958 297L1174 924H1305Z" /> +<glyph unicode="x" glyph-name="x" horiz-adv-x="968" d="M930 0H770L481 373L193 0H33L410 485L63 924H229L492 586L750 924H913L563 477L930 0Z" /> +<glyph unicode="y" glyph-name="y" horiz-adv-x="970" d="M936 924L381 -354Q344 -414 288 -452T174 -494L123 -389Q157 -389 207 -355T276 -276L434 96L31 924H176L510 248L795 924H936Z" /> +<glyph unicode="z" glyph-name="z" horiz-adv-x="921" d="M840 0H74V154L662 788H94V924H840V770L254 135H840V0Z" /> +<glyph unicode="{" glyph-name="braceleft" horiz-adv-x="731" d="M702 -317H659Q447 -317 367 -246Q301 -180 301 27V256Q301 402 246 463Q195 520 55 520H12V641H55Q192 641 246 700Q301 758 301 901V1133Q301 1342 369 1407Q445 1474 659 1477H702V1358H653Q510 +1358 473 1313Q433 1270 430 1128V891Q430 736 391 684Q356 619 250 580Q360 544 391 483Q430 422 430 270V31Q430 -106 473 -152Q511 -194 653 -197H702V-317Z" /> +<glyph unicode="|" glyph-name="bar" horiz-adv-x="430" d="M289 -459H141V1483H289V-459Z" /> +<glyph unicode="}" glyph-name="braceright" horiz-adv-x="727" d="M715 520H674Q532 520 481 463Q428 404 428 256V27Q428 -176 358 -246Q284 -317 72 -317H29V-197H78Q216 -197 254 -154Q299 -109 299 31V270Q299 422 336 481Q370 545 483 580Q418 601 385 625T336 +684Q299 734 299 891V1128Q299 1272 254 1311Q217 1355 78 1358H29V1477H72Q282 1477 358 1407Q428 1344 428 1133V901Q428 757 481 698Q540 641 674 641H715V520Z" /> +<glyph unicode="~" glyph-name="asciitilde" horiz-adv-x="1277" d="M1167 537Q1096 477 1008 438Q926 413 858 410Q760 410 645 463L632 470Q619 476 596 485T544 503T477 519T403 526H397Q311 526 246 494Q190 471 106 385V526Q168 578 264 623Q340 651 418 +651Q454 651 535 631T657 590Q795 535 877 535Q937 535 1028 567Q1125 636 1167 674V537Z" /> +<hkern g1="parenleft" g2="J" k="-135" /> +<hkern g1="hyphen" g2="T" k="143" /> +<hkern g1="hyphen" g2="V" k="106" /> +<hkern g1="hyphen" g2="W" k="74" /> +<hkern g1="hyphen" g2="X" k="55" /> +<hkern g1="hyphen" g2="Y" k="131" /> +<hkern g1="A" g2="comma" k="-33" /> +<hkern g1="A" g2="period" k="-39" /> +<hkern g1="A" g2="A" k="-41" /> +<hkern g1="A" g2="C" k="41" /> +<hkern g1="A" g2="G" k="41" /> +<hkern g1="A" g2="O" k="39" /> +<hkern g1="A" g2="Q" k="39" /> +<hkern g1="A" g2="T" k="211" /> +<hkern g1="A" g2="U" k="39" /> +<hkern g1="A" g2="V" k="178" /> +<hkern g1="A" g2="W" k="141" /> +<hkern g1="A" g2="Y" k="190" /> +<hkern g1="A" g2="d" k="35" /> +<hkern g1="A" g2="f" k="51" /> +<hkern g1="A" g2="g" k="-25" /> +<hkern g1="A" g2="t" k="39" /> +<hkern g1="A" g2="v" k="88" /> +<hkern g1="A" g2="w" k="70" /> +<hkern g1="A" g2="y" k="82" /> +<hkern g1="A" g2="guillemotleft" k="33" /> +<hkern g1="A" g2="Adieresis" k="-41" /> +<hkern g1="A" g2="Ccedilla" k="41" /> +<hkern g1="A" g2="Ograve" k="39" /> +<hkern g1="A" g2="Oacute" k="39" /> +<hkern g1="A" g2="Ocircumflex" k="39" /> +<hkern g1="A" g2="Otilde" k="39" /> +<hkern g1="A" g2="Odieresis" k="39" /> +<hkern g1="A" g2="Ugrave" k="39" /> +<hkern g1="A" g2="Uacute" k="39" /> +<hkern g1="A" g2="Ucircumflex" k="39" /> +<hkern g1="A" g2="Udieresis" k="39" /> +<hkern g1="A" g2="Yacute" k="190" /> +<hkern g1="A" g2="ograve" k="29" /> +<hkern g1="A" g2="oacute" k="29" /> +<hkern g1="A" g2="ocircumflex" k="29" /> +<hkern g1="A" g2="otilde" k="25" /> +<hkern g1="A" g2="odieresis" k="20" /> +<hkern g1="A" g2="udieresis" k="20" /> +<hkern g1="A" g2="Ydieresis" k="190" /> +<hkern g1="A" g2="quoteright" k="104" /> +<hkern g1="A" g2="quotedblright" k="104" /> +<hkern g1="A" g2="guilsinglleft" k="33" /> +<hkern g1="B" g2="hyphen" k="-23" /> +<hkern g1="B" g2="V" k="51" /> +<hkern g1="B" g2="W" k="41" /> +<hkern g1="B" g2="Y" k="70" /> +<hkern g1="B" g2="y" k="29" /> +<hkern g1="C" g2="hyphen" k="307" /> +<hkern g1="C" g2="O" k="61" /> +<hkern g1="C" g2="v" k="184" /> +<hkern g1="C" g2="w" k="139" /> +<hkern g1="C" g2="y" k="182" /> +<hkern g1="C" g2="Oacute" k="61" /> +<hkern g1="C" g2="Odieresis" k="61" /> +<hkern g1="D" g2="A" k="47" /> +<hkern g1="D" g2="T" k="125" /> +<hkern g1="D" g2="V" k="63" /> +<hkern g1="D" g2="W" k="45" /> +<hkern g1="D" g2="X" k="86" /> +<hkern g1="D" g2="Y" k="98" /> +<hkern g1="D" g2="Agrave" k="47" /> +<hkern g1="D" g2="Aacute" k="47" /> +<hkern g1="D" g2="Acircumflex" k="47" /> +<hkern g1="D" g2="Atilde" k="47" /> +<hkern g1="D" g2="Adieresis" k="47" /> +<hkern g1="D" g2="Aring" k="47" /> +<hkern g1="E" g2="G" k="35" /> +<hkern g1="E" g2="c" k="55" /> +<hkern g1="E" g2="d" k="74" /> +<hkern g1="E" g2="v" k="39" /> +<hkern g1="E" g2="w" k="39" /> +<hkern g1="E" g2="y" k="31" /> +<hkern g1="F" g2="comma" k="199" /> +<hkern g1="F" g2="hyphen" k="195" /> +<hkern g1="F" g2="period" k="195" /> +<hkern g1="F" g2="A" k="152" /> +<hkern g1="F" g2="O" k="29" /> +<hkern g1="F" g2="a" k="76" /> +<hkern g1="F" g2="e" k="76" /> +<hkern g1="F" g2="o" k="72" /> +<hkern g1="F" g2="r" k="59" /> +<hkern g1="F" g2="u" k="51" /> +<hkern g1="F" g2="y" k="29" /> +<hkern g1="F" g2="Agrave" k="152" /> +<hkern g1="F" g2="Aacute" k="152" /> +<hkern g1="F" g2="Acircumflex" k="152" /> +<hkern g1="F" g2="Atilde" k="152" /> +<hkern g1="F" g2="Adieresis" k="152" /> +<hkern g1="F" g2="Aring" k="152" /> +<hkern g1="F" g2="Odieresis" k="29" /> +<hkern g1="F" g2="Oslash" k="39" /> +<hkern g1="F" g2="agrave" k="82" /> +<hkern g1="F" g2="aacute" k="86" /> +<hkern g1="F" g2="acircumflex" k="84" /> +<hkern g1="F" g2="atilde" k="74" /> +<hkern g1="F" g2="adieresis" k="74" /> +<hkern g1="F" g2="aring" k="74" /> +<hkern g1="F" g2="ae" k="76" /> +<hkern g1="F" g2="egrave" k="84" /> +<hkern g1="F" g2="eacute" k="86" /> +<hkern g1="F" g2="ecircumflex" k="86" /> +<hkern g1="F" g2="edieresis" k="78" /> +<hkern g1="F" g2="ograve" k="82" /> +<hkern g1="F" g2="oacute" k="84" /> +<hkern g1="F" g2="ocircumflex" k="82" /> +<hkern g1="F" g2="otilde" k="76" /> +<hkern g1="F" g2="odieresis" k="74" /> +<hkern g1="F" g2="oslash" k="80" /> +<hkern g1="F" g2="ugrave" k="63" /> +<hkern g1="F" g2="uacute" k="66" /> +<hkern g1="F" g2="ucircumflex" k="63" /> +<hkern g1="F" g2="udieresis" k="57" /> +<hkern g1="F" g2="oe" k="70" /> +<hkern g1="G" g2="T" k="31" /> +<hkern g1="G" g2="V" k="41" /> +<hkern g1="G" g2="W" k="41" /> +<hkern g1="G" g2="Y" k="43" /> +<hkern g1="K" g2="hyphen" k="98" /> +<hkern g1="K" g2="A" k="-49" /> +<hkern g1="K" g2="C" k="117" /> +<hkern g1="K" g2="G" k="117" /> +<hkern g1="K" g2="O" k="113" /> +<hkern g1="K" g2="Q" k="115" /> +<hkern g1="K" g2="U" k="43" /> +<hkern g1="K" g2="Y" k="-20" /> +<hkern g1="K" g2="a" k="29" /> +<hkern g1="K" g2="e" k="78" /> +<hkern g1="K" g2="o" k="82" /> +<hkern g1="K" g2="u" k="70" /> +<hkern g1="K" g2="v" k="201" /> +<hkern g1="K" g2="w" k="152" /> +<hkern g1="K" g2="y" k="182" /> +<hkern g1="K" g2="Adieresis" k="-49" /> +<hkern g1="K" g2="Aring" k="-49" /> +<hkern g1="K" g2="Ograve" k="113" /> +<hkern g1="K" g2="Oacute" k="113" /> +<hkern g1="K" g2="Ocircumflex" k="113" /> +<hkern g1="K" g2="Otilde" k="113" /> +<hkern g1="K" g2="Odieresis" k="113" /> +<hkern g1="K" g2="adieresis" k="35" /> +<hkern g1="K" g2="aring" k="39" /> +<hkern g1="K" g2="ae" k="29" /> +<hkern g1="K" g2="egrave" k="92" /> +<hkern g1="K" g2="eacute" k="94" /> +<hkern g1="K" g2="ecircumflex" k="92" /> +<hkern g1="K" g2="edieresis" k="86" /> +<hkern g1="K" g2="oacute" k="98" /> +<hkern g1="K" g2="odieresis" k="88" /> +<hkern g1="K" g2="udieresis" k="76" /> +<hkern g1="K" g2="OE" k="135" /> +<hkern g1="K" g2="oe" k="82" /> +<hkern g1="L" g2="hyphen" k="211" /> +<hkern g1="L" g2="A" k="-41" /> +<hkern g1="L" g2="C" k="135" /> +<hkern g1="L" g2="G" k="133" /> +<hkern g1="L" g2="O" k="129" /> +<hkern g1="L" g2="T" k="264" /> +<hkern g1="L" g2="U" k="102" /> +<hkern g1="L" g2="V" k="295" /> +<hkern g1="L" g2="W" k="221" /> +<hkern g1="L" g2="Y" k="244" /> +<hkern g1="L" g2="u" k="55" /> +<hkern g1="L" g2="y" k="190" /> +<hkern g1="L" g2="Aacute" k="-41" /> +<hkern g1="L" g2="Adieresis" k="-41" /> +<hkern g1="L" g2="Aring" k="-41" /> +<hkern g1="L" g2="AE" k="-43" /> +<hkern g1="L" g2="Ccedilla" k="137" /> +<hkern g1="L" g2="Ograve" k="129" /> +<hkern g1="L" g2="Oacute" k="129" /> +<hkern g1="L" g2="Ocircumflex" k="129" /> +<hkern g1="L" g2="Otilde" k="129" /> +<hkern g1="L" g2="Odieresis" k="129" /> +<hkern g1="L" g2="Udieresis" k="104" /> +<hkern g1="L" g2="udieresis" k="63" /> +<hkern g1="L" g2="quoteright" k="209" /> +<hkern g1="L" g2="quotedblright" k="209" /> +<hkern g1="N" g2="aacute" k="20" /> +<hkern g1="N" g2="eacute" k="23" /> +<hkern g1="N" g2="oacute" k="20" /> +<hkern g1="O" g2="comma" k="59" /> +<hkern g1="O" g2="period" k="49" /> +<hkern g1="O" g2="A" k="45" /> +<hkern g1="O" g2="T" k="117" /> +<hkern g1="O" g2="V" k="63" /> +<hkern g1="O" g2="W" k="49" /> +<hkern g1="O" g2="X" k="78" /> +<hkern g1="O" g2="Y" k="94" /> +<hkern g1="O" g2="Agrave" k="45" /> +<hkern g1="O" g2="Aacute" k="45" /> +<hkern g1="O" g2="Acircumflex" k="45" /> +<hkern g1="O" g2="Atilde" k="45" /> +<hkern g1="O" g2="Adieresis" k="45" /> +<hkern g1="O" g2="Aring" k="45" /> +<hkern g1="O" g2="AE" k="51" /> +<hkern g1="P" g2="comma" k="248" /> +<hkern g1="P" g2="hyphen" k="244" /> +<hkern g1="P" g2="period" k="244" /> +<hkern g1="P" g2="A" k="139" /> +<hkern g1="P" g2="a" k="66" /> +<hkern g1="P" g2="e" k="82" /> +<hkern g1="P" g2="i" k="37" /> +<hkern g1="P" g2="n" k="43" /> +<hkern g1="P" g2="o" k="80" /> +<hkern g1="P" g2="r" k="43" /> +<hkern g1="P" g2="s" k="47" /> +<hkern g1="P" g2="u" k="35" /> +<hkern g1="P" g2="Agrave" k="139" /> +<hkern g1="P" g2="Aacute" k="139" /> +<hkern g1="P" g2="Acircumflex" k="139" /> +<hkern g1="P" g2="Atilde" k="139" /> +<hkern g1="P" g2="Adieresis" k="139" /> +<hkern g1="P" g2="Aring" k="139" /> +<hkern g1="P" g2="AE" k="154" /> +<hkern g1="P" g2="agrave" k="74" /> +<hkern g1="P" g2="aacute" k="74" /> +<hkern g1="P" g2="acircumflex" k="63" /> +<hkern g1="P" g2="atilde" k="53" /> +<hkern g1="P" g2="adieresis" k="59" /> +<hkern g1="P" g2="aring" k="70" /> +<hkern g1="P" g2="ae" k="66" /> +<hkern g1="P" g2="egrave" k="94" /> +<hkern g1="P" g2="eacute" k="94" /> +<hkern g1="P" g2="ecircumflex" k="84" /> +<hkern g1="P" g2="edieresis" k="78" /> +<hkern g1="P" g2="ograve" k="92" /> +<hkern g1="P" g2="oacute" k="92" /> +<hkern g1="P" g2="ocircumflex" k="82" /> +<hkern g1="P" g2="otilde" k="74" /> +<hkern g1="P" g2="odieresis" k="74" /> +<hkern g1="P" g2="oslash" k="90" /> +<hkern g1="P" g2="ugrave" k="49" /> +<hkern g1="P" g2="uacute" k="49" /> +<hkern g1="P" g2="ucircumflex" k="43" /> +<hkern g1="P" g2="udieresis" k="39" /> +<hkern g1="P" g2="oe" k="78" /> +<hkern g1="Q" g2="A" k="43" /> +<hkern g1="Q" g2="Adieresis" k="43" /> +<hkern g1="R" g2="hyphen" k="29" /> +<hkern g1="R" g2="C" k="20" /> +<hkern g1="R" g2="G" k="20" /> +<hkern g1="R" g2="O" k="20" /> +<hkern g1="R" g2="Q" k="20" /> +<hkern g1="R" g2="T" k="78" /> +<hkern g1="R" g2="V" k="59" /> +<hkern g1="R" g2="W" k="47" /> +<hkern g1="R" g2="Y" k="76" /> +<hkern g1="R" g2="e" k="27" /> +<hkern g1="R" g2="o" k="29" /> +<hkern g1="R" g2="y" k="33" /> +<hkern g1="R" g2="Ccedilla" k="20" /> +<hkern g1="R" g2="Oacute" k="20" /> +<hkern g1="R" g2="Odieresis" k="20" /> +<hkern g1="R" g2="eacute" k="47" /> +<hkern g1="R" g2="oacute" k="51" /> +<hkern g1="R" g2="odieresis" k="39" /> +<hkern g1="R" g2="uacute" k="39" /> +<hkern g1="R" g2="udieresis" k="29" /> +<hkern g1="R" g2="OE" k="25" /> +<hkern g1="R" g2="oe" k="29" /> +<hkern g1="R" g2="quotesinglbase" k="-27" /> +<hkern g1="R" g2="quotedblbase" k="-27" /> +<hkern g1="S" g2="S" k="29" /> +<hkern g1="S" g2="T" k="33" /> +<hkern g1="S" g2="V" k="43" /> +<hkern g1="S" g2="W" k="47" /> +<hkern g1="S" g2="Y" k="41" /> +<hkern g1="S" g2="t" k="35" /> +<hkern g1="S" g2="quoteright" k="37" /> +<hkern g1="T" g2="comma" k="147" /> +<hkern g1="T" g2="hyphen" k="141" /> +<hkern g1="T" g2="period" k="141" /> +<hkern g1="T" g2="colon" k="141" /> +<hkern g1="T" g2="semicolon" k="143" /> +<hkern g1="T" g2="A" k="211" /> +<hkern g1="T" g2="C" k="117" /> +<hkern g1="T" g2="G" k="117" /> +<hkern g1="T" g2="H" k="23" /> +<hkern g1="T" g2="O" k="115" /> +<hkern g1="T" g2="S" k="41" /> +<hkern g1="T" g2="T" k="-51" /> +<hkern g1="T" g2="V" k="-39" /> +<hkern g1="T" g2="W" k="-27" /> +<hkern g1="T" g2="Y" k="-45" /> +<hkern g1="T" g2="a" k="242" /> +<hkern g1="T" g2="c" k="240" /> +<hkern g1="T" g2="e" k="240" /> +<hkern g1="T" g2="g" k="238" /> +<hkern g1="T" g2="h" k="27" /> +<hkern g1="T" g2="o" k="240" /> +<hkern g1="T" g2="r" k="236" /> +<hkern g1="T" g2="s" k="244" /> +<hkern g1="T" g2="u" k="238" /> +<hkern g1="T" g2="v" k="258" /> +<hkern g1="T" g2="w" k="256" /> +<hkern g1="T" g2="y" k="250" /> +<hkern g1="T" g2="z" k="248" /> +<hkern g1="T" g2="guillemotleft" k="248" /> +<hkern g1="T" g2="Agrave" k="211" /> +<hkern g1="T" g2="Aacute" k="211" /> +<hkern g1="T" g2="Acircumflex" k="211" /> +<hkern g1="T" g2="Atilde" k="211" /> +<hkern g1="T" g2="Adieresis" k="211" /> +<hkern g1="T" g2="Aring" k="211" /> +<hkern g1="T" g2="AE" k="223" /> +<hkern g1="T" g2="Ograve" k="115" /> +<hkern g1="T" g2="Oacute" k="115" /> +<hkern g1="T" g2="Ocircumflex" k="115" /> +<hkern g1="T" g2="Otilde" k="115" /> +<hkern g1="T" g2="Odieresis" k="115" /> +<hkern g1="T" g2="Oslash" k="123" /> +<hkern g1="T" g2="agrave" k="147" /> +<hkern g1="T" g2="aacute" k="238" /> +<hkern g1="T" g2="acircumflex" k="178" /> +<hkern g1="T" g2="atilde" k="113" /> +<hkern g1="T" g2="adieresis" k="119" /> +<hkern g1="T" g2="aring" k="115" /> +<hkern g1="T" g2="ae" k="242" /> +<hkern g1="T" g2="egrave" k="182" /> +<hkern g1="T" g2="eacute" k="244" /> +<hkern g1="T" g2="ecircumflex" k="199" /> +<hkern g1="T" g2="edieresis" k="137" /> +<hkern g1="T" g2="ograve" k="190" /> +<hkern g1="T" g2="oacute" k="248" /> +<hkern g1="T" g2="ocircumflex" k="203" /> +<hkern g1="T" g2="otilde" k="147" /> +<hkern g1="T" g2="odieresis" k="133" /> +<hkern g1="T" g2="oslash" k="244" /> +<hkern g1="T" g2="ugrave" k="186" /> +<hkern g1="T" g2="uacute" k="242" /> +<hkern g1="T" g2="ucircumflex" k="201" /> +<hkern g1="T" g2="udieresis" k="133" /> +<hkern g1="T" g2="OE" k="135" /> +<hkern g1="T" g2="oe" k="238" /> +<hkern g1="T" g2="guilsinglleft" k="248" /> +<hkern g1="U" g2="comma" k="45" /> +<hkern g1="U" g2="period" k="35" /> +<hkern g1="U" g2="A" k="41" /> +<hkern g1="U" g2="Aacute" k="41" /> +<hkern g1="U" g2="Acircumflex" k="41" /> +<hkern g1="U" g2="Atilde" k="41" /> +<hkern g1="U" g2="Adieresis" k="41" /> +<hkern g1="U" g2="Aring" k="41" /> +<hkern g1="U" g2="AE" k="47" /> +<hkern g1="V" g2="comma" k="168" /> +<hkern g1="V" g2="hyphen" k="104" /> +<hkern g1="V" g2="period" k="160" /> +<hkern g1="V" g2="colon" k="76" /> +<hkern g1="V" g2="semicolon" k="82" /> +<hkern g1="V" g2="A" k="178" /> +<hkern g1="V" g2="C" k="63" /> +<hkern g1="V" g2="G" k="63" /> +<hkern g1="V" g2="O" k="63" /> +<hkern g1="V" g2="S" k="29" /> +<hkern g1="V" g2="T" k="-37" /> +<hkern g1="V" g2="a" k="160" /> +<hkern g1="V" g2="e" k="160" /> +<hkern g1="V" g2="g" k="168" /> +<hkern g1="V" g2="i" k="27" /> +<hkern g1="V" g2="o" k="158" /> +<hkern g1="V" g2="r" k="133" /> +<hkern g1="V" g2="u" k="129" /> +<hkern g1="V" g2="y" k="94" /> +<hkern g1="V" g2="guillemotleft" k="172" /> +<hkern g1="V" g2="Agrave" k="178" /> +<hkern g1="V" g2="Aacute" k="178" /> +<hkern g1="V" g2="Acircumflex" k="178" /> +<hkern g1="V" g2="Atilde" k="178" /> +<hkern g1="V" g2="Adieresis" k="178" /> +<hkern g1="V" g2="Aring" k="178" /> +<hkern g1="V" g2="AE" k="190" /> +<hkern g1="V" g2="Ograve" k="63" /> +<hkern g1="V" g2="Oacute" k="63" /> +<hkern g1="V" g2="Ocircumflex" k="63" /> +<hkern g1="V" g2="Otilde" k="63" /> +<hkern g1="V" g2="Odieresis" k="63" /> +<hkern g1="V" g2="Oslash" k="70" /> +<hkern g1="V" g2="agrave" k="137" /> +<hkern g1="V" g2="aacute" k="162" /> +<hkern g1="V" g2="acircumflex" k="131" /> +<hkern g1="V" g2="atilde" k="100" /> +<hkern g1="V" g2="adieresis" k="113" /> +<hkern g1="V" g2="aring" k="109" /> +<hkern g1="V" g2="ae" k="160" /> +<hkern g1="V" g2="egrave" k="156" /> +<hkern g1="V" g2="eacute" k="168" /> +<hkern g1="V" g2="ecircumflex" k="143" /> +<hkern g1="V" g2="edieresis" k="125" /> +<hkern g1="V" g2="ograve" k="158" /> +<hkern g1="V" g2="oacute" k="168" /> +<hkern g1="V" g2="ocircumflex" k="145" /> +<hkern g1="V" g2="otilde" k="125" /> +<hkern g1="V" g2="odieresis" k="121" /> +<hkern g1="V" g2="oslash" k="166" /> +<hkern g1="V" g2="ugrave" k="135" /> +<hkern g1="V" g2="uacute" k="141" /> +<hkern g1="V" g2="ucircumflex" k="127" /> +<hkern g1="V" g2="udieresis" k="109" /> +<hkern g1="V" g2="OE" k="66" /> +<hkern g1="V" g2="oe" k="156" /> +<hkern g1="V" g2="quoteright" k="-20" /> +<hkern g1="V" g2="quotedblright" k="-20" /> +<hkern g1="V" g2="guilsinglleft" k="172" /> +<hkern g1="W" g2="comma" k="119" /> +<hkern g1="W" g2="hyphen" k="72" /> +<hkern g1="W" g2="period" k="111" /> +<hkern g1="W" g2="colon" k="55" /> +<hkern g1="W" g2="semicolon" k="59" /> +<hkern g1="W" g2="A" k="139" /> +<hkern g1="W" g2="C" k="47" /> +<hkern g1="W" g2="G" k="47" /> +<hkern g1="W" g2="O" k="45" /> +<hkern g1="W" g2="S" k="23" /> +<hkern g1="W" g2="T" k="-27" /> +<hkern g1="W" g2="a" k="117" /> +<hkern g1="W" g2="e" k="113" /> +<hkern g1="W" g2="g" k="121" /> +<hkern g1="W" g2="i" k="25" /> +<hkern g1="W" g2="o" k="113" /> +<hkern g1="W" g2="r" k="94" /> +<hkern g1="W" g2="u" k="92" /> +<hkern g1="W" g2="y" k="68" /> +<hkern g1="W" g2="guillemotleft" k="121" /> +<hkern g1="W" g2="Agrave" k="139" /> +<hkern g1="W" g2="Aacute" k="139" /> +<hkern g1="W" g2="Acircumflex" k="139" /> +<hkern g1="W" g2="Atilde" k="139" /> +<hkern g1="W" g2="Adieresis" k="139" /> +<hkern g1="W" g2="Aring" k="139" /> +<hkern g1="W" g2="AE" k="150" /> +<hkern g1="W" g2="Ograve" k="45" /> +<hkern g1="W" g2="Oacute" k="45" /> +<hkern g1="W" g2="Ocircumflex" k="45" /> +<hkern g1="W" g2="Otilde" k="45" /> +<hkern g1="W" g2="Odieresis" k="45" /> +<hkern g1="W" g2="Oslash" k="51" /> +<hkern g1="W" g2="agrave" k="117" /> +<hkern g1="W" g2="aacute" k="127" /> +<hkern g1="W" g2="acircumflex" k="106" /> +<hkern g1="W" g2="atilde" k="84" /> +<hkern g1="W" g2="adieresis" k="94" /> +<hkern g1="W" g2="aring" k="98" /> +<hkern g1="W" g2="ae" k="117" /> +<hkern g1="W" g2="egrave" k="121" /> +<hkern g1="W" g2="eacute" k="127" /> +<hkern g1="W" g2="ecircumflex" k="113" /> +<hkern g1="W" g2="edieresis" k="98" /> +<hkern g1="W" g2="ograve" k="123" /> +<hkern g1="W" g2="oacute" k="127" /> +<hkern g1="W" g2="ocircumflex" k="113" /> +<hkern g1="W" g2="otilde" k="98" /> +<hkern g1="W" g2="odieresis" k="98" /> +<hkern g1="W" g2="oslash" k="119" /> +<hkern g1="W" g2="ugrave" k="104" /> +<hkern g1="W" g2="uacute" k="109" /> +<hkern g1="W" g2="ucircumflex" k="98" /> +<hkern g1="W" g2="udieresis" k="86" /> +<hkern g1="W" g2="oe" k="111" /> +<hkern g1="W" g2="quoteright" k="-20" /> +<hkern g1="W" g2="quotedblright" k="-20" /> +<hkern g1="W" g2="guilsinglleft" k="121" /> +<hkern g1="X" g2="hyphen" k="55" /> +<hkern g1="X" g2="A" k="-31" /> +<hkern g1="X" g2="C" k="74" /> +<hkern g1="X" g2="G" k="74" /> +<hkern g1="X" g2="O" k="70" /> +<hkern g1="X" g2="Q" k="72" /> +<hkern g1="X" g2="e" k="51" /> +<hkern g1="X" g2="o" k="55" /> +<hkern g1="X" g2="u" k="47" /> +<hkern g1="X" g2="y" k="139" /> +<hkern g1="X" g2="Adieresis" k="-31" /> +<hkern g1="X" g2="Aring" k="-31" /> +<hkern g1="X" g2="Ograve" k="70" /> +<hkern g1="X" g2="Oacute" k="70" /> +<hkern g1="X" g2="Ocircumflex" k="70" /> +<hkern g1="X" g2="Otilde" k="70" /> +<hkern g1="X" g2="Odieresis" k="70" /> +<hkern g1="X" g2="adieresis" k="25" /> +<hkern g1="X" g2="egrave" k="70" /> +<hkern g1="X" g2="eacute" k="72" /> +<hkern g1="X" g2="ecircumflex" k="68" /> +<hkern g1="X" g2="edieresis" k="59" /> +<hkern g1="X" g2="ograve" k="72" /> +<hkern g1="X" g2="oacute" k="74" /> +<hkern g1="X" g2="ocircumflex" k="70" /> +<hkern g1="X" g2="otilde" k="63" /> +<hkern g1="X" g2="odieresis" k="61" /> +<hkern g1="X" g2="udieresis" k="55" /> +<hkern g1="X" g2="OE" k="84" /> +<hkern g1="X" g2="oe" k="55" /> +<hkern g1="Y" g2="comma" k="135" /> +<hkern g1="Y" g2="hyphen" k="131" /> +<hkern g1="Y" g2="period" k="131" /> +<hkern g1="Y" g2="colon" k="109" /> +<hkern g1="Y" g2="semicolon" k="113" /> +<hkern g1="Y" g2="A" k="190" /> +<hkern g1="Y" g2="C" k="94" /> +<hkern g1="Y" g2="G" k="94" /> +<hkern g1="Y" g2="O" k="94" /> +<hkern g1="Y" g2="S" k="43" /> +<hkern g1="Y" g2="T" k="-47" /> +<hkern g1="Y" g2="a" k="201" /> +<hkern g1="Y" g2="d" k="236" /> +<hkern g1="Y" g2="e" k="211" /> +<hkern g1="Y" g2="g" k="209" /> +<hkern g1="Y" g2="i" k="25" /> +<hkern g1="Y" g2="o" k="209" /> +<hkern g1="Y" g2="p" k="190" /> +<hkern g1="Y" g2="q" k="209" /> +<hkern g1="Y" g2="u" k="186" /> +<hkern g1="Y" g2="v" k="164" /> +<hkern g1="Y" g2="guillemotleft" k="227" /> +<hkern g1="Y" g2="Agrave" k="190" /> +<hkern g1="Y" g2="Aacute" k="190" /> +<hkern g1="Y" g2="Acircumflex" k="190" /> +<hkern g1="Y" g2="Atilde" k="190" /> +<hkern g1="Y" g2="Adieresis" k="190" /> +<hkern g1="Y" g2="Aring" k="190" /> +<hkern g1="Y" g2="AE" k="201" /> +<hkern g1="Y" g2="Ograve" k="94" /> +<hkern g1="Y" g2="Oacute" k="94" /> +<hkern g1="Y" g2="Ocircumflex" k="94" /> +<hkern g1="Y" g2="Otilde" k="94" /> +<hkern g1="Y" g2="Odieresis" k="94" /> +<hkern g1="Y" g2="Oslash" k="98" /> +<hkern g1="Y" g2="agrave" k="145" /> +<hkern g1="Y" g2="aacute" k="199" /> +<hkern g1="Y" g2="acircumflex" k="158" /> +<hkern g1="Y" g2="atilde" k="119" /> +<hkern g1="Y" g2="adieresis" k="129" /> +<hkern g1="Y" g2="aring" k="115" /> +<hkern g1="Y" g2="ae" k="201" /> +<hkern g1="Y" g2="egrave" k="178" /> +<hkern g1="Y" g2="eacute" k="213" /> +<hkern g1="Y" g2="ecircumflex" k="178" /> +<hkern g1="Y" g2="edieresis" k="147" /> +<hkern g1="Y" g2="ograve" k="186" /> +<hkern g1="Y" g2="oacute" k="217" /> +<hkern g1="Y" g2="ocircumflex" k="180" /> +<hkern g1="Y" g2="otilde" k="150" /> +<hkern g1="Y" g2="odieresis" k="145" /> +<hkern g1="Y" g2="oslash" k="215" /> +<hkern g1="Y" g2="ugrave" k="174" /> +<hkern g1="Y" g2="uacute" k="193" /> +<hkern g1="Y" g2="ucircumflex" k="168" /> +<hkern g1="Y" g2="udieresis" k="139" /> +<hkern g1="Y" g2="oe" k="209" /> +<hkern g1="Y" g2="guilsinglleft" k="229" /> +<hkern g1="Z" g2="O" k="86" /> +<hkern g1="Z" g2="v" k="168" /> +<hkern g1="Z" g2="y" k="158" /> +<hkern g1="Z" g2="Odieresis" k="86" /> +<hkern g1="a" g2="t" k="35" /> +<hkern g1="a" g2="v" k="70" /> +<hkern g1="a" g2="w" k="59" /> +<hkern g1="a" g2="y" k="63" /> +<hkern g1="b" g2="v" k="49" /> +<hkern g1="b" g2="w" k="39" /> +<hkern g1="b" g2="y" k="43" /> +<hkern g1="e" g2="t" k="27" /> +<hkern g1="e" g2="v" k="39" /> +<hkern g1="e" g2="w" k="33" /> +<hkern g1="e" g2="y" k="31" /> +<hkern g1="f" g2="comma" k="68" /> +<hkern g1="f" g2="hyphen" k="61" /> +<hkern g1="f" g2="period" k="61" /> +<hkern g1="f" g2="a" k="33" /> +<hkern g1="f" g2="e" k="63" /> +<hkern g1="f" g2="o" k="61" /> +<hkern g1="f" g2="s" k="29" /> +<hkern g1="f" g2="y" k="-31" /> +<hkern g1="f" g2="aacute" k="47" /> +<hkern g1="f" g2="adieresis" k="39" /> +<hkern g1="f" g2="aring" k="43" /> +<hkern g1="f" g2="ae" k="33" /> +<hkern g1="f" g2="egrave" k="78" /> +<hkern g1="f" g2="eacute" k="82" /> +<hkern g1="f" g2="ecircumflex" k="78" /> +<hkern g1="f" g2="edieresis" k="70" /> +<hkern g1="f" g2="idieresis" k="-31" /> +<hkern g1="f" g2="oacute" k="80" /> +<hkern g1="f" g2="odieresis" k="70" /> +<hkern g1="f" g2="oslash" k="70" /> +<hkern g1="f" g2="udieresis" k="20" /> +<hkern g1="f" g2="oe" k="59" /> +<hkern g1="g" g2="a" k="27" /> +<hkern g1="g" g2="e" k="29" /> +<hkern g1="g" g2="g" k="-70" /> +<hkern g1="g" g2="o" k="27" /> +<hkern g1="g" g2="adieresis" k="27" /> +<hkern g1="g" g2="aring" k="27" /> +<hkern g1="g" g2="ae" k="27" /> +<hkern g1="g" g2="egrave" k="29" /> +<hkern g1="g" g2="eacute" k="29" /> +<hkern g1="g" g2="ecircumflex" k="29" /> +<hkern g1="g" g2="edieresis" k="29" /> +<hkern g1="g" g2="oacute" k="27" /> +<hkern g1="g" g2="odieresis" k="27" /> +<hkern g1="h" g2="t" k="35" /> +<hkern g1="h" g2="y" k="35" /> +<hkern g1="h" g2="yacute" k="59" /> +<hkern g1="h" g2="ydieresis" k="51" /> +<hkern g1="h" g2="quoteright" k="252" /> +<hkern g1="k" g2="hyphen" k="133" /> +<hkern g1="k" g2="a" k="31" /> +<hkern g1="k" g2="e" k="78" /> +<hkern g1="k" g2="o" k="78" /> +<hkern g1="k" g2="u" k="29" /> +<hkern g1="k" g2="aacute" k="51" /> +<hkern g1="k" g2="adieresis" k="45" /> +<hkern g1="k" g2="aring" k="51" /> +<hkern g1="k" g2="ae" k="31" /> +<hkern g1="k" g2="eacute" k="100" /> +<hkern g1="k" g2="oacute" k="102" /> +<hkern g1="k" g2="odieresis" k="94" /> +<hkern g1="k" g2="udieresis" k="43" /> +<hkern g1="l" g2="v" k="47" /> +<hkern g1="l" g2="y" k="39" /> +<hkern g1="m" g2="v" k="43" /> +<hkern g1="m" g2="w" k="35" /> +<hkern g1="m" g2="y" k="35" /> +<hkern g1="n" g2="T" k="240" /> +<hkern g1="n" g2="v" k="43" /> +<hkern g1="n" g2="w" k="35" /> +<hkern g1="n" g2="y" k="35" /> +<hkern g1="o" g2="t" k="23" /> +<hkern g1="o" g2="v" k="47" /> +<hkern g1="o" g2="w" k="39" /> +<hkern g1="o" g2="x" k="51" /> +<hkern g1="o" g2="y" k="43" /> +<hkern g1="p" g2="t" k="25" /> +<hkern g1="p" g2="y" k="72" /> +<hkern g1="p" g2="yacute" k="72" /> +<hkern g1="p" g2="ydieresis" k="72" /> +<hkern g1="r" g2="comma" k="133" /> +<hkern g1="r" g2="hyphen" k="129" /> +<hkern g1="r" g2="period" k="129" /> +<hkern g1="r" g2="a" k="33" /> +<hkern g1="r" g2="c" k="57" /> +<hkern g1="r" g2="d" k="57" /> +<hkern g1="r" g2="e" k="59" /> +<hkern g1="r" g2="f" k="-20" /> +<hkern g1="r" g2="g" k="59" /> +<hkern g1="r" g2="h" k="23" /> +<hkern g1="r" g2="i" k="23" /> +<hkern g1="r" g2="j" k="23" /> +<hkern g1="r" g2="k" k="23" /> +<hkern g1="r" g2="m" k="23" /> +<hkern g1="r" g2="n" k="23" /> +<hkern g1="r" g2="o" k="55" /> +<hkern g1="r" g2="p" k="20" /> +<hkern g1="r" g2="q" k="55" /> +<hkern g1="r" g2="r" k="23" /> +<hkern g1="r" g2="s" k="20" /> +<hkern g1="r" g2="y" k="-20" /> +<hkern g1="r" g2="agrave" k="33" /> +<hkern g1="r" g2="aacute" k="33" /> +<hkern g1="r" g2="acircumflex" k="33" /> +<hkern g1="r" g2="adieresis" k="33" /> +<hkern g1="r" g2="aring" k="33" /> +<hkern g1="r" g2="ae" k="33" /> +<hkern g1="r" g2="ccedilla" k="55" /> +<hkern g1="r" g2="egrave" k="59" /> +<hkern g1="r" g2="eacute" k="59" /> +<hkern g1="r" g2="ecircumflex" k="59" /> +<hkern g1="r" g2="edieresis" k="59" /> +<hkern g1="r" g2="ograve" k="55" /> +<hkern g1="r" g2="oacute" k="55" /> +<hkern g1="r" g2="ocircumflex" k="55" /> +<hkern g1="r" g2="otilde" k="55" /> +<hkern g1="r" g2="odieresis" k="55" /> +<hkern g1="r" g2="oslash" k="63" /> +<hkern g1="r" g2="oe" k="53" /> +<hkern g1="r" g2="scaron" k="20" /> +<hkern g1="s" g2="s" k="25" /> +<hkern g1="t" g2="e" k="63" /> +<hkern g1="t" g2="h" k="25" /> +<hkern g1="t" g2="o" k="66" /> +<hkern g1="t" g2="t" k="25" /> +<hkern g1="t" g2="aacute" k="25" /> +<hkern g1="t" g2="atilde" k="23" /> +<hkern g1="t" g2="adieresis" k="23" /> +<hkern g1="t" g2="aring" k="25" /> +<hkern g1="t" g2="eacute" k="74" /> +<hkern g1="t" g2="oacute" k="76" /> +<hkern g1="t" g2="odieresis" k="74" /> +<hkern g1="t" g2="quoteright" k="86" /> +<hkern g1="u" g2="v" k="20" /> +<hkern g1="v" g2="comma" k="115" /> +<hkern g1="v" g2="hyphen" k="43" /> +<hkern g1="v" g2="period" k="104" /> +<hkern g1="v" g2="a" k="43" /> +<hkern g1="v" g2="c" k="47" /> +<hkern g1="v" g2="e" k="47" /> +<hkern g1="v" g2="g" k="55" /> +<hkern g1="v" g2="o" k="45" /> +<hkern g1="v" g2="s" k="29" /> +<hkern g1="v" g2="agrave" k="43" /> +<hkern g1="v" g2="aacute" k="43" /> +<hkern g1="v" g2="acircumflex" k="43" /> +<hkern g1="v" g2="atilde" k="43" /> +<hkern g1="v" g2="adieresis" k="43" /> +<hkern g1="v" g2="aring" k="43" /> +<hkern g1="v" g2="ae" k="43" /> +<hkern g1="v" g2="egrave" k="47" /> +<hkern g1="v" g2="eacute" k="47" /> +<hkern g1="v" g2="ecircumflex" k="47" /> +<hkern g1="v" g2="ograve" k="45" /> +<hkern g1="v" g2="oacute" k="45" /> +<hkern g1="v" g2="odieresis" k="45" /> +<hkern g1="v" g2="oslash" k="51" /> +<hkern g1="w" g2="comma" k="82" /> +<hkern g1="w" g2="hyphen" k="29" /> +<hkern g1="w" g2="period" k="74" /> +<hkern g1="w" g2="a" k="41" /> +<hkern g1="w" g2="c" k="39" /> +<hkern g1="w" g2="e" k="39" /> +<hkern g1="w" g2="g" k="47" /> +<hkern g1="w" g2="o" k="37" /> +<hkern g1="w" g2="s" k="27" /> +<hkern g1="w" g2="agrave" k="41" /> +<hkern g1="w" g2="aacute" k="41" /> +<hkern g1="w" g2="acircumflex" k="41" /> +<hkern g1="w" g2="atilde" k="41" /> +<hkern g1="w" g2="adieresis" k="41" /> +<hkern g1="w" g2="aring" k="41" /> +<hkern g1="w" g2="ae" k="41" /> +<hkern g1="w" g2="egrave" k="39" /> +<hkern g1="w" g2="eacute" k="39" /> +<hkern g1="w" g2="ecircumflex" k="39" /> +<hkern g1="w" g2="ograve" k="37" /> +<hkern g1="w" g2="oacute" k="37" /> +<hkern g1="w" g2="odieresis" k="37" /> +<hkern g1="w" g2="oslash" k="41" /> +<hkern g1="x" g2="c" k="49" /> +<hkern g1="x" g2="e" k="47" /> +<hkern g1="x" g2="o" k="49" /> +<hkern g1="x" g2="q" k="47" /> +<hkern g1="x" g2="eacute" k="47" /> +<hkern g1="x" g2="odieresis" k="49" /> +<hkern g1="y" g2="comma" k="109" /> +<hkern g1="y" g2="hyphen" k="35" /> +<hkern g1="y" g2="period" k="90" /> +<hkern g1="y" g2="semicolon" k="27" /> +<hkern g1="y" g2="a" k="35" /> +<hkern g1="y" g2="c" k="35" /> +<hkern g1="y" g2="d" k="35" /> +<hkern g1="y" g2="e" k="37" /> +<hkern g1="y" g2="g" k="66" /> +<hkern g1="y" g2="o" k="35" /> +<hkern g1="y" g2="q" k="63" /> +<hkern g1="y" g2="s" k="20" /> +<hkern g1="y" g2="agrave" k="35" /> +<hkern g1="y" g2="aacute" k="35" /> +<hkern g1="y" g2="acircumflex" k="35" /> +<hkern g1="y" g2="atilde" k="35" /> +<hkern g1="y" g2="adieresis" k="35" /> +<hkern g1="y" g2="aring" k="35" /> +<hkern g1="y" g2="ae" k="35" /> +<hkern g1="y" g2="egrave" k="37" /> +<hkern g1="y" g2="eacute" k="37" /> +<hkern g1="y" g2="ecircumflex" k="37" /> +<hkern g1="y" g2="ograve" k="35" /> +<hkern g1="y" g2="oacute" k="35" /> +<hkern g1="y" g2="odieresis" k="35" /> +<hkern g1="y" g2="oslash" k="43" /> +<hkern g1="y" g2="scaron" k="20" /> +<hkern g1="z" g2="c" k="41" /> +<hkern g1="z" g2="e" k="41" /> +<hkern g1="z" g2="o" k="41" /> +<hkern g1="z" g2="egrave" k="41" /> +<hkern g1="z" g2="eacute" k="41" /> +<hkern g1="z" g2="odieresis" k="41" /> +<hkern g1="z" g2="oslash" k="20" /> +<hkern g1="guillemotright" g2="A" k="35" /> +<hkern g1="guillemotright" g2="T" k="250" /> +<hkern g1="guillemotright" g2="V" k="172" /> +<hkern g1="guillemotright" g2="W" k="123" /> +<hkern g1="guillemotright" g2="Y" k="229" /> +<hkern g1="guillemotright" g2="Aacute" k="35" /> +<hkern g1="guillemotright" g2="Adieresis" k="35" /> +<hkern g1="guillemotright" g2="Aring" k="35" /> +<hkern g1="guillemotright" g2="AE" k="41" /> +<hkern g1="Agrave" g2="comma" k="-33" /> +<hkern g1="Agrave" g2="period" k="-39" /> +<hkern g1="Agrave" g2="C" k="41" /> +<hkern g1="Agrave" g2="G" k="41" /> +<hkern g1="Agrave" g2="O" k="39" /> +<hkern g1="Agrave" g2="Q" k="39" /> +<hkern g1="Agrave" g2="T" k="211" /> +<hkern g1="Agrave" g2="U" k="39" /> +<hkern g1="Agrave" g2="V" k="178" /> +<hkern g1="Agrave" g2="W" k="141" /> +<hkern g1="Agrave" g2="Y" k="190" /> +<hkern g1="Agrave" g2="d" k="35" /> +<hkern g1="Agrave" g2="v" k="88" /> +<hkern g1="Agrave" g2="w" k="70" /> +<hkern g1="Agrave" g2="y" k="82" /> +<hkern g1="Agrave" g2="Odieresis" k="51" /> +<hkern g1="Agrave" g2="Udieresis" k="51" /> +<hkern g1="Agrave" g2="quoteright" k="104" /> +<hkern g1="Aacute" g2="comma" k="-33" /> +<hkern g1="Aacute" g2="period" k="-39" /> +<hkern g1="Aacute" g2="C" k="41" /> +<hkern g1="Aacute" g2="G" k="41" /> +<hkern g1="Aacute" g2="O" k="39" /> +<hkern g1="Aacute" g2="Q" k="39" /> +<hkern g1="Aacute" g2="T" k="211" /> +<hkern g1="Aacute" g2="U" k="39" /> +<hkern g1="Aacute" g2="V" k="178" /> +<hkern g1="Aacute" g2="W" k="141" /> +<hkern g1="Aacute" g2="Y" k="190" /> +<hkern g1="Aacute" g2="d" k="35" /> +<hkern g1="Aacute" g2="g" k="-25" /> +<hkern g1="Aacute" g2="t" k="39" /> +<hkern g1="Aacute" g2="v" k="88" /> +<hkern g1="Aacute" g2="w" k="70" /> +<hkern g1="Aacute" g2="y" k="82" /> +<hkern g1="Aacute" g2="guillemotleft" k="33" /> +<hkern g1="Aacute" g2="Odieresis" k="51" /> +<hkern g1="Aacute" g2="Udieresis" k="51" /> +<hkern g1="Aacute" g2="udieresis" k="20" /> +<hkern g1="Aacute" g2="quoteright" k="104" /> +<hkern g1="Aacute" g2="guilsinglleft" k="33" /> +<hkern g1="Acircumflex" g2="comma" k="-33" /> +<hkern g1="Acircumflex" g2="period" k="-39" /> +<hkern g1="Acircumflex" g2="C" k="41" /> +<hkern g1="Acircumflex" g2="G" k="41" /> +<hkern g1="Acircumflex" g2="O" k="39" /> +<hkern g1="Acircumflex" g2="Q" k="39" /> +<hkern g1="Acircumflex" g2="T" k="211" /> +<hkern g1="Acircumflex" g2="U" k="39" /> +<hkern g1="Acircumflex" g2="V" k="178" /> +<hkern g1="Acircumflex" g2="W" k="141" /> +<hkern g1="Acircumflex" g2="Y" k="190" /> +<hkern g1="Acircumflex" g2="d" k="35" /> +<hkern g1="Acircumflex" g2="v" k="88" /> +<hkern g1="Acircumflex" g2="w" k="70" /> +<hkern g1="Acircumflex" g2="y" k="82" /> +<hkern g1="Acircumflex" g2="Odieresis" k="51" /> +<hkern g1="Acircumflex" g2="Udieresis" k="51" /> +<hkern g1="Acircumflex" g2="quoteright" k="104" /> +<hkern g1="Atilde" g2="comma" k="-33" /> +<hkern g1="Atilde" g2="period" k="-39" /> +<hkern g1="Atilde" g2="C" k="41" /> +<hkern g1="Atilde" g2="G" k="41" /> +<hkern g1="Atilde" g2="O" k="39" /> +<hkern g1="Atilde" g2="Q" k="39" /> +<hkern g1="Atilde" g2="T" k="211" /> +<hkern g1="Atilde" g2="U" k="39" /> +<hkern g1="Atilde" g2="V" k="178" /> +<hkern g1="Atilde" g2="W" k="141" /> +<hkern g1="Atilde" g2="Y" k="190" /> +<hkern g1="Atilde" g2="d" k="35" /> +<hkern g1="Atilde" g2="v" k="88" /> +<hkern g1="Atilde" g2="w" k="70" /> +<hkern g1="Atilde" g2="y" k="82" /> +<hkern g1="Atilde" g2="Odieresis" k="49" /> +<hkern g1="Atilde" g2="Udieresis" k="49" /> +<hkern g1="Atilde" g2="quoteright" k="104" /> +<hkern g1="Adieresis" g2="comma" k="-33" /> +<hkern g1="Adieresis" g2="period" k="-39" /> +<hkern g1="Adieresis" g2="A" k="-41" /> +<hkern g1="Adieresis" g2="C" k="41" /> +<hkern g1="Adieresis" g2="G" k="41" /> +<hkern g1="Adieresis" g2="O" k="39" /> +<hkern g1="Adieresis" g2="Q" k="39" /> +<hkern g1="Adieresis" g2="T" k="211" /> +<hkern g1="Adieresis" g2="U" k="39" /> +<hkern g1="Adieresis" g2="V" k="178" /> +<hkern g1="Adieresis" g2="W" k="141" /> +<hkern g1="Adieresis" g2="Y" k="190" /> +<hkern g1="Adieresis" g2="d" k="35" /> +<hkern g1="Adieresis" g2="f" k="51" /> +<hkern g1="Adieresis" g2="g" k="-25" /> +<hkern g1="Adieresis" g2="t" k="39" /> +<hkern g1="Adieresis" g2="v" k="88" /> +<hkern g1="Adieresis" g2="w" k="70" /> +<hkern g1="Adieresis" g2="y" k="82" /> +<hkern g1="Adieresis" g2="guillemotleft" k="33" /> +<hkern g1="Adieresis" g2="Adieresis" k="-35" /> +<hkern g1="Adieresis" g2="Ccedilla" k="41" /> +<hkern g1="Adieresis" g2="Ograve" k="51" /> +<hkern g1="Adieresis" g2="Oacute" k="51" /> +<hkern g1="Adieresis" g2="Ocircumflex" k="51" /> +<hkern g1="Adieresis" g2="Otilde" k="47" /> +<hkern g1="Adieresis" g2="Odieresis" k="51" /> +<hkern g1="Adieresis" g2="Ugrave" k="51" /> +<hkern g1="Adieresis" g2="Uacute" k="51" /> +<hkern g1="Adieresis" g2="Ucircumflex" k="51" /> +<hkern g1="Adieresis" g2="Udieresis" k="51" /> +<hkern g1="Adieresis" g2="Yacute" k="201" /> +<hkern g1="Adieresis" g2="ograve" k="29" /> +<hkern g1="Adieresis" g2="oacute" k="29" /> +<hkern g1="Adieresis" g2="ocircumflex" k="29" /> +<hkern g1="Adieresis" g2="otilde" k="25" /> +<hkern g1="Adieresis" g2="odieresis" k="20" /> +<hkern g1="Adieresis" g2="udieresis" k="20" /> +<hkern g1="Adieresis" g2="Ydieresis" k="195" /> +<hkern g1="Adieresis" g2="quoteright" k="104" /> +<hkern g1="Adieresis" g2="quotedblright" k="104" /> +<hkern g1="Adieresis" g2="guilsinglleft" k="33" /> +<hkern g1="Aring" g2="comma" k="-33" /> +<hkern g1="Aring" g2="period" k="-39" /> +<hkern g1="Aring" g2="C" k="41" /> +<hkern g1="Aring" g2="G" k="41" /> +<hkern g1="Aring" g2="O" k="39" /> +<hkern g1="Aring" g2="Q" k="39" /> +<hkern g1="Aring" g2="T" k="211" /> +<hkern g1="Aring" g2="U" k="39" /> +<hkern g1="Aring" g2="V" k="178" /> +<hkern g1="Aring" g2="W" k="141" /> +<hkern g1="Aring" g2="Y" k="190" /> +<hkern g1="Aring" g2="d" k="35" /> +<hkern g1="Aring" g2="f" k="51" /> +<hkern g1="Aring" g2="g" k="-25" /> +<hkern g1="Aring" g2="t" k="39" /> +<hkern g1="Aring" g2="v" k="88" /> +<hkern g1="Aring" g2="w" k="70" /> +<hkern g1="Aring" g2="y" k="82" /> +<hkern g1="Aring" g2="guillemotleft" k="33" /> +<hkern g1="Aring" g2="Odieresis" k="51" /> +<hkern g1="Aring" g2="Udieresis" k="51" /> +<hkern g1="Aring" g2="udieresis" k="20" /> +<hkern g1="Aring" g2="quoteright" k="104" /> +<hkern g1="Aring" g2="quotedblright" k="104" /> +<hkern g1="Aring" g2="guilsinglleft" k="33" /> +<hkern g1="AE" g2="hyphen" k="236" /> +<hkern g1="Eacute" g2="G" k="35" /> +<hkern g1="Eacute" g2="Q" k="33" /> +<hkern g1="Eacute" g2="c" k="55" /> +<hkern g1="Eth" g2="A" k="47" /> +<hkern g1="Eth" g2="V" k="63" /> +<hkern g1="Eth" g2="Y" k="98" /> +<hkern g1="Eth" g2="Adieresis" k="47" /> +<hkern g1="Eth" g2="Aring" k="47" /> +<hkern g1="Ograve" g2="T" k="117" /> +<hkern g1="Ograve" g2="V" k="63" /> +<hkern g1="Ograve" g2="Y" k="94" /> +<hkern g1="Oacute" g2="A" k="45" /> +<hkern g1="Oacute" g2="T" k="117" /> +<hkern g1="Oacute" g2="V" k="63" /> +<hkern g1="Oacute" g2="W" k="49" /> +<hkern g1="Oacute" g2="Y" k="94" /> +<hkern g1="Oacute" g2="Adieresis" k="55" /> +<hkern g1="Ocircumflex" g2="T" k="117" /> +<hkern g1="Ocircumflex" g2="V" k="63" /> +<hkern g1="Ocircumflex" g2="Y" k="94" /> +<hkern g1="Otilde" g2="T" k="117" /> +<hkern g1="Otilde" g2="V" k="63" /> +<hkern g1="Otilde" g2="Y" k="94" /> +<hkern g1="Odieresis" g2="comma" k="59" /> +<hkern g1="Odieresis" g2="period" k="49" /> +<hkern g1="Odieresis" g2="A" k="45" /> +<hkern g1="Odieresis" g2="T" k="117" /> +<hkern g1="Odieresis" g2="V" k="63" /> +<hkern g1="Odieresis" g2="W" k="49" /> +<hkern g1="Odieresis" g2="X" k="78" /> +<hkern g1="Odieresis" g2="Y" k="94" /> +<hkern g1="Odieresis" g2="Agrave" k="55" /> +<hkern g1="Odieresis" g2="Aacute" k="55" /> +<hkern g1="Odieresis" g2="Acircumflex" k="55" /> +<hkern g1="Odieresis" g2="Atilde" k="55" /> +<hkern g1="Odieresis" g2="Adieresis" k="55" /> +<hkern g1="Odieresis" g2="Aring" k="55" /> +<hkern g1="Odieresis" g2="AE" k="51" /> +<hkern g1="Oslash" g2="comma" k="72" /> +<hkern g1="Oslash" g2="period" k="55" /> +<hkern g1="Oslash" g2="A" k="51" /> +<hkern g1="Oslash" g2="X" k="35" /> +<hkern g1="Oslash" g2="Adieresis" k="51" /> +<hkern g1="Ugrave" g2="A" k="41" /> +<hkern g1="Ugrave" g2="Adieresis" k="53" /> +<hkern g1="Uacute" g2="comma" k="43" /> +<hkern g1="Uacute" g2="period" k="35" /> +<hkern g1="Uacute" g2="A" k="41" /> +<hkern g1="Uacute" g2="Adieresis" k="51" /> +<hkern g1="Ucircumflex" g2="A" k="41" /> +<hkern g1="Ucircumflex" g2="Adieresis" k="51" /> +<hkern g1="Udieresis" g2="comma" k="43" /> +<hkern g1="Udieresis" g2="period" k="35" /> +<hkern g1="Udieresis" g2="A" k="41" /> +<hkern g1="Udieresis" g2="Aacute" k="53" /> +<hkern g1="Udieresis" g2="Acircumflex" k="51" /> +<hkern g1="Udieresis" g2="Atilde" k="51" /> +<hkern g1="Udieresis" g2="Adieresis" k="51" /> +<hkern g1="Udieresis" g2="Aring" k="51" /> +<hkern g1="Udieresis" g2="AE" k="47" /> +<hkern g1="Thorn" g2="A" k="78" /> +<hkern g1="Thorn" g2="Aacute" k="78" /> +<hkern g1="Thorn" g2="Adieresis" k="78" /> +<hkern g1="Thorn" g2="Aring" k="78" /> +<hkern g1="Thorn" g2="AE" k="88" /> +<hkern g1="germandbls" g2="T" k="94" /> +<hkern g1="germandbls" g2="V" k="90" /> +<hkern g1="germandbls" g2="W" k="84" /> +<hkern g1="germandbls" g2="f" k="59" /> +<hkern g1="germandbls" g2="t" k="43" /> +<hkern g1="germandbls" g2="v" k="104" /> +<hkern g1="germandbls" g2="w" k="78" /> +<hkern g1="agrave" g2="t" k="49" /> +<hkern g1="agrave" g2="v" k="74" /> +<hkern g1="agrave" g2="w" k="63" /> +<hkern g1="agrave" g2="y" k="66" /> +<hkern g1="aacute" g2="t" k="51" /> +<hkern g1="aacute" g2="v" k="74" /> +<hkern g1="aacute" g2="w" k="63" /> +<hkern g1="aacute" g2="y" k="66" /> +<hkern g1="acircumflex" g2="t" k="47" /> +<hkern g1="adieresis" g2="t" k="47" /> +<hkern g1="adieresis" g2="v" k="74" /> +<hkern g1="adieresis" g2="w" k="63" /> +<hkern g1="adieresis" g2="y" k="66" /> +<hkern g1="adieresis" g2="germandbls" k="20" /> +<hkern g1="adieresis" g2="adieresis" k="20" /> +<hkern g1="aring" g2="t" k="49" /> +<hkern g1="aring" g2="v" k="74" /> +<hkern g1="aring" g2="w" k="63" /> +<hkern g1="aring" g2="y" k="66" /> +<hkern g1="ae" g2="v" k="37" /> +<hkern g1="ae" g2="w" k="33" /> +<hkern g1="ae" g2="y" k="29" /> +<hkern g1="egrave" g2="d" k="29" /> +<hkern g1="eacute" g2="d" k="29" /> +<hkern g1="eacute" g2="v" k="39" /> +<hkern g1="eacute" g2="w" k="33" /> +<hkern g1="eacute" g2="y" k="31" /> +<hkern g1="ecircumflex" g2="v" k="39" /> +<hkern g1="ecircumflex" g2="w" k="33" /> +<hkern g1="ecircumflex" g2="y" k="31" /> +<hkern g1="ograve" g2="v" k="47" /> +<hkern g1="ograve" g2="w" k="37" /> +<hkern g1="ograve" g2="y" k="41" /> +<hkern g1="oacute" g2="t" k="35" /> +<hkern g1="oacute" g2="v" k="47" /> +<hkern g1="oacute" g2="w" k="37" /> +<hkern g1="oacute" g2="y" k="41" /> +<hkern g1="ocircumflex" g2="t" k="33" /> +<hkern g1="ocircumflex" g2="v" k="47" /> +<hkern g1="odieresis" g2="t" k="31" /> +<hkern g1="odieresis" g2="v" k="47" /> +<hkern g1="odieresis" g2="w" k="37" /> +<hkern g1="odieresis" g2="x" k="51" /> +<hkern g1="odieresis" g2="y" k="41" /> +<hkern g1="udieresis" g2="v" k="20" /> +<hkern g1="yacute" g2="a" k="35" /> +<hkern g1="yacute" g2="c" k="35" /> +<hkern g1="yacute" g2="d" k="59" /> +<hkern g1="yacute" g2="e" k="37" /> +<hkern g1="yacute" g2="o" k="35" /> +<hkern g1="yacute" g2="adieresis" k="47" /> +<hkern g1="yacute" g2="odieresis" k="47" /> +<hkern g1="ydieresis" g2="a" k="35" /> +<hkern g1="ydieresis" g2="c" k="35" /> +<hkern g1="ydieresis" g2="d" k="51" /> +<hkern g1="ydieresis" g2="e" k="37" /> +<hkern g1="ydieresis" g2="o" k="35" /> +<hkern g1="ydieresis" g2="adieresis" k="43" /> +<hkern g1="ydieresis" g2="odieresis" k="45" /> +<hkern g1="ydieresis" g2="oslash" k="43" /> +<hkern g1="Scaron" g2="T" k="33" /> +<hkern g1="scaron" g2="w" k="33" /> +<hkern g1="quoteleft" g2="A" k="119" /> +<hkern g1="quoteleft" g2="T" k="-23" /> +<hkern g1="quoteleft" g2="V" k="-29" /> +<hkern g1="quoteleft" g2="W" k="-25" /> +<hkern g1="quoteleft" g2="Y" k="-29" /> +<hkern g1="quoteleft" g2="Aacute" k="119" /> +<hkern g1="quoteleft" g2="Adieresis" k="119" /> +<hkern g1="quoteleft" g2="Aring" k="119" /> +<hkern g1="quoteleft" g2="AE" k="131" /> +<hkern g1="quoteright" g2="A" k="125" /> +<hkern g1="quoteright" g2="d" k="254" /> +<hkern g1="quoteright" g2="t" k="55" /> +<hkern g1="quoteright" g2="Aacute" k="125" /> +<hkern g1="quoteright" g2="Adieresis" k="125" /> +<hkern g1="quoteright" g2="Aring" k="125" /> +<hkern g1="quoteright" g2="AE" k="139" /> +<hkern g1="quotedblleft" g2="A" k="119" /> +<hkern g1="quotedblleft" g2="T" k="-23" /> +<hkern g1="quotedblleft" g2="V" k="-29" /> +<hkern g1="quotedblleft" g2="W" k="-25" /> +<hkern g1="quotedblleft" g2="Y" k="-29" /> +<hkern g1="quotedblleft" g2="Aacute" k="119" /> +<hkern g1="quotedblleft" g2="Adieresis" k="119" /> +<hkern g1="quotedblleft" g2="Aring" k="119" /> +<hkern g1="quotedblleft" g2="AE" k="131" /> +<hkern g1="quotedblright" g2="A" k="125" /> +<hkern g1="quotedblright" g2="T" k="-27" /> +<hkern g1="quotedblright" g2="V" k="-29" /> +<hkern g1="quotedblright" g2="W" k="-25" /> +<hkern g1="quotedblright" g2="Y" k="-29" /> +<hkern g1="quotedblright" g2="Aacute" k="125" /> +<hkern g1="quotedblright" g2="Adieresis" k="125" /> +<hkern g1="quotedblright" g2="Aring" k="125" /> +<hkern g1="quotedblright" g2="AE" k="139" /> +<hkern g1="quotedblbase" g2="A" k="-51" /> +<hkern g1="quotedblbase" g2="T" k="131" /> +<hkern g1="quotedblbase" g2="V" k="156" /> +<hkern g1="quotedblbase" g2="W" k="106" /> +<hkern g1="quotedblbase" g2="Y" k="121" /> +<hkern g1="quotedblbase" g2="Adieresis" k="-51" /> +<hkern g1="quotedblbase" g2="AE" k="-51" /> +<hkern g1="guilsinglright" g2="A" k="35" /> +<hkern g1="guilsinglright" g2="T" k="250" /> +<hkern g1="guilsinglright" g2="V" k="172" /> +<hkern g1="guilsinglright" g2="W" k="123" /> +<hkern g1="guilsinglright" g2="Y" k="227" /> +<hkern g1="guilsinglright" g2="Aacute" k="35" /> +<hkern g1="guilsinglright" g2="Adieresis" k="35" /> +<hkern g1="guilsinglright" g2="Aring" k="35" /> +<hkern g1="guilsinglright" g2="AE" k="41" /> +</font> +</defs> +</svg> diff --git a/js/dojo-1.6/dojox/gfx/resources/README b/js/dojo-1.6/dojox/gfx/resources/README new file mode 100644 index 0000000..e938c47 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/resources/README @@ -0,0 +1,3 @@ +http://xmlgraphics.apache.org/batik/tools/font-converter.html + + diff --git a/js/dojo-1.6/dojox/gfx/resources/gfxSvgProxyFrame.html b/js/dojo-1.6/dojox/gfx/resources/gfxSvgProxyFrame.html new file mode 100644 index 0000000..1a9ed5e --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/resources/gfxSvgProxyFrame.html @@ -0,0 +1,14 @@ +<html> + <head> + <script type="text/javascript"> + djConfig = {forceGfxRenderer: "svg"}; + </script> + <script type="text/javascript" src="../../../dojo/dojo.js" ></script> + <script type="text/javascript"> + dojo.require("dojox.gfx"); + dojo.require("dojox.gfx.utils"); + </script> + </head> + <body> + </body> +</html> diff --git a/js/dojo-1.6/dojox/gfx/resources/svg2gfx-simple.xsl b/js/dojo-1.6/dojox/gfx/resources/svg2gfx-simple.xsl new file mode 100644 index 0000000..90a463f --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/resources/svg2gfx-simple.xsl @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Super simple XSLT to convert Nils.svg and Lars.svg to our format --> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> + <xsl:output method="text" version="1.0" encoding="UTF-8"/> + <xsl:template name="fill"> + <xsl:param name="node"/> + <xsl:if test="count($node/@fill) > 0"> + <xsl:text>fill: "</xsl:text> + <xsl:value-of select="$node/@fill"/> + <xsl:text>",</xsl:text> + </xsl:if> + </xsl:template> + <xsl:template name="stroke"> + <xsl:param name="node"/> + <xsl:text>stroke: {</xsl:text> + <xsl:if test="count($node/@stroke) > 0"> + <xsl:text>color: "</xsl:text> + <xsl:value-of select="$node/@stroke"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:if test="count($node/@stroke-width) > 0"> + <xsl:text>width: "</xsl:text> + <xsl:value-of select="$node/@stroke-width"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:if test="count($node/@stroke-linecap) > 0"> + <xsl:text>cap: "</xsl:text> + <xsl:value-of select="$node/@stroke-linecap"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:if test="count($node/@stroke-linejoin) > 0"> + <xsl:text>join: "</xsl:text> + <xsl:value-of select="$node/@stroke-linejoin"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:text>},</xsl:text> + </xsl:template> + <xsl:template match="g"> + <xsl:text>{</xsl:text> + <xsl:if test="count(@id) > 0"> + <xsl:text>name: "</xsl:text> + <xsl:value-of select="@id"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:text>children: [</xsl:text> + <xsl:apply-templates select="g|path"/> + <xsl:text>]},</xsl:text> + </xsl:template> + <xsl:template match="path"> + <xsl:text>{</xsl:text> + <xsl:if test="count(@id) > 0"> + <xsl:text>name: "</xsl:text> + <xsl:value-of select="@id"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:text>shape: {type: "path", path: "</xsl:text> + <xsl:value-of select="@d"/> + <xsl:text>"},</xsl:text> + <xsl:call-template name="fill"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:call-template name="stroke"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:text>},</xsl:text> + </xsl:template> + <xsl:template match="svg"> + <xsl:text>[</xsl:text> + <xsl:apply-templates select="g|path"/> + <xsl:text>]</xsl:text> + </xsl:template> +</xsl:stylesheet> diff --git a/js/dojo-1.6/dojox/gfx/resources/svg2gfx.xsl b/js/dojo-1.6/dojox/gfx/resources/svg2gfx.xsl new file mode 100644 index 0000000..91ba90f --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/resources/svg2gfx.xsl @@ -0,0 +1,1085 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE xsl:stylesheet [ +<!ENTITY SupportedElements "svg:a|svg:circle|svg:ellipse|svg:g|svg:image|svg:line|svg:path|svg:polygon|svg:polyline|svg:rect|svg:text|svg:textPath|svg:use"> +]> +<!-- This is a complete rewrite of the original svg2gfx.xslt used for testing. --> +<!-- +This version supports polygons, polylines, circles, ellipses, rectangles, +lines, images, text, patterns, linear gradients, radial gradients, transforms +(although gradient transforms are limited), and more in addition to the +paths, strokes, groups, and constant fills supported by the original. It +even handles little niceties like the SVG use element. All that being said, +It does not even come close to supporting all of the features found in SVG, +but should hopefully be a fairly useful subset. + +Caveats: Completely ignores many SVG features (such as named views, filters, +object bounding box in gradient transforms, etc.). Now requires properly +formed SVG (that is, SVG using the appropriate SVG namespace) which most +editors create by default these days anyhow (the old version required that +namespaces be stripped off). Can't convert to GFX constructs that cannot +be reconstructed from JSON (such as textpath or using vector fonts). +Requires EXSLT for many transforms. Handles nested styles in a simple way +that is usually right but sometimes wrong. + +Questions / comments / bug reports can be sent to Feneric (on Twitter, IRC, +GMail, etc.) or Eric (Saugus.net, ShellTown, etc.) +--> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:math="http://exslt.org/math" + xmlns:exsl="http://exslt.org/common" + xmlns:saxon="http://icl.com/saxon" + xmlns:xalan="http://xml.apache.org/Xalan" + extension-element-prefixes="math exsl saxon xalan"> + <xsl:output method="text" version="1.0" encoding="UTF-8"/> + <xsl:strip-space elements="*"/> + + <!-- We currently need this constant for some transformation calculations. --> + <!-- GFX enhancements could obviate it in the future. --> + <xsl:variable name="degressInRadian" select="57.295779513082322"/> + + <!-- The following templates process little bits of things that can often occur in multiple contexts --> + + <xsl:template name="kill-extra-spaces" mode="kill-extra-spaces"> + <xsl:param name="string"/> + <!-- Some don't feel that SVG is verbose enough and thus add extra spaces, which when --> + <!-- untreated can look exactly like delimiters in point sets. --> + <xsl:choose> + <!-- Hopefully most cases won't have the extra spaces --> + <xsl:when test="not(contains($string,', '))"> + <xsl:value-of select="$string"/> + </xsl:when> + <xsl:otherwise> + <!-- We split at comma / space pairs and recursively chop spaces --> + <xsl:call-template name="kill-extra-spaces"> + <xsl:with-param name="string" select="substring-before($string,', ')"/> + </xsl:call-template> + <xsl:text>,</xsl:text> + <xsl:call-template name="kill-extra-spaces"> + <xsl:with-param name="string" select="substring-after($string,', ')"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="arg-processor" mode="arg-processor"> + <xsl:param name="values"/> + <xsl:param name="labels"/> + <!-- Recursively chew through the arguments in a traditional CAR / CDR pattern --> + <xsl:variable name="valuesCdr" select="substring-after($values,',')"/> + <!-- We're going "backwards" here to take advantage of tail recursion --> + <xsl:choose> + <xsl:when test="not($valuesCdr)"> + <!-- handle the final argument --> + <xsl:value-of select="$labels"/> + <xsl:text>:</xsl:text> + <xsl:value-of select="$values"/> + <!-- This last trailing comma is needed in the (odd) case of multiple transforms --> + <xsl:text>,</xsl:text> + </xsl:when> + <xsl:otherwise> + <!-- handle the current argument --> + <xsl:value-of select="substring-before($labels,',')"/> + <xsl:text>:</xsl:text> + <xsl:value-of select="substring-before($values,',')"/> + <xsl:text>,</xsl:text> + <xsl:call-template name="arg-processor"> + <xsl:with-param name="values" select="$valuesCdr"/> + <xsl:with-param name="labels" select="substring-after($labels,',')"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="background-processor" mode="background-processor"> + <xsl:param name="background"/> + <xsl:choose> + <xsl:when test="starts-with($background,'url')"> + <!-- Check if we have a URL (for a gradient or pattern) --> + <xsl:variable name="arguments" select="translate(normalize-space(substring-before(substring-after($background,'('),')')),' ',',')"/> + <xsl:call-template name="url-processor"> + <xsl:with-param name="url" select="$arguments"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- We probably have a solid color. --> + <xsl:call-template name="color-processor"> + <xsl:with-param name="color" select="$background"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="color-processor"> + <xsl:param name="color"/> + <xsl:choose> + <xsl:when test="starts-with($color,'rgb')"> + <!-- Check if we have an RGB triple --> + <xsl:variable name="arguments" select="normalize-space(substring-before(substring-after($color,'('),')'))"/> + <xsl:call-template name="rgb-triple-processor"> + <xsl:with-param name="triple" select="$arguments"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="$color='none'"> + <!-- Check if we have a literal 'none' --> + <!-- Literal nones seem to actually map to black in practice --> + <xsl:text>"#000000",</xsl:text> + </xsl:when> + <xsl:otherwise> + <!-- This color could either be by name or value. Either way, we --> + <!-- have to ensure that there are no bogus semi-colons. --> + <xsl:text>"</xsl:text> + <xsl:value-of select="normalize-space(translate($color,';',' '))"/> + <xsl:text>",</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="point-processor" mode="point-processor"> + <xsl:param name="points"/> + <!-- Recursively process points in a traditional CAR / CDR pattern --> + <xsl:variable name="pointsCdr" select="normalize-space(substring-after($points,' '))"/> + <!-- We're going "backwards" here to take advantage of tail recursion --> + <xsl:choose> + <xsl:when test="not($pointsCdr)"> + <!-- handle the final argument --> + <xsl:text>{x:</xsl:text> + <xsl:value-of select="substring-before($points,',')"/> + <xsl:text>,y:</xsl:text> + <xsl:value-of select="substring-after($points,',')"/> + <xsl:text>},</xsl:text> + </xsl:when> + <xsl:otherwise> + <!-- handle the current argument --> + <xsl:variable name="pointsCar" select="substring-before($points,' ')"/> + <xsl:text>{x:</xsl:text> + <xsl:value-of select="substring-before($pointsCar,',')"/> + <xsl:text>,y:</xsl:text> + <xsl:value-of select="substring-after($pointsCar,',')"/> + <xsl:text>},</xsl:text> + <xsl:call-template name="point-processor"> + <xsl:with-param name="points" select="$pointsCdr"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="rgb-triple-processor" mode="rgb-triple-processor"> + <xsl:param name="triple"/> + <!-- Note that as SVG triples cannot contain alpha values, we hardcode it to be fully opaque --> + <!-- This could theoretically be better handled by watching for fill-opacity --> + <xsl:variable name="red" select="substring-before($triple,',')"/> + <xsl:variable name="green" select="substring-before(substring-after($triple,concat($red,',')),',')"/> + <xsl:variable name="blue" select="substring-after($triple,concat($red,',',$green,','))"/> + <xsl:text>{"r":</xsl:text> + <xsl:value-of select="normalize-space($red)"/> + <xsl:text>,"g":</xsl:text> + <xsl:value-of select="normalize-space($green)"/> + <xsl:text>,"b":</xsl:text> + <xsl:value-of select="normalize-space($blue)"/> + <xsl:text>,"a":1},</xsl:text> + </xsl:template> + + <xsl:template name="styles-processor" mode="styles-processor"> + <xsl:param name="styles"/> + <!-- Recursively chew through the styles in a traditional CAR / CDR pattern --> + <xsl:variable name="stylesCdr" select="substring-after($styles,';')"/> + <!-- We're going "backwards" here to take advantage of tail recursion --> + <xsl:choose> + <xsl:when test="not($stylesCdr)"> + <!-- handle the final style --> + <xsl:attribute name="{normalize-space(substring-before($styles,':'))}"> + <xsl:value-of select="normalize-space(substring-after($styles,':'))"/> + </xsl:attribute> + </xsl:when> + <xsl:otherwise> + <!-- handle the current style --> + <xsl:variable name="stylesCar" select="substring-before($styles,';')"/> + <xsl:attribute name="{normalize-space(substring-before($stylesCar,':'))}"> + <xsl:value-of select="normalize-space(substring-after($stylesCar,':'))"/> + </xsl:attribute> + <xsl:call-template name="styles-processor"> + <xsl:with-param name="styles" select="$stylesCdr"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="transform-processor" mode="transform-processor"> + <xsl:param name="transforms"/> + <!-- Recursively chew through the transforms in a traditional CAR / CDR pattern --> + <xsl:variable name="transformsCdr" select="normalize-space(substring-after($transforms,')'))"/> + <xsl:variable name="arguments" select="translate(normalize-space(substring-before(substring-after($transforms,'('),')')),' ',',')"/> + <xsl:choose> + <!-- We only handle simple (i.e. nonoverlapping) chained transforms. --> + <!-- This covers most real-world cases, and exceptions are generally --> + <!-- hand-generated and can likewise be hand fixed. --> + <xsl:when test="starts-with($transforms,'matrix')"> + <xsl:call-template name="arg-processor"> + <xsl:with-param name="values" select="$arguments"/> + <xsl:with-param name="labels" select="string('xx,yx,xy,yy,dx,dy')"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="starts-with($transforms,'translate')"> + <!-- If only one argument is provided, it's assumed for both --> + <xsl:choose> + <xsl:when test="contains($arguments,',')"> + <xsl:call-template name="arg-processor"> + <xsl:with-param name="values" select="$arguments"/> + <xsl:with-param name="labels" select="string('dx,dy')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="arg-processor"> + <xsl:with-param name="values" select="concat($arguments,',',$arguments)"/> + <xsl:with-param name="labels" select="string('dx,dy')"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="starts-with($transforms,'scale')"> + <!-- If only one argument is provided, it's assumed for both --> + <xsl:choose> + <xsl:when test="contains($arguments,',')"> + <xsl:call-template name="arg-processor"> + <xsl:with-param name="values" select="$arguments"/> + <xsl:with-param name="labels" select="string('xx,yy')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="arg-processor"> + <xsl:with-param name="values" select="concat($arguments,',',$arguments)"/> + <xsl:with-param name="labels" select="string('xx,yy')"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="starts-with($transforms,'rotate')"> + <!-- Kluge alert - we're redoing a function GFX aleady provides here because --> + <!-- GFX doesn't yet expose it to JSON input. It requires XSLT extensions, too. --> + <!-- If you don't have the extensions, comment the following out (bye bye rotate). --> + <xsl:choose> + <xsl:when test="function-available('math:sin') and function-available('math:cos')"> + <xsl:variable name="sinOfAngle" select="math:sin($arguments div $degressInRadian)"/> + <xsl:variable name="cosOfAngle" select="math:cos($arguments div $degressInRadian)"/> + <xsl:variable name="subarguments" select="concat($cosOfAngle,',',-$sinOfAngle,',',$sinOfAngle,',',$cosOfAngle)"/> + <xsl:call-template name="arg-processor"> + <xsl:with-param name="values" select="$subarguments"/> + <xsl:with-param name="labels" select="string('xx,yx,xy,yy')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message> + <xsl:text>exslt:sin and exslt:cos must be supported for a rotation.</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="starts-with($transforms,'skewX')"> + <!-- Kluge alert - we're redoing a function GFX aleady provides here because --> + <!-- GFX doesn't yet expose it to JSON input. It requires XSLT extensions, too. --> + <!-- If you don't have the extensions, comment the following out (bye bye skewX). --> + <xsl:choose> + <xsl:when test="function-available('math:tan')"> + <xsl:variable name="tanOfAngle" select="math:tan($arguments div $degressInRadian)"/> + <xsl:call-template name="arg-processor"> + <xsl:with-param name="values" select="$tanOfAngle"/> + <xsl:with-param name="labels" select="string('xy')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message> + <xsl:text>exslt:tan must be supported for a skewX.</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="starts-with($transforms,'skewY')"> + <!-- Kluge alert - we're redoing a function GFX aleady provides here because --> + <!-- GFX doesn't yet expose it to JSON input. It requires XSLT extensions, too. --> + <!-- If you don't have the extensions, comment the following out (bye bye skewY). --> + <xsl:choose> + <xsl:when test="function-available('math:tan')"> + <xsl:variable name="tanOfAngle" select="math:tan($arguments div $degressInRadian)"/> + <xsl:call-template name="arg-processor"> + <xsl:with-param name="values" select="$tanOfAngle"/> + <xsl:with-param name="labels" select="string('yx')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message> + <xsl:text>exslt:tan must be supported for a skewY.</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + </xsl:choose> + <xsl:if test="$transformsCdr"> + <!-- handle the other transforms --> + <xsl:call-template name="transform-processor"> + <xsl:with-param name="transforms" select="$transformsCdr"/> + </xsl:call-template> + </xsl:if> + </xsl:template> + + <xsl:template name="url-processor" mode="url-processor"> + <xsl:param name="url"/> + <xsl:param name="groupAttrs" select="''"/> + <!-- We can only handle local references; that's probably all we should get anyway --> + <xsl:if test="starts-with($url,'#')"> + <xsl:apply-templates select="id(substring-after($url,'#'))"> + <xsl:with-param name="groupAttrs" select="$groupAttrs"/> + </xsl:apply-templates> + </xsl:if> + </xsl:template> + + <!-- The following templates help with gradient transforms --> + + <!-- We're temporarily supporting a few SVG features that GFX does not currently support. --> + <!-- The biggest of these is gradient transforms; when GFX natively supports it all the --> + <!-- kluges made to support it here (including all the following code) should be removed. --> + + <xsl:template name="gradient-transform-helper" mode="gradient-transform-helper"> + <!-- This nasty little routine helps gradient adjuster and can be --> + <!-- removed when GFX gets gradientTransform support. --> + <xsl:param name="cxa"/> + <xsl:param name="cya"/> + <xsl:param name="x1a"/> + <xsl:param name="y1a"/> + <xsl:param name="x2a"/> + <xsl:param name="y2a"/> + <xsl:param name="xx"/> + <xsl:param name="xy"/> + <xsl:param name="yx"/> + <xsl:param name="yy"/> + <xsl:param name="dx"/> + <xsl:param name="dy"/> + <xsl:choose> + <xsl:when test="local-name()='radialGradient'"> + <xsl:variable name="cx" select="$xx*$cxa+$xy*$cya+$dx"/> + <xsl:text>cx:</xsl:text> + <xsl:value-of select="$cx"/> + <xsl:text>,</xsl:text> + <xsl:variable name="cy" select="$yx*$cxa+$yy*$cya+$dy"/> + <xsl:text>cy:</xsl:text> + <xsl:value-of select="$cy"/> + <xsl:text>,</xsl:text> + <!-- The results for r here are going to just be approximate --> + <xsl:variable name="r" select="($cx+$cy) div 2"/> + <xsl:text>r:</xsl:text> + <xsl:value-of select="$r"/> + </xsl:when> + <xsl:otherwise> + <xsl:variable name="x1" select="$xx*$x1a+$xy*$y1a+$dx"/> + <xsl:text>x1:</xsl:text> + <xsl:value-of select="$x1"/> + <xsl:text>,</xsl:text> + <xsl:variable name="y1" select="$yx*$x1a+$yy*$y1a+$dy"/> + <xsl:text>y1:</xsl:text> + <xsl:value-of select="$y1"/> + <xsl:text>,</xsl:text> + <xsl:variable name="x2" select="$xx*$x2a+$xy*$y2a+$dx"/> + <xsl:text>x2:</xsl:text> + <xsl:value-of select="$x2"/> + <xsl:text>,</xsl:text> + <xsl:variable name="y2" select="$yx*$x2a+$yy*$y2a+$dy"/> + <xsl:text>y2:</xsl:text> + <xsl:value-of select="$y2"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="gradient-adjuster" mode="gradient-adjuster"> + <xsl:param name="node"/> + <!-- This code is awful and only meant to serve until GFX gets gradientTransform support. --> + <!-- Once GFX does gradientTransforms, the following should be destroyed and forgotten. --> + <!-- While this support is better than nothing, it cannot 100% reproduce the effects --> + <!-- that true gradientTransform support in GFX could provide. --> + <xsl:choose> + <xsl:when test="starts-with($node/@gradientTransform,'matrix')"> + <xsl:variable name="args" select="normalize-space(substring-before(substring-after($node/@gradientTransform,'matrix('),')'))"/> + <xsl:variable name="xx" select="substring-before($args,' ')"/> + <xsl:variable name="yx" select="substring-before(substring-after($args,' '),' ')"/> + <xsl:variable name="xy" select="substring-before(substring-after($args,concat($xx,' ',$yx,' ')),' ')"/> + <xsl:variable name="yy" select="substring-before(substring-after($args,concat($xx,' ',$yx,' ',$xy,' ')),' ')"/> + <xsl:variable name="dx" select="substring-before(substring-after($args,concat($xx,' ',$yx,' ',$xy,' ',$yy,' ')),' ')"/> + <xsl:variable name="dy" select="substring-after($args,concat($xx,' ',$yx,' ',$xy,' ',$yy,' ',$dx,' '))"/> + <xsl:call-template name="gradient-transform-helper"> + <xsl:with-param name="cxa" select="$node/@cx"/> + <xsl:with-param name="cya" select="$node/@cy"/> + <xsl:with-param name="x1a" select="$node/@x1"/> + <xsl:with-param name="y1a" select="$node/@y1"/> + <xsl:with-param name="x2a" select="$node/@x2"/> + <xsl:with-param name="y2a" select="$node/@y2"/> + <xsl:with-param name="xx" select="$xx"/> + <xsl:with-param name="yx" select="$yx"/> + <xsl:with-param name="xy" select="$xy"/> + <xsl:with-param name="yy" select="$yy"/> + <xsl:with-param name="dx" select="$dx"/> + <xsl:with-param name="dy" select="$dy"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="starts-with($node/@gradientTransform,'translate')"> + <xsl:variable name="args" select="normalize-space(substring-before(substring-after($node/@gradientTransform,'translate('),')'))"/> + <!-- If only one argument is provided, it's assumed for both --> + <xsl:choose> + <xsl:when test="contains($args,',')"> + <xsl:call-template name="gradient-transform-helper"> + <xsl:with-param name="cxa" select="$node/@cx"/> + <xsl:with-param name="cya" select="$node/@cy"/> + <xsl:with-param name="x1a" select="$node/@x1"/> + <xsl:with-param name="y1a" select="$node/@y1"/> + <xsl:with-param name="x2a" select="$node/@x2"/> + <xsl:with-param name="y2a" select="$node/@y2"/> + <xsl:with-param name="xx" select="1"/> + <xsl:with-param name="yx" select="0"/> + <xsl:with-param name="xy" select="1"/> + <xsl:with-param name="yy" select="0"/> + <xsl:with-param name="dx" select="substring-before($args,' ')"/> + <xsl:with-param name="dy" select="substring-after($args,' ')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="gradient-transform-helper"> + <xsl:with-param name="cxa" select="$node/@cx"/> + <xsl:with-param name="cya" select="$node/@cy"/> + <xsl:with-param name="x1a" select="$node/@x1"/> + <xsl:with-param name="y1a" select="$node/@y1"/> + <xsl:with-param name="x2a" select="$node/@x2"/> + <xsl:with-param name="y2a" select="$node/@y2"/> + <xsl:with-param name="xx" select="1"/> + <xsl:with-param name="yx" select="0"/> + <xsl:with-param name="xy" select="1"/> + <xsl:with-param name="yy" select="0"/> + <xsl:with-param name="dx" select="$args"/> + <xsl:with-param name="dy" select="$args"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="starts-with($node/@gradientTransform,'scale')"> + <xsl:variable name="args" select="normalize-space(substring-before(substring-after($node/@gradientTransform,'scale('),')'))"/> + <!-- If only one argument is provided, it's assumed for both --> + <xsl:choose> + <xsl:when test="contains($args,',')"> + <xsl:call-template name="gradient-transform-helper"> + <xsl:with-param name="cxa" select="$node/@cx"/> + <xsl:with-param name="cya" select="$node/@cy"/> + <xsl:with-param name="x1a" select="$node/@x1"/> + <xsl:with-param name="y1a" select="$node/@y1"/> + <xsl:with-param name="x2a" select="$node/@x2"/> + <xsl:with-param name="y2a" select="$node/@y2"/> + <xsl:with-param name="xx" select="substring-before($args,' ')"/> + <xsl:with-param name="yx" select="0"/> + <xsl:with-param name="xy" select="substring-after($args,' ')"/> + <xsl:with-param name="yy" select="0"/> + <xsl:with-param name="dx" select="0"/> + <xsl:with-param name="dy" select="0"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="gradient-transform-helper"> + <xsl:with-param name="cxa" select="$node/@cx"/> + <xsl:with-param name="cya" select="$node/@cy"/> + <xsl:with-param name="x1a" select="$node/@x1"/> + <xsl:with-param name="y1a" select="$node/@y1"/> + <xsl:with-param name="x2a" select="$node/@x2"/> + <xsl:with-param name="y2a" select="$node/@y2"/> + <xsl:with-param name="xx" select="$args"/> + <xsl:with-param name="yx" select="0"/> + <xsl:with-param name="xy" select="$args"/> + <xsl:with-param name="yy" select="0"/> + <xsl:with-param name="dx" select="0"/> + <xsl:with-param name="dy" select="0"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> <!-- Otherwise it's got to be a rotation --> + <xsl:variable name="args" select="normalize-space(substring-before(substring-after($node/@gradientTransform,'rotate('),')'))"/> + <xsl:choose> + <xsl:when test="function-available('math:sin') and function-available('math:cos')"> + <xsl:variable name="sinOfAngle" select="math:sin($args div $degressInRadian)"/> + <xsl:variable name="cosOfAngle" select="math:cos($args div $degressInRadian)"/> + <xsl:call-template name="gradient-transform-helper"> + <xsl:with-param name="cxa" select="$node/@cx"/> + <xsl:with-param name="cya" select="$node/@cy"/> + <xsl:with-param name="x1a" select="$node/@x1"/> + <xsl:with-param name="y1a" select="$node/@y1"/> + <xsl:with-param name="x2a" select="$node/@x2"/> + <xsl:with-param name="y2a" select="$node/@y2"/> + <xsl:with-param name="xx" select="$cosOfAngle"/> + <xsl:with-param name="yx" select="-$sinOfAngle"/> + <xsl:with-param name="xy" select="$sinOfAngle"/> + <xsl:with-param name="yy" select="$cosOfAngle"/> + <xsl:with-param name="dy" select="0"/> + <xsl:with-param name="dy" select="0"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message> + <xsl:text>exslt:sin and exslt:cos must be supported for a gradient rotation.</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + <xsl:text>,</xsl:text> + </xsl:template> + + <!-- The following templates handle related batches of attributes --> + + <xsl:template name="font"> + <xsl:param name="node"/> + <!-- Only include if we have at least some font properties defined --> + <xsl:if test="$node/@font-style or $node/@font-variant or $node/@font-weight or $node/@font-size or $node/@font-family"> + <xsl:text>font:{ type:"font",</xsl:text> + <xsl:if test="$node/@font-style"> + <xsl:text>style:"</xsl:text> + <xsl:value-of select="$node/@font-style"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:if test="$node/@font-variant"> + <xsl:text>variant:"</xsl:text> + <xsl:value-of select="$node/@font-variant"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:if test="$node/@font-weight"> + <xsl:text>weight:"</xsl:text> + <xsl:value-of select="$node/@font-weight"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:if test="$node/@font-size"> + <xsl:text>size:"</xsl:text> + <xsl:value-of select="$node/@font-size"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:if test="$node/@font-family"> + <xsl:text>family:"</xsl:text> + <xsl:value-of select="$node/@font-family"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:text>},</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template name="stroke"> + <xsl:param name="node"/> + <!-- Only include if we have at least some stroke properties defined --> + <xsl:if test="$node/@stroke or $node/@stroke-width or $node/@stroke-linecap or $node/@stroke-linejoin"> + <xsl:text>stroke:{</xsl:text> + <!-- We don't currently handle stroke-dasharray or stroke-dashoffset --> + <!-- Note that while we'll pass stroke background info, GFX won't yet use it. --> + <xsl:if test="$node/@stroke"> + <xsl:text>color:</xsl:text> + <xsl:call-template name="background-processor"> + <xsl:with-param name="background" select="$node/@stroke"/> + </xsl:call-template> + </xsl:if> + <xsl:if test="$node/@stroke-width"> + <xsl:text>width:"</xsl:text> + <xsl:value-of select="$node/@stroke-width"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:if test="$node/@stroke-linecap"> + <xsl:text>cap:"</xsl:text> + <xsl:value-of select="$node/@stroke-linecap"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:if test="$node/@stroke-linejoin"> + <xsl:text>join:"</xsl:text> + <xsl:value-of select="$node/@stroke-linejoin"/> + <xsl:text>",</xsl:text> + </xsl:if> + <xsl:choose> + <!-- This is really cheesy but better than nothing. --> + <!-- We probably ought to match a few specific cases when we can. %FIX% --> + <xsl:when test="$node/@stroke-dasharray"> + <xsl:text>style:"Dash",</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>style:"Solid",</xsl:text> + </xsl:otherwise> + </xsl:choose> + <xsl:text>},</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template name="common-attributes"> + <xsl:param name="node"/> + <!-- Pretty much every shape has to handle this same batch of attributes. --> + <xsl:apply-templates select="$node/@style"/> + <!-- Note that we make no effort to guard against overlapping styles. --> + <xsl:apply-templates select="$node/@fill"/> + <xsl:call-template name="stroke"> + <xsl:with-param name="node" select="$node"/> + </xsl:call-template> + <xsl:apply-templates select="$node/@transform"/> + <!-- Fonts are actually illegal in most shapes, but including them here doesn't --> + <!-- really slow things down much and does clean up code a bit for the shapes --> + <!-- that do allow them. --> + <xsl:call-template name="font"> + <xsl:with-param name="node" select="$node"/> + </xsl:call-template> + <!-- Ditto for stop-colors. --> + <xsl:apply-templates select="$node/@stop-color"/> + </xsl:template> + + <!-- SVG Attribute Handling --> + + <xsl:template match="@id"> + <xsl:text>name:"</xsl:text> + <xsl:apply-templates/> + <xsl:text>",</xsl:text> + </xsl:template> + + <xsl:template match="@x|@y|@x1|@x2|@y1|@y2|@cx|@cy|@r|@rx|@ry|@fx|@fy|@width|@height|@offset"> + <!-- Generic attribute followed by comma --> + <xsl:value-of select="local-name()"/> + <xsl:text>:</xsl:text> + <xsl:value-of select="."/> + <xsl:text>,</xsl:text> + </xsl:template> + + <xsl:template match="@d"> + <!-- Used only by path objects; often has tons of extra whitespace --> + <xsl:text>path:"</xsl:text> + <xsl:value-of select="normalize-space(.)"/> + <xsl:text>",</xsl:text> + </xsl:template> + + <xsl:template match="@fill"> + <!-- Used by most shapes and can have a URL, a solid color, or "none" --> + <xsl:if test=". != 'none'"> + <xsl:text>fill:</xsl:text> + <xsl:call-template name="background-processor"> + <xsl:with-param name="background" select="."/> + </xsl:call-template> + </xsl:if> + </xsl:template> + + <xsl:template match="@stop-color"> + <xsl:call-template name="color-processor"> + <xsl:with-param name="color" select="."/> + </xsl:call-template> + </xsl:template> + + <xsl:template match="@style"> + <!-- A style property is really a bunch of other properties crammed together. --> + <!-- We therefore make a dummy element and process it as normal. --> + <xsl:variable name="dummy"> + <dummy> + <xsl:call-template name="styles-processor"> + <xsl:with-param name="styles" select="."/> + </xsl:call-template> + </dummy> + </xsl:variable> + <xsl:choose> + <!-- Using a dummy element requires node-set capability. Straight XSLT 1.0 --> + <!-- lacks this, but pretty much every XSLT processor offers it as an extension. --> + <xsl:when test="function-available('exsl:node-set')"> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="exsl:node-set($dummy)/dummy"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('saxon:node-set')"> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="saxon:node-set($dummy)"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeSet')"> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="xalan:nodeSet($dummy)"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message> + <xsl:text>exslt:node-set is required for processing the style attribute.</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="@transform|@gradientTransform"> + <!-- Several transform types are supported --> + <xsl:text>transform:{</xsl:text> + <xsl:call-template name="transform-processor"> + <xsl:with-param name="transforms" select="."/> + </xsl:call-template> + <xsl:text>}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <!-- SVG Element Handling --> + + <xsl:template match="svg:a"> + <xsl:param name="groupAttrs" select="''"/> + <!-- Anchors are actually meaningless to us, but their contents should usually be processed. --> + <xsl:variable name="newGroupAttrs"> + <xsl:value-of select="$groupAttrs"/> + <xsl:apply-templates select="@style"/> + <!-- Note that we make no effort to guard against overlapping styles; we just order --> + <!-- them to be consistent. This naive approach will usually, but not always, work. --> + <xsl:apply-templates select="@fill"/> + <xsl:call-template name="stroke"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </xsl:variable> + <xsl:apply-templates select="&SupportedElements;"> + <xsl:with-param name="groupAttrs" select="$newGroupAttrs"/> + </xsl:apply-templates> + </xsl:template> + + <xsl:template match="svg:circle"> + <xsl:param name="groupAttrs" select="''"/> + <xsl:text>{</xsl:text> + <xsl:apply-templates select="@id"/> + <xsl:text>shape:{type:"circle",</xsl:text> + <xsl:apply-templates select="@cx|@cy|@r"/> + <xsl:text>},</xsl:text> + <xsl:value-of select="$groupAttrs"/> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:text>}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:ellipse"> + <xsl:param name="groupAttrs" select="''"/> + <xsl:text>{</xsl:text> + <xsl:apply-templates select="@id"/> + <xsl:text>shape:{type:"ellipse",</xsl:text> + <xsl:apply-templates select="@cx|@cy|@rx|@ry"/> + <xsl:text>}</xsl:text> + <xsl:value-of select="$groupAttrs"/> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:text>}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:g"> + <xsl:param name="groupAttrs" select="''"/> + <!-- The basic grouping type can contain shapes, other groups, and have a transform --> + <xsl:text>{</xsl:text> + <xsl:apply-templates select="@id"/> + <xsl:text>children:[</xsl:text> + <!-- Note that GFX does not yet support fills etc. on a group, even though SVG does. --> + <!-- It's a planned enhancement though, so when GFX gets the ability to handle these, --> + <!-- remove the following ten lines and stop propagating groupAttrs. --> + <xsl:variable name="newGroupAttrs"> + <xsl:value-of select="$groupAttrs"/> + <xsl:apply-templates select="@style"/> + <!-- Note that we make no effort to guard against overlapping styles; we just order --> + <!-- them to be consistent. This naive approach will usually, but not always, work. --> + <xsl:apply-templates select="@fill"/> + <xsl:call-template name="stroke"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </xsl:variable> + <xsl:apply-templates select="&SupportedElements;"> + <xsl:with-param name="groupAttrs" select="$newGroupAttrs"/> + </xsl:apply-templates> + <xsl:text>]</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + <!-- When GFX gets group fills etc., remove the following line and uncomment the ones below. --> + <xsl:apply-templates select="@transform"/> + <!--<xsl:call-template name="common-attributes">--> + <!-- <xsl:with-param name="node" select="."/>--> + <!--</xsl:call-template>--> + <xsl:text>}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:image"> + <xsl:param name="groupAttrs" select="''"/> + <!-- Note that images must be GIF, JPEG, or PNG. --> + <xsl:if test="not(parent::pattern)"> + <!-- When being used as a background pattern we don't want type info. --> + <xsl:text>{</xsl:text> + <xsl:apply-templates select="@id"/> + <xsl:text>shape:{type:"image",</xsl:text> + </xsl:if> + <xsl:apply-templates select="@x|@y|@width|@height"/> + <xsl:text>src:"</xsl:text> + <xsl:value-of select="@xlink:href"/> + <xsl:text>",</xsl:text> + <xsl:if test="not(parent::pattern)"> + <xsl:text>},</xsl:text> + <xsl:value-of select="$groupAttrs"/> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:text>},</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:line"> + <xsl:param name="groupAttrs" select="''"/> + <xsl:text>{</xsl:text> + <xsl:apply-templates select="@id"/> + <xsl:text>shape:{type:"line",</xsl:text> + <xsl:apply-templates select="@x1|@y1|@x2|@y2"/> + <xsl:text>},</xsl:text> + <xsl:value-of select="$groupAttrs"/> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:text>}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:linearGradient"> + <xsl:text>{type:"linear",</xsl:text> + <!-- Kluge alert - GFX doesn't handle gradientTransforms. We can help in --> + <!-- the common case of matrix transforms in user space. Other cases we ignore. --> + <!-- Even for this one case the results aren't anywhere near as good as real support in GFX. --> + <xsl:choose> + <!-- Kluge alert - this code is only meant to serve until GFX gets gradientTransform support. --> + <!-- Once GFX does gradientTransforms, only the straight apply-templates should be kept. --> + <xsl:when test="starts-with(@gradientTransform,'matrix') and @gradientUnits='userSpaceOnUse'"> + <xsl:call-template name="gradient-adjuster"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="@x1|@x2|@y1|@y2"/> + </xsl:otherwise> + </xsl:choose> + <xsl:text>colors:[</xsl:text> + <xsl:apply-templates select="svg:stop"/> + <!-- Unfortunately GFX doesn't do gradientTransforms. --> + <!-- Uncommenting the following would support it here. --> + <!-- <xsl:apply-templates select="@x1|@x2|@y1|@y2"/> --> + <!-- <xsl:apply-templates select="@gradientTransform"/> --> + <xsl:text>]}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:path"> + <xsl:param name="groupAttrs" select="''"/> + <xsl:if test="not(parent::textpath)"> + <!-- When being used within a textpath we don't want type info. --> + <xsl:text>{</xsl:text> + <xsl:apply-templates select="@id"/> + <xsl:text>shape:{type:"path",</xsl:text> + </xsl:if> + <xsl:apply-templates select="@d"/> + <xsl:if test="not(parent::textpath)"> + <xsl:text>},</xsl:text> + <xsl:value-of select="$groupAttrs"/> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:text>},</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:pattern"> + <!-- GFX only seems to handle image pattern type fills, so that's all we do --> + <xsl:text>{type:"pattern",</xsl:text> + <xsl:apply-templates select="@width|@height|@xlink:href"/> + <xsl:text>}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:polygon|svg:polyline"> + <xsl:param name="groupAttrs" select="''"/> + <!-- Polygons are mostly treated as polylines --> + <xsl:text>{</xsl:text> + <xsl:apply-templates select="@id"/> + <xsl:text>shape:{type:"polyline",points:[</xsl:text> + <!-- We just have to ensure that endpoints match for a polygon; it's assumed in SVG --> + <xsl:variable name="seminormalizedPoints" select="normalize-space(@points)"/> + <xsl:variable name="normalizedPoints"> + <xsl:call-template name="kill-extra-spaces"> + <xsl:with-param name="string" select="$seminormalizedPoints"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="firstPoint" select="substring-before($normalizedPoints,' ')"/> + <xsl:choose> + <xsl:when test="contains(local-name(),'polygon') and + $firstPoint!=substring($normalizedPoints,string-length($normalizedPoints)-string-length($firstPoint)+1)"> + <xsl:call-template name="point-processor"> + <xsl:with-param name="points" select="concat($normalizedPoints,' ',$firstPoint)"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="point-processor"> + <xsl:with-param name="points" select="$normalizedPoints"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + <xsl:text>]},</xsl:text> + <xsl:value-of select="$groupAttrs"/> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:text>}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:radialGradient"> + <xsl:text>{type:"radial",</xsl:text> + <!-- Kluge alert - GFX doesn't handle gradientTransforms. We can help in --> + <!-- the common case of matrix transforms in user space. Other cases we ignore. --> + <!-- Even for this one case the results aren't anywhere near as good as real support in GFX. --> + <xsl:choose> + <!-- Kluge alert - this code is only meant to serve until GFX gets gradientTransform support. --> + <!-- Once GFX does gradientTransforms, only the straight apply-templates should be kept. --> + <xsl:when test="starts-with(@gradientTransform,'matrix') and @gradientUnits='userSpaceOnUse'"> + <xsl:call-template name="gradient-adjuster"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="@cx|@cy|@r"/> + </xsl:otherwise> + </xsl:choose> + <!-- GFX doesn't currently support fx & fy --> + <!-- Uncommenting the following would support it here. --> + <!-- <xsl:apply-templates select="@fx|@fy"/> --> + <xsl:text>colors:[</xsl:text> + <xsl:apply-templates select="svg:stop"/> + <!-- Unfortunately GFX doesn't do gradientTransforms. --> + <!-- Uncommenting the following would support it here. --> + <!-- <xsl:apply-templates select="@cx|@cy|@r"/> --> + <!-- <xsl:apply-templates select="@gradientTransform"/> --> + <xsl:text>]}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:rect"> + <xsl:param name="groupAttrs" select="''"/> + <xsl:text>{</xsl:text> + <xsl:apply-templates select="@id"/> + <xsl:text>shape:{type:"rect",</xsl:text> + <xsl:apply-templates select="@x|@y|@width|@height"/> + <xsl:if test="@rx and @ry"> + <!-- Do approximate rounded corners if both an rx and ry are present. --> + <xsl:variable name="r" select="(@rx+@ry) div 2"/> + <xsl:text>r:</xsl:text> + <xsl:value-of select="$r"/> + </xsl:if> + <xsl:text>},</xsl:text> + <xsl:value-of select="$groupAttrs"/> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:text>}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:stop"> + <!-- Both gradient types use the same sort of stops --> + <xsl:text>{</xsl:text> + <xsl:apply-templates select="@offset"/> + <xsl:text>color:</xsl:text> + <xsl:apply-templates select="@style"/> + <xsl:text>}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:text|svg:textPath"> + <xsl:param name="groupAttrs" select="''"/> + <!-- Support for textPath is not functional as GFX doesn't seem to have a --> + <!-- complete serialized form at this time. %FIX% --> + <xsl:text>{</xsl:text> + <xsl:apply-templates select="@id"/> + <xsl:choose> + <xsl:when test="contains(local-name(),'textpath')"> + <xsl:text>shape:{type:"textpath",text:"</xsl:text> + <xsl:apply-templates/> + <xsl:text>",</xsl:text> + <xsl:variable name="arguments" select="translate(normalize-space(substring-before(substring-after(@xlink:href,'('),')')),' ',',')"/> + <xsl:call-template name="url-processor"> + <xsl:with-param name="url" select="$arguments"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- Regular text has slightly different attributes --> + <xsl:choose> + <!-- It's possible for a text element to contain a textpath element. --> + <xsl:when test="not(textpath)"> + <xsl:text>shape:{type:"text",text:"</xsl:text> + <xsl:apply-templates/> + <xsl:text>",</xsl:text> + <xsl:apply-templates select="@x|@y"/> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates/> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + <xsl:text>},</xsl:text> + <!-- Kluge alert - if no fill is defined, GFX won't display anything --> + <!-- Our quick fix here is to force a fill of some sort. --> + <xsl:if test="not(@fill)"> + <xsl:text>fill:"#000000",</xsl:text> + </xsl:if> + <xsl:value-of select="$groupAttrs"/> + <xsl:call-template name="common-attributes"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:text>}</xsl:text> + <xsl:if test="not(position()=last())"> + <xsl:text >,</xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="svg:use"> + <xsl:param name="groupAttrs" select="''"/> + <!-- Use just refers to an existing element, essentially duplicating it. --> + <xsl:variable name="newGroupAttrs"> + <xsl:value-of select="$groupAttrs"/> + <xsl:apply-templates select="@style"/> + <!-- Note that we make no effort to guard against overlapping styles; we just order --> + <!-- them to be consistent. This naive approach will usually, but not always, work. --> + <xsl:apply-templates select="@fill"/> + <xsl:call-template name="stroke"> + <xsl:with-param name="node" select="."/> + </xsl:call-template> + <xsl:apply-templates select="@transform"/> + </xsl:variable> + <xsl:call-template name="url-processor"> + <xsl:with-param name="url" select="normalize-space(@xlink:href)"/> + <xsl:with-param name="groupAttrs" select="$newGroupAttrs"/> + </xsl:call-template> + </xsl:template> + + <!-- The main SVG element itself --> + + <xsl:template match="/svg:svg"> + <xsl:text>[</xsl:text> + <xsl:apply-templates select="&SupportedElements;"/> + <xsl:text>]</xsl:text> + </xsl:template> +</xsl:stylesheet>
\ No newline at end of file diff --git a/js/dojo-1.6/dojox/gfx/shape.js b/js/dojo-1.6/dojox/gfx/shape.js new file mode 100644 index 0000000..f2e5e70 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/shape.js @@ -0,0 +1,761 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.shape"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.shape"] = true;
+dojo.provide("dojox.gfx.shape");
+
+dojo.require("dojox.gfx._base");
+
+dojo.declare("dojox.gfx.shape.Shape", null, {
+ // summary: a Shape object, which knows how to apply
+ // graphical attributes and transformations
+
+ constructor: function(){
+ // rawNode: Node: underlying node
+ this.rawNode = null;
+
+ // shape: Object: an abstract shape object
+ // (see dojox.gfx.defaultPath,
+ // dojox.gfx.defaultPolyline,
+ // dojox.gfx.defaultRect,
+ // dojox.gfx.defaultEllipse,
+ // dojox.gfx.defaultCircle,
+ // dojox.gfx.defaultLine,
+ // or dojox.gfx.defaultImage)
+ this.shape = null;
+
+ // matrix: dojox.gfx.Matrix2D: a transformation matrix
+ this.matrix = null;
+
+ // fillStyle: Object: a fill object
+ // (see dojox.gfx.defaultLinearGradient,
+ // dojox.gfx.defaultRadialGradient,
+ // dojox.gfx.defaultPattern,
+ // or dojo.Color)
+ this.fillStyle = null;
+
+ // strokeStyle: Object: a stroke object
+ // (see dojox.gfx.defaultStroke)
+ this.strokeStyle = null;
+
+ // bbox: dojox.gfx.Rectangle: a bounding box of this shape
+ // (see dojox.gfx.defaultRect)
+ this.bbox = null;
+
+ // virtual group structure
+
+ // parent: Object: a parent or null
+ // (see dojox.gfx.Surface,
+ // dojox.gfx.shape.VirtualGroup,
+ // or dojox.gfx.Group)
+ this.parent = null;
+
+ // parentMatrix: dojox.gfx.Matrix2D
+ // a transformation matrix inherited from the parent
+ this.parentMatrix = null;
+ },
+
+ // trivial getters
+
+ getNode: function(){
+ // summary: returns the current DOM Node or null
+ return this.rawNode; // Node
+ },
+ getShape: function(){
+ // summary: returns the current shape object or null
+ // (see dojox.gfx.defaultPath,
+ // dojox.gfx.defaultPolyline,
+ // dojox.gfx.defaultRect,
+ // dojox.gfx.defaultEllipse,
+ // dojox.gfx.defaultCircle,
+ // dojox.gfx.defaultLine,
+ // or dojox.gfx.defaultImage)
+ return this.shape; // Object
+ },
+ getTransform: function(){
+ // summary: returns the current transformation matrix or null
+ return this.matrix; // dojox.gfx.Matrix2D
+ },
+ getFill: function(){
+ // summary: returns the current fill object or null
+ // (see dojox.gfx.defaultLinearGradient,
+ // dojox.gfx.defaultRadialGradient,
+ // dojox.gfx.defaultPattern,
+ // or dojo.Color)
+ return this.fillStyle; // Object
+ },
+ getStroke: function(){
+ // summary: returns the current stroke object or null
+ // (see dojox.gfx.defaultStroke)
+ return this.strokeStyle; // Object
+ },
+ getParent: function(){
+ // summary: returns the parent or null
+ // (see dojox.gfx.Surface,
+ // dojox.gfx.shape.VirtualGroup,
+ // or dojox.gfx.Group)
+ return this.parent; // Object
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box or null
+ // (see dojox.gfx.defaultRect)
+ return this.bbox; // dojox.gfx.Rectangle
+ },
+ getTransformedBoundingBox: function(){
+ // summary: returns an array of four points or null
+ // four points represent four corners of the untransformed bounding box
+ var b = this.getBoundingBox();
+ if(!b){
+ return null; // null
+ }
+ var m = this._getRealMatrix();
+ gm = dojox.gfx.matrix;
+ return [ // Array
+ gm.multiplyPoint(m, b.x, b.y),
+ gm.multiplyPoint(m, b.x + b.width, b.y),
+ gm.multiplyPoint(m, b.x + b.width, b.y + b.height),
+ gm.multiplyPoint(m, b.x, b.y + b.height)
+ ];
+ },
+ getEventSource: function(){
+ // summary: returns a Node, which is used as
+ // a source of events for this shape
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ return this.rawNode; // Node
+ },
+
+ // empty settings
+
+ setShape: function(shape){
+ // summary: sets a shape object
+ // (the default implementation simply ignores it)
+ // shape: Object: a shape object
+ // (see dojox.gfx.defaultPath,
+ // dojox.gfx.defaultPolyline,
+ // dojox.gfx.defaultRect,
+ // dojox.gfx.defaultEllipse,
+ // dojox.gfx.defaultCircle,
+ // dojox.gfx.defaultLine,
+ // or dojox.gfx.defaultImage)
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ this.shape = dojox.gfx.makeParameters(this.shape, shape);
+ this.bbox = null;
+ return this; // self
+ },
+ setFill: function(fill){
+ // summary: sets a fill object
+ // (the default implementation simply ignores it)
+ // fill: Object: a fill object
+ // (see dojox.gfx.defaultLinearGradient,
+ // dojox.gfx.defaultRadialGradient,
+ // dojox.gfx.defaultPattern,
+ // or dojo.Color)
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ if(!fill){
+ // don't fill
+ this.fillStyle = null;
+ return this; // self
+ }
+ var f = null;
+ if(typeof(fill) == "object" && "type" in fill){
+ // gradient or pattern
+ switch(fill.type){
+ case "linear":
+ f = dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient, fill);
+ break;
+ case "radial":
+ f = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);
+ break;
+ case "pattern":
+ f = dojox.gfx.makeParameters(dojox.gfx.defaultPattern, fill);
+ break;
+ }
+ }else{
+ // color object
+ f = dojox.gfx.normalizeColor(fill);
+ }
+ this.fillStyle = f;
+ return this; // self
+ },
+ setStroke: function(stroke){
+ // summary: sets a stroke object
+ // (the default implementation simply ignores it)
+ // stroke: Object: a stroke object
+ // (see dojox.gfx.defaultStroke)
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ if(!stroke){
+ // don't stroke
+ this.strokeStyle = null;
+ return this; // self
+ }
+ // normalize the stroke
+ if(typeof stroke == "string" || dojo.isArray(stroke) || stroke instanceof dojo.Color){
+ stroke = {color: stroke};
+ }
+ var s = this.strokeStyle = dojox.gfx.makeParameters(dojox.gfx.defaultStroke, stroke);
+ s.color = dojox.gfx.normalizeColor(s.color);
+ return this; // self
+ },
+ setTransform: function(matrix){
+ // summary: sets a transformation matrix
+ // matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+ // (see an argument of dojox.gfx.Matrix2D
+ // constructor for a list of acceptable arguments)
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ this.matrix = dojox.gfx.matrix.clone(matrix ? dojox.gfx.matrix.normalize(matrix) : dojox.gfx.matrix.identity);
+ return this._applyTransform(); // self
+ },
+
+ _applyTransform: function(){
+ // summary: physically sets a matrix
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ return this; // self
+ },
+
+ // z-index
+
+ moveToFront: function(){
+ // summary: moves a shape to front of its parent's list of shapes
+ var p = this.getParent();
+ if(p){
+ p._moveChildToFront(this);
+ this._moveToFront(); // execute renderer-specific action
+ }
+ return this; // self
+ },
+ moveToBack: function(){
+ // summary: moves a shape to back of its parent's list of shapes
+ var p = this.getParent();
+ if(p){
+ p._moveChildToBack(this);
+ this._moveToBack(); // execute renderer-specific action
+ }
+ return this;
+ },
+ _moveToFront: function(){
+ // summary: renderer-specific hook, see dojox.gfx.shape.Shape.moveToFront()
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+ },
+ _moveToBack: function(){
+ // summary: renderer-specific hook, see dojox.gfx.shape.Shape.moveToFront()
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+ },
+
+ // apply left & right transformation
+
+ applyRightTransform: function(matrix){
+ // summary: multiplies the existing matrix with an argument on right side
+ // (this.matrix * matrix)
+ // matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+ // (see an argument of dojox.gfx.Matrix2D
+ // constructor for a list of acceptable arguments)
+ return matrix ? this.setTransform([this.matrix, matrix]) : this; // self
+ },
+ applyLeftTransform: function(matrix){
+ // summary: multiplies the existing matrix with an argument on left side
+ // (matrix * this.matrix)
+ // matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+ // (see an argument of dojox.gfx.Matrix2D
+ // constructor for a list of acceptable arguments)
+ return matrix ? this.setTransform([matrix, this.matrix]) : this; // self
+ },
+ applyTransform: function(matrix){
+ // summary: a shortcut for dojox.gfx.Shape.applyRightTransform
+ // matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+ // (see an argument of dojox.gfx.Matrix2D
+ // constructor for a list of acceptable arguments)
+ return matrix ? this.setTransform([this.matrix, matrix]) : this; // self
+ },
+
+ // virtual group methods
+
+ removeShape: function(silently){
+ // summary: removes the shape from its parent's list of shapes
+ // silently: Boolean?: if true, do not redraw a picture yet
+ if(this.parent){
+ this.parent.remove(this, silently);
+ }
+ return this; // self
+ },
+ _setParent: function(parent, matrix){
+ // summary: sets a parent
+ // parent: Object: a parent or null
+ // (see dojox.gfx.Surface,
+ // dojox.gfx.shape.VirtualGroup,
+ // or dojox.gfx.Group)
+ // matrix: dojox.gfx.Matrix2D:
+ // a 2D matrix or a matrix-like object
+ this.parent = parent;
+ return this._updateParentMatrix(matrix); // self
+ },
+ _updateParentMatrix: function(matrix){
+ // summary: updates the parent matrix with new matrix
+ // matrix: dojox.gfx.Matrix2D:
+ // a 2D matrix or a matrix-like object
+ this.parentMatrix = matrix ? dojox.gfx.matrix.clone(matrix) : null;
+ return this._applyTransform(); // self
+ },
+ _getRealMatrix: function(){
+ // summary: returns the cumulative ("real") transformation matrix
+ // by combining the shape's matrix with its parent's matrix
+ var m = this.matrix;
+ var p = this.parent;
+ while(p){
+ if(p.matrix){
+ m = dojox.gfx.matrix.multiply(p.matrix, m);
+ }
+ p = p.parent;
+ }
+ return m; // dojox.gfx.Matrix2D
+ }
+});
+
+dojox.gfx.shape._eventsProcessing = {
+ connect: function(name, object, method){
+ // summary: connects a handler to an event on this shape
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ return arguments.length > 2 ? // Object
+ dojo.connect(this.getEventSource(), name, object, method) :
+ dojo.connect(this.getEventSource(), name, object);
+ },
+ disconnect: function(token){
+ // summary: connects a handler by token from an event on this shape
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ dojo.disconnect(token);
+ }
+};
+
+dojo.extend(dojox.gfx.shape.Shape, dojox.gfx.shape._eventsProcessing);
+
+dojox.gfx.shape.Container = {
+ // summary: a container of shapes, which can be used
+ // as a foundation for renderer-specific groups, or as a way
+ // to logically group shapes (e.g, to propagate matricies)
+
+ _init: function() {
+ // children: Array: a list of children
+ this.children = [];
+ },
+
+ // group management
+
+ openBatch: function() {
+ // summary: starts a new batch, subsequent new child shapes will be held in
+ // the batch instead of appending to the container directly
+ },
+ closeBatch: function() {
+ // summary: submits the current batch, append all pending child shapes to DOM
+ },
+ add: function(shape){
+ // summary: adds a shape to the list
+ // shape: dojox.gfx.Shape: a shape
+ var oldParent = shape.getParent();
+ if(oldParent){
+ oldParent.remove(shape, true);
+ }
+ this.children.push(shape);
+ return shape._setParent(this, this._getRealMatrix()); // self
+ },
+ remove: function(shape, silently){
+ // summary: removes a shape from the list
+ // silently: Boolean?: if true, do not redraw a picture yet
+ for(var i = 0; i < this.children.length; ++i){
+ if(this.children[i] == shape){
+ if(silently){
+ // skip for now
+ }else{
+ shape.parent = null;
+ shape.parentMatrix = null;
+ }
+ this.children.splice(i, 1);
+ break;
+ }
+ }
+ return this; // self
+ },
+ clear: function(){
+ // summary: removes all shapes from a group/surface
+ this.children = [];
+ return this; // self
+ },
+
+ // moving child nodes
+
+ _moveChildToFront: function(shape){
+ // summary: moves a shape to front of the list of shapes
+ for(var i = 0; i < this.children.length; ++i){
+ if(this.children[i] == shape){
+ this.children.splice(i, 1);
+ this.children.push(shape);
+ break;
+ }
+ }
+ return this; // self
+ },
+ _moveChildToBack: function(shape){
+ // summary: moves a shape to back of the list of shapes
+ for(var i = 0; i < this.children.length; ++i){
+ if(this.children[i] == shape){
+ this.children.splice(i, 1);
+ this.children.unshift(shape);
+ break;
+ }
+ }
+ return this; // self
+ }
+};
+
+dojo.declare("dojox.gfx.shape.Surface", null, {
+ // summary: a surface object to be used for drawings
+ constructor: function(){
+ // underlying node
+ this.rawNode = null;
+ // the parent node
+ this._parent = null;
+ // the list of DOM nodes to be deleted in the case of destruction
+ this._nodes = [];
+ // the list of events to be detached in the case of destruction
+ this._events = [];
+ },
+ destroy: function(){
+ // summary: destroy all relevant external resources and release all
+ // external references to make this object garbage-collectible
+ dojo.forEach(this._nodes, dojo.destroy);
+ this._nodes = [];
+ dojo.forEach(this._events, dojo.disconnect);
+ this._events = [];
+ this.rawNode = null; // recycle it in _nodes, if it needs to be recycled
+ if(dojo.isIE){
+ while(this._parent.lastChild){
+ dojo.destroy(this._parent.lastChild);
+ }
+ }else{
+ this._parent.innerHTML = "";
+ }
+ this._parent = null;
+ },
+ getEventSource: function(){
+ // summary: returns a node, which can be used to attach event listeners
+ return this.rawNode; // Node
+ },
+ _getRealMatrix: function(){
+ // summary: always returns the identity matrix
+ return null; // dojox.gfx.Matrix2D
+ },
+ isLoaded: true,
+ onLoad: function(/*dojox.gfx.Surface*/ surface){
+ // summary: local event, fired once when the surface is created
+ // asynchronously, used only when isLoaded is false, required
+ // only for Silverlight.
+ },
+ whenLoaded: function(
+ /*Object?*/ context,
+ /*Function|String*/ method
+ ){
+ var f = dojo.hitch(context, method);
+ if(this.isLoaded){
+ f(this);
+ }else{
+ var h = dojo.connect(this, "onLoad", function(surface){
+ dojo.disconnect(h);
+ f(surface);
+ });
+ }
+ }
+});
+
+dojo.extend(dojox.gfx.shape.Surface, dojox.gfx.shape._eventsProcessing);
+
+dojo.declare("dojox.gfx.Point", null, {
+ // summary: a hypothetical 2D point to be used for drawings - {x, y}
+ // description: This object is defined for documentation purposes.
+ // You should use the naked object instead: {x: 1, y: 2}.
+});
+
+dojo.declare("dojox.gfx.Rectangle", null, {
+ // summary: a hypothetical rectangle - {x, y, width, height}
+ // description: This object is defined for documentation purposes.
+ // You should use the naked object instead: {x: 1, y: 2, width: 100, height: 200}.
+});
+
+dojo.declare("dojox.gfx.shape.Rect", dojox.gfx.shape.Shape, {
+ // summary: a generic rectangle
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Rect");
+ this.rawNode = rawNode;
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box (its shape in this case)
+ return this.shape; // dojox.gfx.Rectangle
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Ellipse", dojox.gfx.shape.Shape, {
+ // summary: a generic ellipse
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Ellipse");
+ this.rawNode = rawNode;
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box
+ if(!this.bbox){
+ var shape = this.shape;
+ this.bbox = {x: shape.cx - shape.rx, y: shape.cy - shape.ry,
+ width: 2 * shape.rx, height: 2 * shape.ry};
+ }
+ return this.bbox; // dojox.gfx.Rectangle
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Circle", dojox.gfx.shape.Shape, {
+ // summary: a generic circle
+ // (this is a helper object, which is defined for convenience)
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Circle");
+ this.rawNode = rawNode;
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box
+ if(!this.bbox){
+ var shape = this.shape;
+ this.bbox = {x: shape.cx - shape.r, y: shape.cy - shape.r,
+ width: 2 * shape.r, height: 2 * shape.r};
+ }
+ return this.bbox; // dojox.gfx.Rectangle
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Line", dojox.gfx.shape.Shape, {
+ // summary: a generic line
+ // (this is a helper object, which is defined for convenience)
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Line");
+ this.rawNode = rawNode;
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box
+ if(!this.bbox){
+ var shape = this.shape;
+ this.bbox = {
+ x: Math.min(shape.x1, shape.x2),
+ y: Math.min(shape.y1, shape.y2),
+ width: Math.abs(shape.x2 - shape.x1),
+ height: Math.abs(shape.y2 - shape.y1)
+ };
+ }
+ return this.bbox; // dojox.gfx.Rectangle
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Polyline", dojox.gfx.shape.Shape, {
+ // summary: a generic polyline/polygon
+ // (this is a helper object, which is defined for convenience)
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Polyline");
+ this.rawNode = rawNode;
+ },
+ setShape: function(points, closed){
+ // summary: sets a polyline/polygon shape object
+ // points: Object: a polyline/polygon shape object
+ // closed: Boolean: close the polyline to make a polygon
+ if(points && points instanceof Array){
+ // points: Array: an array of points
+ this.inherited(arguments, [{points: points}]);
+ if(closed && this.shape.points.length){
+ this.shape.points.push(this.shape.points[0]);
+ }
+ }else{
+ this.inherited(arguments, [points]);
+ }
+ return this; // self
+ },
+ _normalizePoints: function(){
+ // summary: normalize points to array of {x:number, y:number}
+ var p = this.shape.points, l = p && p.length;
+ if(l && typeof p[0] == "number"){
+ var points = [];
+ for(var i = 0; i < l; i += 2){
+ points.push({x: p[i], y: p[i + 1]});
+ }
+ this.shape.points = points;
+ }
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box
+ if(!this.bbox && this.shape.points.length){
+ var p = this.shape.points;
+ var l = p.length;
+ var t = p[0];
+ var bbox = {l: t.x, t: t.y, r: t.x, b: t.y};
+ for(var i = 1; i < l; ++i){
+ t = p[i];
+ if(bbox.l > t.x) bbox.l = t.x;
+ if(bbox.r < t.x) bbox.r = t.x;
+ if(bbox.t > t.y) bbox.t = t.y;
+ if(bbox.b < t.y) bbox.b = t.y;
+ }
+ this.bbox = {
+ x: bbox.l,
+ y: bbox.t,
+ width: bbox.r - bbox.l,
+ height: bbox.b - bbox.t
+ };
+ }
+ return this.bbox; // dojox.gfx.Rectangle
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Image", dojox.gfx.shape.Shape, {
+ // summary: a generic image
+ // (this is a helper object, which is defined for convenience)
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Image");
+ this.rawNode = rawNode;
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box (its shape in this case)
+ return this.shape; // dojox.gfx.Rectangle
+ },
+ setStroke: function(){
+ // summary: ignore setting a stroke style
+ return this; // self
+ },
+ setFill: function(){
+ // summary: ignore setting a fill style
+ return this; // self
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Text", dojox.gfx.shape.Shape, {
+ // summary: a generic text
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.fontStyle = null;
+ this.shape = dojox.gfx.getDefault("Text");
+ this.rawNode = rawNode;
+ },
+ getFont: function(){
+ // summary: returns the current font object or null
+ return this.fontStyle; // Object
+ },
+ setFont: function(newFont){
+ // summary: sets a font for text
+ // newFont: Object: a font object (see dojox.gfx.defaultFont) or a font string
+ this.fontStyle = typeof newFont == "string" ? dojox.gfx.splitFontString(newFont) :
+ dojox.gfx.makeParameters(dojox.gfx.defaultFont, newFont);
+ this._setFont();
+ return this; // self
+ }
+});
+
+dojox.gfx.shape.Creator = {
+ // summary: shape creators
+ createShape: function(shape){
+ // summary: creates a shape object based on its type; it is meant to be used
+ // by group-like objects
+ // shape: Object: a shape descriptor object
+ var gfx = dojox.gfx;
+ switch(shape.type){
+ case gfx.defaultPath.type: return this.createPath(shape);
+ case gfx.defaultRect.type: return this.createRect(shape);
+ case gfx.defaultCircle.type: return this.createCircle(shape);
+ case gfx.defaultEllipse.type: return this.createEllipse(shape);
+ case gfx.defaultLine.type: return this.createLine(shape);
+ case gfx.defaultPolyline.type: return this.createPolyline(shape);
+ case gfx.defaultImage.type: return this.createImage(shape);
+ case gfx.defaultText.type: return this.createText(shape);
+ case gfx.defaultTextPath.type: return this.createTextPath(shape);
+ }
+ return null;
+ },
+ createGroup: function(){
+ // summary: creates a group shape
+ return this.createObject(dojox.gfx.Group); // dojox.gfx.Group
+ },
+ createRect: function(rect){
+ // summary: creates a rectangle shape
+ // rect: Object: a path object (see dojox.gfx.defaultRect)
+ return this.createObject(dojox.gfx.Rect, rect); // dojox.gfx.Rect
+ },
+ createEllipse: function(ellipse){
+ // summary: creates an ellipse shape
+ // ellipse: Object: an ellipse object (see dojox.gfx.defaultEllipse)
+ return this.createObject(dojox.gfx.Ellipse, ellipse); // dojox.gfx.Ellipse
+ },
+ createCircle: function(circle){
+ // summary: creates a circle shape
+ // circle: Object: a circle object (see dojox.gfx.defaultCircle)
+ return this.createObject(dojox.gfx.Circle, circle); // dojox.gfx.Circle
+ },
+ createLine: function(line){
+ // summary: creates a line shape
+ // line: Object: a line object (see dojox.gfx.defaultLine)
+ return this.createObject(dojox.gfx.Line, line); // dojox.gfx.Line
+ },
+ createPolyline: function(points){
+ // summary: creates a polyline/polygon shape
+ // points: Object: a points object (see dojox.gfx.defaultPolyline)
+ // or an Array of points
+ return this.createObject(dojox.gfx.Polyline, points); // dojox.gfx.Polyline
+ },
+ createImage: function(image){
+ // summary: creates a image shape
+ // image: Object: an image object (see dojox.gfx.defaultImage)
+ return this.createObject(dojox.gfx.Image, image); // dojox.gfx.Image
+ },
+ createText: function(text){
+ // summary: creates a text shape
+ // text: Object: a text object (see dojox.gfx.defaultText)
+ return this.createObject(dojox.gfx.Text, text); // dojox.gfx.Text
+ },
+ createPath: function(path){
+ // summary: creates a path shape
+ // path: Object: a path object (see dojox.gfx.defaultPath)
+ return this.createObject(dojox.gfx.Path, path); // dojox.gfx.Path
+ },
+ createTextPath: function(text){
+ // summary: creates a text shape
+ // text: Object: a textpath object (see dojox.gfx.defaultTextPath)
+ return this.createObject(dojox.gfx.TextPath, {}).setText(text); // dojox.gfx.TextPath
+ },
+ 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
+
+ // SHOULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ return null; // dojox.gfx.Shape
+ }
+};
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/shape.xd.js b/js/dojo-1.6/dojox/gfx/shape.xd.js new file mode 100644 index 0000000..977fc06 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/shape.xd.js @@ -0,0 +1,766 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.shape"],
+["require", "dojox.gfx._base"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.shape"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.shape"] = true;
+dojo.provide("dojox.gfx.shape");
+
+dojo.require("dojox.gfx._base");
+
+dojo.declare("dojox.gfx.shape.Shape", null, {
+ // summary: a Shape object, which knows how to apply
+ // graphical attributes and transformations
+
+ constructor: function(){
+ // rawNode: Node: underlying node
+ this.rawNode = null;
+
+ // shape: Object: an abstract shape object
+ // (see dojox.gfx.defaultPath,
+ // dojox.gfx.defaultPolyline,
+ // dojox.gfx.defaultRect,
+ // dojox.gfx.defaultEllipse,
+ // dojox.gfx.defaultCircle,
+ // dojox.gfx.defaultLine,
+ // or dojox.gfx.defaultImage)
+ this.shape = null;
+
+ // matrix: dojox.gfx.Matrix2D: a transformation matrix
+ this.matrix = null;
+
+ // fillStyle: Object: a fill object
+ // (see dojox.gfx.defaultLinearGradient,
+ // dojox.gfx.defaultRadialGradient,
+ // dojox.gfx.defaultPattern,
+ // or dojo.Color)
+ this.fillStyle = null;
+
+ // strokeStyle: Object: a stroke object
+ // (see dojox.gfx.defaultStroke)
+ this.strokeStyle = null;
+
+ // bbox: dojox.gfx.Rectangle: a bounding box of this shape
+ // (see dojox.gfx.defaultRect)
+ this.bbox = null;
+
+ // virtual group structure
+
+ // parent: Object: a parent or null
+ // (see dojox.gfx.Surface,
+ // dojox.gfx.shape.VirtualGroup,
+ // or dojox.gfx.Group)
+ this.parent = null;
+
+ // parentMatrix: dojox.gfx.Matrix2D
+ // a transformation matrix inherited from the parent
+ this.parentMatrix = null;
+ },
+
+ // trivial getters
+
+ getNode: function(){
+ // summary: returns the current DOM Node or null
+ return this.rawNode; // Node
+ },
+ getShape: function(){
+ // summary: returns the current shape object or null
+ // (see dojox.gfx.defaultPath,
+ // dojox.gfx.defaultPolyline,
+ // dojox.gfx.defaultRect,
+ // dojox.gfx.defaultEllipse,
+ // dojox.gfx.defaultCircle,
+ // dojox.gfx.defaultLine,
+ // or dojox.gfx.defaultImage)
+ return this.shape; // Object
+ },
+ getTransform: function(){
+ // summary: returns the current transformation matrix or null
+ return this.matrix; // dojox.gfx.Matrix2D
+ },
+ getFill: function(){
+ // summary: returns the current fill object or null
+ // (see dojox.gfx.defaultLinearGradient,
+ // dojox.gfx.defaultRadialGradient,
+ // dojox.gfx.defaultPattern,
+ // or dojo.Color)
+ return this.fillStyle; // Object
+ },
+ getStroke: function(){
+ // summary: returns the current stroke object or null
+ // (see dojox.gfx.defaultStroke)
+ return this.strokeStyle; // Object
+ },
+ getParent: function(){
+ // summary: returns the parent or null
+ // (see dojox.gfx.Surface,
+ // dojox.gfx.shape.VirtualGroup,
+ // or dojox.gfx.Group)
+ return this.parent; // Object
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box or null
+ // (see dojox.gfx.defaultRect)
+ return this.bbox; // dojox.gfx.Rectangle
+ },
+ getTransformedBoundingBox: function(){
+ // summary: returns an array of four points or null
+ // four points represent four corners of the untransformed bounding box
+ var b = this.getBoundingBox();
+ if(!b){
+ return null; // null
+ }
+ var m = this._getRealMatrix();
+ gm = dojox.gfx.matrix;
+ return [ // Array
+ gm.multiplyPoint(m, b.x, b.y),
+ gm.multiplyPoint(m, b.x + b.width, b.y),
+ gm.multiplyPoint(m, b.x + b.width, b.y + b.height),
+ gm.multiplyPoint(m, b.x, b.y + b.height)
+ ];
+ },
+ getEventSource: function(){
+ // summary: returns a Node, which is used as
+ // a source of events for this shape
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ return this.rawNode; // Node
+ },
+
+ // empty settings
+
+ setShape: function(shape){
+ // summary: sets a shape object
+ // (the default implementation simply ignores it)
+ // shape: Object: a shape object
+ // (see dojox.gfx.defaultPath,
+ // dojox.gfx.defaultPolyline,
+ // dojox.gfx.defaultRect,
+ // dojox.gfx.defaultEllipse,
+ // dojox.gfx.defaultCircle,
+ // dojox.gfx.defaultLine,
+ // or dojox.gfx.defaultImage)
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ this.shape = dojox.gfx.makeParameters(this.shape, shape);
+ this.bbox = null;
+ return this; // self
+ },
+ setFill: function(fill){
+ // summary: sets a fill object
+ // (the default implementation simply ignores it)
+ // fill: Object: a fill object
+ // (see dojox.gfx.defaultLinearGradient,
+ // dojox.gfx.defaultRadialGradient,
+ // dojox.gfx.defaultPattern,
+ // or dojo.Color)
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ if(!fill){
+ // don't fill
+ this.fillStyle = null;
+ return this; // self
+ }
+ var f = null;
+ if(typeof(fill) == "object" && "type" in fill){
+ // gradient or pattern
+ switch(fill.type){
+ case "linear":
+ f = dojox.gfx.makeParameters(dojox.gfx.defaultLinearGradient, fill);
+ break;
+ case "radial":
+ f = dojox.gfx.makeParameters(dojox.gfx.defaultRadialGradient, fill);
+ break;
+ case "pattern":
+ f = dojox.gfx.makeParameters(dojox.gfx.defaultPattern, fill);
+ break;
+ }
+ }else{
+ // color object
+ f = dojox.gfx.normalizeColor(fill);
+ }
+ this.fillStyle = f;
+ return this; // self
+ },
+ setStroke: function(stroke){
+ // summary: sets a stroke object
+ // (the default implementation simply ignores it)
+ // stroke: Object: a stroke object
+ // (see dojox.gfx.defaultStroke)
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ if(!stroke){
+ // don't stroke
+ this.strokeStyle = null;
+ return this; // self
+ }
+ // normalize the stroke
+ if(typeof stroke == "string" || dojo.isArray(stroke) || stroke instanceof dojo.Color){
+ stroke = {color: stroke};
+ }
+ var s = this.strokeStyle = dojox.gfx.makeParameters(dojox.gfx.defaultStroke, stroke);
+ s.color = dojox.gfx.normalizeColor(s.color);
+ return this; // self
+ },
+ setTransform: function(matrix){
+ // summary: sets a transformation matrix
+ // matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+ // (see an argument of dojox.gfx.Matrix2D
+ // constructor for a list of acceptable arguments)
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ this.matrix = dojox.gfx.matrix.clone(matrix ? dojox.gfx.matrix.normalize(matrix) : dojox.gfx.matrix.identity);
+ return this._applyTransform(); // self
+ },
+
+ _applyTransform: function(){
+ // summary: physically sets a matrix
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ return this; // self
+ },
+
+ // z-index
+
+ moveToFront: function(){
+ // summary: moves a shape to front of its parent's list of shapes
+ var p = this.getParent();
+ if(p){
+ p._moveChildToFront(this);
+ this._moveToFront(); // execute renderer-specific action
+ }
+ return this; // self
+ },
+ moveToBack: function(){
+ // summary: moves a shape to back of its parent's list of shapes
+ var p = this.getParent();
+ if(p){
+ p._moveChildToBack(this);
+ this._moveToBack(); // execute renderer-specific action
+ }
+ return this;
+ },
+ _moveToFront: function(){
+ // summary: renderer-specific hook, see dojox.gfx.shape.Shape.moveToFront()
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+ },
+ _moveToBack: function(){
+ // summary: renderer-specific hook, see dojox.gfx.shape.Shape.moveToFront()
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+ },
+
+ // apply left & right transformation
+
+ applyRightTransform: function(matrix){
+ // summary: multiplies the existing matrix with an argument on right side
+ // (this.matrix * matrix)
+ // matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+ // (see an argument of dojox.gfx.Matrix2D
+ // constructor for a list of acceptable arguments)
+ return matrix ? this.setTransform([this.matrix, matrix]) : this; // self
+ },
+ applyLeftTransform: function(matrix){
+ // summary: multiplies the existing matrix with an argument on left side
+ // (matrix * this.matrix)
+ // matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+ // (see an argument of dojox.gfx.Matrix2D
+ // constructor for a list of acceptable arguments)
+ return matrix ? this.setTransform([matrix, this.matrix]) : this; // self
+ },
+ applyTransform: function(matrix){
+ // summary: a shortcut for dojox.gfx.Shape.applyRightTransform
+ // matrix: dojox.gfx.Matrix2D: a matrix or a matrix-like object
+ // (see an argument of dojox.gfx.Matrix2D
+ // constructor for a list of acceptable arguments)
+ return matrix ? this.setTransform([this.matrix, matrix]) : this; // self
+ },
+
+ // virtual group methods
+
+ removeShape: function(silently){
+ // summary: removes the shape from its parent's list of shapes
+ // silently: Boolean?: if true, do not redraw a picture yet
+ if(this.parent){
+ this.parent.remove(this, silently);
+ }
+ return this; // self
+ },
+ _setParent: function(parent, matrix){
+ // summary: sets a parent
+ // parent: Object: a parent or null
+ // (see dojox.gfx.Surface,
+ // dojox.gfx.shape.VirtualGroup,
+ // or dojox.gfx.Group)
+ // matrix: dojox.gfx.Matrix2D:
+ // a 2D matrix or a matrix-like object
+ this.parent = parent;
+ return this._updateParentMatrix(matrix); // self
+ },
+ _updateParentMatrix: function(matrix){
+ // summary: updates the parent matrix with new matrix
+ // matrix: dojox.gfx.Matrix2D:
+ // a 2D matrix or a matrix-like object
+ this.parentMatrix = matrix ? dojox.gfx.matrix.clone(matrix) : null;
+ return this._applyTransform(); // self
+ },
+ _getRealMatrix: function(){
+ // summary: returns the cumulative ("real") transformation matrix
+ // by combining the shape's matrix with its parent's matrix
+ var m = this.matrix;
+ var p = this.parent;
+ while(p){
+ if(p.matrix){
+ m = dojox.gfx.matrix.multiply(p.matrix, m);
+ }
+ p = p.parent;
+ }
+ return m; // dojox.gfx.Matrix2D
+ }
+});
+
+dojox.gfx.shape._eventsProcessing = {
+ connect: function(name, object, method){
+ // summary: connects a handler to an event on this shape
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ return arguments.length > 2 ? // Object
+ dojo.connect(this.getEventSource(), name, object, method) :
+ dojo.connect(this.getEventSource(), name, object);
+ },
+ disconnect: function(token){
+ // summary: connects a handler by token from an event on this shape
+
+ // COULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ dojo.disconnect(token);
+ }
+};
+
+dojo.extend(dojox.gfx.shape.Shape, dojox.gfx.shape._eventsProcessing);
+
+dojox.gfx.shape.Container = {
+ // summary: a container of shapes, which can be used
+ // as a foundation for renderer-specific groups, or as a way
+ // to logically group shapes (e.g, to propagate matricies)
+
+ _init: function() {
+ // children: Array: a list of children
+ this.children = [];
+ },
+
+ // group management
+
+ openBatch: function() {
+ // summary: starts a new batch, subsequent new child shapes will be held in
+ // the batch instead of appending to the container directly
+ },
+ closeBatch: function() {
+ // summary: submits the current batch, append all pending child shapes to DOM
+ },
+ add: function(shape){
+ // summary: adds a shape to the list
+ // shape: dojox.gfx.Shape: a shape
+ var oldParent = shape.getParent();
+ if(oldParent){
+ oldParent.remove(shape, true);
+ }
+ this.children.push(shape);
+ return shape._setParent(this, this._getRealMatrix()); // self
+ },
+ remove: function(shape, silently){
+ // summary: removes a shape from the list
+ // silently: Boolean?: if true, do not redraw a picture yet
+ for(var i = 0; i < this.children.length; ++i){
+ if(this.children[i] == shape){
+ if(silently){
+ // skip for now
+ }else{
+ shape.parent = null;
+ shape.parentMatrix = null;
+ }
+ this.children.splice(i, 1);
+ break;
+ }
+ }
+ return this; // self
+ },
+ clear: function(){
+ // summary: removes all shapes from a group/surface
+ this.children = [];
+ return this; // self
+ },
+
+ // moving child nodes
+
+ _moveChildToFront: function(shape){
+ // summary: moves a shape to front of the list of shapes
+ for(var i = 0; i < this.children.length; ++i){
+ if(this.children[i] == shape){
+ this.children.splice(i, 1);
+ this.children.push(shape);
+ break;
+ }
+ }
+ return this; // self
+ },
+ _moveChildToBack: function(shape){
+ // summary: moves a shape to back of the list of shapes
+ for(var i = 0; i < this.children.length; ++i){
+ if(this.children[i] == shape){
+ this.children.splice(i, 1);
+ this.children.unshift(shape);
+ break;
+ }
+ }
+ return this; // self
+ }
+};
+
+dojo.declare("dojox.gfx.shape.Surface", null, {
+ // summary: a surface object to be used for drawings
+ constructor: function(){
+ // underlying node
+ this.rawNode = null;
+ // the parent node
+ this._parent = null;
+ // the list of DOM nodes to be deleted in the case of destruction
+ this._nodes = [];
+ // the list of events to be detached in the case of destruction
+ this._events = [];
+ },
+ destroy: function(){
+ // summary: destroy all relevant external resources and release all
+ // external references to make this object garbage-collectible
+ dojo.forEach(this._nodes, dojo.destroy);
+ this._nodes = [];
+ dojo.forEach(this._events, dojo.disconnect);
+ this._events = [];
+ this.rawNode = null; // recycle it in _nodes, if it needs to be recycled
+ if(dojo.isIE){
+ while(this._parent.lastChild){
+ dojo.destroy(this._parent.lastChild);
+ }
+ }else{
+ this._parent.innerHTML = "";
+ }
+ this._parent = null;
+ },
+ getEventSource: function(){
+ // summary: returns a node, which can be used to attach event listeners
+ return this.rawNode; // Node
+ },
+ _getRealMatrix: function(){
+ // summary: always returns the identity matrix
+ return null; // dojox.gfx.Matrix2D
+ },
+ isLoaded: true,
+ onLoad: function(/*dojox.gfx.Surface*/ surface){
+ // summary: local event, fired once when the surface is created
+ // asynchronously, used only when isLoaded is false, required
+ // only for Silverlight.
+ },
+ whenLoaded: function(
+ /*Object?*/ context,
+ /*Function|String*/ method
+ ){
+ var f = dojo.hitch(context, method);
+ if(this.isLoaded){
+ f(this);
+ }else{
+ var h = dojo.connect(this, "onLoad", function(surface){
+ dojo.disconnect(h);
+ f(surface);
+ });
+ }
+ }
+});
+
+dojo.extend(dojox.gfx.shape.Surface, dojox.gfx.shape._eventsProcessing);
+
+dojo.declare("dojox.gfx.Point", null, {
+ // summary: a hypothetical 2D point to be used for drawings - {x, y}
+ // description: This object is defined for documentation purposes.
+ // You should use the naked object instead: {x: 1, y: 2}.
+});
+
+dojo.declare("dojox.gfx.Rectangle", null, {
+ // summary: a hypothetical rectangle - {x, y, width, height}
+ // description: This object is defined for documentation purposes.
+ // You should use the naked object instead: {x: 1, y: 2, width: 100, height: 200}.
+});
+
+dojo.declare("dojox.gfx.shape.Rect", dojox.gfx.shape.Shape, {
+ // summary: a generic rectangle
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Rect");
+ this.rawNode = rawNode;
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box (its shape in this case)
+ return this.shape; // dojox.gfx.Rectangle
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Ellipse", dojox.gfx.shape.Shape, {
+ // summary: a generic ellipse
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Ellipse");
+ this.rawNode = rawNode;
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box
+ if(!this.bbox){
+ var shape = this.shape;
+ this.bbox = {x: shape.cx - shape.rx, y: shape.cy - shape.ry,
+ width: 2 * shape.rx, height: 2 * shape.ry};
+ }
+ return this.bbox; // dojox.gfx.Rectangle
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Circle", dojox.gfx.shape.Shape, {
+ // summary: a generic circle
+ // (this is a helper object, which is defined for convenience)
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Circle");
+ this.rawNode = rawNode;
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box
+ if(!this.bbox){
+ var shape = this.shape;
+ this.bbox = {x: shape.cx - shape.r, y: shape.cy - shape.r,
+ width: 2 * shape.r, height: 2 * shape.r};
+ }
+ return this.bbox; // dojox.gfx.Rectangle
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Line", dojox.gfx.shape.Shape, {
+ // summary: a generic line
+ // (this is a helper object, which is defined for convenience)
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Line");
+ this.rawNode = rawNode;
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box
+ if(!this.bbox){
+ var shape = this.shape;
+ this.bbox = {
+ x: Math.min(shape.x1, shape.x2),
+ y: Math.min(shape.y1, shape.y2),
+ width: Math.abs(shape.x2 - shape.x1),
+ height: Math.abs(shape.y2 - shape.y1)
+ };
+ }
+ return this.bbox; // dojox.gfx.Rectangle
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Polyline", dojox.gfx.shape.Shape, {
+ // summary: a generic polyline/polygon
+ // (this is a helper object, which is defined for convenience)
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Polyline");
+ this.rawNode = rawNode;
+ },
+ setShape: function(points, closed){
+ // summary: sets a polyline/polygon shape object
+ // points: Object: a polyline/polygon shape object
+ // closed: Boolean: close the polyline to make a polygon
+ if(points && points instanceof Array){
+ // points: Array: an array of points
+ this.inherited(arguments, [{points: points}]);
+ if(closed && this.shape.points.length){
+ this.shape.points.push(this.shape.points[0]);
+ }
+ }else{
+ this.inherited(arguments, [points]);
+ }
+ return this; // self
+ },
+ _normalizePoints: function(){
+ // summary: normalize points to array of {x:number, y:number}
+ var p = this.shape.points, l = p && p.length;
+ if(l && typeof p[0] == "number"){
+ var points = [];
+ for(var i = 0; i < l; i += 2){
+ points.push({x: p[i], y: p[i + 1]});
+ }
+ this.shape.points = points;
+ }
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box
+ if(!this.bbox && this.shape.points.length){
+ var p = this.shape.points;
+ var l = p.length;
+ var t = p[0];
+ var bbox = {l: t.x, t: t.y, r: t.x, b: t.y};
+ for(var i = 1; i < l; ++i){
+ t = p[i];
+ if(bbox.l > t.x) bbox.l = t.x;
+ if(bbox.r < t.x) bbox.r = t.x;
+ if(bbox.t > t.y) bbox.t = t.y;
+ if(bbox.b < t.y) bbox.b = t.y;
+ }
+ this.bbox = {
+ x: bbox.l,
+ y: bbox.t,
+ width: bbox.r - bbox.l,
+ height: bbox.b - bbox.t
+ };
+ }
+ return this.bbox; // dojox.gfx.Rectangle
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Image", dojox.gfx.shape.Shape, {
+ // summary: a generic image
+ // (this is a helper object, which is defined for convenience)
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.shape = dojox.gfx.getDefault("Image");
+ this.rawNode = rawNode;
+ },
+ getBoundingBox: function(){
+ // summary: returns the bounding box (its shape in this case)
+ return this.shape; // dojox.gfx.Rectangle
+ },
+ setStroke: function(){
+ // summary: ignore setting a stroke style
+ return this; // self
+ },
+ setFill: function(){
+ // summary: ignore setting a fill style
+ return this; // self
+ }
+});
+
+dojo.declare("dojox.gfx.shape.Text", dojox.gfx.shape.Shape, {
+ // summary: a generic text
+ constructor: function(rawNode){
+ // rawNode: Node: a DOM Node
+ this.fontStyle = null;
+ this.shape = dojox.gfx.getDefault("Text");
+ this.rawNode = rawNode;
+ },
+ getFont: function(){
+ // summary: returns the current font object or null
+ return this.fontStyle; // Object
+ },
+ setFont: function(newFont){
+ // summary: sets a font for text
+ // newFont: Object: a font object (see dojox.gfx.defaultFont) or a font string
+ this.fontStyle = typeof newFont == "string" ? dojox.gfx.splitFontString(newFont) :
+ dojox.gfx.makeParameters(dojox.gfx.defaultFont, newFont);
+ this._setFont();
+ return this; // self
+ }
+});
+
+dojox.gfx.shape.Creator = {
+ // summary: shape creators
+ createShape: function(shape){
+ // summary: creates a shape object based on its type; it is meant to be used
+ // by group-like objects
+ // shape: Object: a shape descriptor object
+ var gfx = dojox.gfx;
+ switch(shape.type){
+ case gfx.defaultPath.type: return this.createPath(shape);
+ case gfx.defaultRect.type: return this.createRect(shape);
+ case gfx.defaultCircle.type: return this.createCircle(shape);
+ case gfx.defaultEllipse.type: return this.createEllipse(shape);
+ case gfx.defaultLine.type: return this.createLine(shape);
+ case gfx.defaultPolyline.type: return this.createPolyline(shape);
+ case gfx.defaultImage.type: return this.createImage(shape);
+ case gfx.defaultText.type: return this.createText(shape);
+ case gfx.defaultTextPath.type: return this.createTextPath(shape);
+ }
+ return null;
+ },
+ createGroup: function(){
+ // summary: creates a group shape
+ return this.createObject(dojox.gfx.Group); // dojox.gfx.Group
+ },
+ createRect: function(rect){
+ // summary: creates a rectangle shape
+ // rect: Object: a path object (see dojox.gfx.defaultRect)
+ return this.createObject(dojox.gfx.Rect, rect); // dojox.gfx.Rect
+ },
+ createEllipse: function(ellipse){
+ // summary: creates an ellipse shape
+ // ellipse: Object: an ellipse object (see dojox.gfx.defaultEllipse)
+ return this.createObject(dojox.gfx.Ellipse, ellipse); // dojox.gfx.Ellipse
+ },
+ createCircle: function(circle){
+ // summary: creates a circle shape
+ // circle: Object: a circle object (see dojox.gfx.defaultCircle)
+ return this.createObject(dojox.gfx.Circle, circle); // dojox.gfx.Circle
+ },
+ createLine: function(line){
+ // summary: creates a line shape
+ // line: Object: a line object (see dojox.gfx.defaultLine)
+ return this.createObject(dojox.gfx.Line, line); // dojox.gfx.Line
+ },
+ createPolyline: function(points){
+ // summary: creates a polyline/polygon shape
+ // points: Object: a points object (see dojox.gfx.defaultPolyline)
+ // or an Array of points
+ return this.createObject(dojox.gfx.Polyline, points); // dojox.gfx.Polyline
+ },
+ createImage: function(image){
+ // summary: creates a image shape
+ // image: Object: an image object (see dojox.gfx.defaultImage)
+ return this.createObject(dojox.gfx.Image, image); // dojox.gfx.Image
+ },
+ createText: function(text){
+ // summary: creates a text shape
+ // text: Object: a text object (see dojox.gfx.defaultText)
+ return this.createObject(dojox.gfx.Text, text); // dojox.gfx.Text
+ },
+ createPath: function(path){
+ // summary: creates a path shape
+ // path: Object: a path object (see dojox.gfx.defaultPath)
+ return this.createObject(dojox.gfx.Path, path); // dojox.gfx.Path
+ },
+ createTextPath: function(text){
+ // summary: creates a text shape
+ // text: Object: a textpath object (see dojox.gfx.defaultTextPath)
+ return this.createObject(dojox.gfx.TextPath, {}).setText(text); // dojox.gfx.TextPath
+ },
+ 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
+
+ // SHOULD BE RE-IMPLEMENTED BY THE RENDERER!
+
+ return null; // dojox.gfx.Shape
+ }
+};
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/silverlight.js b/js/dojo-1.6/dojox/gfx/silverlight.js new file mode 100644 index 0000000..361ffd3 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/silverlight.js @@ -0,0 +1,823 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.silverlight"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.silverlight"] = true;
+dojo.provide("dojox.gfx.silverlight");
+
+dojo.require("dojox.gfx._base");
+dojo.require("dojox.gfx.shape");
+dojo.require("dojox.gfx.path");
+
+dojo.experimental("dojox.gfx.silverlight");
+
+(function(){
+ var d = dojo, g = dojox.gfx, gs = g.shape, sl = g.silverlight;
+
+ var dasharray = {
+ solid: "none",
+ shortdash: [4, 1],
+ shortdot: [1, 1],
+ shortdashdot: [4, 1, 1, 1],
+ shortdashdotdot: [4, 1, 1, 1, 1, 1],
+ dot: [1, 3],
+ dash: [4, 3],
+ longdash: [8, 3],
+ dashdot: [4, 3, 1, 3],
+ longdashdot: [8, 3, 1, 3],
+ longdashdotdot: [8, 3, 1, 3, 1, 3]
+ },
+ fontweight = {
+ normal: 400,
+ bold: 700
+ },
+ caps = {butt: "Flat", round: "Round", square: "Square"},
+ joins = {bevel: "Bevel", round: "Round"},
+ fonts = {
+ serif: "Times New Roman",
+ times: "Times New Roman",
+ "sans-serif": "Arial",
+ helvetica: "Arial",
+ monotone: "Courier New",
+ courier: "Courier New"
+ };
+
+ function hexColor(/*String|Array|dojo.Color*/ color){
+ // summary: converts a color object to a Silverlight hex color string (#aarrggbb)
+ var c = g.normalizeColor(color),
+ t = c.toHex(), a = Math.round(c.a * 255);
+ a = (a < 0 ? 0 : a > 255 ? 255 : a).toString(16);
+ return "#" + (a.length < 2 ? "0" + a : a) + t.slice(1); // String
+ }
+
+ d.declare("dojox.gfx.silverlight.Shape", gs.Shape, {
+ // summary: Silverlight-specific implementation of dojox.gfx.Shape methods
+
+ setFill: function(fill){
+ // summary: sets a fill object (Silverlight)
+ // fill: Object: a fill object
+ // (see dojox.gfx.defaultLinearGradient,
+ // dojox.gfx.defaultRadialGradient,
+ // dojox.gfx.defaultPattern,
+ // or dojo.Color)
+
+ var p = this.rawNode.getHost().content, r = this.rawNode, f;
+ if(!fill){
+ // don't fill
+ this.fillStyle = null;
+ this._setFillAttr(null);
+ return this; // self
+ }
+ if(typeof(fill) == "object" && "type" in fill){
+ // gradient
+ switch(fill.type){
+ case "linear":
+ this.fillStyle = f = g.makeParameters(g.defaultLinearGradient, fill);
+ var lgb = p.createFromXaml("<LinearGradientBrush/>");
+ lgb.mappingMode = "Absolute";
+ lgb.startPoint = f.x1 + "," + f.y1;
+ lgb.endPoint = f.x2 + "," + f.y2;
+ d.forEach(f.colors, function(c){
+ var t = p.createFromXaml("<GradientStop/>");
+ t.offset = c.offset;
+ t.color = hexColor(c.color);
+ lgb.gradientStops.add(t);
+ });
+ this._setFillAttr(lgb);
+ break;
+ case "radial":
+ this.fillStyle = f = g.makeParameters(g.defaultRadialGradient, fill);
+ var rgb = p.createFromXaml("<RadialGradientBrush/>"),
+ c = g.matrix.multiplyPoint(g.matrix.invert(this._getAdjustedMatrix()), f.cx, f.cy),
+ pt = c.x + "," + c.y;
+ rgb.mappingMode = "Absolute";
+ rgb.gradientOrigin = pt;
+ rgb.center = pt;
+ rgb.radiusX = rgb.radiusY = f.r;
+ d.forEach(f.colors, function(c){
+ var t = p.createFromXaml("<GradientStop/>");
+ t.offset = c.offset;
+ t.color = hexColor(c.color);
+ rgb.gradientStops.add(t);
+ });
+ this._setFillAttr(rgb);
+ break;
+ case "pattern":
+ // don't fill: Silverlight doesn't define TileBrush for some reason
+ this.fillStyle = null;
+ this._setFillAttr(null);
+ break;
+ }
+ return this; // self
+ }
+ // color object
+ this.fillStyle = f = g.normalizeColor(fill);
+ var scb = p.createFromXaml("<SolidColorBrush/>");
+ scb.color = f.toHex();
+ scb.opacity = f.a;
+ this._setFillAttr(scb);
+ return this; // self
+ },
+ _setFillAttr: function(f){
+ this.rawNode.fill = f;
+ },
+
+ setStroke: function(stroke){
+ // summary: sets a stroke object (Silverlight)
+ // stroke: Object: a stroke object
+ // (see dojox.gfx.defaultStroke)
+
+ var p = this.rawNode.getHost().content, r = this.rawNode;
+ if(!stroke){
+ // don't stroke
+ this.strokeStyle = null;
+ r.stroke = null;
+ return this;
+ }
+ // normalize the stroke
+ if(typeof stroke == "string" || d.isArray(stroke) || stroke instanceof d.Color){
+ stroke = {color: stroke};
+ }
+ var s = this.strokeStyle = g.makeParameters(g.defaultStroke, stroke);
+ s.color = g.normalizeColor(s.color);
+ // generate attributes
+ if(s){
+ var scb = p.createFromXaml("<SolidColorBrush/>");
+ scb.color = s.color.toHex();
+ scb.opacity = s.color.a;
+ r.stroke = scb;
+ r.strokeThickness = s.width;
+ r.strokeStartLineCap = r.strokeEndLineCap = r.strokeDashCap =
+ caps[s.cap];
+ if(typeof s.join == "number"){
+ r.strokeLineJoin = "Miter";
+ r.strokeMiterLimit = s.join;
+ }else{
+ r.strokeLineJoin = joins[s.join];
+ }
+ var da = s.style.toLowerCase();
+ if(da in dasharray){ da = dasharray[da]; }
+ if(da instanceof Array){
+ da = d.clone(da);
+ var i;
+ /*
+ for(var i = 0; i < da.length; ++i){
+ da[i] *= s.width;
+ }
+ */
+ if(s.cap != "butt"){
+ for(i = 0; i < da.length; i += 2){
+ //da[i] -= s.width;
+ --da[i]
+ if(da[i] < 1){ da[i] = 1; }
+ }
+ for(i = 1; i < da.length; i += 2){
+ //da[i] += s.width;
+ ++da[i];
+ }
+ }
+ r.strokeDashArray = da.join(",");
+ }else{
+ r.strokeDashArray = null;
+ }
+ }
+ return this; // self
+ },
+
+ _getParentSurface: function(){
+ var surface = this.parent;
+ for(; surface && !(surface instanceof g.Surface); surface = surface.parent);
+ return surface;
+ },
+
+ _applyTransform: function() {
+ var tm = this._getAdjustedMatrix(), r = this.rawNode;
+ if(tm){
+ var p = this.rawNode.getHost().content,
+ mt = p.createFromXaml("<MatrixTransform/>"),
+ mm = p.createFromXaml("<Matrix/>");
+ mm.m11 = tm.xx;
+ mm.m21 = tm.xy;
+ mm.m12 = tm.yx;
+ mm.m22 = tm.yy;
+ mm.offsetX = tm.dx;
+ mm.offsetY = tm.dy;
+ mt.matrix = mm;
+ r.renderTransform = mt;
+ }else{
+ r.renderTransform = null;
+ }
+ 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.fill = null;
+ rawNode.stroke = null;
+ this.rawNode = rawNode;
+ },
+
+ // move family
+
+ _moveToFront: function(){
+ // summary: moves a shape to front of its parent's list of shapes (Silverlight)
+ var c = this.parent.rawNode.children, r = this.rawNode;
+ c.remove(r);
+ c.add(r);
+ return this; // self
+ },
+ _moveToBack: function(){
+ // summary: moves a shape to back of its parent's list of shapes (Silverlight)
+ var c = this.parent.rawNode.children, r = this.rawNode;
+ c.remove(r);
+ c.insert(0, r);
+ return this; // self
+ },
+
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ return this.matrix; // dojox.gfx.Matrix2D
+ }
+ });
+
+ d.declare("dojox.gfx.silverlight.Group", sl.Shape, {
+ // summary: a group shape (Silverlight), which can be used
+ // to logically group shapes (e.g, to propagate matricies)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ setRawNode: function(rawNode){
+ // summary: sets a raw Silverlight node to be used by this shape
+ // rawNode: Node: an Silverlight node
+ this.rawNode = rawNode;
+ }
+ });
+ sl.Group.nodeType = "Canvas";
+
+ d.declare("dojox.gfx.silverlight.Rect", [sl.Shape, gs.Rect], {
+ // summary: a rectangle shape (Silverlight)
+ setShape: function(newShape){
+ // summary: sets a rectangle shape object (Silverlight)
+ // newShape: Object: a rectangle shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, n = this.shape;
+ r.width = n.width;
+ r.height = n.height;
+ r.radiusX = r.radiusY = n.r;
+ return this._applyTransform(); // self
+ },
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ var matrix = this.matrix, s = this.shape, delta = {dx: s.x, dy: s.y};
+ return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
+ }
+ });
+ sl.Rect.nodeType = "Rectangle";
+
+ d.declare("dojox.gfx.silverlight.Ellipse", [sl.Shape, gs.Ellipse], {
+ // summary: an ellipse shape (Silverlight)
+ setShape: function(newShape){
+ // summary: sets an ellipse shape object (Silverlight)
+ // newShape: Object: an ellipse shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, n = this.shape;
+ r.width = 2 * n.rx;
+ r.height = 2 * n.ry;
+ return this._applyTransform(); // self
+ },
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ var matrix = this.matrix, s = this.shape, delta = {dx: s.cx - s.rx, dy: s.cy - s.ry};
+ return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
+ }
+ });
+ sl.Ellipse.nodeType = "Ellipse";
+
+ d.declare("dojox.gfx.silverlight.Circle", [sl.Shape, gs.Circle], {
+ // summary: a circle shape (Silverlight)
+ setShape: function(newShape){
+ // summary: sets a circle shape object (Silverlight)
+ // newShape: Object: a circle shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, n = this.shape;
+ r.width = r.height = 2 * n.r;
+ return this._applyTransform(); // self
+ },
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ var matrix = this.matrix, s = this.shape, delta = {dx: s.cx - s.r, dy: s.cy - s.r};
+ return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
+ }
+ });
+ sl.Circle.nodeType = "Ellipse";
+
+ d.declare("dojox.gfx.silverlight.Line", [sl.Shape, gs.Line], {
+ // summary: a line shape (Silverlight)
+ setShape: function(newShape){
+ // summary: sets a line shape object (Silverlight)
+ // newShape: Object: a line shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, n = this.shape;
+ r.x1 = n.x1; r.y1 = n.y1; r.x2 = n.x2; r.y2 = n.y2;
+ return this; // self
+ }
+ });
+ sl.Line.nodeType = "Line";
+
+ d.declare("dojox.gfx.silverlight.Polyline", [sl.Shape, gs.Polyline], {
+ // summary: a polyline/polygon shape (Silverlight)
+ setShape: function(points, closed){
+ // summary: sets a polyline/polygon shape object (Silverlight)
+ // points: Object: a polyline/polygon shape object
+ if(points && points instanceof Array){
+ // branch
+ // points: Array: an array of points
+ this.shape = g.makeParameters(this.shape, {points: points});
+ if(closed && this.shape.points.length){
+ this.shape.points.push(this.shape.points[0]);
+ }
+ }else{
+ this.shape = g.makeParameters(this.shape, points);
+ }
+ this.bbox = null;
+ this._normalizePoints();
+ var p = this.shape.points, rp = [];
+ for(var i = 0; i < p.length; ++i){
+ rp.push(p[i].x, p[i].y);
+ }
+ this.rawNode.points = rp.join(",");
+ return this; // self
+ }
+ });
+ sl.Polyline.nodeType = "Polyline";
+
+ d.declare("dojox.gfx.silverlight.Image", [sl.Shape, gs.Image], {
+ // summary: an image (Silverlight)
+ setShape: function(newShape){
+ // summary: sets an image shape object (Silverlight)
+ // newShape: Object: an image shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, n = this.shape;
+ r.width = n.width;
+ r.height = n.height;
+ r.source = n.src;
+ return this._applyTransform(); // self
+ },
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ var matrix = this.matrix, s = this.shape, delta = {dx: s.x, dy: s.y};
+ return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
+ },
+ 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)
+ this.rawNode = rawNode;
+ }
+ });
+ sl.Image.nodeType = "Image";
+
+ d.declare("dojox.gfx.silverlight.Text", [sl.Shape, gs.Text], {
+ // summary: an anchored text (Silverlight)
+ setShape: function(newShape){
+ // summary: sets a text shape object (Silverlight)
+ // newShape: Object: a text shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, s = this.shape;
+ r.text = s.text;
+ r.textDecorations = s.decoration === "underline" ? "Underline" : "None";
+ r["Canvas.Left"] = -10000;
+ r["Canvas.Top"] = -10000;
+ if(!this._delay){
+ this._delay = window.setTimeout(d.hitch(this, "_delayAlignment"), 10);
+ }
+ return this; // self
+ },
+ _delayAlignment: function(){
+ // handle alignment
+ var r = this.rawNode, s = this.shape, w, h;
+ try{
+ w = r.actualWidth;
+ h = r.actualHeight;
+ }catch(e){
+ // bail out if the node is hidden
+ return;
+ }
+ var x = s.x, y = s.y - h * 0.75;
+ switch(s.align){
+ case "middle":
+ x -= w / 2;
+ break;
+ case "end":
+ x -= w;
+ break;
+ }
+ this._delta = {dx: x, dy: y};
+ r["Canvas.Left"] = 0;
+ r["Canvas.Top"] = 0;
+ this._applyTransform();
+ delete this._delay;
+ },
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ var matrix = this.matrix, delta = this._delta, x;
+ if(matrix){
+ x = delta ? [matrix, delta] : matrix;
+ }else{
+ x = delta ? delta : {};
+ }
+ return new g.Matrix2D(x);
+ },
+ setStroke: function(){
+ // summary: ignore setting a stroke style
+ return this; // self
+ },
+ _setFillAttr: function(f){
+ this.rawNode.foreground = f;
+ },
+ 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)
+ this.rawNode = rawNode;
+ },
+ getTextWidth: function(){
+ // summary: get the text width in pixels
+ return this.rawNode.actualWidth;
+ }
+ });
+ sl.Text.nodeType = "TextBlock";
+
+ d.declare("dojox.gfx.silverlight.Path", [sl.Shape, g.path.Path], {
+ // summary: a path shape (Silverlight)
+ _updateWithSegment: function(segment){
+ // summary: updates the bounding box of path with new segment
+ // segment: Object: a segment
+ this.inherited(arguments);
+ var p = this.shape.path;
+ if(typeof(p) == "string"){
+ this.rawNode.data = p ? p : null;
+ }
+ },
+ setShape: function(newShape){
+ // summary: forms a path using a shape (Silverlight)
+ // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+ this.inherited(arguments);
+ var p = this.shape.path;
+ this.rawNode.data = p ? p : null;
+ return this; // self
+ }
+ });
+ sl.Path.nodeType = "Path";
+
+ d.declare("dojox.gfx.silverlight.TextPath", [sl.Shape, g.path.TextPath], {
+ // summary: a textpath shape (Silverlight)
+ _updateWithSegment: function(segment){
+ // summary: updates the bounding box of path with new segment
+ // segment: Object: a segment
+ },
+ setShape: function(newShape){
+ // summary: forms a path using a shape (Silverlight)
+ // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+ },
+ _setText: function(){
+ }
+ });
+ sl.TextPath.nodeType = "text";
+
+ var surfaces = {}, nullFunc = new Function;
+
+ d.declare("dojox.gfx.silverlight.Surface", gs.Surface, {
+ // summary: a surface object to be used for drawings (Silverlight)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ destroy: function(){
+ window[this._onLoadName] = nullFunc;
+ delete surfaces[this._nodeName];
+ this.inherited(arguments);
+ },
+ 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 = g.normalizedLength(width); // in pixels
+ this.height = g.normalizedLength(height); // in pixels
+ var p = this.rawNode && this.rawNode.getHost();
+ if(p){
+ p.width = width;
+ p.height = height;
+ }
+ return this; // self
+ },
+ getDimensions: function(){
+ // summary: returns an object with properties "width" and "height"
+ var p = this.rawNode && this.rawNode.getHost();
+ var t = p ? {width: p.content.actualWidth, height: p.content.actualHeight} : null;
+ if(t.width <= 0){ t.width = this.width; }
+ if(t.height <= 0){ t.height = this.height; }
+ return t; // Object
+ }
+ });
+
+ sl.createSurface = function(parentNode, width, height){
+ // summary: creates a surface (Silverlight)
+ // parentNode: Node: a parent node
+ // width: String: width of surface, e.g., "100px"
+ // height: String: height of surface, e.g., "100px"
+
+ if(!width && !height){
+ var pos = d.position(parentNode);
+ width = width || pos.w;
+ height = height || pos.h;
+ }
+ if(typeof width == "number"){
+ width = width + "px";
+ }
+ if(typeof height == "number"){
+ height = height + "px";
+ }
+
+ var s = new sl.Surface();
+ parentNode = d.byId(parentNode);
+ s._parent = parentNode;
+ s._nodeName = g._base._getUniqueId();
+
+ // create an empty canvas
+ var t = parentNode.ownerDocument.createElement("script");
+ t.type = "text/xaml";
+ t.id = g._base._getUniqueId();
+ t.text = "<?xml version='1.0'?><Canvas xmlns='http://schemas.microsoft.com/client/2007' Name='" +
+ s._nodeName + "'/>";
+ parentNode.parentNode.insertBefore(t, parentNode);
+ s._nodes.push(t);
+
+ // build the object
+ var obj, pluginName = g._base._getUniqueId(),
+ onLoadName = "__" + g._base._getUniqueId() + "_onLoad";
+ s._onLoadName = onLoadName;
+ window[onLoadName] = function(sender){
+ if(!s.rawNode){
+ s.rawNode = d.byId(pluginName).content.root;
+ // register the plugin with its parent node
+ surfaces[s._nodeName] = parentNode;
+ s.onLoad(s);
+ }
+ };
+ if(d.isSafari){
+ obj = "<embed type='application/x-silverlight' id='" +
+ pluginName + "' width='" + width + "' height='" + height +
+ " background='transparent'" +
+ " source='#" + t.id + "'" +
+ " windowless='true'" +
+ " maxFramerate='60'" +
+ " onLoad='" + onLoadName + "'" +
+ " onError='__dojoSilverlightError'" +
+ " /><iframe style='visibility:hidden;height:0;width:0'/>";
+ }else{
+ obj = "<object type='application/x-silverlight' data='data:application/x-silverlight,' id='" +
+ pluginName + "' width='" + width + "' height='" + height + "'>" +
+ "<param name='background' value='transparent' />" +
+ "<param name='source' value='#" + t.id + "' />" +
+ "<param name='windowless' value='true' />" +
+ "<param name='maxFramerate' value='60' />" +
+ "<param name='onLoad' value='" + onLoadName + "' />" +
+ "<param name='onError' value='__dojoSilverlightError' />" +
+ "</object>";
+ }
+ parentNode.innerHTML = obj;
+
+ var pluginNode = d.byId(pluginName);
+ if(pluginNode.content && pluginNode.content.root){
+ // the plugin was created synchronously
+ s.rawNode = pluginNode.content.root;
+ // register the plugin with its parent node
+ surfaces[s._nodeName] = parentNode;
+ }else{
+ // the plugin is being created asynchronously
+ s.rawNode = null;
+ s.isLoaded = false;
+ }
+ s._nodes.push(pluginNode);
+
+ s.width = g.normalizedLength(width); // in pixels
+ s.height = g.normalizedLength(height); // in pixels
+
+ return s; // dojox.gfx.Surface
+ };
+
+ // the function below is meant to be global, it is called from
+ // the Silverlight's error handler
+ __dojoSilverlightError = function(sender, err){
+ var t = "Silverlight Error:\n" +
+ "Code: " + err.ErrorCode + "\n" +
+ "Type: " + err.ErrorType + "\n" +
+ "Message: " + err.ErrorMessage + "\n";
+ switch(err.ErrorType){
+ case "ParserError":
+ t += "XamlFile: " + err.xamlFile + "\n" +
+ "Line: " + err.lineNumber + "\n" +
+ "Position: " + err.charPosition + "\n";
+ break;
+ case "RuntimeError":
+ t += "MethodName: " + err.methodName + "\n";
+ if(err.lineNumber != 0){
+ t +=
+ "Line: " + err.lineNumber + "\n" +
+ "Position: " + err.charPosition + "\n";
+ }
+ break;
+ }
+ };
+
+ // Extenders
+
+ var Font = {
+ _setFont: function(){
+ // summary: sets a font object (Silverlight)
+ var f = this.fontStyle, r = this.rawNode, t = f.family.toLowerCase();
+ r.fontStyle = f.style == "italic" ? "Italic" : "Normal";
+ r.fontWeight = f.weight in fontweight ? fontweight[f.weight] : f.weight;
+ r.fontSize = g.normalizedLength(f.size);
+ r.fontFamily = t in fonts ? fonts[t] : f.family;
+
+ // update the transform
+ if(!this._delay){
+ this._delay = window.setTimeout(d.hitch(this, "_delayAlignment"), 10);
+ }
+ }
+ };
+
+ var C = gs.Container, Container = {
+ add: function(shape){
+ // summary: adds a shape to a group/surface
+ // shape: dojox.gfx.Shape: a Silverlight shape object
+ if(this != shape.getParent()){
+ C.add.apply(this, arguments);
+ this.rawNode.children.add(shape.rawNode);
+ }
+ return this; // self
+ },
+ remove: function(shape, silently){
+ // summary: remove a shape from a group/surface
+ // shape: dojox.gfx.Shape: a Silverlight shape object
+ // silently: Boolean?: if true, regenerate a picture
+ if(this == shape.getParent()){
+ var parent = shape.rawNode.getParent();
+ if(parent){
+ parent.children.remove(shape.rawNode);
+ }
+ C.remove.apply(this, arguments);
+ }
+ return this; // self
+ },
+ clear: function(){
+ // summary: removes all shapes from a group/surface
+ this.rawNode.children.clear();
+ return C.clear.apply(this, arguments);
+ },
+ _moveChildToFront: C._moveChildToFront,
+ _moveChildToBack: C._moveChildToBack
+ };
+
+ var Creator = {
+ 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
+ if(!this.rawNode){ return null; }
+ var shape = new shapeType();
+ var node = this.rawNode.getHost().content.createFromXaml("<" + shapeType.nodeType + "/>");
+ shape.setRawNode(node);
+ shape.setShape(rawShape);
+ this.add(shape);
+ return shape; // dojox.gfx.Shape
+ }
+ };
+
+ d.extend(sl.Text, Font);
+ //d.extend(sl.TextPath, Font);
+
+ d.extend(sl.Group, Container);
+ d.extend(sl.Group, gs.Creator);
+ d.extend(sl.Group, Creator);
+
+ d.extend(sl.Surface, Container);
+ d.extend(sl.Surface, gs.Creator);
+ d.extend(sl.Surface, Creator);
+
+ function mouseFix(s, a){
+ var ev = {target: s, currentTarget: s, preventDefault: function(){}, stopPropagation: function(){}};
+ try{
+ if(a.source){
+ // support silverlight 2.0
+ ev.target = a.source;
+ }
+ }catch(e){
+ // a.source does not exist in 1.0
+ }
+
+ if(a){
+ try{
+ ev.ctrlKey = a.ctrl;
+ ev.shiftKey = a.shift;
+ var p = a.getPosition(null);
+ ev.x = ev.offsetX = ev.layerX = p.x;
+ ev.y = ev.offsetY = ev.layerY = p.y;
+ // calculate clientX and clientY
+ var parent = surfaces[s.getHost().content.root.name];
+ var t = d.position(parent);
+ ev.clientX = t.x + p.x;
+ ev.clientY = t.y + p.y;
+ }catch(e){
+ // squelch bugs in MouseLeave's implementation
+ }
+ }
+ return ev;
+ }
+
+ function keyFix(s, a){
+ var ev = {
+ keyCode: a.platformKeyCode,
+ ctrlKey: a.ctrl,
+ shiftKey: a.shift
+ };
+ try{
+ if(a.source){
+ // source is defined from Silverlight 2+
+ ev.target = a.source;
+ }
+ }catch(e){
+ // a.source does not exist in 1.0
+ }
+ return ev;
+ }
+
+ var eventNames = {
+ onclick: {name: "MouseLeftButtonUp", fix: mouseFix},
+ onmouseenter: {name: "MouseEnter", fix: mouseFix},
+ onmouseleave: {name: "MouseLeave", fix: mouseFix},
+ onmouseover: {name: "MouseEnter", fix: mouseFix},
+ onmouseout: {name: "MouseLeave", fix: mouseFix},
+ onmousedown: {name: "MouseLeftButtonDown", fix: mouseFix},
+ onmouseup: {name: "MouseLeftButtonUp", fix: mouseFix},
+ onmousemove: {name: "MouseMove", fix: mouseFix},
+ onkeydown: {name: "KeyDown", fix: keyFix},
+ onkeyup: {name: "KeyUp", fix: keyFix}
+ };
+
+ var eventsProcessing = {
+ connect: function(name, object, method){
+ var token, n = name in eventNames ? eventNames[name] :
+ {name: name, fix: function(){ return {}; }};
+ if(arguments.length > 2){
+ token = this.getEventSource().addEventListener(n.name,
+ function(s, a){ d.hitch(object, method)(n.fix(s, a)); });
+ }else{
+ token = this.getEventSource().addEventListener(n.name,
+ function(s, a){ object(n.fix(s, a)); });
+ }
+ return {name: n.name, token: token};
+ },
+ disconnect: function(token){
+ try{
+ this.getEventSource().removeEventListener(token.name, token.token);
+ }catch(e){
+ // bail out if the node is hidden
+ }
+ }
+ };
+
+ d.extend(sl.Shape, eventsProcessing);
+ d.extend(sl.Surface, eventsProcessing);
+
+ // patch dojox.gfx
+ g.equalSources = function(a, b){
+ // summary: compares event sources, returns true if they are equal
+ return a && b && a.equals(b);
+ };
+
+ // see if we are required to initilize
+ if(g.loadAndSwitch === "silverlight"){
+ g.switchTo("silverlight");
+ delete g.loadAndSwitch;
+ }
+})();
+
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/silverlight.xd.js b/js/dojo-1.6/dojox/gfx/silverlight.xd.js new file mode 100644 index 0000000..32cb278 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/silverlight.xd.js @@ -0,0 +1,830 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.silverlight"],
+["require", "dojox.gfx._base"],
+["require", "dojox.gfx.shape"],
+["require", "dojox.gfx.path"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.silverlight"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.silverlight"] = true;
+dojo.provide("dojox.gfx.silverlight");
+
+dojo.require("dojox.gfx._base");
+dojo.require("dojox.gfx.shape");
+dojo.require("dojox.gfx.path");
+
+dojo.experimental("dojox.gfx.silverlight");
+
+(function(){
+ var d = dojo, g = dojox.gfx, gs = g.shape, sl = g.silverlight;
+
+ var dasharray = {
+ solid: "none",
+ shortdash: [4, 1],
+ shortdot: [1, 1],
+ shortdashdot: [4, 1, 1, 1],
+ shortdashdotdot: [4, 1, 1, 1, 1, 1],
+ dot: [1, 3],
+ dash: [4, 3],
+ longdash: [8, 3],
+ dashdot: [4, 3, 1, 3],
+ longdashdot: [8, 3, 1, 3],
+ longdashdotdot: [8, 3, 1, 3, 1, 3]
+ },
+ fontweight = {
+ normal: 400,
+ bold: 700
+ },
+ caps = {butt: "Flat", round: "Round", square: "Square"},
+ joins = {bevel: "Bevel", round: "Round"},
+ fonts = {
+ serif: "Times New Roman",
+ times: "Times New Roman",
+ "sans-serif": "Arial",
+ helvetica: "Arial",
+ monotone: "Courier New",
+ courier: "Courier New"
+ };
+
+ function hexColor(/*String|Array|dojo.Color*/ color){
+ // summary: converts a color object to a Silverlight hex color string (#aarrggbb)
+ var c = g.normalizeColor(color),
+ t = c.toHex(), a = Math.round(c.a * 255);
+ a = (a < 0 ? 0 : a > 255 ? 255 : a).toString(16);
+ return "#" + (a.length < 2 ? "0" + a : a) + t.slice(1); // String
+ }
+
+ d.declare("dojox.gfx.silverlight.Shape", gs.Shape, {
+ // summary: Silverlight-specific implementation of dojox.gfx.Shape methods
+
+ setFill: function(fill){
+ // summary: sets a fill object (Silverlight)
+ // fill: Object: a fill object
+ // (see dojox.gfx.defaultLinearGradient,
+ // dojox.gfx.defaultRadialGradient,
+ // dojox.gfx.defaultPattern,
+ // or dojo.Color)
+
+ var p = this.rawNode.getHost().content, r = this.rawNode, f;
+ if(!fill){
+ // don't fill
+ this.fillStyle = null;
+ this._setFillAttr(null);
+ return this; // self
+ }
+ if(typeof(fill) == "object" && "type" in fill){
+ // gradient
+ switch(fill.type){
+ case "linear":
+ this.fillStyle = f = g.makeParameters(g.defaultLinearGradient, fill);
+ var lgb = p.createFromXaml("<LinearGradientBrush/>");
+ lgb.mappingMode = "Absolute";
+ lgb.startPoint = f.x1 + "," + f.y1;
+ lgb.endPoint = f.x2 + "," + f.y2;
+ d.forEach(f.colors, function(c){
+ var t = p.createFromXaml("<GradientStop/>");
+ t.offset = c.offset;
+ t.color = hexColor(c.color);
+ lgb.gradientStops.add(t);
+ });
+ this._setFillAttr(lgb);
+ break;
+ case "radial":
+ this.fillStyle = f = g.makeParameters(g.defaultRadialGradient, fill);
+ var rgb = p.createFromXaml("<RadialGradientBrush/>"),
+ c = g.matrix.multiplyPoint(g.matrix.invert(this._getAdjustedMatrix()), f.cx, f.cy),
+ pt = c.x + "," + c.y;
+ rgb.mappingMode = "Absolute";
+ rgb.gradientOrigin = pt;
+ rgb.center = pt;
+ rgb.radiusX = rgb.radiusY = f.r;
+ d.forEach(f.colors, function(c){
+ var t = p.createFromXaml("<GradientStop/>");
+ t.offset = c.offset;
+ t.color = hexColor(c.color);
+ rgb.gradientStops.add(t);
+ });
+ this._setFillAttr(rgb);
+ break;
+ case "pattern":
+ // don't fill: Silverlight doesn't define TileBrush for some reason
+ this.fillStyle = null;
+ this._setFillAttr(null);
+ break;
+ }
+ return this; // self
+ }
+ // color object
+ this.fillStyle = f = g.normalizeColor(fill);
+ var scb = p.createFromXaml("<SolidColorBrush/>");
+ scb.color = f.toHex();
+ scb.opacity = f.a;
+ this._setFillAttr(scb);
+ return this; // self
+ },
+ _setFillAttr: function(f){
+ this.rawNode.fill = f;
+ },
+
+ setStroke: function(stroke){
+ // summary: sets a stroke object (Silverlight)
+ // stroke: Object: a stroke object
+ // (see dojox.gfx.defaultStroke)
+
+ var p = this.rawNode.getHost().content, r = this.rawNode;
+ if(!stroke){
+ // don't stroke
+ this.strokeStyle = null;
+ r.stroke = null;
+ return this;
+ }
+ // normalize the stroke
+ if(typeof stroke == "string" || d.isArray(stroke) || stroke instanceof d.Color){
+ stroke = {color: stroke};
+ }
+ var s = this.strokeStyle = g.makeParameters(g.defaultStroke, stroke);
+ s.color = g.normalizeColor(s.color);
+ // generate attributes
+ if(s){
+ var scb = p.createFromXaml("<SolidColorBrush/>");
+ scb.color = s.color.toHex();
+ scb.opacity = s.color.a;
+ r.stroke = scb;
+ r.strokeThickness = s.width;
+ r.strokeStartLineCap = r.strokeEndLineCap = r.strokeDashCap =
+ caps[s.cap];
+ if(typeof s.join == "number"){
+ r.strokeLineJoin = "Miter";
+ r.strokeMiterLimit = s.join;
+ }else{
+ r.strokeLineJoin = joins[s.join];
+ }
+ var da = s.style.toLowerCase();
+ if(da in dasharray){ da = dasharray[da]; }
+ if(da instanceof Array){
+ da = d.clone(da);
+ var i;
+ /*
+ for(var i = 0; i < da.length; ++i){
+ da[i] *= s.width;
+ }
+ */
+ if(s.cap != "butt"){
+ for(i = 0; i < da.length; i += 2){
+ //da[i] -= s.width;
+ --da[i]
+ if(da[i] < 1){ da[i] = 1; }
+ }
+ for(i = 1; i < da.length; i += 2){
+ //da[i] += s.width;
+ ++da[i];
+ }
+ }
+ r.strokeDashArray = da.join(",");
+ }else{
+ r.strokeDashArray = null;
+ }
+ }
+ return this; // self
+ },
+
+ _getParentSurface: function(){
+ var surface = this.parent;
+ for(; surface && !(surface instanceof g.Surface); surface = surface.parent);
+ return surface;
+ },
+
+ _applyTransform: function() {
+ var tm = this._getAdjustedMatrix(), r = this.rawNode;
+ if(tm){
+ var p = this.rawNode.getHost().content,
+ mt = p.createFromXaml("<MatrixTransform/>"),
+ mm = p.createFromXaml("<Matrix/>");
+ mm.m11 = tm.xx;
+ mm.m21 = tm.xy;
+ mm.m12 = tm.yx;
+ mm.m22 = tm.yy;
+ mm.offsetX = tm.dx;
+ mm.offsetY = tm.dy;
+ mt.matrix = mm;
+ r.renderTransform = mt;
+ }else{
+ r.renderTransform = null;
+ }
+ 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.fill = null;
+ rawNode.stroke = null;
+ this.rawNode = rawNode;
+ },
+
+ // move family
+
+ _moveToFront: function(){
+ // summary: moves a shape to front of its parent's list of shapes (Silverlight)
+ var c = this.parent.rawNode.children, r = this.rawNode;
+ c.remove(r);
+ c.add(r);
+ return this; // self
+ },
+ _moveToBack: function(){
+ // summary: moves a shape to back of its parent's list of shapes (Silverlight)
+ var c = this.parent.rawNode.children, r = this.rawNode;
+ c.remove(r);
+ c.insert(0, r);
+ return this; // self
+ },
+
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ return this.matrix; // dojox.gfx.Matrix2D
+ }
+ });
+
+ d.declare("dojox.gfx.silverlight.Group", sl.Shape, {
+ // summary: a group shape (Silverlight), which can be used
+ // to logically group shapes (e.g, to propagate matricies)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ setRawNode: function(rawNode){
+ // summary: sets a raw Silverlight node to be used by this shape
+ // rawNode: Node: an Silverlight node
+ this.rawNode = rawNode;
+ }
+ });
+ sl.Group.nodeType = "Canvas";
+
+ d.declare("dojox.gfx.silverlight.Rect", [sl.Shape, gs.Rect], {
+ // summary: a rectangle shape (Silverlight)
+ setShape: function(newShape){
+ // summary: sets a rectangle shape object (Silverlight)
+ // newShape: Object: a rectangle shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, n = this.shape;
+ r.width = n.width;
+ r.height = n.height;
+ r.radiusX = r.radiusY = n.r;
+ return this._applyTransform(); // self
+ },
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ var matrix = this.matrix, s = this.shape, delta = {dx: s.x, dy: s.y};
+ return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
+ }
+ });
+ sl.Rect.nodeType = "Rectangle";
+
+ d.declare("dojox.gfx.silverlight.Ellipse", [sl.Shape, gs.Ellipse], {
+ // summary: an ellipse shape (Silverlight)
+ setShape: function(newShape){
+ // summary: sets an ellipse shape object (Silverlight)
+ // newShape: Object: an ellipse shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, n = this.shape;
+ r.width = 2 * n.rx;
+ r.height = 2 * n.ry;
+ return this._applyTransform(); // self
+ },
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ var matrix = this.matrix, s = this.shape, delta = {dx: s.cx - s.rx, dy: s.cy - s.ry};
+ return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
+ }
+ });
+ sl.Ellipse.nodeType = "Ellipse";
+
+ d.declare("dojox.gfx.silverlight.Circle", [sl.Shape, gs.Circle], {
+ // summary: a circle shape (Silverlight)
+ setShape: function(newShape){
+ // summary: sets a circle shape object (Silverlight)
+ // newShape: Object: a circle shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, n = this.shape;
+ r.width = r.height = 2 * n.r;
+ return this._applyTransform(); // self
+ },
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ var matrix = this.matrix, s = this.shape, delta = {dx: s.cx - s.r, dy: s.cy - s.r};
+ return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
+ }
+ });
+ sl.Circle.nodeType = "Ellipse";
+
+ d.declare("dojox.gfx.silverlight.Line", [sl.Shape, gs.Line], {
+ // summary: a line shape (Silverlight)
+ setShape: function(newShape){
+ // summary: sets a line shape object (Silverlight)
+ // newShape: Object: a line shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, n = this.shape;
+ r.x1 = n.x1; r.y1 = n.y1; r.x2 = n.x2; r.y2 = n.y2;
+ return this; // self
+ }
+ });
+ sl.Line.nodeType = "Line";
+
+ d.declare("dojox.gfx.silverlight.Polyline", [sl.Shape, gs.Polyline], {
+ // summary: a polyline/polygon shape (Silverlight)
+ setShape: function(points, closed){
+ // summary: sets a polyline/polygon shape object (Silverlight)
+ // points: Object: a polyline/polygon shape object
+ if(points && points instanceof Array){
+ // branch
+ // points: Array: an array of points
+ this.shape = g.makeParameters(this.shape, {points: points});
+ if(closed && this.shape.points.length){
+ this.shape.points.push(this.shape.points[0]);
+ }
+ }else{
+ this.shape = g.makeParameters(this.shape, points);
+ }
+ this.bbox = null;
+ this._normalizePoints();
+ var p = this.shape.points, rp = [];
+ for(var i = 0; i < p.length; ++i){
+ rp.push(p[i].x, p[i].y);
+ }
+ this.rawNode.points = rp.join(",");
+ return this; // self
+ }
+ });
+ sl.Polyline.nodeType = "Polyline";
+
+ d.declare("dojox.gfx.silverlight.Image", [sl.Shape, gs.Image], {
+ // summary: an image (Silverlight)
+ setShape: function(newShape){
+ // summary: sets an image shape object (Silverlight)
+ // newShape: Object: an image shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, n = this.shape;
+ r.width = n.width;
+ r.height = n.height;
+ r.source = n.src;
+ return this._applyTransform(); // self
+ },
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ var matrix = this.matrix, s = this.shape, delta = {dx: s.x, dy: s.y};
+ return new g.Matrix2D(matrix ? [matrix, delta] : delta); // dojox.gfx.Matrix2D
+ },
+ 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)
+ this.rawNode = rawNode;
+ }
+ });
+ sl.Image.nodeType = "Image";
+
+ d.declare("dojox.gfx.silverlight.Text", [sl.Shape, gs.Text], {
+ // summary: an anchored text (Silverlight)
+ setShape: function(newShape){
+ // summary: sets a text shape object (Silverlight)
+ // newShape: Object: a text shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, s = this.shape;
+ r.text = s.text;
+ r.textDecorations = s.decoration === "underline" ? "Underline" : "None";
+ r["Canvas.Left"] = -10000;
+ r["Canvas.Top"] = -10000;
+ if(!this._delay){
+ this._delay = window.setTimeout(d.hitch(this, "_delayAlignment"), 10);
+ }
+ return this; // self
+ },
+ _delayAlignment: function(){
+ // handle alignment
+ var r = this.rawNode, s = this.shape, w, h;
+ try{
+ w = r.actualWidth;
+ h = r.actualHeight;
+ }catch(e){
+ // bail out if the node is hidden
+ return;
+ }
+ var x = s.x, y = s.y - h * 0.75;
+ switch(s.align){
+ case "middle":
+ x -= w / 2;
+ break;
+ case "end":
+ x -= w;
+ break;
+ }
+ this._delta = {dx: x, dy: y};
+ r["Canvas.Left"] = 0;
+ r["Canvas.Top"] = 0;
+ this._applyTransform();
+ delete this._delay;
+ },
+ _getAdjustedMatrix: function(){
+ // summary: returns the adjusted ("real") transformation matrix
+ var matrix = this.matrix, delta = this._delta, x;
+ if(matrix){
+ x = delta ? [matrix, delta] : matrix;
+ }else{
+ x = delta ? delta : {};
+ }
+ return new g.Matrix2D(x);
+ },
+ setStroke: function(){
+ // summary: ignore setting a stroke style
+ return this; // self
+ },
+ _setFillAttr: function(f){
+ this.rawNode.foreground = f;
+ },
+ 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)
+ this.rawNode = rawNode;
+ },
+ getTextWidth: function(){
+ // summary: get the text width in pixels
+ return this.rawNode.actualWidth;
+ }
+ });
+ sl.Text.nodeType = "TextBlock";
+
+ d.declare("dojox.gfx.silverlight.Path", [sl.Shape, g.path.Path], {
+ // summary: a path shape (Silverlight)
+ _updateWithSegment: function(segment){
+ // summary: updates the bounding box of path with new segment
+ // segment: Object: a segment
+ this.inherited(arguments);
+ var p = this.shape.path;
+ if(typeof(p) == "string"){
+ this.rawNode.data = p ? p : null;
+ }
+ },
+ setShape: function(newShape){
+ // summary: forms a path using a shape (Silverlight)
+ // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+ this.inherited(arguments);
+ var p = this.shape.path;
+ this.rawNode.data = p ? p : null;
+ return this; // self
+ }
+ });
+ sl.Path.nodeType = "Path";
+
+ d.declare("dojox.gfx.silverlight.TextPath", [sl.Shape, g.path.TextPath], {
+ // summary: a textpath shape (Silverlight)
+ _updateWithSegment: function(segment){
+ // summary: updates the bounding box of path with new segment
+ // segment: Object: a segment
+ },
+ setShape: function(newShape){
+ // summary: forms a path using a shape (Silverlight)
+ // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+ },
+ _setText: function(){
+ }
+ });
+ sl.TextPath.nodeType = "text";
+
+ var surfaces = {}, nullFunc = new Function;
+
+ d.declare("dojox.gfx.silverlight.Surface", gs.Surface, {
+ // summary: a surface object to be used for drawings (Silverlight)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ destroy: function(){
+ window[this._onLoadName] = nullFunc;
+ delete surfaces[this._nodeName];
+ this.inherited(arguments);
+ },
+ 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 = g.normalizedLength(width); // in pixels
+ this.height = g.normalizedLength(height); // in pixels
+ var p = this.rawNode && this.rawNode.getHost();
+ if(p){
+ p.width = width;
+ p.height = height;
+ }
+ return this; // self
+ },
+ getDimensions: function(){
+ // summary: returns an object with properties "width" and "height"
+ var p = this.rawNode && this.rawNode.getHost();
+ var t = p ? {width: p.content.actualWidth, height: p.content.actualHeight} : null;
+ if(t.width <= 0){ t.width = this.width; }
+ if(t.height <= 0){ t.height = this.height; }
+ return t; // Object
+ }
+ });
+
+ sl.createSurface = function(parentNode, width, height){
+ // summary: creates a surface (Silverlight)
+ // parentNode: Node: a parent node
+ // width: String: width of surface, e.g., "100px"
+ // height: String: height of surface, e.g., "100px"
+
+ if(!width && !height){
+ var pos = d.position(parentNode);
+ width = width || pos.w;
+ height = height || pos.h;
+ }
+ if(typeof width == "number"){
+ width = width + "px";
+ }
+ if(typeof height == "number"){
+ height = height + "px";
+ }
+
+ var s = new sl.Surface();
+ parentNode = d.byId(parentNode);
+ s._parent = parentNode;
+ s._nodeName = g._base._getUniqueId();
+
+ // create an empty canvas
+ var t = parentNode.ownerDocument.createElement("script");
+ t.type = "text/xaml";
+ t.id = g._base._getUniqueId();
+ t.text = "<?xml version='1.0'?><Canvas xmlns='http://schemas.microsoft.com/client/2007' Name='" +
+ s._nodeName + "'/>";
+ parentNode.parentNode.insertBefore(t, parentNode);
+ s._nodes.push(t);
+
+ // build the object
+ var obj, pluginName = g._base._getUniqueId(),
+ onLoadName = "__" + g._base._getUniqueId() + "_onLoad";
+ s._onLoadName = onLoadName;
+ window[onLoadName] = function(sender){
+ if(!s.rawNode){
+ s.rawNode = d.byId(pluginName).content.root;
+ // register the plugin with its parent node
+ surfaces[s._nodeName] = parentNode;
+ s.onLoad(s);
+ }
+ };
+ if(d.isSafari){
+ obj = "<embed type='application/x-silverlight' id='" +
+ pluginName + "' width='" + width + "' height='" + height +
+ " background='transparent'" +
+ " source='#" + t.id + "'" +
+ " windowless='true'" +
+ " maxFramerate='60'" +
+ " onLoad='" + onLoadName + "'" +
+ " onError='__dojoSilverlightError'" +
+ " /><iframe style='visibility:hidden;height:0;width:0'/>";
+ }else{
+ obj = "<object type='application/x-silverlight' data='data:application/x-silverlight,' id='" +
+ pluginName + "' width='" + width + "' height='" + height + "'>" +
+ "<param name='background' value='transparent' />" +
+ "<param name='source' value='#" + t.id + "' />" +
+ "<param name='windowless' value='true' />" +
+ "<param name='maxFramerate' value='60' />" +
+ "<param name='onLoad' value='" + onLoadName + "' />" +
+ "<param name='onError' value='__dojoSilverlightError' />" +
+ "</object>";
+ }
+ parentNode.innerHTML = obj;
+
+ var pluginNode = d.byId(pluginName);
+ if(pluginNode.content && pluginNode.content.root){
+ // the plugin was created synchronously
+ s.rawNode = pluginNode.content.root;
+ // register the plugin with its parent node
+ surfaces[s._nodeName] = parentNode;
+ }else{
+ // the plugin is being created asynchronously
+ s.rawNode = null;
+ s.isLoaded = false;
+ }
+ s._nodes.push(pluginNode);
+
+ s.width = g.normalizedLength(width); // in pixels
+ s.height = g.normalizedLength(height); // in pixels
+
+ return s; // dojox.gfx.Surface
+ };
+
+ // the function below is meant to be global, it is called from
+ // the Silverlight's error handler
+ __dojoSilverlightError = function(sender, err){
+ var t = "Silverlight Error:\n" +
+ "Code: " + err.ErrorCode + "\n" +
+ "Type: " + err.ErrorType + "\n" +
+ "Message: " + err.ErrorMessage + "\n";
+ switch(err.ErrorType){
+ case "ParserError":
+ t += "XamlFile: " + err.xamlFile + "\n" +
+ "Line: " + err.lineNumber + "\n" +
+ "Position: " + err.charPosition + "\n";
+ break;
+ case "RuntimeError":
+ t += "MethodName: " + err.methodName + "\n";
+ if(err.lineNumber != 0){
+ t +=
+ "Line: " + err.lineNumber + "\n" +
+ "Position: " + err.charPosition + "\n";
+ }
+ break;
+ }
+ };
+
+ // Extenders
+
+ var Font = {
+ _setFont: function(){
+ // summary: sets a font object (Silverlight)
+ var f = this.fontStyle, r = this.rawNode, t = f.family.toLowerCase();
+ r.fontStyle = f.style == "italic" ? "Italic" : "Normal";
+ r.fontWeight = f.weight in fontweight ? fontweight[f.weight] : f.weight;
+ r.fontSize = g.normalizedLength(f.size);
+ r.fontFamily = t in fonts ? fonts[t] : f.family;
+
+ // update the transform
+ if(!this._delay){
+ this._delay = window.setTimeout(d.hitch(this, "_delayAlignment"), 10);
+ }
+ }
+ };
+
+ var C = gs.Container, Container = {
+ add: function(shape){
+ // summary: adds a shape to a group/surface
+ // shape: dojox.gfx.Shape: a Silverlight shape object
+ if(this != shape.getParent()){
+ C.add.apply(this, arguments);
+ this.rawNode.children.add(shape.rawNode);
+ }
+ return this; // self
+ },
+ remove: function(shape, silently){
+ // summary: remove a shape from a group/surface
+ // shape: dojox.gfx.Shape: a Silverlight shape object
+ // silently: Boolean?: if true, regenerate a picture
+ if(this == shape.getParent()){
+ var parent = shape.rawNode.getParent();
+ if(parent){
+ parent.children.remove(shape.rawNode);
+ }
+ C.remove.apply(this, arguments);
+ }
+ return this; // self
+ },
+ clear: function(){
+ // summary: removes all shapes from a group/surface
+ this.rawNode.children.clear();
+ return C.clear.apply(this, arguments);
+ },
+ _moveChildToFront: C._moveChildToFront,
+ _moveChildToBack: C._moveChildToBack
+ };
+
+ var Creator = {
+ 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
+ if(!this.rawNode){ return null; }
+ var shape = new shapeType();
+ var node = this.rawNode.getHost().content.createFromXaml("<" + shapeType.nodeType + "/>");
+ shape.setRawNode(node);
+ shape.setShape(rawShape);
+ this.add(shape);
+ return shape; // dojox.gfx.Shape
+ }
+ };
+
+ d.extend(sl.Text, Font);
+ //d.extend(sl.TextPath, Font);
+
+ d.extend(sl.Group, Container);
+ d.extend(sl.Group, gs.Creator);
+ d.extend(sl.Group, Creator);
+
+ d.extend(sl.Surface, Container);
+ d.extend(sl.Surface, gs.Creator);
+ d.extend(sl.Surface, Creator);
+
+ function mouseFix(s, a){
+ var ev = {target: s, currentTarget: s, preventDefault: function(){}, stopPropagation: function(){}};
+ try{
+ if(a.source){
+ // support silverlight 2.0
+ ev.target = a.source;
+ }
+ }catch(e){
+ // a.source does not exist in 1.0
+ }
+
+ if(a){
+ try{
+ ev.ctrlKey = a.ctrl;
+ ev.shiftKey = a.shift;
+ var p = a.getPosition(null);
+ ev.x = ev.offsetX = ev.layerX = p.x;
+ ev.y = ev.offsetY = ev.layerY = p.y;
+ // calculate clientX and clientY
+ var parent = surfaces[s.getHost().content.root.name];
+ var t = d.position(parent);
+ ev.clientX = t.x + p.x;
+ ev.clientY = t.y + p.y;
+ }catch(e){
+ // squelch bugs in MouseLeave's implementation
+ }
+ }
+ return ev;
+ }
+
+ function keyFix(s, a){
+ var ev = {
+ keyCode: a.platformKeyCode,
+ ctrlKey: a.ctrl,
+ shiftKey: a.shift
+ };
+ try{
+ if(a.source){
+ // source is defined from Silverlight 2+
+ ev.target = a.source;
+ }
+ }catch(e){
+ // a.source does not exist in 1.0
+ }
+ return ev;
+ }
+
+ var eventNames = {
+ onclick: {name: "MouseLeftButtonUp", fix: mouseFix},
+ onmouseenter: {name: "MouseEnter", fix: mouseFix},
+ onmouseleave: {name: "MouseLeave", fix: mouseFix},
+ onmouseover: {name: "MouseEnter", fix: mouseFix},
+ onmouseout: {name: "MouseLeave", fix: mouseFix},
+ onmousedown: {name: "MouseLeftButtonDown", fix: mouseFix},
+ onmouseup: {name: "MouseLeftButtonUp", fix: mouseFix},
+ onmousemove: {name: "MouseMove", fix: mouseFix},
+ onkeydown: {name: "KeyDown", fix: keyFix},
+ onkeyup: {name: "KeyUp", fix: keyFix}
+ };
+
+ var eventsProcessing = {
+ connect: function(name, object, method){
+ var token, n = name in eventNames ? eventNames[name] :
+ {name: name, fix: function(){ return {}; }};
+ if(arguments.length > 2){
+ token = this.getEventSource().addEventListener(n.name,
+ function(s, a){ d.hitch(object, method)(n.fix(s, a)); });
+ }else{
+ token = this.getEventSource().addEventListener(n.name,
+ function(s, a){ object(n.fix(s, a)); });
+ }
+ return {name: n.name, token: token};
+ },
+ disconnect: function(token){
+ try{
+ this.getEventSource().removeEventListener(token.name, token.token);
+ }catch(e){
+ // bail out if the node is hidden
+ }
+ }
+ };
+
+ d.extend(sl.Shape, eventsProcessing);
+ d.extend(sl.Surface, eventsProcessing);
+
+ // patch dojox.gfx
+ g.equalSources = function(a, b){
+ // summary: compares event sources, returns true if they are equal
+ return a && b && a.equals(b);
+ };
+
+ // see if we are required to initilize
+ if(g.loadAndSwitch === "silverlight"){
+ g.switchTo("silverlight");
+ delete g.loadAndSwitch;
+ }
+})();
+
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/silverlight_attach.js b/js/dojo-1.6/dojox/gfx/silverlight_attach.js new file mode 100644 index 0000000..c0e8411 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/silverlight_attach.js @@ -0,0 +1,32 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.silverlight_attach"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.silverlight_attach"] = true;
+dojo.provide("dojox.gfx.silverlight_attach");
+
+dojo.require("dojox.gfx.silverlight");
+
+dojo.experimental("dojox.gfx.silverlight_attach");
+
+(function(){
+ var g = dojox.gfx, sl = g.silverlight;
+
+ sl.attachNode = function(node){
+ // summary: creates a shape from a Node
+ // node: Node: an Silverlight node
+ return null; // not implemented
+ };
+
+ sl.attachSurface = function(node){
+ // summary: creates a surface from a Node
+ // node: Node: an Silverlight node
+ return null; // dojox.gfx.Surface
+ };
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/silverlight_attach.xd.js b/js/dojo-1.6/dojox/gfx/silverlight_attach.xd.js new file mode 100644 index 0000000..b54c130 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/silverlight_attach.xd.js @@ -0,0 +1,37 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.silverlight_attach"],
+["require", "dojox.gfx.silverlight"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.silverlight_attach"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.silverlight_attach"] = true;
+dojo.provide("dojox.gfx.silverlight_attach");
+
+dojo.require("dojox.gfx.silverlight");
+
+dojo.experimental("dojox.gfx.silverlight_attach");
+
+(function(){
+ var g = dojox.gfx, sl = g.silverlight;
+
+ sl.attachNode = function(node){
+ // summary: creates a shape from a Node
+ // node: Node: an Silverlight node
+ return null; // not implemented
+ };
+
+ sl.attachSurface = function(node){
+ // summary: creates a surface from a Node
+ // node: Node: an Silverlight node
+ return null; // dojox.gfx.Surface
+ };
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/svg.js b/js/dojo-1.6/dojox/gfx/svg.js new file mode 100644 index 0000000..d25354e --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/svg.js @@ -0,0 +1,804 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.svg"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.svg"] = true;
+dojo.provide("dojox.gfx.svg");
+
+dojo.require("dojox.gfx._base");
+dojo.require("dojox.gfx.shape");
+dojo.require("dojox.gfx.path");
+
+(function(){
+ var d = dojo, g = dojox.gfx, gs = g.shape, svg = g.svg;
+ svg.useSvgWeb = (typeof window.svgweb != "undefined");
+
+ function _createElementNS(ns, nodeType){
+ // summary:
+ // Internal helper to deal with creating elements that
+ // are namespaced. Mainly to get SVG markup output
+ // working on IE.
+ if(dojo.doc.createElementNS){
+ return dojo.doc.createElementNS(ns,nodeType);
+ }else{
+ return dojo.doc.createElement(nodeType);
+ }
+ }
+
+ function _createTextNode(text){
+ if(svg.useSvgWeb){
+ return dojo.doc.createTextNode(text, true);
+ }else{
+ return dojo.doc.createTextNode(text);
+ }
+ }
+
+ function _createFragment(){
+ if(svg.useSvgWeb){
+ return dojo.doc.createDocumentFragment(true);
+ }else{
+ return dojo.doc.createDocumentFragment();
+ }
+ }
+
+ svg.xmlns = {
+ xlink: "http://www.w3.org/1999/xlink",
+ svg: "http://www.w3.org/2000/svg"
+ };
+
+ svg.getRef = function(name){
+ // summary: returns a DOM Node specified by the name argument or null
+ // name: String: an SVG external reference
+ if(!name || name == "none") return null;
+ if(name.match(/^url\(#.+\)$/)){
+ return d.byId(name.slice(5, -1)); // Node
+ }
+ // alternative representation of a reference
+ if(name.match(/^#dojoUnique\d+$/)){
+ // we assume here that a reference was generated by dojox.gfx
+ return d.byId(name.slice(1)); // Node
+ }
+ return null; // Node
+ };
+
+ svg.dasharray = {
+ solid: "none",
+ shortdash: [4, 1],
+ shortdot: [1, 1],
+ shortdashdot: [4, 1, 1, 1],
+ shortdashdotdot: [4, 1, 1, 1, 1, 1],
+ dot: [1, 3],
+ dash: [4, 3],
+ longdash: [8, 3],
+ dashdot: [4, 3, 1, 3],
+ longdashdot: [8, 3, 1, 3],
+ longdashdotdot: [8, 3, 1, 3, 1, 3]
+ };
+
+ d.declare("dojox.gfx.svg.Shape", gs.Shape, {
+ // summary: SVG-specific implementation of dojox.gfx.Shape methods
+
+ setFill: function(fill){
+ // summary: sets a fill object (SVG)
+ // fill: Object: a fill object
+ // (see dojox.gfx.defaultLinearGradient,
+ // dojox.gfx.defaultRadialGradient,
+ // dojox.gfx.defaultPattern,
+ // or dojo.Color)
+
+ if(!fill){
+ // don't fill
+ this.fillStyle = null;
+ this.rawNode.setAttribute("fill", "none");
+ this.rawNode.setAttribute("fill-opacity", 0);
+ return this;
+ }
+ var f;
+ // FIXME: slightly magical. We're using the outer scope's "f", but setting it later
+ var setter = function(x){
+ // we assume that we're executing in the scope of the node to mutate
+ this.setAttribute(x, f[x].toFixed(8));
+ };
+ if(typeof(fill) == "object" && "type" in fill){
+ // gradient
+ switch(fill.type){
+ case "linear":
+ f = g.makeParameters(g.defaultLinearGradient, fill);
+ var gradient = this._setFillObject(f, "linearGradient");
+ d.forEach(["x1", "y1", "x2", "y2"], setter, gradient);
+ break;
+ case "radial":
+ f = g.makeParameters(g.defaultRadialGradient, fill);
+ var gradient = this._setFillObject(f, "radialGradient");
+ d.forEach(["cx", "cy", "r"], setter, gradient);
+ break;
+ case "pattern":
+ f = g.makeParameters(g.defaultPattern, fill);
+ var pattern = this._setFillObject(f, "pattern");
+ d.forEach(["x", "y", "width", "height"], setter, pattern);
+ break;
+ }
+ this.fillStyle = f;
+ return this;
+ }
+ // color object
+ var f = g.normalizeColor(fill);
+ this.fillStyle = f;
+ this.rawNode.setAttribute("fill", f.toCss());
+ this.rawNode.setAttribute("fill-opacity", f.a);
+ this.rawNode.setAttribute("fill-rule", "evenodd");
+ return this; // self
+ },
+
+ setStroke: function(stroke){
+ // summary:
+ // sets a stroke object (SVG)
+ // stroke: Object
+ // a stroke object (see dojox.gfx.defaultStroke)
+
+ var rn = this.rawNode;
+ if(!stroke){
+ // don't stroke
+ this.strokeStyle = null;
+ rn.setAttribute("stroke", "none");
+ rn.setAttribute("stroke-opacity", 0);
+ return this;
+ }
+ // normalize the stroke
+ if(typeof stroke == "string" || d.isArray(stroke) || stroke instanceof d.Color){
+ stroke = { color: stroke };
+ }
+ var s = this.strokeStyle = g.makeParameters(g.defaultStroke, stroke);
+ s.color = g.normalizeColor(s.color);
+ // generate attributes
+ if(s){
+ rn.setAttribute("stroke", s.color.toCss());
+ rn.setAttribute("stroke-opacity", s.color.a);
+ rn.setAttribute("stroke-width", s.width);
+ rn.setAttribute("stroke-linecap", s.cap);
+ if(typeof s.join == "number"){
+ rn.setAttribute("stroke-linejoin", "miter");
+ rn.setAttribute("stroke-miterlimit", s.join);
+ }else{
+ rn.setAttribute("stroke-linejoin", s.join);
+ }
+ var da = s.style.toLowerCase();
+ if(da in svg.dasharray){
+ da = svg.dasharray[da];
+ }
+ if(da instanceof Array){
+ da = d._toArray(da);
+ for(var i = 0; i < da.length; ++i){
+ da[i] *= s.width;
+ }
+ if(s.cap != "butt"){
+ for(var i = 0; i < da.length; i += 2){
+ da[i] -= s.width;
+ if(da[i] < 1){ da[i] = 1; }
+ }
+ for(var i = 1; i < da.length; i += 2){
+ da[i] += s.width;
+ }
+ }
+ da = da.join(",");
+ }
+ rn.setAttribute("stroke-dasharray", da);
+ rn.setAttribute("dojoGfxStrokeStyle", s.style);
+ }
+ return this; // self
+ },
+
+ _getParentSurface: function(){
+ var surface = this.parent;
+ for(; surface && !(surface instanceof g.Surface); surface = surface.parent);
+ return surface;
+ },
+
+ _setFillObject: function(f, nodeType){
+ var svgns = svg.xmlns.svg;
+ this.fillStyle = f;
+ var surface = this._getParentSurface(),
+ defs = surface.defNode,
+ fill = this.rawNode.getAttribute("fill"),
+ ref = svg.getRef(fill);
+ if(ref){
+ fill = ref;
+ if(fill.tagName.toLowerCase() != nodeType.toLowerCase()){
+ var id = fill.id;
+ fill.parentNode.removeChild(fill);
+ fill = _createElementNS(svgns, nodeType);
+ fill.setAttribute("id", id);
+ defs.appendChild(fill);
+ }else{
+ while(fill.childNodes.length){
+ fill.removeChild(fill.lastChild);
+ }
+ }
+ }else{
+ fill = _createElementNS(svgns, nodeType);
+ fill.setAttribute("id", g._base._getUniqueId());
+ defs.appendChild(fill);
+ }
+ if(nodeType == "pattern"){
+ fill.setAttribute("patternUnits", "userSpaceOnUse");
+ var img = _createElementNS(svgns, "image");
+ img.setAttribute("x", 0);
+ img.setAttribute("y", 0);
+ img.setAttribute("width", f.width .toFixed(8));
+ img.setAttribute("height", f.height.toFixed(8));
+ img.setAttributeNS(svg.xmlns.xlink, "xlink:href", f.src);
+ fill.appendChild(img);
+ }else{
+ fill.setAttribute("gradientUnits", "userSpaceOnUse");
+ for(var i = 0; i < f.colors.length; ++i){
+ var c = f.colors[i], t = _createElementNS(svgns, "stop"),
+ cc = c.color = g.normalizeColor(c.color);
+ t.setAttribute("offset", c.offset.toFixed(8));
+ t.setAttribute("stop-color", cc.toCss());
+ t.setAttribute("stop-opacity", cc.a);
+ fill.appendChild(t);
+ }
+ }
+ this.rawNode.setAttribute("fill", "url(#" + fill.getAttribute("id") +")");
+ this.rawNode.removeAttribute("fill-opacity");
+ this.rawNode.setAttribute("fill-rule", "evenodd");
+ return fill;
+ },
+
+ _applyTransform: function() {
+ var matrix = this.matrix;
+ if(matrix){
+ var tm = this.matrix;
+ this.rawNode.setAttribute("transform", "matrix(" +
+ tm.xx.toFixed(8) + "," + tm.yx.toFixed(8) + "," +
+ tm.xy.toFixed(8) + "," + tm.yy.toFixed(8) + "," +
+ tm.dx.toFixed(8) + "," + tm.dy.toFixed(8) + ")");
+ }else{
+ this.rawNode.removeAttribute("transform");
+ }
+ 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)
+ var r = this.rawNode = rawNode;
+ if(this.shape.type!="image"){
+ r.setAttribute("fill", "none");
+ }
+ r.setAttribute("fill-opacity", 0);
+ r.setAttribute("stroke", "none");
+ r.setAttribute("stroke-opacity", 0);
+ r.setAttribute("stroke-width", 1);
+ r.setAttribute("stroke-linecap", "butt");
+ r.setAttribute("stroke-linejoin", "miter");
+ r.setAttribute("stroke-miterlimit", 4);
+ },
+
+ setShape: function(newShape){
+ // summary: sets a shape object (SVG)
+ // newShape: Object: a shape object
+ // (see dojox.gfx.defaultPath,
+ // dojox.gfx.defaultPolyline,
+ // dojox.gfx.defaultRect,
+ // dojox.gfx.defaultEllipse,
+ // dojox.gfx.defaultCircle,
+ // dojox.gfx.defaultLine,
+ // or dojox.gfx.defaultImage)
+ this.shape = g.makeParameters(this.shape, newShape);
+ for(var i in this.shape){
+ if(i != "type"){
+ this.rawNode.setAttribute(i, this.shape[i]);
+ }
+ }
+ this.bbox = null;
+ return this; // self
+ },
+
+ // move family
+
+ _moveToFront: function(){
+ // summary: moves a shape to front of its parent's list of shapes (SVG)
+ this.rawNode.parentNode.appendChild(this.rawNode);
+ return this; // self
+ },
+ _moveToBack: function(){
+ // summary: moves a shape to back of its parent's list of shapes (SVG)
+ this.rawNode.parentNode.insertBefore(this.rawNode, this.rawNode.parentNode.firstChild);
+ return this; // self
+ }
+ });
+
+ dojo.declare("dojox.gfx.svg.Group", svg.Shape, {
+ // summary: a group shape (SVG), which can be used
+ // to logically group shapes (e.g, to propagate matricies)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ setRawNode: function(rawNode){
+ // summary: sets a raw SVG node to be used by this shape
+ // rawNode: Node: an SVG node
+ this.rawNode = rawNode;
+ }
+ });
+ svg.Group.nodeType = "g";
+
+ dojo.declare("dojox.gfx.svg.Rect", [svg.Shape, gs.Rect], {
+ // summary: a rectangle shape (SVG)
+ setShape: function(newShape){
+ // summary: sets a rectangle shape object (SVG)
+ // newShape: Object: a rectangle shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ for(var i in this.shape){
+ if(i != "type" && i != "r"){
+ this.rawNode.setAttribute(i, this.shape[i]);
+ }
+ }
+ if(this.shape.r){
+ this.rawNode.setAttribute("ry", this.shape.r);
+ this.rawNode.setAttribute("rx", this.shape.r);
+ }
+ return this; // self
+ }
+ });
+ svg.Rect.nodeType = "rect";
+
+ dojo.declare("dojox.gfx.svg.Ellipse", [svg.Shape, gs.Ellipse], {});
+ svg.Ellipse.nodeType = "ellipse";
+
+ dojo.declare("dojox.gfx.svg.Circle", [svg.Shape, gs.Circle], {});
+ svg.Circle.nodeType = "circle";
+
+ dojo.declare("dojox.gfx.svg.Line", [svg.Shape, gs.Line], {});
+ svg.Line.nodeType = "line";
+
+ dojo.declare("dojox.gfx.svg.Polyline", [svg.Shape, gs.Polyline], {
+ // summary: a polyline/polygon shape (SVG)
+ setShape: function(points, closed){
+ // summary: sets a polyline/polygon shape object (SVG)
+ // points: Object: a polyline/polygon shape object
+ if(points && points instanceof Array){
+ // branch
+ // points: Array: an array of points
+ this.shape = g.makeParameters(this.shape, { points: points });
+ if(closed && this.shape.points.length){
+ this.shape.points.push(this.shape.points[0]);
+ }
+ }else{
+ this.shape = g.makeParameters(this.shape, points);
+ }
+ this.bbox = null;
+ this._normalizePoints();
+ var attr = [], p = this.shape.points;
+ for(var i = 0; i < p.length; ++i){
+ attr.push(p[i].x.toFixed(8), p[i].y.toFixed(8));
+ }
+ this.rawNode.setAttribute("points", attr.join(" "));
+ return this; // self
+ }
+ });
+ svg.Polyline.nodeType = "polyline";
+
+ dojo.declare("dojox.gfx.svg.Image", [svg.Shape, gs.Image], {
+ // summary: an image (SVG)
+ setShape: function(newShape){
+ // summary: sets an image shape object (SVG)
+ // newShape: Object: an image shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var rawNode = this.rawNode;
+ for(var i in this.shape){
+ if(i != "type" && i != "src"){
+ rawNode.setAttribute(i, this.shape[i]);
+ }
+ }
+ rawNode.setAttribute("preserveAspectRatio", "none");
+ rawNode.setAttributeNS(svg.xmlns.xlink, "xlink:href", this.shape.src);
+ return this; // self
+ }
+ });
+ svg.Image.nodeType = "image";
+
+ dojo.declare("dojox.gfx.svg.Text", [svg.Shape, gs.Text], {
+ // summary: an anchored text (SVG)
+ setShape: function(newShape){
+ // summary: sets a text shape object (SVG)
+ // newShape: Object: a text shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, s = this.shape;
+ r.setAttribute("x", s.x);
+ r.setAttribute("y", s.y);
+ r.setAttribute("text-anchor", s.align);
+ r.setAttribute("text-decoration", s.decoration);
+ r.setAttribute("rotate", s.rotated ? 90 : 0);
+ r.setAttribute("kerning", s.kerning ? "auto" : 0);
+ r.setAttribute("text-rendering", "optimizeLegibility");
+
+ // update the text content
+ if(r.firstChild){
+ r.firstChild.nodeValue = s.text;
+ }else{
+ r.appendChild(_createTextNode(s.text));
+ }
+ return this; // self
+ },
+ getTextWidth: function(){
+ // summary: get the text width in pixels
+ var rawNode = this.rawNode,
+ oldParent = rawNode.parentNode,
+ _measurementNode = rawNode.cloneNode(true);
+ _measurementNode.style.visibility = "hidden";
+
+ // solution to the "orphan issue" in FF
+ var _width = 0, _text = _measurementNode.firstChild.nodeValue;
+ oldParent.appendChild(_measurementNode);
+
+ // solution to the "orphan issue" in Opera
+ // (nodeValue == "" hangs firefox)
+ if(_text!=""){
+ while(!_width){
+//Yang: work around svgweb bug 417 -- http://code.google.com/p/svgweb/issues/detail?id=417
+if (_measurementNode.getBBox)
+ _width = parseInt(_measurementNode.getBBox().width);
+else
+ _width = 68;
+ }
+ }
+ oldParent.removeChild(_measurementNode);
+ return _width;
+ }
+ });
+ svg.Text.nodeType = "text";
+
+ dojo.declare("dojox.gfx.svg.Path", [svg.Shape, g.path.Path], {
+ // summary: a path shape (SVG)
+ _updateWithSegment: function(segment){
+ // summary: updates the bounding box of path with new segment
+ // segment: Object: a segment
+ this.inherited(arguments);
+ if(typeof(this.shape.path) == "string"){
+ this.rawNode.setAttribute("d", this.shape.path);
+ }
+ },
+ setShape: function(newShape){
+ // summary: forms a path using a shape (SVG)
+ // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+ this.inherited(arguments);
+ if(this.shape.path){
+ this.rawNode.setAttribute("d", this.shape.path);
+ }else{
+ this.rawNode.removeAttribute("d");
+ }
+ return this; // self
+ }
+ });
+ svg.Path.nodeType = "path";
+
+ dojo.declare("dojox.gfx.svg.TextPath", [svg.Shape, g.path.TextPath], {
+ // summary: a textpath shape (SVG)
+ _updateWithSegment: function(segment){
+ // summary: updates the bounding box of path with new segment
+ // segment: Object: a segment
+ this.inherited(arguments);
+ this._setTextPath();
+ },
+ setShape: function(newShape){
+ // summary: forms a path using a shape (SVG)
+ // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+ this.inherited(arguments);
+ this._setTextPath();
+ return this; // self
+ },
+ _setTextPath: function(){
+ if(typeof this.shape.path != "string"){ return; }
+ var r = this.rawNode;
+ if(!r.firstChild){
+ var tp = _createElementNS(svg.xmlns.svg, "textPath"),
+ tx = _createTextNode("");
+ tp.appendChild(tx);
+ r.appendChild(tp);
+ }
+ var ref = r.firstChild.getAttributeNS(svg.xmlns.xlink, "href"),
+ path = ref && svg.getRef(ref);
+ if(!path){
+ var surface = this._getParentSurface();
+ if(surface){
+ var defs = surface.defNode;
+ path = _createElementNS(svg.xmlns.svg, "path");
+ var id = g._base._getUniqueId();
+ path.setAttribute("id", id);
+ defs.appendChild(path);
+ r.firstChild.setAttributeNS(svg.xmlns.xlink, "xlink:href", "#" + id);
+ }
+ }
+ if(path){
+ path.setAttribute("d", this.shape.path);
+ }
+ },
+ _setText: function(){
+ var r = this.rawNode;
+ if(!r.firstChild){
+ var tp = _createElementNS(svg.xmlns.svg, "textPath"),
+ tx = _createTextNode("");
+ tp.appendChild(tx);
+ r.appendChild(tp);
+ }
+ r = r.firstChild;
+ var t = this.text;
+ r.setAttribute("alignment-baseline", "middle");
+ switch(t.align){
+ case "middle":
+ r.setAttribute("text-anchor", "middle");
+ r.setAttribute("startOffset", "50%");
+ break;
+ case "end":
+ r.setAttribute("text-anchor", "end");
+ r.setAttribute("startOffset", "100%");
+ break;
+ default:
+ r.setAttribute("text-anchor", "start");
+ r.setAttribute("startOffset", "0%");
+ break;
+ }
+ //r.parentNode.setAttribute("alignment-baseline", "central");
+ //r.setAttribute("dominant-baseline", "central");
+ r.setAttribute("baseline-shift", "0.5ex");
+ r.setAttribute("text-decoration", t.decoration);
+ r.setAttribute("rotate", t.rotated ? 90 : 0);
+ r.setAttribute("kerning", t.kerning ? "auto" : 0);
+ r.firstChild.data = t.text;
+ }
+ });
+ svg.TextPath.nodeType = "text";
+
+ dojo.declare("dojox.gfx.svg.Surface", gs.Surface, {
+ // summary: a surface object to be used for drawings (SVG)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ destroy: function(){
+ this.defNode = null; // release the external reference
+ this.inherited(arguments);
+ },
+ 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"
+ if(!this.rawNode){ return this; }
+ this.rawNode.setAttribute("width", width);
+ this.rawNode.setAttribute("height", height);
+ return this; // self
+ },
+ getDimensions: function(){
+ // summary: returns an object with properties "width" and "height"
+ var t = this.rawNode ? {
+ width: g.normalizedLength(this.rawNode.getAttribute("width")),
+ height: g.normalizedLength(this.rawNode.getAttribute("height"))} : null;
+ return t; // Object
+ }
+ });
+
+ svg.createSurface = function(parentNode, width, height){
+ // summary: creates a surface (SVG)
+ // parentNode: Node: a parent node
+ // width: String: width of surface, e.g., "100px"
+ // height: String: height of surface, e.g., "100px"
+
+ var s = new svg.Surface();
+ s.rawNode = _createElementNS(svg.xmlns.svg, "svg");
+ if(width){
+ s.rawNode.setAttribute("width", width);
+ }
+ if(height){
+ s.rawNode.setAttribute("height", height);
+ }
+
+ var defNode = _createElementNS(svg.xmlns.svg, "defs");
+ s.rawNode.appendChild(defNode);
+ s.defNode = defNode;
+
+ s._parent = d.byId(parentNode);
+ s._parent.appendChild(s.rawNode);
+
+ return s; // dojox.gfx.Surface
+ };
+
+ // Extenders
+
+ var Font = {
+ _setFont: function(){
+ // summary: sets a font object (SVG)
+ var f = this.fontStyle;
+ // next line doesn't work in Firefox 2 or Opera 9
+ //this.rawNode.setAttribute("font", dojox.gfx.makeFontString(this.fontStyle));
+ this.rawNode.setAttribute("font-style", f.style);
+ this.rawNode.setAttribute("font-variant", f.variant);
+ this.rawNode.setAttribute("font-weight", f.weight);
+ this.rawNode.setAttribute("font-size", f.size);
+ this.rawNode.setAttribute("font-family", f.family);
+ }
+ };
+
+ var C = gs.Container, Container = {
+ openBatch: function() {
+ // summary: starts a new batch, subsequent new child shapes will be held in
+ // the batch instead of appending to the container directly
+ this.fragment = _createFragment();
+ },
+ closeBatch: function() {
+ // summary: submits the current batch, append all pending child shapes to DOM
+ if (this.fragment) {
+ this.rawNode.appendChild(this.fragment);
+ delete this.fragment;
+ }
+ },
+ add: function(shape){
+ // summary: adds a shape to a group/surface
+ // shape: dojox.gfx.Shape: an VML shape object
+ if(this != shape.getParent()){
+ if (this.fragment) {
+ this.fragment.appendChild(shape.rawNode);
+ } else {
+ this.rawNode.appendChild(shape.rawNode);
+ }
+ C.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 picture
+ if(this == shape.getParent()){
+ if(this.rawNode == shape.rawNode.parentNode){
+ this.rawNode.removeChild(shape.rawNode);
+ }
+ if(this.fragment && this.fragment == shape.rawNode.parentNode){
+ this.fragment.removeChild(shape.rawNode);
+ }
+ C.remove.apply(this, arguments);
+ }
+ return this; // self
+ },
+ clear: function(){
+ // summary: removes all shapes from a group/surface
+ var r = this.rawNode;
+ while(r.lastChild){
+ r.removeChild(r.lastChild);
+ }
+ var defNode = this.defNode;
+ if(defNode){
+ while(defNode.lastChild){
+ defNode.removeChild(defNode.lastChild);
+ }
+ r.appendChild(defNode);
+ }
+ return C.clear.apply(this, arguments);
+ },
+ _moveChildToFront: C._moveChildToFront,
+ _moveChildToBack: C._moveChildToBack
+ };
+
+ var Creator = {
+ // summary: SVG shape creators
+ 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
+ if(!this.rawNode){ return null; }
+ var shape = new shapeType(),
+ node = _createElementNS(svg.xmlns.svg, shapeType.nodeType);
+
+ shape.setRawNode(node);
+ shape.setShape(rawShape);
+ // rawNode.appendChild() will be done inside this.add(shape) below
+ this.add(shape);
+ return shape; // dojox.gfx.Shape
+ }
+ };
+
+ d.extend(svg.Text, Font);
+ d.extend(svg.TextPath, Font);
+
+ d.extend(svg.Group, Container);
+ d.extend(svg.Group, gs.Creator);
+ d.extend(svg.Group, Creator);
+
+ d.extend(svg.Surface, Container);
+ d.extend(svg.Surface, gs.Creator);
+ d.extend(svg.Surface, Creator);
+
+
+ // some specific override for svgweb + flash
+ if(svg.useSvgWeb){
+ // override createSurface()
+ svg.createSurface = function(parentNode, width, height){
+ var s = new svg.Surface();
+
+ // ensure width / height
+ if(!width || !height){
+ var pos = d.position(parentNode);
+ width = width || pos.w;
+ height = height || pos.h;
+ }
+
+ // ensure id
+ parentNode = d.byId(parentNode);
+ var id = parentNode.id ? parentNode.id+'_svgweb' : g._base._getUniqueId();
+
+ // create dynamic svg root
+ var mockSvg = _createElementNS(svg.xmlns.svg, 'svg');
+ mockSvg.id = id;
+ mockSvg.setAttribute('width', width);
+ mockSvg.setAttribute('height', height);
+ svgweb.appendChild(mockSvg, parentNode);
+
+ // notice: any call to the raw node before flash init will fail.
+ mockSvg.addEventListener('SVGLoad', function(){
+ // become loaded
+ s.rawNode = this;
+ s.isLoaded = true;
+
+ // init defs
+ var defNode = _createElementNS(svg.xmlns.svg, "defs");
+ s.rawNode.appendChild(defNode);
+ s.defNode = defNode;
+
+ // notify application
+ if (s.onLoad)
+ s.onLoad(s);
+ }, false);
+
+ // flash not loaded yet
+ s.isLoaded = false;
+ return s;
+ };
+
+ // override Surface.destroy()
+ svg.Surface.extend({
+ destroy: function(){
+ var mockSvg = this.rawNode;
+ svgweb.removeChild(mockSvg, mockSvg.parentNode);
+ }
+ });
+
+ // override connect() & disconnect() for Shape & Surface event processing
+ var _eventsProcessing = {
+ connect: function(name, object, method){
+ // connect events using the mock addEventListener() provided by svgweb
+ if (name.substring(0, 2)==='on') { name = name.substring(2); }
+ if (arguments.length == 2) {
+ method = object;
+ } else {
+ method = d.hitch(object, method);
+ }
+ this.getEventSource().addEventListener(name, method, false);
+ return [this, name, method];
+ },
+ disconnect: function(token){
+ // disconnect events using the mock removeEventListener() provided by svgweb
+ this.getEventSource().removeEventListener(token[1], token[2], false);
+ delete token[0];
+ }
+ };
+
+ dojo.extend(svg.Shape, _eventsProcessing);
+ dojo.extend(svg.Surface, _eventsProcessing);
+ }
+
+ // see if we are required to initilize
+ if(g.loadAndSwitch === "svg"){
+ g.switchTo("svg");
+ delete g.loadAndSwitch;
+ }
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/svg.xd.js b/js/dojo-1.6/dojox/gfx/svg.xd.js new file mode 100644 index 0000000..866fc5f --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/svg.xd.js @@ -0,0 +1,811 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.svg"],
+["require", "dojox.gfx._base"],
+["require", "dojox.gfx.shape"],
+["require", "dojox.gfx.path"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.svg"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.svg"] = true;
+dojo.provide("dojox.gfx.svg");
+
+dojo.require("dojox.gfx._base");
+dojo.require("dojox.gfx.shape");
+dojo.require("dojox.gfx.path");
+
+(function(){
+ var d = dojo, g = dojox.gfx, gs = g.shape, svg = g.svg;
+ svg.useSvgWeb = (typeof window.svgweb != "undefined");
+
+ function _createElementNS(ns, nodeType){
+ // summary:
+ // Internal helper to deal with creating elements that
+ // are namespaced. Mainly to get SVG markup output
+ // working on IE.
+ if(dojo.doc.createElementNS){
+ return dojo.doc.createElementNS(ns,nodeType);
+ }else{
+ return dojo.doc.createElement(nodeType);
+ }
+ }
+
+ function _createTextNode(text){
+ if(svg.useSvgWeb){
+ return dojo.doc.createTextNode(text, true);
+ }else{
+ return dojo.doc.createTextNode(text);
+ }
+ }
+
+ function _createFragment(){
+ if(svg.useSvgWeb){
+ return dojo.doc.createDocumentFragment(true);
+ }else{
+ return dojo.doc.createDocumentFragment();
+ }
+ }
+
+ svg.xmlns = {
+ xlink: "http://www.w3.org/1999/xlink",
+ svg: "http://www.w3.org/2000/svg"
+ };
+
+ svg.getRef = function(name){
+ // summary: returns a DOM Node specified by the name argument or null
+ // name: String: an SVG external reference
+ if(!name || name == "none") return null;
+ if(name.match(/^url\(#.+\)$/)){
+ return d.byId(name.slice(5, -1)); // Node
+ }
+ // alternative representation of a reference
+ if(name.match(/^#dojoUnique\d+$/)){
+ // we assume here that a reference was generated by dojox.gfx
+ return d.byId(name.slice(1)); // Node
+ }
+ return null; // Node
+ };
+
+ svg.dasharray = {
+ solid: "none",
+ shortdash: [4, 1],
+ shortdot: [1, 1],
+ shortdashdot: [4, 1, 1, 1],
+ shortdashdotdot: [4, 1, 1, 1, 1, 1],
+ dot: [1, 3],
+ dash: [4, 3],
+ longdash: [8, 3],
+ dashdot: [4, 3, 1, 3],
+ longdashdot: [8, 3, 1, 3],
+ longdashdotdot: [8, 3, 1, 3, 1, 3]
+ };
+
+ d.declare("dojox.gfx.svg.Shape", gs.Shape, {
+ // summary: SVG-specific implementation of dojox.gfx.Shape methods
+
+ setFill: function(fill){
+ // summary: sets a fill object (SVG)
+ // fill: Object: a fill object
+ // (see dojox.gfx.defaultLinearGradient,
+ // dojox.gfx.defaultRadialGradient,
+ // dojox.gfx.defaultPattern,
+ // or dojo.Color)
+
+ if(!fill){
+ // don't fill
+ this.fillStyle = null;
+ this.rawNode.setAttribute("fill", "none");
+ this.rawNode.setAttribute("fill-opacity", 0);
+ return this;
+ }
+ var f;
+ // FIXME: slightly magical. We're using the outer scope's "f", but setting it later
+ var setter = function(x){
+ // we assume that we're executing in the scope of the node to mutate
+ this.setAttribute(x, f[x].toFixed(8));
+ };
+ if(typeof(fill) == "object" && "type" in fill){
+ // gradient
+ switch(fill.type){
+ case "linear":
+ f = g.makeParameters(g.defaultLinearGradient, fill);
+ var gradient = this._setFillObject(f, "linearGradient");
+ d.forEach(["x1", "y1", "x2", "y2"], setter, gradient);
+ break;
+ case "radial":
+ f = g.makeParameters(g.defaultRadialGradient, fill);
+ var gradient = this._setFillObject(f, "radialGradient");
+ d.forEach(["cx", "cy", "r"], setter, gradient);
+ break;
+ case "pattern":
+ f = g.makeParameters(g.defaultPattern, fill);
+ var pattern = this._setFillObject(f, "pattern");
+ d.forEach(["x", "y", "width", "height"], setter, pattern);
+ break;
+ }
+ this.fillStyle = f;
+ return this;
+ }
+ // color object
+ var f = g.normalizeColor(fill);
+ this.fillStyle = f;
+ this.rawNode.setAttribute("fill", f.toCss());
+ this.rawNode.setAttribute("fill-opacity", f.a);
+ this.rawNode.setAttribute("fill-rule", "evenodd");
+ return this; // self
+ },
+
+ setStroke: function(stroke){
+ // summary:
+ // sets a stroke object (SVG)
+ // stroke: Object
+ // a stroke object (see dojox.gfx.defaultStroke)
+
+ var rn = this.rawNode;
+ if(!stroke){
+ // don't stroke
+ this.strokeStyle = null;
+ rn.setAttribute("stroke", "none");
+ rn.setAttribute("stroke-opacity", 0);
+ return this;
+ }
+ // normalize the stroke
+ if(typeof stroke == "string" || d.isArray(stroke) || stroke instanceof d.Color){
+ stroke = { color: stroke };
+ }
+ var s = this.strokeStyle = g.makeParameters(g.defaultStroke, stroke);
+ s.color = g.normalizeColor(s.color);
+ // generate attributes
+ if(s){
+ rn.setAttribute("stroke", s.color.toCss());
+ rn.setAttribute("stroke-opacity", s.color.a);
+ rn.setAttribute("stroke-width", s.width);
+ rn.setAttribute("stroke-linecap", s.cap);
+ if(typeof s.join == "number"){
+ rn.setAttribute("stroke-linejoin", "miter");
+ rn.setAttribute("stroke-miterlimit", s.join);
+ }else{
+ rn.setAttribute("stroke-linejoin", s.join);
+ }
+ var da = s.style.toLowerCase();
+ if(da in svg.dasharray){
+ da = svg.dasharray[da];
+ }
+ if(da instanceof Array){
+ da = d._toArray(da);
+ for(var i = 0; i < da.length; ++i){
+ da[i] *= s.width;
+ }
+ if(s.cap != "butt"){
+ for(var i = 0; i < da.length; i += 2){
+ da[i] -= s.width;
+ if(da[i] < 1){ da[i] = 1; }
+ }
+ for(var i = 1; i < da.length; i += 2){
+ da[i] += s.width;
+ }
+ }
+ da = da.join(",");
+ }
+ rn.setAttribute("stroke-dasharray", da);
+ rn.setAttribute("dojoGfxStrokeStyle", s.style);
+ }
+ return this; // self
+ },
+
+ _getParentSurface: function(){
+ var surface = this.parent;
+ for(; surface && !(surface instanceof g.Surface); surface = surface.parent);
+ return surface;
+ },
+
+ _setFillObject: function(f, nodeType){
+ var svgns = svg.xmlns.svg;
+ this.fillStyle = f;
+ var surface = this._getParentSurface(),
+ defs = surface.defNode,
+ fill = this.rawNode.getAttribute("fill"),
+ ref = svg.getRef(fill);
+ if(ref){
+ fill = ref;
+ if(fill.tagName.toLowerCase() != nodeType.toLowerCase()){
+ var id = fill.id;
+ fill.parentNode.removeChild(fill);
+ fill = _createElementNS(svgns, nodeType);
+ fill.setAttribute("id", id);
+ defs.appendChild(fill);
+ }else{
+ while(fill.childNodes.length){
+ fill.removeChild(fill.lastChild);
+ }
+ }
+ }else{
+ fill = _createElementNS(svgns, nodeType);
+ fill.setAttribute("id", g._base._getUniqueId());
+ defs.appendChild(fill);
+ }
+ if(nodeType == "pattern"){
+ fill.setAttribute("patternUnits", "userSpaceOnUse");
+ var img = _createElementNS(svgns, "image");
+ img.setAttribute("x", 0);
+ img.setAttribute("y", 0);
+ img.setAttribute("width", f.width .toFixed(8));
+ img.setAttribute("height", f.height.toFixed(8));
+ img.setAttributeNS(svg.xmlns.xlink, "xlink:href", f.src);
+ fill.appendChild(img);
+ }else{
+ fill.setAttribute("gradientUnits", "userSpaceOnUse");
+ for(var i = 0; i < f.colors.length; ++i){
+ var c = f.colors[i], t = _createElementNS(svgns, "stop"),
+ cc = c.color = g.normalizeColor(c.color);
+ t.setAttribute("offset", c.offset.toFixed(8));
+ t.setAttribute("stop-color", cc.toCss());
+ t.setAttribute("stop-opacity", cc.a);
+ fill.appendChild(t);
+ }
+ }
+ this.rawNode.setAttribute("fill", "url(#" + fill.getAttribute("id") +")");
+ this.rawNode.removeAttribute("fill-opacity");
+ this.rawNode.setAttribute("fill-rule", "evenodd");
+ return fill;
+ },
+
+ _applyTransform: function() {
+ var matrix = this.matrix;
+ if(matrix){
+ var tm = this.matrix;
+ this.rawNode.setAttribute("transform", "matrix(" +
+ tm.xx.toFixed(8) + "," + tm.yx.toFixed(8) + "," +
+ tm.xy.toFixed(8) + "," + tm.yy.toFixed(8) + "," +
+ tm.dx.toFixed(8) + "," + tm.dy.toFixed(8) + ")");
+ }else{
+ this.rawNode.removeAttribute("transform");
+ }
+ 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)
+ var r = this.rawNode = rawNode;
+ if(this.shape.type!="image"){
+ r.setAttribute("fill", "none");
+ }
+ r.setAttribute("fill-opacity", 0);
+ r.setAttribute("stroke", "none");
+ r.setAttribute("stroke-opacity", 0);
+ r.setAttribute("stroke-width", 1);
+ r.setAttribute("stroke-linecap", "butt");
+ r.setAttribute("stroke-linejoin", "miter");
+ r.setAttribute("stroke-miterlimit", 4);
+ },
+
+ setShape: function(newShape){
+ // summary: sets a shape object (SVG)
+ // newShape: Object: a shape object
+ // (see dojox.gfx.defaultPath,
+ // dojox.gfx.defaultPolyline,
+ // dojox.gfx.defaultRect,
+ // dojox.gfx.defaultEllipse,
+ // dojox.gfx.defaultCircle,
+ // dojox.gfx.defaultLine,
+ // or dojox.gfx.defaultImage)
+ this.shape = g.makeParameters(this.shape, newShape);
+ for(var i in this.shape){
+ if(i != "type"){
+ this.rawNode.setAttribute(i, this.shape[i]);
+ }
+ }
+ this.bbox = null;
+ return this; // self
+ },
+
+ // move family
+
+ _moveToFront: function(){
+ // summary: moves a shape to front of its parent's list of shapes (SVG)
+ this.rawNode.parentNode.appendChild(this.rawNode);
+ return this; // self
+ },
+ _moveToBack: function(){
+ // summary: moves a shape to back of its parent's list of shapes (SVG)
+ this.rawNode.parentNode.insertBefore(this.rawNode, this.rawNode.parentNode.firstChild);
+ return this; // self
+ }
+ });
+
+ dojo.declare("dojox.gfx.svg.Group", svg.Shape, {
+ // summary: a group shape (SVG), which can be used
+ // to logically group shapes (e.g, to propagate matricies)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ setRawNode: function(rawNode){
+ // summary: sets a raw SVG node to be used by this shape
+ // rawNode: Node: an SVG node
+ this.rawNode = rawNode;
+ }
+ });
+ svg.Group.nodeType = "g";
+
+ dojo.declare("dojox.gfx.svg.Rect", [svg.Shape, gs.Rect], {
+ // summary: a rectangle shape (SVG)
+ setShape: function(newShape){
+ // summary: sets a rectangle shape object (SVG)
+ // newShape: Object: a rectangle shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ for(var i in this.shape){
+ if(i != "type" && i != "r"){
+ this.rawNode.setAttribute(i, this.shape[i]);
+ }
+ }
+ if(this.shape.r){
+ this.rawNode.setAttribute("ry", this.shape.r);
+ this.rawNode.setAttribute("rx", this.shape.r);
+ }
+ return this; // self
+ }
+ });
+ svg.Rect.nodeType = "rect";
+
+ dojo.declare("dojox.gfx.svg.Ellipse", [svg.Shape, gs.Ellipse], {});
+ svg.Ellipse.nodeType = "ellipse";
+
+ dojo.declare("dojox.gfx.svg.Circle", [svg.Shape, gs.Circle], {});
+ svg.Circle.nodeType = "circle";
+
+ dojo.declare("dojox.gfx.svg.Line", [svg.Shape, gs.Line], {});
+ svg.Line.nodeType = "line";
+
+ dojo.declare("dojox.gfx.svg.Polyline", [svg.Shape, gs.Polyline], {
+ // summary: a polyline/polygon shape (SVG)
+ setShape: function(points, closed){
+ // summary: sets a polyline/polygon shape object (SVG)
+ // points: Object: a polyline/polygon shape object
+ if(points && points instanceof Array){
+ // branch
+ // points: Array: an array of points
+ this.shape = g.makeParameters(this.shape, { points: points });
+ if(closed && this.shape.points.length){
+ this.shape.points.push(this.shape.points[0]);
+ }
+ }else{
+ this.shape = g.makeParameters(this.shape, points);
+ }
+ this.bbox = null;
+ this._normalizePoints();
+ var attr = [], p = this.shape.points;
+ for(var i = 0; i < p.length; ++i){
+ attr.push(p[i].x.toFixed(8), p[i].y.toFixed(8));
+ }
+ this.rawNode.setAttribute("points", attr.join(" "));
+ return this; // self
+ }
+ });
+ svg.Polyline.nodeType = "polyline";
+
+ dojo.declare("dojox.gfx.svg.Image", [svg.Shape, gs.Image], {
+ // summary: an image (SVG)
+ setShape: function(newShape){
+ // summary: sets an image shape object (SVG)
+ // newShape: Object: an image shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var rawNode = this.rawNode;
+ for(var i in this.shape){
+ if(i != "type" && i != "src"){
+ rawNode.setAttribute(i, this.shape[i]);
+ }
+ }
+ rawNode.setAttribute("preserveAspectRatio", "none");
+ rawNode.setAttributeNS(svg.xmlns.xlink, "xlink:href", this.shape.src);
+ return this; // self
+ }
+ });
+ svg.Image.nodeType = "image";
+
+ dojo.declare("dojox.gfx.svg.Text", [svg.Shape, gs.Text], {
+ // summary: an anchored text (SVG)
+ setShape: function(newShape){
+ // summary: sets a text shape object (SVG)
+ // newShape: Object: a text shape object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, s = this.shape;
+ r.setAttribute("x", s.x);
+ r.setAttribute("y", s.y);
+ r.setAttribute("text-anchor", s.align);
+ r.setAttribute("text-decoration", s.decoration);
+ r.setAttribute("rotate", s.rotated ? 90 : 0);
+ r.setAttribute("kerning", s.kerning ? "auto" : 0);
+ r.setAttribute("text-rendering", "optimizeLegibility");
+
+ // update the text content
+ if(r.firstChild){
+ r.firstChild.nodeValue = s.text;
+ }else{
+ r.appendChild(_createTextNode(s.text));
+ }
+ return this; // self
+ },
+ getTextWidth: function(){
+ // summary: get the text width in pixels
+ var rawNode = this.rawNode,
+ oldParent = rawNode.parentNode,
+ _measurementNode = rawNode.cloneNode(true);
+ _measurementNode.style.visibility = "hidden";
+
+ // solution to the "orphan issue" in FF
+ var _width = 0, _text = _measurementNode.firstChild.nodeValue;
+ oldParent.appendChild(_measurementNode);
+
+ // solution to the "orphan issue" in Opera
+ // (nodeValue == "" hangs firefox)
+ if(_text!=""){
+ while(!_width){
+//Yang: work around svgweb bug 417 -- http://code.google.com/p/svgweb/issues/detail?id=417
+if (_measurementNode.getBBox)
+ _width = parseInt(_measurementNode.getBBox().width);
+else
+ _width = 68;
+ }
+ }
+ oldParent.removeChild(_measurementNode);
+ return _width;
+ }
+ });
+ svg.Text.nodeType = "text";
+
+ dojo.declare("dojox.gfx.svg.Path", [svg.Shape, g.path.Path], {
+ // summary: a path shape (SVG)
+ _updateWithSegment: function(segment){
+ // summary: updates the bounding box of path with new segment
+ // segment: Object: a segment
+ this.inherited(arguments);
+ if(typeof(this.shape.path) == "string"){
+ this.rawNode.setAttribute("d", this.shape.path);
+ }
+ },
+ setShape: function(newShape){
+ // summary: forms a path using a shape (SVG)
+ // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+ this.inherited(arguments);
+ if(this.shape.path){
+ this.rawNode.setAttribute("d", this.shape.path);
+ }else{
+ this.rawNode.removeAttribute("d");
+ }
+ return this; // self
+ }
+ });
+ svg.Path.nodeType = "path";
+
+ dojo.declare("dojox.gfx.svg.TextPath", [svg.Shape, g.path.TextPath], {
+ // summary: a textpath shape (SVG)
+ _updateWithSegment: function(segment){
+ // summary: updates the bounding box of path with new segment
+ // segment: Object: a segment
+ this.inherited(arguments);
+ this._setTextPath();
+ },
+ setShape: function(newShape){
+ // summary: forms a path using a shape (SVG)
+ // newShape: Object: an SVG path string or a path object (see dojox.gfx.defaultPath)
+ this.inherited(arguments);
+ this._setTextPath();
+ return this; // self
+ },
+ _setTextPath: function(){
+ if(typeof this.shape.path != "string"){ return; }
+ var r = this.rawNode;
+ if(!r.firstChild){
+ var tp = _createElementNS(svg.xmlns.svg, "textPath"),
+ tx = _createTextNode("");
+ tp.appendChild(tx);
+ r.appendChild(tp);
+ }
+ var ref = r.firstChild.getAttributeNS(svg.xmlns.xlink, "href"),
+ path = ref && svg.getRef(ref);
+ if(!path){
+ var surface = this._getParentSurface();
+ if(surface){
+ var defs = surface.defNode;
+ path = _createElementNS(svg.xmlns.svg, "path");
+ var id = g._base._getUniqueId();
+ path.setAttribute("id", id);
+ defs.appendChild(path);
+ r.firstChild.setAttributeNS(svg.xmlns.xlink, "xlink:href", "#" + id);
+ }
+ }
+ if(path){
+ path.setAttribute("d", this.shape.path);
+ }
+ },
+ _setText: function(){
+ var r = this.rawNode;
+ if(!r.firstChild){
+ var tp = _createElementNS(svg.xmlns.svg, "textPath"),
+ tx = _createTextNode("");
+ tp.appendChild(tx);
+ r.appendChild(tp);
+ }
+ r = r.firstChild;
+ var t = this.text;
+ r.setAttribute("alignment-baseline", "middle");
+ switch(t.align){
+ case "middle":
+ r.setAttribute("text-anchor", "middle");
+ r.setAttribute("startOffset", "50%");
+ break;
+ case "end":
+ r.setAttribute("text-anchor", "end");
+ r.setAttribute("startOffset", "100%");
+ break;
+ default:
+ r.setAttribute("text-anchor", "start");
+ r.setAttribute("startOffset", "0%");
+ break;
+ }
+ //r.parentNode.setAttribute("alignment-baseline", "central");
+ //r.setAttribute("dominant-baseline", "central");
+ r.setAttribute("baseline-shift", "0.5ex");
+ r.setAttribute("text-decoration", t.decoration);
+ r.setAttribute("rotate", t.rotated ? 90 : 0);
+ r.setAttribute("kerning", t.kerning ? "auto" : 0);
+ r.firstChild.data = t.text;
+ }
+ });
+ svg.TextPath.nodeType = "text";
+
+ dojo.declare("dojox.gfx.svg.Surface", gs.Surface, {
+ // summary: a surface object to be used for drawings (SVG)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ destroy: function(){
+ this.defNode = null; // release the external reference
+ this.inherited(arguments);
+ },
+ 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"
+ if(!this.rawNode){ return this; }
+ this.rawNode.setAttribute("width", width);
+ this.rawNode.setAttribute("height", height);
+ return this; // self
+ },
+ getDimensions: function(){
+ // summary: returns an object with properties "width" and "height"
+ var t = this.rawNode ? {
+ width: g.normalizedLength(this.rawNode.getAttribute("width")),
+ height: g.normalizedLength(this.rawNode.getAttribute("height"))} : null;
+ return t; // Object
+ }
+ });
+
+ svg.createSurface = function(parentNode, width, height){
+ // summary: creates a surface (SVG)
+ // parentNode: Node: a parent node
+ // width: String: width of surface, e.g., "100px"
+ // height: String: height of surface, e.g., "100px"
+
+ var s = new svg.Surface();
+ s.rawNode = _createElementNS(svg.xmlns.svg, "svg");
+ if(width){
+ s.rawNode.setAttribute("width", width);
+ }
+ if(height){
+ s.rawNode.setAttribute("height", height);
+ }
+
+ var defNode = _createElementNS(svg.xmlns.svg, "defs");
+ s.rawNode.appendChild(defNode);
+ s.defNode = defNode;
+
+ s._parent = d.byId(parentNode);
+ s._parent.appendChild(s.rawNode);
+
+ return s; // dojox.gfx.Surface
+ };
+
+ // Extenders
+
+ var Font = {
+ _setFont: function(){
+ // summary: sets a font object (SVG)
+ var f = this.fontStyle;
+ // next line doesn't work in Firefox 2 or Opera 9
+ //this.rawNode.setAttribute("font", dojox.gfx.makeFontString(this.fontStyle));
+ this.rawNode.setAttribute("font-style", f.style);
+ this.rawNode.setAttribute("font-variant", f.variant);
+ this.rawNode.setAttribute("font-weight", f.weight);
+ this.rawNode.setAttribute("font-size", f.size);
+ this.rawNode.setAttribute("font-family", f.family);
+ }
+ };
+
+ var C = gs.Container, Container = {
+ openBatch: function() {
+ // summary: starts a new batch, subsequent new child shapes will be held in
+ // the batch instead of appending to the container directly
+ this.fragment = _createFragment();
+ },
+ closeBatch: function() {
+ // summary: submits the current batch, append all pending child shapes to DOM
+ if (this.fragment) {
+ this.rawNode.appendChild(this.fragment);
+ delete this.fragment;
+ }
+ },
+ add: function(shape){
+ // summary: adds a shape to a group/surface
+ // shape: dojox.gfx.Shape: an VML shape object
+ if(this != shape.getParent()){
+ if (this.fragment) {
+ this.fragment.appendChild(shape.rawNode);
+ } else {
+ this.rawNode.appendChild(shape.rawNode);
+ }
+ C.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 picture
+ if(this == shape.getParent()){
+ if(this.rawNode == shape.rawNode.parentNode){
+ this.rawNode.removeChild(shape.rawNode);
+ }
+ if(this.fragment && this.fragment == shape.rawNode.parentNode){
+ this.fragment.removeChild(shape.rawNode);
+ }
+ C.remove.apply(this, arguments);
+ }
+ return this; // self
+ },
+ clear: function(){
+ // summary: removes all shapes from a group/surface
+ var r = this.rawNode;
+ while(r.lastChild){
+ r.removeChild(r.lastChild);
+ }
+ var defNode = this.defNode;
+ if(defNode){
+ while(defNode.lastChild){
+ defNode.removeChild(defNode.lastChild);
+ }
+ r.appendChild(defNode);
+ }
+ return C.clear.apply(this, arguments);
+ },
+ _moveChildToFront: C._moveChildToFront,
+ _moveChildToBack: C._moveChildToBack
+ };
+
+ var Creator = {
+ // summary: SVG shape creators
+ 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
+ if(!this.rawNode){ return null; }
+ var shape = new shapeType(),
+ node = _createElementNS(svg.xmlns.svg, shapeType.nodeType);
+
+ shape.setRawNode(node);
+ shape.setShape(rawShape);
+ // rawNode.appendChild() will be done inside this.add(shape) below
+ this.add(shape);
+ return shape; // dojox.gfx.Shape
+ }
+ };
+
+ d.extend(svg.Text, Font);
+ d.extend(svg.TextPath, Font);
+
+ d.extend(svg.Group, Container);
+ d.extend(svg.Group, gs.Creator);
+ d.extend(svg.Group, Creator);
+
+ d.extend(svg.Surface, Container);
+ d.extend(svg.Surface, gs.Creator);
+ d.extend(svg.Surface, Creator);
+
+
+ // some specific override for svgweb + flash
+ if(svg.useSvgWeb){
+ // override createSurface()
+ svg.createSurface = function(parentNode, width, height){
+ var s = new svg.Surface();
+
+ // ensure width / height
+ if(!width || !height){
+ var pos = d.position(parentNode);
+ width = width || pos.w;
+ height = height || pos.h;
+ }
+
+ // ensure id
+ parentNode = d.byId(parentNode);
+ var id = parentNode.id ? parentNode.id+'_svgweb' : g._base._getUniqueId();
+
+ // create dynamic svg root
+ var mockSvg = _createElementNS(svg.xmlns.svg, 'svg');
+ mockSvg.id = id;
+ mockSvg.setAttribute('width', width);
+ mockSvg.setAttribute('height', height);
+ svgweb.appendChild(mockSvg, parentNode);
+
+ // notice: any call to the raw node before flash init will fail.
+ mockSvg.addEventListener('SVGLoad', function(){
+ // become loaded
+ s.rawNode = this;
+ s.isLoaded = true;
+
+ // init defs
+ var defNode = _createElementNS(svg.xmlns.svg, "defs");
+ s.rawNode.appendChild(defNode);
+ s.defNode = defNode;
+
+ // notify application
+ if (s.onLoad)
+ s.onLoad(s);
+ }, false);
+
+ // flash not loaded yet
+ s.isLoaded = false;
+ return s;
+ };
+
+ // override Surface.destroy()
+ svg.Surface.extend({
+ destroy: function(){
+ var mockSvg = this.rawNode;
+ svgweb.removeChild(mockSvg, mockSvg.parentNode);
+ }
+ });
+
+ // override connect() & disconnect() for Shape & Surface event processing
+ var _eventsProcessing = {
+ connect: function(name, object, method){
+ // connect events using the mock addEventListener() provided by svgweb
+ if (name.substring(0, 2)==='on') { name = name.substring(2); }
+ if (arguments.length == 2) {
+ method = object;
+ } else {
+ method = d.hitch(object, method);
+ }
+ this.getEventSource().addEventListener(name, method, false);
+ return [this, name, method];
+ },
+ disconnect: function(token){
+ // disconnect events using the mock removeEventListener() provided by svgweb
+ this.getEventSource().removeEventListener(token[1], token[2], false);
+ delete token[0];
+ }
+ };
+
+ dojo.extend(svg.Shape, _eventsProcessing);
+ dojo.extend(svg.Surface, _eventsProcessing);
+ }
+
+ // see if we are required to initilize
+ if(g.loadAndSwitch === "svg"){
+ g.switchTo("svg");
+ delete g.loadAndSwitch;
+ }
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/svg_attach.js b/js/dojo-1.6/dojox/gfx/svg_attach.js new file mode 100644 index 0000000..fb6242f --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/svg_attach.js @@ -0,0 +1,241 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.svg_attach"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.svg_attach"] = true;
+dojo.provide("dojox.gfx.svg_attach");
+
+dojo.require("dojox.gfx.svg");
+
+dojo.experimental("dojox.gfx.svg_attach");
+
+(function(){
+ var g = dojox.gfx, svg = g.svg;
+
+ svg.attachNode = function(node){
+ // summary: creates a shape from a Node
+ // node: Node: an SVG node
+ if(!node){
+ return null;
+ }
+ var s = null;
+ switch(node.tagName.toLowerCase()){
+ case svg.Rect.nodeType:
+ s = new svg.Rect(node);
+ attachRect(s);
+ break;
+ case svg.Ellipse.nodeType:
+ s = new svg.Ellipse(node);
+ attachShape(s, g.defaultEllipse);
+ break;
+ case svg.Polyline.nodeType:
+ s = new svg.Polyline(node);
+ attachShape(s, g.defaultPolyline);
+ break;
+ case svg.Path.nodeType:
+ s = new svg.Path(node);
+ attachShape(s, g.defaultPath);
+ break;
+ case svg.Circle.nodeType:
+ s = new svg.Circle(node);
+ attachShape(s, g.defaultCircle);
+ break;
+ case svg.Line.nodeType:
+ s = new svg.Line(node);
+ attachShape(s, g.defaultLine);
+ break;
+ case svg.Image.nodeType:
+ s = new svg.Image(node);
+ attachShape(s, g.defaultImage);
+ break;
+ case svg.Text.nodeType:
+ var t = node.getElementsByTagName("textPath");
+ if(t && t.length){
+ s = new svg.TextPath(node);
+ attachShape(s, g.defaultPath);
+ attachTextPath(s);
+ }else{
+ s = new svg.Text(node);
+ attachText(s);
+ }
+ attachFont(s);
+ break;
+ default:
+ //console.debug("FATAL ERROR! tagName = " + node.tagName);
+ return null;
+ }
+ if(!(s instanceof svg.Image)){
+ attachFill(s);
+ attachStroke(s);
+ }
+ attachTransform(s);
+ return s; // dojox.gfx.Shape
+ };
+
+ svg.attachSurface = function(node){
+ // summary: creates a surface from a Node
+ // node: Node: an SVG node
+ var s = new svg.Surface();
+ s.rawNode = node;
+ var def_elems = node.getElementsByTagName("defs");
+ if(def_elems.length == 0){
+ return null; // dojox.gfx.Surface
+ }
+ s.defNode = def_elems[0];
+ return s; // dojox.gfx.Surface
+ };
+
+ function attachFill(object){
+ // summary: deduces a fill style from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var fill = object.rawNode.getAttribute("fill");
+ if(fill == "none"){
+ object.fillStyle = null;
+ return;
+ }
+ var fillStyle = null, gradient = svg.getRef(fill);
+ if(gradient){
+ switch(gradient.tagName.toLowerCase()){
+ case "lineargradient":
+ fillStyle = _getGradient(g.defaultLinearGradient, gradient);
+ dojo.forEach(["x1", "y1", "x2", "y2"], function(x){
+ fillStyle[x] = gradient.getAttribute(x);
+ });
+ break;
+ case "radialgradient":
+ fillStyle = _getGradient(g.defaultRadialGradient, gradient);
+ dojo.forEach(["cx", "cy", "r"], function(x){
+ fillStyle[x] = gradient.getAttribute(x);
+ });
+ fillStyle.cx = gradient.getAttribute("cx");
+ fillStyle.cy = gradient.getAttribute("cy");
+ fillStyle.r = gradient.getAttribute("r");
+ break;
+ case "pattern":
+ fillStyle = dojo.clone(g.defaultPattern);
+ dojo.forEach(["x", "y", "width", "height"], function(x){
+ fillStyle[x] = gradient.getAttribute(x);
+ });
+ fillStyle.src = gradient.firstChild.getAttributeNS(svg.xmlns.xlink, "href");
+ break;
+ }
+ }else{
+ fillStyle = new dojo.Color(fill);
+ var opacity = object.rawNode.getAttribute("fill-opacity");
+ if(opacity != null){ fillStyle.a = opacity; }
+ }
+ object.fillStyle = fillStyle;
+ }
+
+ function _getGradient(defaultGradient, gradient){
+ var fillStyle = dojo.clone(defaultGradient);
+ fillStyle.colors = [];
+ for(var i = 0; i < gradient.childNodes.length; ++i){
+ fillStyle.colors.push({
+ offset: gradient.childNodes[i].getAttribute("offset"),
+ color: new dojo.Color(gradient.childNodes[i].getAttribute("stop-color"))
+ });
+ }
+ return fillStyle;
+ }
+
+ function attachStroke(object){
+ // summary: deduces a stroke style from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var rawNode = object.rawNode, stroke = rawNode.getAttribute("stroke");
+ if(stroke == null || stroke == "none"){
+ object.strokeStyle = null;
+ return;
+ }
+ var strokeStyle = object.strokeStyle = dojo.clone(g.defaultStroke);
+ var color = new dojo.Color(stroke);
+ if(color){
+ strokeStyle.color = color;
+ strokeStyle.color.a = rawNode.getAttribute("stroke-opacity");
+ strokeStyle.width = rawNode.getAttribute("stroke-width");
+ strokeStyle.cap = rawNode.getAttribute("stroke-linecap");
+ strokeStyle.join = rawNode.getAttribute("stroke-linejoin");
+ if(strokeStyle.join == "miter"){
+ strokeStyle.join = rawNode.getAttribute("stroke-miterlimit");
+ }
+ strokeStyle.style = rawNode.getAttribute("dojoGfxStrokeStyle");
+ }
+ }
+
+ function attachTransform(object){
+ // summary: deduces a transformation matrix from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var matrix = object.rawNode.getAttribute("transform");
+ if(matrix.match(/^matrix\(.+\)$/)){
+ var t = matrix.slice(7, -1).split(",");
+ object.matrix = g.matrix.normalize({
+ xx: parseFloat(t[0]), xy: parseFloat(t[2]),
+ yx: parseFloat(t[1]), yy: parseFloat(t[3]),
+ dx: parseFloat(t[4]), dy: parseFloat(t[5])
+ });
+ }else{
+ object.matrix = null;
+ }
+ }
+
+ function attachFont(object){
+ // summary: deduces a font style from a Node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var fontStyle = object.fontStyle = dojo.clone(g.defaultFont),
+ r = object.rawNode;
+ fontStyle.style = r.getAttribute("font-style");
+ fontStyle.variant = r.getAttribute("font-variant");
+ fontStyle.weight = r.getAttribute("font-weight");
+ fontStyle.size = r.getAttribute("font-size");
+ fontStyle.family = r.getAttribute("font-family");
+ }
+
+ function attachShape(object, def){
+ // summary: builds a shape from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ // def: Object: a default shape template
+ var shape = object.shape = dojo.clone(def), r = object.rawNode;
+ for(var i in shape) {
+ shape[i] = r.getAttribute(i);
+ }
+ }
+
+ function attachRect(object){
+ // summary: builds a rectangle shape from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ attachShape(object, g.defaultRect);
+ object.shape.r = Math.min(object.rawNode.getAttribute("rx"), object.rawNode.getAttribute("ry"));
+ }
+
+ function attachText(object){
+ // summary: builds a text shape from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var shape = object.shape = dojo.clone(g.defaultText),
+ r = object.rawNode;
+ shape.x = r.getAttribute("x");
+ shape.y = r.getAttribute("y");
+ shape.align = r.getAttribute("text-anchor");
+ shape.decoration = r.getAttribute("text-decoration");
+ shape.rotated = parseFloat(r.getAttribute("rotate")) != 0;
+ shape.kerning = r.getAttribute("kerning") == "auto";
+ shape.text = r.firstChild.nodeValue;
+ }
+
+ function attachTextPath(object){
+ // summary: builds a textpath shape from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var shape = object.shape = dojo.clone(g.defaultTextPath),
+ r = object.rawNode;
+ shape.align = r.getAttribute("text-anchor");
+ shape.decoration = r.getAttribute("text-decoration");
+ shape.rotated = parseFloat(r.getAttribute("rotate")) != 0;
+ shape.kerning = r.getAttribute("kerning") == "auto";
+ shape.text = r.firstChild.nodeValue;
+ }
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/svg_attach.xd.js b/js/dojo-1.6/dojox/gfx/svg_attach.xd.js new file mode 100644 index 0000000..663de9e --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/svg_attach.xd.js @@ -0,0 +1,246 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.svg_attach"],
+["require", "dojox.gfx.svg"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.svg_attach"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.svg_attach"] = true;
+dojo.provide("dojox.gfx.svg_attach");
+
+dojo.require("dojox.gfx.svg");
+
+dojo.experimental("dojox.gfx.svg_attach");
+
+(function(){
+ var g = dojox.gfx, svg = g.svg;
+
+ svg.attachNode = function(node){
+ // summary: creates a shape from a Node
+ // node: Node: an SVG node
+ if(!node){
+ return null;
+ }
+ var s = null;
+ switch(node.tagName.toLowerCase()){
+ case svg.Rect.nodeType:
+ s = new svg.Rect(node);
+ attachRect(s);
+ break;
+ case svg.Ellipse.nodeType:
+ s = new svg.Ellipse(node);
+ attachShape(s, g.defaultEllipse);
+ break;
+ case svg.Polyline.nodeType:
+ s = new svg.Polyline(node);
+ attachShape(s, g.defaultPolyline);
+ break;
+ case svg.Path.nodeType:
+ s = new svg.Path(node);
+ attachShape(s, g.defaultPath);
+ break;
+ case svg.Circle.nodeType:
+ s = new svg.Circle(node);
+ attachShape(s, g.defaultCircle);
+ break;
+ case svg.Line.nodeType:
+ s = new svg.Line(node);
+ attachShape(s, g.defaultLine);
+ break;
+ case svg.Image.nodeType:
+ s = new svg.Image(node);
+ attachShape(s, g.defaultImage);
+ break;
+ case svg.Text.nodeType:
+ var t = node.getElementsByTagName("textPath");
+ if(t && t.length){
+ s = new svg.TextPath(node);
+ attachShape(s, g.defaultPath);
+ attachTextPath(s);
+ }else{
+ s = new svg.Text(node);
+ attachText(s);
+ }
+ attachFont(s);
+ break;
+ default:
+ //console.debug("FATAL ERROR! tagName = " + node.tagName);
+ return null;
+ }
+ if(!(s instanceof svg.Image)){
+ attachFill(s);
+ attachStroke(s);
+ }
+ attachTransform(s);
+ return s; // dojox.gfx.Shape
+ };
+
+ svg.attachSurface = function(node){
+ // summary: creates a surface from a Node
+ // node: Node: an SVG node
+ var s = new svg.Surface();
+ s.rawNode = node;
+ var def_elems = node.getElementsByTagName("defs");
+ if(def_elems.length == 0){
+ return null; // dojox.gfx.Surface
+ }
+ s.defNode = def_elems[0];
+ return s; // dojox.gfx.Surface
+ };
+
+ function attachFill(object){
+ // summary: deduces a fill style from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var fill = object.rawNode.getAttribute("fill");
+ if(fill == "none"){
+ object.fillStyle = null;
+ return;
+ }
+ var fillStyle = null, gradient = svg.getRef(fill);
+ if(gradient){
+ switch(gradient.tagName.toLowerCase()){
+ case "lineargradient":
+ fillStyle = _getGradient(g.defaultLinearGradient, gradient);
+ dojo.forEach(["x1", "y1", "x2", "y2"], function(x){
+ fillStyle[x] = gradient.getAttribute(x);
+ });
+ break;
+ case "radialgradient":
+ fillStyle = _getGradient(g.defaultRadialGradient, gradient);
+ dojo.forEach(["cx", "cy", "r"], function(x){
+ fillStyle[x] = gradient.getAttribute(x);
+ });
+ fillStyle.cx = gradient.getAttribute("cx");
+ fillStyle.cy = gradient.getAttribute("cy");
+ fillStyle.r = gradient.getAttribute("r");
+ break;
+ case "pattern":
+ fillStyle = dojo.clone(g.defaultPattern);
+ dojo.forEach(["x", "y", "width", "height"], function(x){
+ fillStyle[x] = gradient.getAttribute(x);
+ });
+ fillStyle.src = gradient.firstChild.getAttributeNS(svg.xmlns.xlink, "href");
+ break;
+ }
+ }else{
+ fillStyle = new dojo.Color(fill);
+ var opacity = object.rawNode.getAttribute("fill-opacity");
+ if(opacity != null){ fillStyle.a = opacity; }
+ }
+ object.fillStyle = fillStyle;
+ }
+
+ function _getGradient(defaultGradient, gradient){
+ var fillStyle = dojo.clone(defaultGradient);
+ fillStyle.colors = [];
+ for(var i = 0; i < gradient.childNodes.length; ++i){
+ fillStyle.colors.push({
+ offset: gradient.childNodes[i].getAttribute("offset"),
+ color: new dojo.Color(gradient.childNodes[i].getAttribute("stop-color"))
+ });
+ }
+ return fillStyle;
+ }
+
+ function attachStroke(object){
+ // summary: deduces a stroke style from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var rawNode = object.rawNode, stroke = rawNode.getAttribute("stroke");
+ if(stroke == null || stroke == "none"){
+ object.strokeStyle = null;
+ return;
+ }
+ var strokeStyle = object.strokeStyle = dojo.clone(g.defaultStroke);
+ var color = new dojo.Color(stroke);
+ if(color){
+ strokeStyle.color = color;
+ strokeStyle.color.a = rawNode.getAttribute("stroke-opacity");
+ strokeStyle.width = rawNode.getAttribute("stroke-width");
+ strokeStyle.cap = rawNode.getAttribute("stroke-linecap");
+ strokeStyle.join = rawNode.getAttribute("stroke-linejoin");
+ if(strokeStyle.join == "miter"){
+ strokeStyle.join = rawNode.getAttribute("stroke-miterlimit");
+ }
+ strokeStyle.style = rawNode.getAttribute("dojoGfxStrokeStyle");
+ }
+ }
+
+ function attachTransform(object){
+ // summary: deduces a transformation matrix from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var matrix = object.rawNode.getAttribute("transform");
+ if(matrix.match(/^matrix\(.+\)$/)){
+ var t = matrix.slice(7, -1).split(",");
+ object.matrix = g.matrix.normalize({
+ xx: parseFloat(t[0]), xy: parseFloat(t[2]),
+ yx: parseFloat(t[1]), yy: parseFloat(t[3]),
+ dx: parseFloat(t[4]), dy: parseFloat(t[5])
+ });
+ }else{
+ object.matrix = null;
+ }
+ }
+
+ function attachFont(object){
+ // summary: deduces a font style from a Node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var fontStyle = object.fontStyle = dojo.clone(g.defaultFont),
+ r = object.rawNode;
+ fontStyle.style = r.getAttribute("font-style");
+ fontStyle.variant = r.getAttribute("font-variant");
+ fontStyle.weight = r.getAttribute("font-weight");
+ fontStyle.size = r.getAttribute("font-size");
+ fontStyle.family = r.getAttribute("font-family");
+ }
+
+ function attachShape(object, def){
+ // summary: builds a shape from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ // def: Object: a default shape template
+ var shape = object.shape = dojo.clone(def), r = object.rawNode;
+ for(var i in shape) {
+ shape[i] = r.getAttribute(i);
+ }
+ }
+
+ function attachRect(object){
+ // summary: builds a rectangle shape from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ attachShape(object, g.defaultRect);
+ object.shape.r = Math.min(object.rawNode.getAttribute("rx"), object.rawNode.getAttribute("ry"));
+ }
+
+ function attachText(object){
+ // summary: builds a text shape from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var shape = object.shape = dojo.clone(g.defaultText),
+ r = object.rawNode;
+ shape.x = r.getAttribute("x");
+ shape.y = r.getAttribute("y");
+ shape.align = r.getAttribute("text-anchor");
+ shape.decoration = r.getAttribute("text-decoration");
+ shape.rotated = parseFloat(r.getAttribute("rotate")) != 0;
+ shape.kerning = r.getAttribute("kerning") == "auto";
+ shape.text = r.firstChild.nodeValue;
+ }
+
+ function attachTextPath(object){
+ // summary: builds a textpath shape from a node.
+ // object: dojox.gfx.Shape: an SVG shape
+ var shape = object.shape = dojo.clone(g.defaultTextPath),
+ r = object.rawNode;
+ shape.align = r.getAttribute("text-anchor");
+ shape.decoration = r.getAttribute("text-decoration");
+ shape.rotated = parseFloat(r.getAttribute("rotate")) != 0;
+ shape.kerning = r.getAttribute("kerning") == "auto";
+ shape.text = r.firstChild.nodeValue;
+ }
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/utils.js b/js/dojo-1.6/dojox/gfx/utils.js new file mode 100644 index 0000000..26e5904 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/utils.js @@ -0,0 +1,288 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+if(!dojo._hasResource["dojox.gfx.utils"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.utils"] = true;
+dojo.provide("dojox.gfx.utils");
+
+dojo.require("dojox.gfx");
+
+(function(){
+ var d = dojo, g = dojox.gfx, gu = g.utils;
+
+ dojo.mixin(gu, {
+ forEach: function(
+ /* dojox.gfx.Surface || dojox.gfx.Shape */ object,
+ /*Function|String|Array*/ f, /*Object?*/ o
+ ){
+ o = o || d.global;
+ f.call(o, object);
+ if(object instanceof g.Surface || object instanceof g.Group){
+ d.forEach(object.children, function(shape){
+ gu.forEach(shape, f, o);
+ });
+ }
+ },
+
+ serialize: function(
+ /* dojox.gfx.Surface || dojox.gfx.Shape */ object
+ ){
+ var t = {}, v, isSurface = object instanceof g.Surface;
+ if(isSurface || object instanceof g.Group){
+ t.children = d.map(object.children, gu.serialize);
+ if(isSurface){
+ return t.children; // Array
+ }
+ }else{
+ t.shape = object.getShape();
+ }
+ if(object.getTransform){
+ v = object.getTransform();
+ if(v){ t.transform = v; }
+ }
+ if(object.getStroke){
+ v = object.getStroke();
+ if(v){ t.stroke = v; }
+ }
+ if(object.getFill){
+ v = object.getFill();
+ if(v){ t.fill = v; }
+ }
+ if(object.getFont){
+ v = object.getFont();
+ if(v){ t.font = v; }
+ }
+ return t; // Object
+ },
+
+ toJson: function(
+ /* dojox.gfx.Surface || dojox.gfx.Shape */ object,
+ /* Boolean? */ prettyPrint
+ ){
+ return d.toJson(gu.serialize(object), prettyPrint); // String
+ },
+
+ deserialize: function(
+ /* dojox.gfx.Surface || dojox.gfx.Shape */ parent,
+ /* dojox.gfx.Shape || Array */ object
+ ){
+ if(object instanceof Array){
+ return d.map(object, d.hitch(null, gu.deserialize, parent)); // Array
+ }
+ var shape = ("shape" in object) ? parent.createShape(object.shape) : parent.createGroup();
+ if("transform" in object){
+ shape.setTransform(object.transform);
+ }
+ if("stroke" in object){
+ shape.setStroke(object.stroke);
+ }
+ if("fill" in object){
+ shape.setFill(object.fill);
+ }
+ if("font" in object){
+ shape.setFont(object.font);
+ }
+ if("children" in object){
+ d.forEach(object.children, d.hitch(null, gu.deserialize, shape));
+ }
+ return shape; // dojox.gfx.Shape
+ },
+
+ fromJson: function(
+ /* dojox.gfx.Surface || dojox.gfx.Shape */ parent,
+ /* String */ json){
+ return gu.deserialize(parent, d.fromJson(json)); // Array || dojox.gfx.Shape
+ },
+
+ toSvg: function(/*GFX object*/surface){
+ // summary:
+ // Function to serialize a GFX surface to SVG text.
+ // description:
+ // Function to serialize a GFX surface to SVG text. The value of this output
+ // is that there are numerous serverside parser libraries that can render
+ // SVG into images in various formats. This provides a way that GFX objects
+ // can be captured in a known format and sent serverside for serialization
+ // into an image.
+ // surface:
+ // The GFX surface to serialize.
+ // returns:
+ // Deferred object that will be called when SVG serialization is complete.
+
+ //Since the init and even surface creation can be async, we need to
+ //return a deferred that will be called when content has serialized.
+ var deferred = new dojo.Deferred();
+
+ if(dojox.gfx.renderer === "svg"){
+ //If we're already in SVG mode, this is easy and quick.
+ try{
+ var svg = gu._cleanSvg(gu._innerXML(surface.rawNode));
+ deferred.callback(svg);
+ }catch(e){
+ deferred.errback(e);
+ }
+ }else{
+ //Okay, now we have to get creative with hidden iframes and the like to
+ //serialize SVG.
+ if (!gu._initSvgSerializerDeferred) {
+ gu._initSvgSerializer();
+ }
+ var jsonForm = dojox.gfx.utils.toJson(surface);
+ var serializer = function(){
+ try{
+ var sDim = surface.getDimensions();
+ var width = sDim.width;
+ var height = sDim.height;
+
+ //Create an attach point in the iframe for the contents.
+ var node = gu._gfxSvgProxy.document.createElement("div");
+ gu._gfxSvgProxy.document.body.appendChild(node);
+ //Set the node scaling.
+ dojo.withDoc(gu._gfxSvgProxy.document, function() {
+ dojo.style(node, "width", width);
+ dojo.style(node, "height", height);
+ }, this);
+
+ //Create temp surface to render object to and render.
+ var ts = gu._gfxSvgProxy[dojox._scopeName].gfx.createSurface(node, width, height);
+
+ //It's apparently possible that a suface creation is async, so we need to use
+ //the whenLoaded function. Probably not needed for SVG, but making it common
+ var draw = function(surface) {
+ try{
+ gu._gfxSvgProxy[dojox._scopeName].gfx.utils.fromJson(surface, jsonForm);
+
+ //Get contents and remove temp surface.
+ var svg = gu._cleanSvg(node.innerHTML);
+ surface.clear();
+ surface.destroy();
+ gu._gfxSvgProxy.document.body.removeChild(node);
+ deferred.callback(svg);
+ }catch(e){
+ deferred.errback(e);
+ }
+ };
+ ts.whenLoaded(null,draw);
+ }catch (ex) {
+ deferred.errback(ex);
+ }
+ };
+ //See if we can call it directly or pass it to the deferred to be
+ //called on initialization.
+ if(gu._initSvgSerializerDeferred.fired > 0){
+ serializer();
+ }else{
+ gu._initSvgSerializerDeferred.addCallback(serializer);
+ }
+ }
+ return deferred; //dojo.Deferred that will be called when serialization finishes.
+ },
+
+ //iFrame document used for handling SVG serialization.
+ _gfxSvgProxy: null,
+
+ //Serializer loaded.
+ _initSvgSerializerDeferred: null,
+
+ _svgSerializerInitialized: function() {
+ // summary:
+ // Internal function to call when the serializer init completed.
+ // tags:
+ // private
+ gu._initSvgSerializerDeferred.callback(true);
+ },
+
+ _initSvgSerializer: function(){
+ // summary:
+ // Internal function to initialize the hidden iframe where SVG rendering
+ // will occur.
+ // tags:
+ // private
+ if(!gu._initSvgSerializerDeferred){
+ gu._initSvgSerializerDeferred = new dojo.Deferred();
+ var f = dojo.doc.createElement("iframe");
+ dojo.style(f, {
+ display: "none",
+ position: "absolute",
+ width: "1em",
+ height: "1em",
+ top: "-10000px"
+ });
+ var intv;
+ if(dojo.isIE){
+ f.onreadystatechange = function(){
+ if(f.contentWindow.document.readyState == "complete"){
+ f.onreadystatechange = function() {};
+ intv = setInterval(function() {
+ if(f.contentWindow[dojo._scopeName] &&
+ f.contentWindow[dojox._scopeName].gfx &&
+ f.contentWindow[dojox._scopeName].gfx.utils){
+ clearInterval(intv);
+ f.contentWindow.parent[dojox._scopeName].gfx.utils._gfxSvgProxy = f.contentWindow;
+ f.contentWindow.parent[dojox._scopeName].gfx.utils._svgSerializerInitialized();
+ }
+ }, 50);
+ }
+ };
+ }else{
+ f.onload = function(){
+ f.onload = function() {};
+ intv = setInterval(function() {
+ if(f.contentWindow[dojo._scopeName] &&
+ f.contentWindow[dojox._scopeName].gfx &&
+ f.contentWindow[dojox._scopeName].gfx.utils){
+ clearInterval(intv);
+ f.contentWindow.parent[dojox._scopeName].gfx.utils._gfxSvgProxy = f.contentWindow;
+ f.contentWindow.parent[dojox._scopeName].gfx.utils._svgSerializerInitialized();
+ }
+ }, 50);
+ };
+ }
+ //We have to load the GFX SVG proxy frame. Default is to use the one packaged in dojox.
+ var uri = (dojo.config["dojoxGfxSvgProxyFrameUrl"]||dojo.moduleUrl("dojox", "gfx/resources/gfxSvgProxyFrame.html"));
+ f.setAttribute("src", uri);
+ dojo.body().appendChild(f);
+ }
+ },
+
+ _innerXML: function(/*Node*/node){
+ // summary:
+ // Implementation of MS's innerXML function, borrowed from dojox.xml.parser.
+ // node:
+ // The node from which to generate the XML text representation.
+ // tags:
+ // private
+ if(node.innerXML){
+ return node.innerXML; //String
+ }else if(node.xml){
+ return node.xml; //String
+ }else if(typeof XMLSerializer != "undefined"){
+ return (new XMLSerializer()).serializeToString(node); //String
+ }
+ return null;
+ },
+
+ _cleanSvg: function(svg) {
+ // summary:
+ // Internal function that cleans up artifacts in extracted SVG content.
+ // tags:
+ // private
+ if(svg){
+ //Make sure the namespace is set.
+ if(svg.indexOf("xmlns=\"http://www.w3.org/2000/svg\"") == -1){
+ svg = svg.substring(4, svg.length);
+ svg = "<svg xmlns=\"http://www.w3.org/2000/svg\"" + svg;
+ }
+ //Do some other cleanup, like stripping out the
+ //dojoGfx attributes.
+ svg = svg.replace(/\bdojoGfx\w*\s*=\s*(['"])\w*\1/g, "");
+ }
+ return svg; //Cleaned SVG text.
+ }
+ });
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/utils.xd.js b/js/dojo-1.6/dojox/gfx/utils.xd.js new file mode 100644 index 0000000..9851a1b --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/utils.xd.js @@ -0,0 +1,293 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.utils"],
+["require", "dojox.gfx"]],
+defineResource: function(dojo, dijit, dojox){if(!dojo._hasResource["dojox.gfx.utils"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojox.gfx.utils"] = true;
+dojo.provide("dojox.gfx.utils");
+
+dojo.require("dojox.gfx");
+
+(function(){
+ var d = dojo, g = dojox.gfx, gu = g.utils;
+
+ dojo.mixin(gu, {
+ forEach: function(
+ /* dojox.gfx.Surface || dojox.gfx.Shape */ object,
+ /*Function|String|Array*/ f, /*Object?*/ o
+ ){
+ o = o || d.global;
+ f.call(o, object);
+ if(object instanceof g.Surface || object instanceof g.Group){
+ d.forEach(object.children, function(shape){
+ gu.forEach(shape, f, o);
+ });
+ }
+ },
+
+ serialize: function(
+ /* dojox.gfx.Surface || dojox.gfx.Shape */ object
+ ){
+ var t = {}, v, isSurface = object instanceof g.Surface;
+ if(isSurface || object instanceof g.Group){
+ t.children = d.map(object.children, gu.serialize);
+ if(isSurface){
+ return t.children; // Array
+ }
+ }else{
+ t.shape = object.getShape();
+ }
+ if(object.getTransform){
+ v = object.getTransform();
+ if(v){ t.transform = v; }
+ }
+ if(object.getStroke){
+ v = object.getStroke();
+ if(v){ t.stroke = v; }
+ }
+ if(object.getFill){
+ v = object.getFill();
+ if(v){ t.fill = v; }
+ }
+ if(object.getFont){
+ v = object.getFont();
+ if(v){ t.font = v; }
+ }
+ return t; // Object
+ },
+
+ toJson: function(
+ /* dojox.gfx.Surface || dojox.gfx.Shape */ object,
+ /* Boolean? */ prettyPrint
+ ){
+ return d.toJson(gu.serialize(object), prettyPrint); // String
+ },
+
+ deserialize: function(
+ /* dojox.gfx.Surface || dojox.gfx.Shape */ parent,
+ /* dojox.gfx.Shape || Array */ object
+ ){
+ if(object instanceof Array){
+ return d.map(object, d.hitch(null, gu.deserialize, parent)); // Array
+ }
+ var shape = ("shape" in object) ? parent.createShape(object.shape) : parent.createGroup();
+ if("transform" in object){
+ shape.setTransform(object.transform);
+ }
+ if("stroke" in object){
+ shape.setStroke(object.stroke);
+ }
+ if("fill" in object){
+ shape.setFill(object.fill);
+ }
+ if("font" in object){
+ shape.setFont(object.font);
+ }
+ if("children" in object){
+ d.forEach(object.children, d.hitch(null, gu.deserialize, shape));
+ }
+ return shape; // dojox.gfx.Shape
+ },
+
+ fromJson: function(
+ /* dojox.gfx.Surface || dojox.gfx.Shape */ parent,
+ /* String */ json){
+ return gu.deserialize(parent, d.fromJson(json)); // Array || dojox.gfx.Shape
+ },
+
+ toSvg: function(/*GFX object*/surface){
+ // summary:
+ // Function to serialize a GFX surface to SVG text.
+ // description:
+ // Function to serialize a GFX surface to SVG text. The value of this output
+ // is that there are numerous serverside parser libraries that can render
+ // SVG into images in various formats. This provides a way that GFX objects
+ // can be captured in a known format and sent serverside for serialization
+ // into an image.
+ // surface:
+ // The GFX surface to serialize.
+ // returns:
+ // Deferred object that will be called when SVG serialization is complete.
+
+ //Since the init and even surface creation can be async, we need to
+ //return a deferred that will be called when content has serialized.
+ var deferred = new dojo.Deferred();
+
+ if(dojox.gfx.renderer === "svg"){
+ //If we're already in SVG mode, this is easy and quick.
+ try{
+ var svg = gu._cleanSvg(gu._innerXML(surface.rawNode));
+ deferred.callback(svg);
+ }catch(e){
+ deferred.errback(e);
+ }
+ }else{
+ //Okay, now we have to get creative with hidden iframes and the like to
+ //serialize SVG.
+ if (!gu._initSvgSerializerDeferred) {
+ gu._initSvgSerializer();
+ }
+ var jsonForm = dojox.gfx.utils.toJson(surface);
+ var serializer = function(){
+ try{
+ var sDim = surface.getDimensions();
+ var width = sDim.width;
+ var height = sDim.height;
+
+ //Create an attach point in the iframe for the contents.
+ var node = gu._gfxSvgProxy.document.createElement("div");
+ gu._gfxSvgProxy.document.body.appendChild(node);
+ //Set the node scaling.
+ dojo.withDoc(gu._gfxSvgProxy.document, function() {
+ dojo.style(node, "width", width);
+ dojo.style(node, "height", height);
+ }, this);
+
+ //Create temp surface to render object to and render.
+ var ts = gu._gfxSvgProxy[dojox._scopeName].gfx.createSurface(node, width, height);
+
+ //It's apparently possible that a suface creation is async, so we need to use
+ //the whenLoaded function. Probably not needed for SVG, but making it common
+ var draw = function(surface) {
+ try{
+ gu._gfxSvgProxy[dojox._scopeName].gfx.utils.fromJson(surface, jsonForm);
+
+ //Get contents and remove temp surface.
+ var svg = gu._cleanSvg(node.innerHTML);
+ surface.clear();
+ surface.destroy();
+ gu._gfxSvgProxy.document.body.removeChild(node);
+ deferred.callback(svg);
+ }catch(e){
+ deferred.errback(e);
+ }
+ };
+ ts.whenLoaded(null,draw);
+ }catch (ex) {
+ deferred.errback(ex);
+ }
+ };
+ //See if we can call it directly or pass it to the deferred to be
+ //called on initialization.
+ if(gu._initSvgSerializerDeferred.fired > 0){
+ serializer();
+ }else{
+ gu._initSvgSerializerDeferred.addCallback(serializer);
+ }
+ }
+ return deferred; //dojo.Deferred that will be called when serialization finishes.
+ },
+
+ //iFrame document used for handling SVG serialization.
+ _gfxSvgProxy: null,
+
+ //Serializer loaded.
+ _initSvgSerializerDeferred: null,
+
+ _svgSerializerInitialized: function() {
+ // summary:
+ // Internal function to call when the serializer init completed.
+ // tags:
+ // private
+ gu._initSvgSerializerDeferred.callback(true);
+ },
+
+ _initSvgSerializer: function(){
+ // summary:
+ // Internal function to initialize the hidden iframe where SVG rendering
+ // will occur.
+ // tags:
+ // private
+ if(!gu._initSvgSerializerDeferred){
+ gu._initSvgSerializerDeferred = new dojo.Deferred();
+ var f = dojo.doc.createElement("iframe");
+ dojo.style(f, {
+ display: "none",
+ position: "absolute",
+ width: "1em",
+ height: "1em",
+ top: "-10000px"
+ });
+ var intv;
+ if(dojo.isIE){
+ f.onreadystatechange = function(){
+ if(f.contentWindow.document.readyState == "complete"){
+ f.onreadystatechange = function() {};
+ intv = setInterval(function() {
+ if(f.contentWindow[dojo._scopeName] &&
+ f.contentWindow[dojox._scopeName].gfx &&
+ f.contentWindow[dojox._scopeName].gfx.utils){
+ clearInterval(intv);
+ f.contentWindow.parent[dojox._scopeName].gfx.utils._gfxSvgProxy = f.contentWindow;
+ f.contentWindow.parent[dojox._scopeName].gfx.utils._svgSerializerInitialized();
+ }
+ }, 50);
+ }
+ };
+ }else{
+ f.onload = function(){
+ f.onload = function() {};
+ intv = setInterval(function() {
+ if(f.contentWindow[dojo._scopeName] &&
+ f.contentWindow[dojox._scopeName].gfx &&
+ f.contentWindow[dojox._scopeName].gfx.utils){
+ clearInterval(intv);
+ f.contentWindow.parent[dojox._scopeName].gfx.utils._gfxSvgProxy = f.contentWindow;
+ f.contentWindow.parent[dojox._scopeName].gfx.utils._svgSerializerInitialized();
+ }
+ }, 50);
+ };
+ }
+ //We have to load the GFX SVG proxy frame. Default is to use the one packaged in dojox.
+ var uri = (dojo.config["dojoxGfxSvgProxyFrameUrl"]||dojo.moduleUrl("dojox", "gfx/resources/gfxSvgProxyFrame.html"));
+ f.setAttribute("src", uri);
+ dojo.body().appendChild(f);
+ }
+ },
+
+ _innerXML: function(/*Node*/node){
+ // summary:
+ // Implementation of MS's innerXML function, borrowed from dojox.xml.parser.
+ // node:
+ // The node from which to generate the XML text representation.
+ // tags:
+ // private
+ if(node.innerXML){
+ return node.innerXML; //String
+ }else if(node.xml){
+ return node.xml; //String
+ }else if(typeof XMLSerializer != "undefined"){
+ return (new XMLSerializer()).serializeToString(node); //String
+ }
+ return null;
+ },
+
+ _cleanSvg: function(svg) {
+ // summary:
+ // Internal function that cleans up artifacts in extracted SVG content.
+ // tags:
+ // private
+ if(svg){
+ //Make sure the namespace is set.
+ if(svg.indexOf("xmlns=\"http://www.w3.org/2000/svg\"") == -1){
+ svg = svg.substring(4, svg.length);
+ svg = "<svg xmlns=\"http://www.w3.org/2000/svg\"" + svg;
+ }
+ //Do some other cleanup, like stripping out the
+ //dojoGfx attributes.
+ svg = svg.replace(/\bdojoGfx\w*\s*=\s*(['"])\w*\1/g, "");
+ }
+ return svg; //Cleaned SVG text.
+ }
+ });
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/vml.js b/js/dojo-1.6/dojox/gfx/vml.js new file mode 100644 index 0000000..fa9003f --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/vml.js @@ -0,0 +1,1220 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+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");
+dojo.require("dojox.gfx.gradient");
+
+(function(){
+ var d = dojo, g = dojox.gfx, m = g.matrix, gs = g.shape, vml = g.vml;
+
+ // dojox.gfx.vml.xmlns: String: a VML's namespace
+ vml.xmlns = "urn:schemas-microsoft-com:vml";
+
+ // dojox.gfx.vml.text_alignment: Object: mapping from SVG alignment to VML alignment
+ vml.text_alignment = {start: "left", middle: "center", end: "right"};
+
+ vml._parseFloat = function(str) {
+ // summary: a helper function to parse VML-specific floating-point values
+ // str: String: a representation of a floating-point number
+ return str.match(/^\d+f$/i) ? parseInt(str) / 65536 : parseFloat(str); // Number
+ };
+
+ vml._bool = {"t": 1, "true": 1};
+
+ d.declare("dojox.gfx.vml.Shape", gs.Shape, {
+ // summary: VML-specific implementation of dojox.gfx.Shape methods
+
+ setFill: 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 fill
+ this.fillStyle = null;
+ this.rawNode.filled = "f";
+ return this;
+ }
+ var i, f, fo, a, s;
+ if(typeof fill == "object" && "type" in fill){
+ // gradient
+ switch(fill.type){
+ case "linear":
+ var matrix = this._getRealMatrix(), bbox = this.getBoundingBox(),
+ tbbox = this._getRealBBox ? this._getRealBBox() : this.getTransformedBoundingBox();
+ s = [];
+ if(this.fillStyle !== fill){
+ this.fillStyle = g.makeParameters(g.defaultLinearGradient, fill);
+ }
+ f = g.gradient.project(matrix, this.fillStyle,
+ {x: bbox.x, y: bbox.y},
+ {x: bbox.x + bbox.width, y: bbox.y + bbox.height},
+ tbbox[0], tbbox[2]);
+ a = f.colors;
+ if(a[0].offset.toFixed(5) != "0.00000"){
+ s.push("0 " + g.normalizeColor(a[0].color).toHex());
+ }
+ for(i = 0; i < a.length; ++i){
+ s.push(a[i].offset.toFixed(5) + " " + g.normalizeColor(a[i].color).toHex());
+ }
+ i = a.length - 1;
+ if(a[i].offset.toFixed(5) != "1.00000"){
+ s.push("1 " + g.normalizeColor(a[i].color).toHex());
+ }
+ fo = this.rawNode.fill;
+ fo.colors.value = s.join(";");
+ fo.method = "sigma";
+ fo.type = "gradient";
+ fo.angle = (270 - m._radToDeg(f.angle)) % 360;
+ fo.on = true;
+ break;
+ case "radial":
+ f = g.makeParameters(g.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 = [];
+ // add a color at the offset 0 (1 in VML coordinates)
+ if(f.colors[0].offset > 0){
+ a.push({offset: 1, color: g.normalizeColor(f.colors[0].color)});
+ }
+ // massage colors
+ d.forEach(f.colors, function(v, i){
+ a.push({offset: 1 - v.offset * c, color: g.normalizeColor(v.color)});
+ });
+ i = a.length - 1;
+ while(i >= 0 && a[i].offset < 0){ --i; }
+ if(i < a.length - 1){
+ // correct excessive colors
+ var q = a[i], p = a[i + 1];
+ p.color = d.blendColors(q.color, p.color, q.offset / (q.offset - p.offset));
+ p.offset = 0;
+ while(a.length - i > 2) a.pop();
+ }
+ // set colors
+ 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(5) + " " + a[i].color.toHex());
+ }
+ 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(5) + " " + ((f.cy - t) / h).toFixed(5);
+ }
+ fo.focussize = "0 0";
+ fo.on = true;
+ break;
+ case "pattern":
+ f = g.makeParameters(g.defaultPattern, fill);
+ this.fillStyle = f;
+ fo = this.rawNode.fill;
+ fo.type = "tile";
+ fo.src = f.src;
+ if(f.width && f.height){
+ // in points
+ fo.size.x = g.px2pt(f.width);
+ fo.size.y = g.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 object
+ this.fillStyle = g.normalizeColor(fill);
+ fo = this.rawNode.fill;
+ if(!fo){
+ fo = this.rawNode.ownerDocument.createElement("v:fill");
+ }
+ fo.method = "any";
+ fo.type = "solid";
+ fo.opacity = this.fillStyle.a;
+ var alphaFilter = this.rawNode.filters["DXImageTransform.Microsoft.Alpha"];
+ if(alphaFilter){
+ alphaFilter.opacity = Math.round(this.fillStyle.a * 100);
+ }
+ this.rawNode.fillcolor = this.fillStyle.toHex();
+ 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 stroke
+ this.strokeStyle = null;
+ this.rawNode.stroked = "f";
+ return this;
+ }
+ // normalize the stroke
+ if(typeof stroke == "string" || d.isArray(stroke) || stroke instanceof d.Color){
+ stroke = {color: stroke};
+ }
+ var s = this.strokeStyle = g.makeParameters(g.defaultStroke, stroke);
+ s.color = g.normalizeColor(s.color);
+ // generate attributes
+ var 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() {
+ var matrix = this._getRealMatrix();
+ if(matrix){
+ 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) w = 1;
+ if(isNaN(h) || !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;
+ }
+ }
+ if(this.fillStyle && this.fillStyle.type == "linear"){
+ this.setFill(this.fillStyle);
+ }
+ return this;
+ },
+
+ _setDimensions: function(width, height){
+ // summary: sets the width and height of the rawNode,
+ // if the surface sixe has been changed
+ // width: String: width in pixels
+ // height: String: height in pixels
+
+ // default implementation does nothing
+ return this; // self
+ },
+
+ 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 preserved
+ n.swapNode(r);
+ }
+ return this;
+ },
+
+ _getRealMatrix: function(){
+ // summary: returns the cumulative ("real") transformation matrix
+ // by combining the shape's matrix with its parent's matrix
+ return this.parentMatrix ? new g.Matrix2D([this.parentMatrix, this.matrix]) : this.matrix; // dojox.gfx.Matrix2D
+ }
+ });
+
+ dojo.declare("dojox.gfx.vml.Group", vml.Shape, {
+ // summary: a group shape (VML), which can be used
+ // to logically group shapes (e.g, to propagate matricies)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ // apply transformation
+ _applyTransform: function(){
+ // summary: applies a transformation matrix to a group
+ var matrix = this._getRealMatrix();
+ for(var i = 0; i < this.children.length; ++i){
+ this.children[i]._updateParentMatrix(matrix);
+ }
+ return this; // self
+ },
+ _setDimensions: function(width, height){
+ // summary: sets the width and height of the rawNode,
+ // if the surface sixe has been changed
+ // width: String: width in pixels
+ // height: String: height in pixels
+ var r = this.rawNode, rs = r.style,
+ bs = this.bgNode.style;
+ rs.width = width;
+ rs.height = height;
+ r.coordsize = width + " " + height;
+ bs.width = width;
+ bs.height = height;
+ for(var i = 0; i < this.children.length; ++i){
+ this.children[i]._setDimensions(width, height);
+ }
+ return this; // self
+ }
+ });
+ vml.Group.nodeType = "group";
+
+ dojo.declare("dojox.gfx.vml.Rect", [vml.Shape, gs.Rect], {
+ // summary: a rectangle shape (VML)
+ setShape: function(newShape){
+ // summary: sets a rectangle shape object (VML)
+ // newShape: Object: a rectangle shape object
+ var shape = this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ 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 node
+ var 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);
+ }
+ if(d.isIE > 7){
+ var node = this.rawNode.ownerDocument.createElement("v:roundrect");
+ node.arcsize = r;
+ node.style.display = "inline-block";
+ this.rawNode = node;
+ }else{
+ this.rawNode.arcsize = r;
+ }
+ if(parent){
+ if(before){
+ parent.insertBefore(this.rawNode, before);
+ }else{
+ parent.appendChild(this.rawNode);
+ }
+ }
+ 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();
+ // 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
+ }
+ });
+ vml.Rect.nodeType = "roundrect"; // use a roundrect so the stroke join type is respected
+
+ dojo.declare("dojox.gfx.vml.Ellipse", [vml.Shape, gs.Ellipse], {
+ // summary: an ellipse shape (VML)
+ setShape: function(newShape){
+ // summary: sets an ellipse shape object (VML)
+ // newShape: Object: an ellipse shape object
+ var shape = this.shape = g.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
+ }
+ });
+ vml.Ellipse.nodeType = "oval";
+
+ dojo.declare("dojox.gfx.vml.Circle", [vml.Shape, gs.Circle], {
+ // summary: a circle shape (VML)
+ setShape: function(newShape){
+ // summary: sets a circle shape object (VML)
+ // newShape: Object: a circle shape object
+ var shape = this.shape = g.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
+ }
+ });
+ vml.Circle.nodeType = "oval";
+
+ dojo.declare("dojox.gfx.vml.Line", [vml.Shape, gs.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 object
+ var shape = this.shape = g.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
+ }
+ });
+ vml.Line.nodeType = "shape";
+
+ dojo.declare("dojox.gfx.vml.Polyline", [vml.Shape, gs.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 explicitely
+ if(points && points instanceof Array){
+ // branch
+ // points: Array: an array of points
+ this.shape = g.makeParameters(this.shape, { points: points });
+ if(closed && this.shape.points.length) this.shape.points.push(this.shape.points[0]);
+ }else{
+ this.shape = g.makeParameters(this.shape, points);
+ }
+ this.bbox = null;
+ this._normalizePoints();
+ var attr = [], p = this.shape.points;
+ if(p.length > 0){
+ attr.push("m");
+ attr.push(p[0].x.toFixed(), p[0].y.toFixed());
+ if(p.length > 1){
+ attr.push("l");
+ for(var i = 1; i < p.length; ++i){
+ attr.push(p[i].x.toFixed(), p[i].y.toFixed());
+ }
+ }
+ }
+ attr.push("e");
+ this.rawNode.path.v = attr.join(" ");
+ return this.setTransform(this.matrix); // self
+ }
+ });
+ vml.Polyline.nodeType = "shape";
+
+ dojo.declare("dojox.gfx.vml.Image", [vml.Shape, gs.Image], {
+ // summary: an image (VML)
+ setShape: function(newShape){
+ // summary: sets an image shape object (VML)
+ // newShape: Object: an image shape object
+ var shape = this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ this.rawNode.firstChild.src = shape.src;
+ return this.setTransform(this.matrix); // self
+ },
+ _applyTransform: function() {
+ var matrix = this._getRealMatrix(),
+ rawNode = this.rawNode,
+ s = rawNode.style,
+ shape = this.shape;
+ if(matrix){
+ matrix = m.multiply(matrix, {dx: shape.x, dy: shape.y});
+ }else{
+ matrix = m.normalize({dx: shape.x, dy: shape.y});
+ }
+ if(matrix.xy == 0 && matrix.yx == 0 && matrix.xx > 0 && matrix.yy > 0){
+ // special case to avoid filters
+ s.filter = "";
+ s.width = Math.floor(matrix.xx * shape.width);
+ s.height = Math.floor(matrix.yy * shape.height);
+ s.left = Math.floor(matrix.dx);
+ s.top = Math.floor(matrix.dy);
+ }else{
+ var ps = rawNode.parentNode.style;
+ s.left = "0px";
+ s.top = "0px";
+ s.width = ps.width;
+ s.height = ps.height;
+ matrix = m.multiply(matrix,
+ {xx: shape.width / parseInt(s.width), yy: shape.height / parseInt(s.height)});
+ var f = rawNode.filters["DXImageTransform.Microsoft.Matrix"];
+ if(f){
+ f.M11 = matrix.xx;
+ f.M12 = matrix.xy;
+ f.M21 = matrix.yx;
+ f.M22 = matrix.yy;
+ f.Dx = matrix.dx;
+ f.Dy = matrix.dy;
+ }else{
+ s.filter = "progid:DXImageTransform.Microsoft.Matrix(M11=" + matrix.xx +
+ ", M12=" + matrix.xy + ", M21=" + matrix.yx + ", M22=" + matrix.yy +
+ ", Dx=" + matrix.dx + ", Dy=" + matrix.dy + ")";
+ }
+ }
+ return this; // self
+ },
+ _setDimensions: function(width, height){
+ // summary: sets the width and height of the rawNode,
+ // if the surface sixe has been changed
+ // width: String: width in pixels
+ // height: String: height in pixels
+
+ var r = this.rawNode, f = r.filters["DXImageTransform.Microsoft.Matrix"];
+ if(f){
+ var s = r.style;
+ s.width = width;
+ s.height = height;
+ return this._applyTransform(); // self
+ }
+ return this; // self
+ }
+ });
+ vml.Image.nodeType = "rect";
+
+ dojo.declare("dojox.gfx.vml.Text", [vml.Shape, gs.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 object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, s = this.shape, x = s.x, y = s.y.toFixed(), path;
+ switch(s.align){
+ case "middle":
+ x -= 5;
+ break;
+ case "end":
+ x -= 10;
+ break;
+ }
+ path = "m" + x.toFixed() + "," + y + "l" + (x + 10).toFixed() + "," + y + "e";
+ // find path and text path
+ var 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 = r.ownerDocument.createElement("v:path");
+ r.appendChild(p);
+ }
+ if(!t){
+ t = r.ownerDocument.createElement("v:textpath");
+ r.appendChild(t);
+ }
+ p.v = path;
+ p.textPathOk = true;
+ t.on = true;
+ var a = 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 = g.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 size
+ var matrix = this.inherited(arguments);
+ // 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 = m.multiply(matrix,
+ {dy: -g.normalizedLength(this.fontStyle ? this.fontStyle.size : "10pt") * 0.35});
+ }
+ return matrix; // dojox.gfx.Matrix2D
+ },
+ getTextWidth: function(){
+ // summary: get the text width, in px
+ var rawNode = this.rawNode, _display = rawNode.style.display;
+ rawNode.style.display = "inline";
+ var _width = g.pt2px(parseFloat(rawNode.currentStyle.width));
+ rawNode.style.display = _display;
+ return _width;
+ }
+ });
+ vml.Text.nodeType = "shape";
+
+ dojo.declare("dojox.gfx.vml.Path", [vml.Shape, g.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 segment
+ var last = d.clone(this.last);
+ this.inherited(arguments);
+ if(arguments.length > 1){ return; } // skip transfomed bbox calculations
+ // add a VML path segment
+ var 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{
+ Array.prototype.push.apply(this.vmlPath, path); //FIXME: why not push()?
+ }
+ },
+ 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.type = ""; // no prior control point
+ this.inherited(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 renderers
+ renderers: {
+ 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, segment, from, upto){
+ var n = segment instanceof Array ? segment : segment.args;
+ for(var i = from; i < upto; ++i){
+ path.push(" ", n[i].toFixed());
+ }
+ },
+ _adjustRelCrd: function(last, segment, step){
+ var n = segment instanceof Array ? segment : segment.args, l = n.length,
+ result = new Array(l), i = 0, x = last.x, y = last.y;
+ if(typeof x != "number"){
+ // there is no last coordinate =>
+ // treat the first pair as an absolute coordinate
+ result[0] = x = n[0];
+ result[1] = y = n[1];
+ i = 2;
+ }
+ if(typeof step == "number" && step != 2){
+ var j = step;
+ while(j <= l){
+ for(; i < j; i += 2){
+ result[i] = x + n[i];
+ result[i + 1] = y + n[i + 1];
+ }
+ x = result[j - 2];
+ y = result[j - 1];
+ j += step;
+ }
+ }else{
+ for(; i < l; i += 2){
+ result[i] = (x += n[i]);
+ result[i + 1] = (y += n[i + 1]);
+ }
+ }
+ return result;
+ },
+ _adjustRelPos: function(last, segment){
+ var n = segment instanceof Array ? segment : segment.args, l = n.length,
+ result = new Array(l);
+ for(var i = 0; i < l; ++i){
+ result[i] = (last += n[i]);
+ }
+ return result;
+ },
+ _moveToA: function(segment){
+ var p = [" m"], n = segment instanceof Array ? segment : segment.args, l = n.length;
+ this._addArgs(p, n, 0, 2);
+ if(l > 2){
+ p.push(" l");
+ this._addArgs(p, n, 2, l);
+ }
+ this.lastControl.type = ""; // no control point after this primitive
+ return p;
+ },
+ _moveToR: function(segment, last){
+ return this._moveToA(this._adjustRelCrd(last, segment));
+ },
+ _lineToA: function(segment){
+ var p = [" l"], n = segment instanceof Array ? segment : segment.args;
+ this._addArgs(p, n, 0, n.length);
+ this.lastControl.type = ""; // no control point after this primitive
+ return p;
+ },
+ _lineToR: function(segment, last){
+ return this._lineToA(this._adjustRelCrd(last, segment));
+ },
+ _hLineToA: function(segment, last){
+ var p = [" l"], y = " " + last.y.toFixed(),
+ n = segment instanceof Array ? segment : segment.args, l = n.length;
+ for(var i = 0; i < l; ++i){
+ p.push(" ", n[i].toFixed(), y);
+ }
+ this.lastControl.type = ""; // no control point after this primitive
+ return p;
+ },
+ _hLineToR: function(segment, last){
+ return this._hLineToA(this._adjustRelPos(last.x, segment), last);
+ },
+ _vLineToA: function(segment, last){
+ var p = [" l"], x = " " + last.x.toFixed(),
+ n = segment instanceof Array ? segment : segment.args, l = n.length;
+ for(var i = 0; i < l; ++i){
+ p.push(x, " ", n[i].toFixed());
+ }
+ this.lastControl.type = ""; // no control point after this primitive
+ return p;
+ },
+ _vLineToR: function(segment, last){
+ return this._vLineToA(this._adjustRelPos(last.y, segment), last);
+ },
+ _curveToA: function(segment){
+ var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+ lc = this.lastControl;
+ for(var i = 0; i < l; i += 6){
+ p.push(" c");
+ this._addArgs(p, n, i, i + 6);
+ }
+ lc.x = n[l - 4];
+ lc.y = n[l - 3];
+ lc.type = "C";
+ return p;
+ },
+ _curveToR: function(segment, last){
+ return this._curveToA(this._adjustRelCrd(last, segment, 6));
+ },
+ _smoothCurveToA: function(segment, last){
+ var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+ lc = this.lastControl, i = 0;
+ if(lc.type != "C"){
+ p.push(" c");
+ this._addArgs(p, [last.x, last.y], 0, 2);
+ this._addArgs(p, n, 0, 4);
+ lc.x = n[0];
+ lc.y = n[1];
+ lc.type = "C";
+ i = 4;
+ }
+ for(; i < l; i += 4){
+ p.push(" c");
+ this._addArgs(p, [
+ 2 * last.x - lc.x,
+ 2 * last.y - lc.y
+ ], 0, 2);
+ this._addArgs(p, n, i, i + 4);
+ lc.x = n[i];
+ lc.y = n[i + 1];
+ }
+ return p;
+ },
+ _smoothCurveToR: function(segment, last){
+ return this._smoothCurveToA(this._adjustRelCrd(last, segment, 4), last);
+ },
+ _qCurveToA: function(segment){
+ var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+ lc = this.lastControl;
+ for(var i = 0; i < l; i += 4){
+ p.push(" qb");
+ this._addArgs(p, n, i, i + 4);
+ }
+ lc.x = n[l - 4];
+ lc.y = n[l - 3];
+ lc.type = "Q";
+ return p;
+ },
+ _qCurveToR: function(segment, last){
+ return this._qCurveToA(this._adjustRelCrd(last, segment, 4));
+ },
+ _qSmoothCurveToA: function(segment, last){
+ var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+ lc = this.lastControl, i = 0;
+ if(lc.type != "Q"){
+ p.push(" qb");
+ this._addArgs(p, [
+ lc.x = last.x,
+ lc.y = last.y
+ ], 0, 2);
+ lc.type = "Q";
+ this._addArgs(p, n, 0, 2);
+ i = 2;
+ }
+ for(; i < l; i += 2){
+ p.push(" qb");
+ this._addArgs(p, [
+ lc.x = 2 * last.x - lc.x,
+ lc.y = 2 * last.y - lc.y
+ ], 0, 2);
+ this._addArgs(p, n, i, i + 2);
+ }
+ return p;
+ },
+ _qSmoothCurveToR: function(segment, last){
+ return this._qSmoothCurveToA(this._adjustRelCrd(last, segment, 2), last);
+ },
+ _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 = g.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");
+ var t = result[j];
+ this._addArgs(p, t, 0, t.length);
+ this._updateBBox(t[0], t[1]);
+ this._updateBBox(t[2], t[3]);
+ this._updateBBox(t[4], t[5]);
+ }
+ last.x = x1;
+ last.y = y1;
+ }
+ this.lastControl.type = ""; // no control point after this primitive
+ return p;
+ },
+ _closePath: function(){
+ this.lastControl.type = ""; // no control point after this primitive
+ return ["x"];
+ }
+ });
+ vml.Path.nodeType = "shape";
+
+ dojo.declare("dojox.gfx.vml.TextPath", [vml.Path, g.path.TextPath], {
+ // summary: a textpath shape (VML)
+ constructor: function(rawNode){
+ if(rawNode){rawNode.setAttribute("dojoGfxType", "textpath");}
+ this.fontStyle = null;
+ if(!("text" in this)){
+ this.text = d.clone(g.defaultTextPath);
+ }
+ if(!("fontStyle" in this)){
+ this.fontStyle = d.clone(g.defaultFont);
+ }
+ },
+ setText: function(newText){
+ // summary: sets a text to be drawn along the path
+ this.text = g.makeParameters(this.text,
+ typeof newText == "string" ? {text: newText} : newText);
+ this._setText();
+ return this; // self
+ },
+ setFont: function(newFont){
+ // summary: sets a font for text
+ this.fontStyle = typeof newFont == "string" ?
+ g.splitFontString(newFont) :
+ g.makeParameters(g.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 path
+ 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 = 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 = g.makeFontString(f);
+ break;
+ }
+ }
+ }
+ });
+ vml.TextPath.nodeType = "shape";
+
+ dojo.declare("dojox.gfx.vml.Surface", gs.Surface, {
+ // summary: a surface object to be used for drawings (VML)
+ constructor: function(){
+ gs.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 = g.normalizedLength(width); // in pixels
+ this.height = g.normalizedLength(height); // in pixels
+ if(!this.rawNode) return this;
+ var cs = this.clipNode.style,
+ r = this.rawNode, rs = r.style,
+ bs = this.bgNode.style,
+ ps = this._parent.style, i;
+ ps.width = width;
+ ps.height = height;
+ cs.width = width;
+ cs.height = height;
+ cs.clip = "rect(0px " + width + "px " + height + "px 0px)";
+ rs.width = width;
+ rs.height = height;
+ r.coordsize = width + " " + height;
+ bs.width = width;
+ bs.height = height;
+ for(i = 0; i < this.children.length; ++i){
+ this.children[i]._setDimensions(width, height);
+ }
+ return this; // self
+ },
+ getDimensions: function(){
+ // summary: returns an object with properties "width" and "height"
+ var t = this.rawNode ? {
+ width: g.normalizedLength(this.rawNode.style.width),
+ height: g.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
+ }
+ });
+
+ vml.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 && !height){
+ var pos = d.position(parentNode);
+ width = width || pos.w;
+ height = height || pos.h;
+ }
+ if(typeof width == "number"){
+ width = width + "px";
+ }
+ if(typeof height == "number"){
+ height = height + "px";
+ }
+
+ var s = new vml.Surface(), p = d.byId(parentNode),
+ c = s.clipNode = p.ownerDocument.createElement("div"),
+ r = s.rawNode = p.ownerDocument.createElement("v:group"),
+ cs = c.style, rs = r.style;
+
+ if(d.isIE > 7){
+ rs.display = "inline-block";
+ }
+
+ s._parent = p;
+ s._nodes.push(c); // other elements will be deleted as parts of "c"
+
+ p.style.width = width;
+ p.style.height = height;
+
+ cs.position = "absolute";
+ cs.width = width;
+ cs.height = height;
+ cs.clip = "rect(0px " + width + " " + height + " 0px)";
+ rs.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 shapes
+ var 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 = g.normalizedLength(width); // in pixels
+ s.height = g.normalizedLength(height); // in pixels
+
+ return s; // dojox.gfx.Surface
+ };
+
+ // Extenders
+
+ // copied from dojox.gfx.utils
+ function forEach(object, f, o){
+ o = o || d.global;
+ f.call(o, object);
+ if(object instanceof g.Surface || object instanceof g.Group){
+ d.forEach(object.children, function(shape){
+ forEach(shape, f, o);
+ });
+ }
+ }
+
+ var C = gs.Container, Container = {
+ add: function(shape){
+ // summary: adds a shape to a group/surface
+ // shape: dojox.gfx.Shape: an VML shape object
+ if(this != shape.getParent()){
+ // cleanup from old parent
+ var oldParent = shape.getParent();
+ if(oldParent) { oldParent.remove(shape); }
+ // then move the raw node
+ this.rawNode.appendChild(shape.rawNode);
+ C.add.apply(this, arguments);
+ // reapply visual attributes (slow..)
+ forEach(this, function(s){
+ if (typeof(s.getFont) == 'function'){ // text shapes need to be completely refreshed
+ s.setShape(s.getShape());
+ s.setFont(s.getFont());
+ }
+ if (typeof(s.setFill) == 'function'){ // if setFill is available a setStroke should be safe to assume also
+ s.setFill(s.getFill());
+ s.setStroke(s.getStroke());
+ }
+ });
+ }
+ 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 picture
+ if(this == shape.getParent()){
+ if(this.rawNode == shape.rawNode.parentNode){
+ this.rawNode.removeChild(shape.rawNode);
+ }
+ C.remove.apply(this, arguments);
+ }
+ return this; // self
+ },
+ clear: function(){
+ // summary: removes all shapes from a group/surface
+ var 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 C.clear.apply(this, arguments);
+ },
+ _moveChildToFront: C._moveChildToFront,
+ _moveChildToBack: C._moveChildToBack
+ };
+
+ var Creator = {
+ // summary: VML shape creators
+ createGroup: function(){
+ // summary: creates a VML group shape
+ var node = this.createObject(vml.Group, null); // dojox.gfx.Group
+ // create a background rectangle, which is required to show all other shapes
+ var r = node.rawNode.ownerDocument.createElement("v:rect");
+ r.style.left = r.style.top = 0;
+ r.style.width = node.rawNode.style.width;
+ r.style.height = node.rawNode.style.height;
+ r.filled = r.stroked = "f";
+ node.rawNode.appendChild(r);
+ node.bgNode = r;
+ return node; // 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 vml.Image(),
+ doc = this.rawNode.ownerDocument,
+ node = doc.createElement('v:rect');
+ node.stroked = "f";
+ node.style.width = this.rawNode.style.width;
+ node.style.height = this.rawNode.style.height;
+ var img = doc.createElement('v:imagedata');
+ node.appendChild(img);
+ shape.setRawNode(node);
+ this.rawNode.appendChild(node);
+ shape.setShape(image);
+ this.add(shape);
+ return shape; // dojox.gfx.Image
+ },
+ createRect: function(rect){
+ // summary: creates a rectangle shape
+ // rect: Object: a path object (see dojox.gfx.defaultRect)
+ if(!this.rawNode) return null;
+ var shape = new vml.Rect,
+ node = this.rawNode.ownerDocument.createElement("v:roundrect");
+ if(d.isIE > 7){
+ node.style.display = "inline-block";
+ }
+ shape.setRawNode(node);
+ this.rawNode.appendChild(node);
+ shape.setShape(rect);
+ this.add(shape);
+ return shape; // dojox.gfx.Rect
+ },
+ 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 true
+ if(!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 vml.Group:
+ case vml.Line:
+ case vml.Polyline:
+ case vml.Image:
+ case vml.Text:
+ case vml.Path:
+ case vml.TextPath:
+ this._overrideSize(node);
+ }
+ shape.setShape(rawShape);
+ this.add(shape);
+ return shape; // dojox.gfx.Shape
+ },
+ _overrideSize: function(node){
+ var s = this.rawNode.style, w = s.width, h = s.height;
+ node.style.width = w;
+ node.style.height = h;
+ node.coordsize = parseInt(w) + " " + parseInt(h);
+ }
+ };
+
+ d.extend(vml.Group, Container);
+ d.extend(vml.Group, gs.Creator);
+ d.extend(vml.Group, Creator);
+
+ d.extend(vml.Surface, Container);
+ d.extend(vml.Surface, gs.Creator);
+ d.extend(vml.Surface, Creator);
+
+ // see if we are required to initilize
+ if(g.loadAndSwitch === "vml"){
+ g.switchTo("vml");
+ delete g.loadAndSwitch;
+ }
+})();
+
+}
diff --git a/js/dojo-1.6/dojox/gfx/vml.xd.js b/js/dojo-1.6/dojox/gfx/vml.xd.js new file mode 100644 index 0000000..a6673f7 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/vml.xd.js @@ -0,0 +1,1229 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["provide", "dojox.gfx.vml"],
+["require", "dojox.gfx._base"],
+["require", "dojox.gfx.shape"],
+["require", "dojox.gfx.path"],
+["require", "dojox.gfx.arc"],
+["require", "dojox.gfx.gradient"]],
+defineResource: function(dojo, dijit, dojox){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");
+dojo.require("dojox.gfx.gradient");
+
+(function(){
+ var d = dojo, g = dojox.gfx, m = g.matrix, gs = g.shape, vml = g.vml;
+
+ // dojox.gfx.vml.xmlns: String: a VML's namespace
+ vml.xmlns = "urn:schemas-microsoft-com:vml";
+
+ // dojox.gfx.vml.text_alignment: Object: mapping from SVG alignment to VML alignment
+ vml.text_alignment = {start: "left", middle: "center", end: "right"};
+
+ vml._parseFloat = function(str) {
+ // summary: a helper function to parse VML-specific floating-point values
+ // str: String: a representation of a floating-point number
+ return str.match(/^\d+f$/i) ? parseInt(str) / 65536 : parseFloat(str); // Number
+ };
+
+ vml._bool = {"t": 1, "true": 1};
+
+ d.declare("dojox.gfx.vml.Shape", gs.Shape, {
+ // summary: VML-specific implementation of dojox.gfx.Shape methods
+
+ setFill: 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 fill
+ this.fillStyle = null;
+ this.rawNode.filled = "f";
+ return this;
+ }
+ var i, f, fo, a, s;
+ if(typeof fill == "object" && "type" in fill){
+ // gradient
+ switch(fill.type){
+ case "linear":
+ var matrix = this._getRealMatrix(), bbox = this.getBoundingBox(),
+ tbbox = this._getRealBBox ? this._getRealBBox() : this.getTransformedBoundingBox();
+ s = [];
+ if(this.fillStyle !== fill){
+ this.fillStyle = g.makeParameters(g.defaultLinearGradient, fill);
+ }
+ f = g.gradient.project(matrix, this.fillStyle,
+ {x: bbox.x, y: bbox.y},
+ {x: bbox.x + bbox.width, y: bbox.y + bbox.height},
+ tbbox[0], tbbox[2]);
+ a = f.colors;
+ if(a[0].offset.toFixed(5) != "0.00000"){
+ s.push("0 " + g.normalizeColor(a[0].color).toHex());
+ }
+ for(i = 0; i < a.length; ++i){
+ s.push(a[i].offset.toFixed(5) + " " + g.normalizeColor(a[i].color).toHex());
+ }
+ i = a.length - 1;
+ if(a[i].offset.toFixed(5) != "1.00000"){
+ s.push("1 " + g.normalizeColor(a[i].color).toHex());
+ }
+ fo = this.rawNode.fill;
+ fo.colors.value = s.join(";");
+ fo.method = "sigma";
+ fo.type = "gradient";
+ fo.angle = (270 - m._radToDeg(f.angle)) % 360;
+ fo.on = true;
+ break;
+ case "radial":
+ f = g.makeParameters(g.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 = [];
+ // add a color at the offset 0 (1 in VML coordinates)
+ if(f.colors[0].offset > 0){
+ a.push({offset: 1, color: g.normalizeColor(f.colors[0].color)});
+ }
+ // massage colors
+ d.forEach(f.colors, function(v, i){
+ a.push({offset: 1 - v.offset * c, color: g.normalizeColor(v.color)});
+ });
+ i = a.length - 1;
+ while(i >= 0 && a[i].offset < 0){ --i; }
+ if(i < a.length - 1){
+ // correct excessive colors
+ var q = a[i], p = a[i + 1];
+ p.color = d.blendColors(q.color, p.color, q.offset / (q.offset - p.offset));
+ p.offset = 0;
+ while(a.length - i > 2) a.pop();
+ }
+ // set colors
+ 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(5) + " " + a[i].color.toHex());
+ }
+ 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(5) + " " + ((f.cy - t) / h).toFixed(5);
+ }
+ fo.focussize = "0 0";
+ fo.on = true;
+ break;
+ case "pattern":
+ f = g.makeParameters(g.defaultPattern, fill);
+ this.fillStyle = f;
+ fo = this.rawNode.fill;
+ fo.type = "tile";
+ fo.src = f.src;
+ if(f.width && f.height){
+ // in points
+ fo.size.x = g.px2pt(f.width);
+ fo.size.y = g.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 object
+ this.fillStyle = g.normalizeColor(fill);
+ fo = this.rawNode.fill;
+ if(!fo){
+ fo = this.rawNode.ownerDocument.createElement("v:fill");
+ }
+ fo.method = "any";
+ fo.type = "solid";
+ fo.opacity = this.fillStyle.a;
+ var alphaFilter = this.rawNode.filters["DXImageTransform.Microsoft.Alpha"];
+ if(alphaFilter){
+ alphaFilter.opacity = Math.round(this.fillStyle.a * 100);
+ }
+ this.rawNode.fillcolor = this.fillStyle.toHex();
+ 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 stroke
+ this.strokeStyle = null;
+ this.rawNode.stroked = "f";
+ return this;
+ }
+ // normalize the stroke
+ if(typeof stroke == "string" || d.isArray(stroke) || stroke instanceof d.Color){
+ stroke = {color: stroke};
+ }
+ var s = this.strokeStyle = g.makeParameters(g.defaultStroke, stroke);
+ s.color = g.normalizeColor(s.color);
+ // generate attributes
+ var 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() {
+ var matrix = this._getRealMatrix();
+ if(matrix){
+ 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) w = 1;
+ if(isNaN(h) || !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;
+ }
+ }
+ if(this.fillStyle && this.fillStyle.type == "linear"){
+ this.setFill(this.fillStyle);
+ }
+ return this;
+ },
+
+ _setDimensions: function(width, height){
+ // summary: sets the width and height of the rawNode,
+ // if the surface sixe has been changed
+ // width: String: width in pixels
+ // height: String: height in pixels
+
+ // default implementation does nothing
+ return this; // self
+ },
+
+ 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 preserved
+ n.swapNode(r);
+ }
+ return this;
+ },
+
+ _getRealMatrix: function(){
+ // summary: returns the cumulative ("real") transformation matrix
+ // by combining the shape's matrix with its parent's matrix
+ return this.parentMatrix ? new g.Matrix2D([this.parentMatrix, this.matrix]) : this.matrix; // dojox.gfx.Matrix2D
+ }
+ });
+
+ dojo.declare("dojox.gfx.vml.Group", vml.Shape, {
+ // summary: a group shape (VML), which can be used
+ // to logically group shapes (e.g, to propagate matricies)
+ constructor: function(){
+ gs.Container._init.call(this);
+ },
+ // apply transformation
+ _applyTransform: function(){
+ // summary: applies a transformation matrix to a group
+ var matrix = this._getRealMatrix();
+ for(var i = 0; i < this.children.length; ++i){
+ this.children[i]._updateParentMatrix(matrix);
+ }
+ return this; // self
+ },
+ _setDimensions: function(width, height){
+ // summary: sets the width and height of the rawNode,
+ // if the surface sixe has been changed
+ // width: String: width in pixels
+ // height: String: height in pixels
+ var r = this.rawNode, rs = r.style,
+ bs = this.bgNode.style;
+ rs.width = width;
+ rs.height = height;
+ r.coordsize = width + " " + height;
+ bs.width = width;
+ bs.height = height;
+ for(var i = 0; i < this.children.length; ++i){
+ this.children[i]._setDimensions(width, height);
+ }
+ return this; // self
+ }
+ });
+ vml.Group.nodeType = "group";
+
+ dojo.declare("dojox.gfx.vml.Rect", [vml.Shape, gs.Rect], {
+ // summary: a rectangle shape (VML)
+ setShape: function(newShape){
+ // summary: sets a rectangle shape object (VML)
+ // newShape: Object: a rectangle shape object
+ var shape = this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ 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 node
+ var 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);
+ }
+ if(d.isIE > 7){
+ var node = this.rawNode.ownerDocument.createElement("v:roundrect");
+ node.arcsize = r;
+ node.style.display = "inline-block";
+ this.rawNode = node;
+ }else{
+ this.rawNode.arcsize = r;
+ }
+ if(parent){
+ if(before){
+ parent.insertBefore(this.rawNode, before);
+ }else{
+ parent.appendChild(this.rawNode);
+ }
+ }
+ 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();
+ // 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
+ }
+ });
+ vml.Rect.nodeType = "roundrect"; // use a roundrect so the stroke join type is respected
+
+ dojo.declare("dojox.gfx.vml.Ellipse", [vml.Shape, gs.Ellipse], {
+ // summary: an ellipse shape (VML)
+ setShape: function(newShape){
+ // summary: sets an ellipse shape object (VML)
+ // newShape: Object: an ellipse shape object
+ var shape = this.shape = g.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
+ }
+ });
+ vml.Ellipse.nodeType = "oval";
+
+ dojo.declare("dojox.gfx.vml.Circle", [vml.Shape, gs.Circle], {
+ // summary: a circle shape (VML)
+ setShape: function(newShape){
+ // summary: sets a circle shape object (VML)
+ // newShape: Object: a circle shape object
+ var shape = this.shape = g.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
+ }
+ });
+ vml.Circle.nodeType = "oval";
+
+ dojo.declare("dojox.gfx.vml.Line", [vml.Shape, gs.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 object
+ var shape = this.shape = g.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
+ }
+ });
+ vml.Line.nodeType = "shape";
+
+ dojo.declare("dojox.gfx.vml.Polyline", [vml.Shape, gs.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 explicitely
+ if(points && points instanceof Array){
+ // branch
+ // points: Array: an array of points
+ this.shape = g.makeParameters(this.shape, { points: points });
+ if(closed && this.shape.points.length) this.shape.points.push(this.shape.points[0]);
+ }else{
+ this.shape = g.makeParameters(this.shape, points);
+ }
+ this.bbox = null;
+ this._normalizePoints();
+ var attr = [], p = this.shape.points;
+ if(p.length > 0){
+ attr.push("m");
+ attr.push(p[0].x.toFixed(), p[0].y.toFixed());
+ if(p.length > 1){
+ attr.push("l");
+ for(var i = 1; i < p.length; ++i){
+ attr.push(p[i].x.toFixed(), p[i].y.toFixed());
+ }
+ }
+ }
+ attr.push("e");
+ this.rawNode.path.v = attr.join(" ");
+ return this.setTransform(this.matrix); // self
+ }
+ });
+ vml.Polyline.nodeType = "shape";
+
+ dojo.declare("dojox.gfx.vml.Image", [vml.Shape, gs.Image], {
+ // summary: an image (VML)
+ setShape: function(newShape){
+ // summary: sets an image shape object (VML)
+ // newShape: Object: an image shape object
+ var shape = this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ this.rawNode.firstChild.src = shape.src;
+ return this.setTransform(this.matrix); // self
+ },
+ _applyTransform: function() {
+ var matrix = this._getRealMatrix(),
+ rawNode = this.rawNode,
+ s = rawNode.style,
+ shape = this.shape;
+ if(matrix){
+ matrix = m.multiply(matrix, {dx: shape.x, dy: shape.y});
+ }else{
+ matrix = m.normalize({dx: shape.x, dy: shape.y});
+ }
+ if(matrix.xy == 0 && matrix.yx == 0 && matrix.xx > 0 && matrix.yy > 0){
+ // special case to avoid filters
+ s.filter = "";
+ s.width = Math.floor(matrix.xx * shape.width);
+ s.height = Math.floor(matrix.yy * shape.height);
+ s.left = Math.floor(matrix.dx);
+ s.top = Math.floor(matrix.dy);
+ }else{
+ var ps = rawNode.parentNode.style;
+ s.left = "0px";
+ s.top = "0px";
+ s.width = ps.width;
+ s.height = ps.height;
+ matrix = m.multiply(matrix,
+ {xx: shape.width / parseInt(s.width), yy: shape.height / parseInt(s.height)});
+ var f = rawNode.filters["DXImageTransform.Microsoft.Matrix"];
+ if(f){
+ f.M11 = matrix.xx;
+ f.M12 = matrix.xy;
+ f.M21 = matrix.yx;
+ f.M22 = matrix.yy;
+ f.Dx = matrix.dx;
+ f.Dy = matrix.dy;
+ }else{
+ s.filter = "progid:DXImageTransform.Microsoft.Matrix(M11=" + matrix.xx +
+ ", M12=" + matrix.xy + ", M21=" + matrix.yx + ", M22=" + matrix.yy +
+ ", Dx=" + matrix.dx + ", Dy=" + matrix.dy + ")";
+ }
+ }
+ return this; // self
+ },
+ _setDimensions: function(width, height){
+ // summary: sets the width and height of the rawNode,
+ // if the surface sixe has been changed
+ // width: String: width in pixels
+ // height: String: height in pixels
+
+ var r = this.rawNode, f = r.filters["DXImageTransform.Microsoft.Matrix"];
+ if(f){
+ var s = r.style;
+ s.width = width;
+ s.height = height;
+ return this._applyTransform(); // self
+ }
+ return this; // self
+ }
+ });
+ vml.Image.nodeType = "rect";
+
+ dojo.declare("dojox.gfx.vml.Text", [vml.Shape, gs.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 object
+ this.shape = g.makeParameters(this.shape, newShape);
+ this.bbox = null;
+ var r = this.rawNode, s = this.shape, x = s.x, y = s.y.toFixed(), path;
+ switch(s.align){
+ case "middle":
+ x -= 5;
+ break;
+ case "end":
+ x -= 10;
+ break;
+ }
+ path = "m" + x.toFixed() + "," + y + "l" + (x + 10).toFixed() + "," + y + "e";
+ // find path and text path
+ var 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 = r.ownerDocument.createElement("v:path");
+ r.appendChild(p);
+ }
+ if(!t){
+ t = r.ownerDocument.createElement("v:textpath");
+ r.appendChild(t);
+ }
+ p.v = path;
+ p.textPathOk = true;
+ t.on = true;
+ var a = 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 = g.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 size
+ var matrix = this.inherited(arguments);
+ // 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 = m.multiply(matrix,
+ {dy: -g.normalizedLength(this.fontStyle ? this.fontStyle.size : "10pt") * 0.35});
+ }
+ return matrix; // dojox.gfx.Matrix2D
+ },
+ getTextWidth: function(){
+ // summary: get the text width, in px
+ var rawNode = this.rawNode, _display = rawNode.style.display;
+ rawNode.style.display = "inline";
+ var _width = g.pt2px(parseFloat(rawNode.currentStyle.width));
+ rawNode.style.display = _display;
+ return _width;
+ }
+ });
+ vml.Text.nodeType = "shape";
+
+ dojo.declare("dojox.gfx.vml.Path", [vml.Shape, g.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 segment
+ var last = d.clone(this.last);
+ this.inherited(arguments);
+ if(arguments.length > 1){ return; } // skip transfomed bbox calculations
+ // add a VML path segment
+ var 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{
+ Array.prototype.push.apply(this.vmlPath, path); //FIXME: why not push()?
+ }
+ },
+ 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.type = ""; // no prior control point
+ this.inherited(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 renderers
+ renderers: {
+ 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, segment, from, upto){
+ var n = segment instanceof Array ? segment : segment.args;
+ for(var i = from; i < upto; ++i){
+ path.push(" ", n[i].toFixed());
+ }
+ },
+ _adjustRelCrd: function(last, segment, step){
+ var n = segment instanceof Array ? segment : segment.args, l = n.length,
+ result = new Array(l), i = 0, x = last.x, y = last.y;
+ if(typeof x != "number"){
+ // there is no last coordinate =>
+ // treat the first pair as an absolute coordinate
+ result[0] = x = n[0];
+ result[1] = y = n[1];
+ i = 2;
+ }
+ if(typeof step == "number" && step != 2){
+ var j = step;
+ while(j <= l){
+ for(; i < j; i += 2){
+ result[i] = x + n[i];
+ result[i + 1] = y + n[i + 1];
+ }
+ x = result[j - 2];
+ y = result[j - 1];
+ j += step;
+ }
+ }else{
+ for(; i < l; i += 2){
+ result[i] = (x += n[i]);
+ result[i + 1] = (y += n[i + 1]);
+ }
+ }
+ return result;
+ },
+ _adjustRelPos: function(last, segment){
+ var n = segment instanceof Array ? segment : segment.args, l = n.length,
+ result = new Array(l);
+ for(var i = 0; i < l; ++i){
+ result[i] = (last += n[i]);
+ }
+ return result;
+ },
+ _moveToA: function(segment){
+ var p = [" m"], n = segment instanceof Array ? segment : segment.args, l = n.length;
+ this._addArgs(p, n, 0, 2);
+ if(l > 2){
+ p.push(" l");
+ this._addArgs(p, n, 2, l);
+ }
+ this.lastControl.type = ""; // no control point after this primitive
+ return p;
+ },
+ _moveToR: function(segment, last){
+ return this._moveToA(this._adjustRelCrd(last, segment));
+ },
+ _lineToA: function(segment){
+ var p = [" l"], n = segment instanceof Array ? segment : segment.args;
+ this._addArgs(p, n, 0, n.length);
+ this.lastControl.type = ""; // no control point after this primitive
+ return p;
+ },
+ _lineToR: function(segment, last){
+ return this._lineToA(this._adjustRelCrd(last, segment));
+ },
+ _hLineToA: function(segment, last){
+ var p = [" l"], y = " " + last.y.toFixed(),
+ n = segment instanceof Array ? segment : segment.args, l = n.length;
+ for(var i = 0; i < l; ++i){
+ p.push(" ", n[i].toFixed(), y);
+ }
+ this.lastControl.type = ""; // no control point after this primitive
+ return p;
+ },
+ _hLineToR: function(segment, last){
+ return this._hLineToA(this._adjustRelPos(last.x, segment), last);
+ },
+ _vLineToA: function(segment, last){
+ var p = [" l"], x = " " + last.x.toFixed(),
+ n = segment instanceof Array ? segment : segment.args, l = n.length;
+ for(var i = 0; i < l; ++i){
+ p.push(x, " ", n[i].toFixed());
+ }
+ this.lastControl.type = ""; // no control point after this primitive
+ return p;
+ },
+ _vLineToR: function(segment, last){
+ return this._vLineToA(this._adjustRelPos(last.y, segment), last);
+ },
+ _curveToA: function(segment){
+ var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+ lc = this.lastControl;
+ for(var i = 0; i < l; i += 6){
+ p.push(" c");
+ this._addArgs(p, n, i, i + 6);
+ }
+ lc.x = n[l - 4];
+ lc.y = n[l - 3];
+ lc.type = "C";
+ return p;
+ },
+ _curveToR: function(segment, last){
+ return this._curveToA(this._adjustRelCrd(last, segment, 6));
+ },
+ _smoothCurveToA: function(segment, last){
+ var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+ lc = this.lastControl, i = 0;
+ if(lc.type != "C"){
+ p.push(" c");
+ this._addArgs(p, [last.x, last.y], 0, 2);
+ this._addArgs(p, n, 0, 4);
+ lc.x = n[0];
+ lc.y = n[1];
+ lc.type = "C";
+ i = 4;
+ }
+ for(; i < l; i += 4){
+ p.push(" c");
+ this._addArgs(p, [
+ 2 * last.x - lc.x,
+ 2 * last.y - lc.y
+ ], 0, 2);
+ this._addArgs(p, n, i, i + 4);
+ lc.x = n[i];
+ lc.y = n[i + 1];
+ }
+ return p;
+ },
+ _smoothCurveToR: function(segment, last){
+ return this._smoothCurveToA(this._adjustRelCrd(last, segment, 4), last);
+ },
+ _qCurveToA: function(segment){
+ var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+ lc = this.lastControl;
+ for(var i = 0; i < l; i += 4){
+ p.push(" qb");
+ this._addArgs(p, n, i, i + 4);
+ }
+ lc.x = n[l - 4];
+ lc.y = n[l - 3];
+ lc.type = "Q";
+ return p;
+ },
+ _qCurveToR: function(segment, last){
+ return this._qCurveToA(this._adjustRelCrd(last, segment, 4));
+ },
+ _qSmoothCurveToA: function(segment, last){
+ var p = [], n = segment instanceof Array ? segment : segment.args, l = n.length,
+ lc = this.lastControl, i = 0;
+ if(lc.type != "Q"){
+ p.push(" qb");
+ this._addArgs(p, [
+ lc.x = last.x,
+ lc.y = last.y
+ ], 0, 2);
+ lc.type = "Q";
+ this._addArgs(p, n, 0, 2);
+ i = 2;
+ }
+ for(; i < l; i += 2){
+ p.push(" qb");
+ this._addArgs(p, [
+ lc.x = 2 * last.x - lc.x,
+ lc.y = 2 * last.y - lc.y
+ ], 0, 2);
+ this._addArgs(p, n, i, i + 2);
+ }
+ return p;
+ },
+ _qSmoothCurveToR: function(segment, last){
+ return this._qSmoothCurveToA(this._adjustRelCrd(last, segment, 2), last);
+ },
+ _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 = g.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");
+ var t = result[j];
+ this._addArgs(p, t, 0, t.length);
+ this._updateBBox(t[0], t[1]);
+ this._updateBBox(t[2], t[3]);
+ this._updateBBox(t[4], t[5]);
+ }
+ last.x = x1;
+ last.y = y1;
+ }
+ this.lastControl.type = ""; // no control point after this primitive
+ return p;
+ },
+ _closePath: function(){
+ this.lastControl.type = ""; // no control point after this primitive
+ return ["x"];
+ }
+ });
+ vml.Path.nodeType = "shape";
+
+ dojo.declare("dojox.gfx.vml.TextPath", [vml.Path, g.path.TextPath], {
+ // summary: a textpath shape (VML)
+ constructor: function(rawNode){
+ if(rawNode){rawNode.setAttribute("dojoGfxType", "textpath");}
+ this.fontStyle = null;
+ if(!("text" in this)){
+ this.text = d.clone(g.defaultTextPath);
+ }
+ if(!("fontStyle" in this)){
+ this.fontStyle = d.clone(g.defaultFont);
+ }
+ },
+ setText: function(newText){
+ // summary: sets a text to be drawn along the path
+ this.text = g.makeParameters(this.text,
+ typeof newText == "string" ? {text: newText} : newText);
+ this._setText();
+ return this; // self
+ },
+ setFont: function(newFont){
+ // summary: sets a font for text
+ this.fontStyle = typeof newFont == "string" ?
+ g.splitFontString(newFont) :
+ g.makeParameters(g.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 path
+ 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 = 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 = g.makeFontString(f);
+ break;
+ }
+ }
+ }
+ });
+ vml.TextPath.nodeType = "shape";
+
+ dojo.declare("dojox.gfx.vml.Surface", gs.Surface, {
+ // summary: a surface object to be used for drawings (VML)
+ constructor: function(){
+ gs.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 = g.normalizedLength(width); // in pixels
+ this.height = g.normalizedLength(height); // in pixels
+ if(!this.rawNode) return this;
+ var cs = this.clipNode.style,
+ r = this.rawNode, rs = r.style,
+ bs = this.bgNode.style,
+ ps = this._parent.style, i;
+ ps.width = width;
+ ps.height = height;
+ cs.width = width;
+ cs.height = height;
+ cs.clip = "rect(0px " + width + "px " + height + "px 0px)";
+ rs.width = width;
+ rs.height = height;
+ r.coordsize = width + " " + height;
+ bs.width = width;
+ bs.height = height;
+ for(i = 0; i < this.children.length; ++i){
+ this.children[i]._setDimensions(width, height);
+ }
+ return this; // self
+ },
+ getDimensions: function(){
+ // summary: returns an object with properties "width" and "height"
+ var t = this.rawNode ? {
+ width: g.normalizedLength(this.rawNode.style.width),
+ height: g.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
+ }
+ });
+
+ vml.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 && !height){
+ var pos = d.position(parentNode);
+ width = width || pos.w;
+ height = height || pos.h;
+ }
+ if(typeof width == "number"){
+ width = width + "px";
+ }
+ if(typeof height == "number"){
+ height = height + "px";
+ }
+
+ var s = new vml.Surface(), p = d.byId(parentNode),
+ c = s.clipNode = p.ownerDocument.createElement("div"),
+ r = s.rawNode = p.ownerDocument.createElement("v:group"),
+ cs = c.style, rs = r.style;
+
+ if(d.isIE > 7){
+ rs.display = "inline-block";
+ }
+
+ s._parent = p;
+ s._nodes.push(c); // other elements will be deleted as parts of "c"
+
+ p.style.width = width;
+ p.style.height = height;
+
+ cs.position = "absolute";
+ cs.width = width;
+ cs.height = height;
+ cs.clip = "rect(0px " + width + " " + height + " 0px)";
+ rs.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 shapes
+ var 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 = g.normalizedLength(width); // in pixels
+ s.height = g.normalizedLength(height); // in pixels
+
+ return s; // dojox.gfx.Surface
+ };
+
+ // Extenders
+
+ // copied from dojox.gfx.utils
+ function forEach(object, f, o){
+ o = o || d.global;
+ f.call(o, object);
+ if(object instanceof g.Surface || object instanceof g.Group){
+ d.forEach(object.children, function(shape){
+ forEach(shape, f, o);
+ });
+ }
+ }
+
+ var C = gs.Container, Container = {
+ add: function(shape){
+ // summary: adds a shape to a group/surface
+ // shape: dojox.gfx.Shape: an VML shape object
+ if(this != shape.getParent()){
+ // cleanup from old parent
+ var oldParent = shape.getParent();
+ if(oldParent) { oldParent.remove(shape); }
+ // then move the raw node
+ this.rawNode.appendChild(shape.rawNode);
+ C.add.apply(this, arguments);
+ // reapply visual attributes (slow..)
+ forEach(this, function(s){
+ if (typeof(s.getFont) == 'function'){ // text shapes need to be completely refreshed
+ s.setShape(s.getShape());
+ s.setFont(s.getFont());
+ }
+ if (typeof(s.setFill) == 'function'){ // if setFill is available a setStroke should be safe to assume also
+ s.setFill(s.getFill());
+ s.setStroke(s.getStroke());
+ }
+ });
+ }
+ 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 picture
+ if(this == shape.getParent()){
+ if(this.rawNode == shape.rawNode.parentNode){
+ this.rawNode.removeChild(shape.rawNode);
+ }
+ C.remove.apply(this, arguments);
+ }
+ return this; // self
+ },
+ clear: function(){
+ // summary: removes all shapes from a group/surface
+ var 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 C.clear.apply(this, arguments);
+ },
+ _moveChildToFront: C._moveChildToFront,
+ _moveChildToBack: C._moveChildToBack
+ };
+
+ var Creator = {
+ // summary: VML shape creators
+ createGroup: function(){
+ // summary: creates a VML group shape
+ var node = this.createObject(vml.Group, null); // dojox.gfx.Group
+ // create a background rectangle, which is required to show all other shapes
+ var r = node.rawNode.ownerDocument.createElement("v:rect");
+ r.style.left = r.style.top = 0;
+ r.style.width = node.rawNode.style.width;
+ r.style.height = node.rawNode.style.height;
+ r.filled = r.stroked = "f";
+ node.rawNode.appendChild(r);
+ node.bgNode = r;
+ return node; // 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 vml.Image(),
+ doc = this.rawNode.ownerDocument,
+ node = doc.createElement('v:rect');
+ node.stroked = "f";
+ node.style.width = this.rawNode.style.width;
+ node.style.height = this.rawNode.style.height;
+ var img = doc.createElement('v:imagedata');
+ node.appendChild(img);
+ shape.setRawNode(node);
+ this.rawNode.appendChild(node);
+ shape.setShape(image);
+ this.add(shape);
+ return shape; // dojox.gfx.Image
+ },
+ createRect: function(rect){
+ // summary: creates a rectangle shape
+ // rect: Object: a path object (see dojox.gfx.defaultRect)
+ if(!this.rawNode) return null;
+ var shape = new vml.Rect,
+ node = this.rawNode.ownerDocument.createElement("v:roundrect");
+ if(d.isIE > 7){
+ node.style.display = "inline-block";
+ }
+ shape.setRawNode(node);
+ this.rawNode.appendChild(node);
+ shape.setShape(rect);
+ this.add(shape);
+ return shape; // dojox.gfx.Rect
+ },
+ 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 true
+ if(!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 vml.Group:
+ case vml.Line:
+ case vml.Polyline:
+ case vml.Image:
+ case vml.Text:
+ case vml.Path:
+ case vml.TextPath:
+ this._overrideSize(node);
+ }
+ shape.setShape(rawShape);
+ this.add(shape);
+ return shape; // dojox.gfx.Shape
+ },
+ _overrideSize: function(node){
+ var s = this.rawNode.style, w = s.width, h = s.height;
+ node.style.width = w;
+ node.style.height = h;
+ node.coordsize = parseInt(w) + " " + parseInt(h);
+ }
+ };
+
+ d.extend(vml.Group, Container);
+ d.extend(vml.Group, gs.Creator);
+ d.extend(vml.Group, Creator);
+
+ d.extend(vml.Surface, Container);
+ d.extend(vml.Surface, gs.Creator);
+ d.extend(vml.Surface, Creator);
+
+ // see if we are required to initilize
+ if(g.loadAndSwitch === "vml"){
+ g.switchTo("vml");
+ delete g.loadAndSwitch;
+ }
+})();
+
+}
+
+}};});
diff --git a/js/dojo-1.6/dojox/gfx/vml_attach.js b/js/dojo-1.6/dojox/gfx/vml_attach.js new file mode 100644 index 0000000..ef817d1 --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/vml_attach.js @@ -0,0 +1,371 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo.require("dojox.gfx.vml");
+
+dojo.experimental("dojox.gfx.vml_attach");
+
+(function(){
+ var g = dojox.gfx, m = g.matrix, vml = g.vml;
+
+ vml.attachNode = function(node){
+ // summary: creates a shape from a Node
+ // node: Node: an VML node
+ if(!node) return null;
+ var s = null;
+ switch(node.tagName.toLowerCase()){
+ case vml.Rect.nodeType:
+ s = new vml.Rect(node);
+ attachRect(s);
+ break;
+ case vml.Ellipse.nodeType:
+ if(node.style.width == node.style.height){
+ s = new vml.Circle(node);
+ attachCircle(s);
+ }else{
+ s = new vml.Ellipse(node);
+ attachEllipse(s);
+ }
+ break;
+ case vml.Path.nodeType:
+ switch(node.getAttribute("dojoGfxType")){
+ case "line":
+ s = new vml.Line(node);
+ attachLine(s);
+ break;
+ case "polyline":
+ s = new vml.Polyline(node);
+ attachPolyline(s);
+ break;
+ case "path":
+ s = new vml.Path(node);
+ attachPath(s);
+ break;
+ case "text":
+ s = new vml.Text(node);
+ attachText(s);
+ attachFont(s);
+ attachTextTransform(s);
+ break;
+ case "textpath":
+ s = new vml.TextPath(node);
+ attachPath(s);
+ attachText(s);
+ attachFont(s);
+ break;
+ }
+ break;
+ case vml.Image.nodeType:
+ switch(node.getAttribute("dojoGfxType")){
+ case "image":
+ s = new vml.Image(node);
+ attachImage(s);
+ attachImageTransform(s);
+ break;
+ }
+ break;
+ default:
+ //console.debug("FATAL ERROR! tagName = " + node.tagName);
+ return null;
+ }
+ if(!(s instanceof vml.Image)){
+ attachFill(s);
+ attachStroke(s);
+ if(!(s instanceof vml.Text)){
+ attachTransform(s);
+ }
+ }
+ return s; // dojox.gfx.Shape
+ };
+
+ vml.attachSurface = function(node){
+ // summary: creates a surface from a Node
+ // node: Node: an VML node
+ var s = new vml.Surface();
+ s.clipNode = node;
+ var r = s.rawNode = node.firstChild;
+ var b = r.firstChild;
+ if(!b || b.tagName != "rect"){
+ return null; // dojox.gfx.Surface
+ }
+ s.bgNode = r;
+ return s; // dojox.gfx.Surface
+ };
+
+ var attachFill = function(object){
+ // summary: deduces a fill style from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var fillStyle = null, r = object.rawNode, fo = r.fill;
+ if(fo.on && fo.type == "gradient"){
+ var fillStyle = dojo.clone(g.defaultLinearGradient),
+ rad = m._degToRad(fo.angle);
+ fillStyle.x2 = Math.cos(rad);
+ fillStyle.y2 = Math.sin(rad);
+ fillStyle.colors = [];
+ var stops = fo.colors.value.split(";");
+ for(var i = 0; i < stops.length; ++i){
+ var t = stops[i].match(/\S+/g);
+ if(!t || t.length != 2){ continue; }
+ fillStyle.colors.push({offset: vml._parseFloat(t[0]), color: new dojo.Color(t[1])});
+ }
+ }else if(fo.on && fo.type == "gradientradial"){
+ var fillStyle = dojo.clone(g.defaultRadialGradient),
+ w = parseFloat(r.style.width), h = parseFloat(r.style.height);
+ fillStyle.cx = isNaN(w) ? 0 : fo.focusposition.x * w;
+ fillStyle.cy = isNaN(h) ? 0 : fo.focusposition.y * h;
+ fillStyle.r = isNaN(w) ? 1 : w / 2;
+ fillStyle.colors = [];
+ var stops = fo.colors.value.split(";");
+ for(var i = stops.length - 1; i >= 0; --i){
+ var t = stops[i].match(/\S+/g);
+ if(!t || t.length != 2){ continue; }
+ fillStyle.colors.push({offset: vml._parseFloat(t[0]), color: new dojo.Color(t[1])});
+ }
+ }else if(fo.on && fo.type == "tile"){
+ var fillStyle = dojo.clone(g.defaultPattern);
+ fillStyle.width = g.pt2px(fo.size.x); // from pt
+ fillStyle.height = g.pt2px(fo.size.y); // from pt
+ fillStyle.x = fo.origin.x * fillStyle.width;
+ fillStyle.y = fo.origin.y * fillStyle.height;
+ fillStyle.src = fo.src;
+ }else if(fo.on && r.fillcolor){
+ // a color object !
+ fillStyle = new dojo.Color(r.fillcolor+"");
+ fillStyle.a = fo.opacity;
+ }
+ object.fillStyle = fillStyle;
+ };
+
+ var attachStroke = function(object) {
+ // summary: deduces a stroke style from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var r = object.rawNode;
+ if(!r.stroked){
+ object.strokeStyle = null;
+ return;
+ }
+ var strokeStyle = object.strokeStyle = dojo.clone(g.defaultStroke),
+ rs = r.stroke;
+ strokeStyle.color = new dojo.Color(r.strokecolor.value);
+ strokeStyle.width = g.normalizedLength(r.strokeweight+"");
+ strokeStyle.color.a = rs.opacity;
+ strokeStyle.cap = this._translate(this._capMapReversed, rs.endcap);
+ strokeStyle.join = rs.joinstyle == "miter" ? rs.miterlimit : rs.joinstyle;
+ strokeStyle.style = rs.dashstyle;
+ };
+
+ var attachTransform = function(object) {
+ // summary: deduces a transformation matrix from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var s = object.rawNode.skew, sm = s.matrix, so = s.offset;
+ object.matrix = m.normalize({
+ xx: sm.xtox,
+ xy: sm.ytox,
+ yx: sm.xtoy,
+ yy: sm.ytoy,
+ dx: g.pt2px(so.x),
+ dy: g.pt2px(so.y)
+ });
+ };
+
+ var attachGroup = function(object){
+ // summary: reconstructs all group shape parameters from a node (VML).
+ // object: dojox.gfx.Shape: an VML shape
+ // attach the background
+ object.bgNode = object.rawNode.firstChild; // TODO: check it first
+ };
+
+ var attachRect = function(object){
+ // summary: builds a rectangle shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ // a workaround for the VML's arcsize bug: cannot read arcsize of an instantiated node
+ var r = object.rawNode, arcsize = r.outerHTML.match(/arcsize = \"(\d*\.?\d+[%f]?)\"/)[1],
+ style = r.style, width = parseFloat(style.width), height = parseFloat(style.height);
+ arcsize = (arcsize.indexOf("%") >= 0) ? parseFloat(arcsize) / 100 : vml._parseFloat(arcsize);
+ // make an object
+ object.shape = g.makeParameters(g.defaultRect, {
+ x: parseInt(style.left),
+ y: parseInt(style.top),
+ width: width,
+ height: height,
+ r: Math.min(width, height) * arcsize
+ });
+ };
+
+ var attachEllipse = function(object){
+ // summary: builds an ellipse shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var style = object.rawNode.style,
+ rx = parseInt(style.width ) / 2,
+ ry = parseInt(style.height) / 2;
+ object.shape = g.makeParameters(g.defaultEllipse, {
+ cx: parseInt(style.left) + rx,
+ cy: parseInt(style.top ) + ry,
+ rx: rx,
+ ry: ry
+ });
+ };
+
+ var attachCircle = function(object){
+ // summary: builds a circle shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var style = object.rawNode.style, r = parseInt(style.width) / 2;
+ object.shape = g.makeParameters(g.defaultCircle, {
+ cx: parseInt(style.left) + r,
+ cy: parseInt(style.top) + r,
+ r: r
+ });
+ };
+
+ var attachLine = function(object){
+ // summary: builds a line shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var shape = object.shape = dojo.clone(g.defaultLine),
+ p = object.rawNode.path.v.match(g.pathVmlRegExp);
+ do{
+ if(p.length < 7 || p[0] != "m" || p[3] != "l" || p[6] != "e"){ break; }
+ shape.x1 = parseInt(p[1]);
+ shape.y1 = parseInt(p[2]);
+ shape.x2 = parseInt(p[4]);
+ shape.y2 = parseInt(p[5]);
+ }while(false);
+ };
+
+ var attachPolyline = function(object){
+ // summary: builds a polyline/polygon shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var shape = object.shape = dojo.clone(g.defaultPolyline),
+ p = object.rawNode.path.v.match(g.pathVmlRegExp);
+ do{
+ if(p.length < 3 || p[0] != "m"){ break; }
+ var x = parseInt(p[0]), y = parseInt(p[1]);
+ if(isNaN(x) || isNaN(y)){ break; }
+ shape.points.push({x: x, y: y});
+ if(p.length < 6 || p[3] != "l"){ break; }
+ for(var i = 4; i < p.length; i += 2){
+ x = parseInt(p[i]);
+ y = parseInt(p[i + 1]);
+ if(isNaN(x) || isNaN(y)){ break; }
+ shape.points.push({x: x, y: y});
+ }
+ }while(false);
+ };
+
+ var attachImage = function(object){
+ // summary: builds an image shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ object.shape = dojo.clone(g.defaultImage);
+ object.shape.src = object.rawNode.firstChild.src;
+ };
+
+ var attachImageTransform = function(object) {
+ // summary: deduces a transformation matrix from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var mm = object.rawNode.filters["DXImageTransform.Microsoft.Matrix"];
+ object.matrix = m.normalize({
+ xx: mm.M11,
+ xy: mm.M12,
+ yx: mm.M21,
+ yy: mm.M22,
+ dx: mm.Dx,
+ dy: mm.Dy
+ });
+ };
+
+ var attachText = function(object){
+ // summary: builds a text shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var shape = object.shape = dojo.clone(g.defaultText),
+ r = object.rawNode, p = r.path.v.match(g.pathVmlRegExp);
+ do{
+ if(!p || p.length != 7){ break; }
+ var c = r.childNodes, i = 0;
+ for(; i < c.length && c[i].tagName != "textpath"; ++i);
+ if(i >= c.length){ break; }
+ var s = c[i].style;
+ shape.text = c[i].string;
+ switch(s["v-text-align"]){
+ case "left":
+ shape.x = parseInt(p[1]);
+ shape.align = "start";
+ break;
+ case "center":
+ shape.x = (parseInt(p[1]) + parseInt(p[4])) / 2;
+ shape.align = "middle";
+ break;
+ case "right":
+ shape.x = parseInt(p[4]);
+ shape.align = "end";
+ break;
+ }
+ shape.y = parseInt(p[2]);
+ shape.decoration = s["text-decoration"];
+ shape.rotated = s["v-rotate-letters"].toLowerCase() in vml._bool;
+ shape.kerning = s["v-text-kern"].toLowerCase() in vml._bool;
+ return;
+ }while(false);
+ object.shape = null;
+ };
+
+ var attachFont = function(object){
+ // summary: deduces a font style from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var fontStyle = object.fontStyle = dojo.clone(g.defaultFont),
+ c = object.rawNode.childNodes, i = 0;
+ for(; i < c.length && c[i].tagName == "textpath"; ++i);
+ if(i >= c.length){
+ object.fontStyle = null;
+ return;
+ }
+ var s = c[i].style;
+ fontStyle.style = s.fontstyle;
+ fontStyle.variant = s.fontvariant;
+ fontStyle.weight = s.fontweight;
+ fontStyle.size = s.fontsize;
+ fontStyle.family = s.fontfamily;
+ };
+
+ var attachTextTransform = function(object) {
+ // summary: deduces a transformation matrix from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ attachTransform(object);
+ var matrix = object.matrix, fs = object.fontStyle;
+ // see comments in _getRealMatrix()
+ if(matrix && fs){
+ object.matrix = m.multiply(matrix, {dy: g.normalizedLength(fs.size) * 0.35});
+ }
+ };
+
+ var attachPath = function(object){
+ // summary: builds a path shape from a Node.
+ // object: dojox.gfx.Shape: an VML shape
+ var shape = object.shape = dojo.clone(g.defaultPath),
+ p = object.rawNode.path.v.match(g.pathVmlRegExp),
+ t = [], skip = false, map = g.Path._pathVmlToSvgMap;
+ for(var i = 0; i < p.length; ++p){
+ var s = p[i];
+ if(s in map) {
+ skip = false;
+ t.push(map[s]);
+ } else if(!skip){
+ var n = parseInt(s);
+ if(isNaN(n)){
+ skip = true;
+ }else{
+ t.push(n);
+ }
+ }
+ }
+ var l = t.length;
+ if(l >= 4 && t[l - 1] == "" && t[l - 2] == 0 && t[l - 3] == 0 && t[l - 4] == "l"){
+ t.splice(l - 4, 4);
+ }
+ if(l){
+ shape.path = t.join(" ");
+ }
+ };
+})();
diff --git a/js/dojo-1.6/dojox/gfx/vml_attach.xd.js b/js/dojo-1.6/dojox/gfx/vml_attach.xd.js new file mode 100644 index 0000000..9f2649c --- /dev/null +++ b/js/dojo-1.6/dojox/gfx/vml_attach.xd.js @@ -0,0 +1,375 @@ +/*
+ Copyright (c) 2004-2011, 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
+*/
+
+
+dojo._xdResourceLoaded(function(dojo, dijit, dojox){
+return {depends: [["require", "dojox.gfx.vml"]],
+defineResource: function(dojo, dijit, dojox){dojo.require("dojox.gfx.vml");
+
+dojo.experimental("dojox.gfx.vml_attach");
+
+(function(){
+ var g = dojox.gfx, m = g.matrix, vml = g.vml;
+
+ vml.attachNode = function(node){
+ // summary: creates a shape from a Node
+ // node: Node: an VML node
+ if(!node) return null;
+ var s = null;
+ switch(node.tagName.toLowerCase()){
+ case vml.Rect.nodeType:
+ s = new vml.Rect(node);
+ attachRect(s);
+ break;
+ case vml.Ellipse.nodeType:
+ if(node.style.width == node.style.height){
+ s = new vml.Circle(node);
+ attachCircle(s);
+ }else{
+ s = new vml.Ellipse(node);
+ attachEllipse(s);
+ }
+ break;
+ case vml.Path.nodeType:
+ switch(node.getAttribute("dojoGfxType")){
+ case "line":
+ s = new vml.Line(node);
+ attachLine(s);
+ break;
+ case "polyline":
+ s = new vml.Polyline(node);
+ attachPolyline(s);
+ break;
+ case "path":
+ s = new vml.Path(node);
+ attachPath(s);
+ break;
+ case "text":
+ s = new vml.Text(node);
+ attachText(s);
+ attachFont(s);
+ attachTextTransform(s);
+ break;
+ case "textpath":
+ s = new vml.TextPath(node);
+ attachPath(s);
+ attachText(s);
+ attachFont(s);
+ break;
+ }
+ break;
+ case vml.Image.nodeType:
+ switch(node.getAttribute("dojoGfxType")){
+ case "image":
+ s = new vml.Image(node);
+ attachImage(s);
+ attachImageTransform(s);
+ break;
+ }
+ break;
+ default:
+ //console.debug("FATAL ERROR! tagName = " + node.tagName);
+ return null;
+ }
+ if(!(s instanceof vml.Image)){
+ attachFill(s);
+ attachStroke(s);
+ if(!(s instanceof vml.Text)){
+ attachTransform(s);
+ }
+ }
+ return s; // dojox.gfx.Shape
+ };
+
+ vml.attachSurface = function(node){
+ // summary: creates a surface from a Node
+ // node: Node: an VML node
+ var s = new vml.Surface();
+ s.clipNode = node;
+ var r = s.rawNode = node.firstChild;
+ var b = r.firstChild;
+ if(!b || b.tagName != "rect"){
+ return null; // dojox.gfx.Surface
+ }
+ s.bgNode = r;
+ return s; // dojox.gfx.Surface
+ };
+
+ var attachFill = function(object){
+ // summary: deduces a fill style from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var fillStyle = null, r = object.rawNode, fo = r.fill;
+ if(fo.on && fo.type == "gradient"){
+ var fillStyle = dojo.clone(g.defaultLinearGradient),
+ rad = m._degToRad(fo.angle);
+ fillStyle.x2 = Math.cos(rad);
+ fillStyle.y2 = Math.sin(rad);
+ fillStyle.colors = [];
+ var stops = fo.colors.value.split(";");
+ for(var i = 0; i < stops.length; ++i){
+ var t = stops[i].match(/\S+/g);
+ if(!t || t.length != 2){ continue; }
+ fillStyle.colors.push({offset: vml._parseFloat(t[0]), color: new dojo.Color(t[1])});
+ }
+ }else if(fo.on && fo.type == "gradientradial"){
+ var fillStyle = dojo.clone(g.defaultRadialGradient),
+ w = parseFloat(r.style.width), h = parseFloat(r.style.height);
+ fillStyle.cx = isNaN(w) ? 0 : fo.focusposition.x * w;
+ fillStyle.cy = isNaN(h) ? 0 : fo.focusposition.y * h;
+ fillStyle.r = isNaN(w) ? 1 : w / 2;
+ fillStyle.colors = [];
+ var stops = fo.colors.value.split(";");
+ for(var i = stops.length - 1; i >= 0; --i){
+ var t = stops[i].match(/\S+/g);
+ if(!t || t.length != 2){ continue; }
+ fillStyle.colors.push({offset: vml._parseFloat(t[0]), color: new dojo.Color(t[1])});
+ }
+ }else if(fo.on && fo.type == "tile"){
+ var fillStyle = dojo.clone(g.defaultPattern);
+ fillStyle.width = g.pt2px(fo.size.x); // from pt
+ fillStyle.height = g.pt2px(fo.size.y); // from pt
+ fillStyle.x = fo.origin.x * fillStyle.width;
+ fillStyle.y = fo.origin.y * fillStyle.height;
+ fillStyle.src = fo.src;
+ }else if(fo.on && r.fillcolor){
+ // a color object !
+ fillStyle = new dojo.Color(r.fillcolor+"");
+ fillStyle.a = fo.opacity;
+ }
+ object.fillStyle = fillStyle;
+ };
+
+ var attachStroke = function(object) {
+ // summary: deduces a stroke style from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var r = object.rawNode;
+ if(!r.stroked){
+ object.strokeStyle = null;
+ return;
+ }
+ var strokeStyle = object.strokeStyle = dojo.clone(g.defaultStroke),
+ rs = r.stroke;
+ strokeStyle.color = new dojo.Color(r.strokecolor.value);
+ strokeStyle.width = g.normalizedLength(r.strokeweight+"");
+ strokeStyle.color.a = rs.opacity;
+ strokeStyle.cap = this._translate(this._capMapReversed, rs.endcap);
+ strokeStyle.join = rs.joinstyle == "miter" ? rs.miterlimit : rs.joinstyle;
+ strokeStyle.style = rs.dashstyle;
+ };
+
+ var attachTransform = function(object) {
+ // summary: deduces a transformation matrix from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var s = object.rawNode.skew, sm = s.matrix, so = s.offset;
+ object.matrix = m.normalize({
+ xx: sm.xtox,
+ xy: sm.ytox,
+ yx: sm.xtoy,
+ yy: sm.ytoy,
+ dx: g.pt2px(so.x),
+ dy: g.pt2px(so.y)
+ });
+ };
+
+ var attachGroup = function(object){
+ // summary: reconstructs all group shape parameters from a node (VML).
+ // object: dojox.gfx.Shape: an VML shape
+ // attach the background
+ object.bgNode = object.rawNode.firstChild; // TODO: check it first
+ };
+
+ var attachRect = function(object){
+ // summary: builds a rectangle shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ // a workaround for the VML's arcsize bug: cannot read arcsize of an instantiated node
+ var r = object.rawNode, arcsize = r.outerHTML.match(/arcsize = \"(\d*\.?\d+[%f]?)\"/)[1],
+ style = r.style, width = parseFloat(style.width), height = parseFloat(style.height);
+ arcsize = (arcsize.indexOf("%") >= 0) ? parseFloat(arcsize) / 100 : vml._parseFloat(arcsize);
+ // make an object
+ object.shape = g.makeParameters(g.defaultRect, {
+ x: parseInt(style.left),
+ y: parseInt(style.top),
+ width: width,
+ height: height,
+ r: Math.min(width, height) * arcsize
+ });
+ };
+
+ var attachEllipse = function(object){
+ // summary: builds an ellipse shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var style = object.rawNode.style,
+ rx = parseInt(style.width ) / 2,
+ ry = parseInt(style.height) / 2;
+ object.shape = g.makeParameters(g.defaultEllipse, {
+ cx: parseInt(style.left) + rx,
+ cy: parseInt(style.top ) + ry,
+ rx: rx,
+ ry: ry
+ });
+ };
+
+ var attachCircle = function(object){
+ // summary: builds a circle shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var style = object.rawNode.style, r = parseInt(style.width) / 2;
+ object.shape = g.makeParameters(g.defaultCircle, {
+ cx: parseInt(style.left) + r,
+ cy: parseInt(style.top) + r,
+ r: r
+ });
+ };
+
+ var attachLine = function(object){
+ // summary: builds a line shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var shape = object.shape = dojo.clone(g.defaultLine),
+ p = object.rawNode.path.v.match(g.pathVmlRegExp);
+ do{
+ if(p.length < 7 || p[0] != "m" || p[3] != "l" || p[6] != "e"){ break; }
+ shape.x1 = parseInt(p[1]);
+ shape.y1 = parseInt(p[2]);
+ shape.x2 = parseInt(p[4]);
+ shape.y2 = parseInt(p[5]);
+ }while(false);
+ };
+
+ var attachPolyline = function(object){
+ // summary: builds a polyline/polygon shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var shape = object.shape = dojo.clone(g.defaultPolyline),
+ p = object.rawNode.path.v.match(g.pathVmlRegExp);
+ do{
+ if(p.length < 3 || p[0] != "m"){ break; }
+ var x = parseInt(p[0]), y = parseInt(p[1]);
+ if(isNaN(x) || isNaN(y)){ break; }
+ shape.points.push({x: x, y: y});
+ if(p.length < 6 || p[3] != "l"){ break; }
+ for(var i = 4; i < p.length; i += 2){
+ x = parseInt(p[i]);
+ y = parseInt(p[i + 1]);
+ if(isNaN(x) || isNaN(y)){ break; }
+ shape.points.push({x: x, y: y});
+ }
+ }while(false);
+ };
+
+ var attachImage = function(object){
+ // summary: builds an image shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ object.shape = dojo.clone(g.defaultImage);
+ object.shape.src = object.rawNode.firstChild.src;
+ };
+
+ var attachImageTransform = function(object) {
+ // summary: deduces a transformation matrix from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var mm = object.rawNode.filters["DXImageTransform.Microsoft.Matrix"];
+ object.matrix = m.normalize({
+ xx: mm.M11,
+ xy: mm.M12,
+ yx: mm.M21,
+ yy: mm.M22,
+ dx: mm.Dx,
+ dy: mm.Dy
+ });
+ };
+
+ var attachText = function(object){
+ // summary: builds a text shape from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var shape = object.shape = dojo.clone(g.defaultText),
+ r = object.rawNode, p = r.path.v.match(g.pathVmlRegExp);
+ do{
+ if(!p || p.length != 7){ break; }
+ var c = r.childNodes, i = 0;
+ for(; i < c.length && c[i].tagName != "textpath"; ++i);
+ if(i >= c.length){ break; }
+ var s = c[i].style;
+ shape.text = c[i].string;
+ switch(s["v-text-align"]){
+ case "left":
+ shape.x = parseInt(p[1]);
+ shape.align = "start";
+ break;
+ case "center":
+ shape.x = (parseInt(p[1]) + parseInt(p[4])) / 2;
+ shape.align = "middle";
+ break;
+ case "right":
+ shape.x = parseInt(p[4]);
+ shape.align = "end";
+ break;
+ }
+ shape.y = parseInt(p[2]);
+ shape.decoration = s["text-decoration"];
+ shape.rotated = s["v-rotate-letters"].toLowerCase() in vml._bool;
+ shape.kerning = s["v-text-kern"].toLowerCase() in vml._bool;
+ return;
+ }while(false);
+ object.shape = null;
+ };
+
+ var attachFont = function(object){
+ // summary: deduces a font style from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ var fontStyle = object.fontStyle = dojo.clone(g.defaultFont),
+ c = object.rawNode.childNodes, i = 0;
+ for(; i < c.length && c[i].tagName == "textpath"; ++i);
+ if(i >= c.length){
+ object.fontStyle = null;
+ return;
+ }
+ var s = c[i].style;
+ fontStyle.style = s.fontstyle;
+ fontStyle.variant = s.fontvariant;
+ fontStyle.weight = s.fontweight;
+ fontStyle.size = s.fontsize;
+ fontStyle.family = s.fontfamily;
+ };
+
+ var attachTextTransform = function(object) {
+ // summary: deduces a transformation matrix from a node.
+ // object: dojox.gfx.Shape: an VML shape
+ attachTransform(object);
+ var matrix = object.matrix, fs = object.fontStyle;
+ // see comments in _getRealMatrix()
+ if(matrix && fs){
+ object.matrix = m.multiply(matrix, {dy: g.normalizedLength(fs.size) * 0.35});
+ }
+ };
+
+ var attachPath = function(object){
+ // summary: builds a path shape from a Node.
+ // object: dojox.gfx.Shape: an VML shape
+ var shape = object.shape = dojo.clone(g.defaultPath),
+ p = object.rawNode.path.v.match(g.pathVmlRegExp),
+ t = [], skip = false, map = g.Path._pathVmlToSvgMap;
+ for(var i = 0; i < p.length; ++p){
+ var s = p[i];
+ if(s in map) {
+ skip = false;
+ t.push(map[s]);
+ } else if(!skip){
+ var n = parseInt(s);
+ if(isNaN(n)){
+ skip = true;
+ }else{
+ t.push(n);
+ }
+ }
+ }
+ var l = t.length;
+ if(l >= 4 && t[l - 1] == "" && t[l - 2] == 0 && t[l - 3] == 0 && t[l - 4] == "l"){
+ t.splice(l - 4, 4);
+ }
+ if(l){
+ shape.path = t.join(" ");
+ }
+ };
+})();
+
+}};});
|
