123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- define("dojox/gfx/utils", ["dojo/_base/kernel","dojo/_base/lang","./_base", "dojo/_base/html","dojo/_base/array", "dojo/_base/window", "dojo/_base/json",
- "dojo/_base/Deferred", "dojo/_base/sniff", "require","dojo/_base/config"],
- function(kernel, lang, g, html, arr, win, jsonLib, Deferred, has, require, config){
- var gu = g.utils = {};
- /*===== g= dojox.gfx; gu = dojox.gfx.utils; =====*/
- lang.mixin(gu, {
- forEach: function(
- /*dojox.gfx.Surface|dojox.gfx.Shape*/ object,
- /*Function|String|Array*/ f, /*Object?*/ o
- ){
- // summary:
- // Takes a shape or a surface and applies a function "f" to in the context of "o"
- // (or global, if missing). If "shape" was a surface or a group, it applies the same
- // function to all children recursively effectively visiting all shapes of the underlying scene graph.
- // object : The gfx container to iterate.
- // f : The function to apply.
- // o : The scope.
- o = o || win.global;
- f.call(o, object);
- if(object instanceof g.Surface || object instanceof g.Group){
- arr.forEach(object.children, function(shape){
- gu.forEach(shape, f, o);
- });
- }
- },
- serialize: function(
- /* dojox.gfx.Surface|dojox.gfx.Shape */ object
- ){
- // summary:
- // Takes a shape or a surface and returns a DOM object, which describes underlying shapes.
- var t = {}, v, isSurface = object instanceof g.Surface;
- if(isSurface || object instanceof g.Group){
- t.children = arr.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
- ){
- // summary:
- // Works just like serialize() but returns a JSON string. If prettyPrint is true, the string is pretty-printed to make it more human-readable.
- return jsonLib.toJson(gu.serialize(object), prettyPrint); // String
- },
- deserialize: function(
- /* dojox.gfx.Surface|dojox.gfx.Shape */ parent,
- /* dojox.gfx.Shape|Array */ object
- ){
- // summary:
- // Takes a surface or a shape and populates it with an object produced by serialize().
- if(object instanceof Array){
- return arr.map(object, lang.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){
- arr.forEach(object.children, lang.hitch(null, gu.deserialize, shape));
- }
- return shape; // dojox.gfx.Shape
- },
- fromJson: function(
- /* dojox.gfx.Surface|dojox.gfx.Shape */ parent,
- /* String */ json){
- // summary:
- // Works just like deserialize() but takes a JSON representation of the object.
- return gu.deserialize(parent, jsonLib.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 Deferred();
-
- if(g.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 = gu.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.
- win.withDoc(gu._gfxSvgProxy.document, function() {
- html.style(node, "width", width);
- html.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 Deferred();
- var f = win.doc.createElement("iframe");
- html.style(f, {
- display: "none",
- position: "absolute",
- width: "1em",
- height: "1em",
- top: "-10000px"
- });
- var intv;
- if(has("ie")){
- f.onreadystatechange = function(){
- if(f.contentWindow.document.readyState == "complete"){
- f.onreadystatechange = function() {};
- intv = setInterval(function() {
- if(f.contentWindow[kernel.scopeMap["dojo"][1]._scopeName] &&
- f.contentWindow[kernel.scopeMap["dojox"][1]._scopeName].gfx &&
- f.contentWindow[kernel.scopeMap["dojox"][1]._scopeName].gfx.utils){
- clearInterval(intv);
- f.contentWindow.parent[kernel.scopeMap["dojox"][1]._scopeName].gfx.utils._gfxSvgProxy = f.contentWindow;
- f.contentWindow.parent[kernel.scopeMap["dojox"][1]._scopeName].gfx.utils._svgSerializerInitialized();
- }
- }, 50);
- }
- };
- }else{
- f.onload = function(){
- f.onload = function() {};
- intv = setInterval(function() {
- if(f.contentWindow[kernel.scopeMap["dojo"][1]._scopeName] &&
- f.contentWindow[kernel.scopeMap["dojox"][1]._scopeName].gfx &&
- f.contentWindow[kernel.scopeMap["dojox"][1]._scopeName].gfx.utils){
- clearInterval(intv);
- f.contentWindow.parent[kernel.scopeMap["dojox"][1]._scopeName].gfx.utils._gfxSvgProxy = f.contentWindow;
- f.contentWindow.parent[kernel.scopeMap["dojox"][1]._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 = (config["dojoxGfxSvgProxyFrameUrl"]||require.toUrl("dojox/gfx/resources/gfxSvgProxyFrame.html"));
- f.setAttribute("src", uri.toString());
- win.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;
- }
- //Same for xmlns:xlink (missing in Chrome and Safari)
- if(svg.indexOf("xmlns:xlink=\"http://www.w3.org/1999/xlink\"") == -1){
- svg = svg.substring(4, svg.length);
- svg = "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\"" + svg;
- }
- //and add namespace to href attribute if not done yet
- //(FF 5+ adds xlink:href but not the xmlns def)
- if(svg.indexOf("xlink:href") === -1){
- svg = svg.replace(/href\s*=/g, "xlink:href=");
- }
- //Do some other cleanup, like stripping out the
- //dojoGfx attributes and quoting ids.
- svg = svg.replace(/\bdojoGfx\w*\s*=\s*(['"])\w*\1/g, "");
- svg = svg.replace(/\b__gfxObject__\s*=\s*(['"])\w*\1/g, "");
- svg = svg.replace(/[=]([^"']+?)(\s|>)/g,'="$1"$2');
-
- // Undefined strokes (IE 8 seralization weirdness) should be removed to
- // allow default. 'undefined' is not a valid value.
- svg = svg.replace(/\bstroke-opacity\w*\s*=\s*(['"])undefined\1/g, "");
- }
- return svg; //Cleaned SVG text.
- }
- });
- return gu;
- });
|