Subversion Repositories Applications.papyrus

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
        Copyright (c) 2004-2006, The Dojo Foundation
        All Rights Reserved.

        Licensed under the Academic Free License version 2.1 or above OR the
        modified BSD license. For more information on Dojo licensing, see:

                http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.gfx.path");
dojo.require("dojo.math");
dojo.require("dojo.gfx.shape");
dojo.declare("dojo.gfx.path.Path", dojo.gfx.Shape, {initializer:function (rawNode) {
        this.shape = dojo.lang.shallowCopy(dojo.gfx.defaultPath, true);
        this.segments = [];
        this.absolute = true;
        this.last = {};
        this.attach(rawNode);
}, setAbsoluteMode:function (mode) {
        this.absolute = typeof (mode) == "string" ? (mode == "absolute") : mode;
        return this;
}, getAbsoluteMode:function () {
        return this.absolute;
}, getBoundingBox:function () {
        return "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;
}, getLastPosition:function () {
        return "x" in this.last ? this.last : null;
}, _updateBBox:function (x, y) {
        if ("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) {
        var n = segment.args;
        var l = n.length;
        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(this.bbox, n[i], n[i + 1]);
                }
                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(this.bbox, n[i], this.last.y);
                }
                this.last.x = n[l - 1];
                this.absolute = true;
                break;
          case "V":
                for (var i = 0; i < l; ++i) {
                        this._updateBBox(this.bbox, this.last.x, n[i]);
                }
                this.last.y = n[l - 1];
                this.absolute = true;
                break;
          case "m":
                var start = 0;
                if (!("x" in this.last)) {
                        this._updateBBox(this.bbox, this.last.x = n[0], this.last.y = n[1]);
                        start = 2;
                }
                for (var i = start; i < l; i += 2) {
                        this._updateBBox(this.bbox, this.last.x += n[i], this.last.y += n[i + 1]);
                }
                this.absolute = false;
                break;
          case "l":
          case "t":
                for (var i = 0; i < l; i += 2) {
                        this._updateBBox(this.bbox, this.last.x += n[i], this.last.y += n[i + 1]);
                }
                this.absolute = false;
                break;
          case "h":
                for (var i = 0; i < l; ++i) {
                        this._updateBBox(this.bbox, this.last.x += n[i], this.last.y);
                }
                this.absolute = false;
                break;
          case "v":
                for (var i = 0; i < l; ++i) {
                        this._updateBBox(this.bbox, this.last.x, this.last.y += n[i]);
                }
                this.absolute = false;
                break;
          case "c":
                for (var i = 0; i < l; i += 6) {
                        this._updateBBox(this.bbox, this.last.x + n[i], this.last.y + n[i + 1]);
                        this._updateBBox(this.bbox, this.last.x + n[i + 2], this.last.y + n[i + 3]);
                        this._updateBBox(this.bbox, this.last.x += n[i + 4], this.last.y += n[i + 5]);
                }
                this.absolute = false;
                break;
          case "s":
          case "q":
                for (var i = 0; i < l; i += 4) {
                        this._updateBBox(this.bbox, this.last.x + n[i], this.last.y + n[i + 1]);
                        this._updateBBox(this.bbox, this.last.x += n[i + 2], this.last.y += n[i + 3]);
                }
                this.absolute = false;
                break;
          case "A":
                for (var i = 0; i < l; i += 7) {
                        this._updateBBox(this.bbox, n[i + 5], n[i + 6]);
                }
                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.bbox, this.last.x += n[i + 5], this.last.y += n[i + 6]);
                }
                this.absolute = false;
                break;
        }
        var path = [segment.action];
        for (var i = 0; i < l; ++i) {
                path.push(dojo.gfx.formatNumber(n[i], true));
        }
        if (typeof (this.shape.path) == "string") {
                this.shape.path += path.join("");
        } else {
                this.shape.path = this.shape.path.concat(path);
        }
}, _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) {
        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) {
        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);
                                                array.push(t.y);
                                        }
                                }
                        }
                }
        }
}, moveTo:function () {
        var args = [];
        this._collectArgs(args, arguments);
        this._pushSegment(this.absolute ? "M" : "m", args);
        return this;
}, lineTo:function () {
        var args = [];
        this._collectArgs(args, arguments);
        this._pushSegment(this.absolute ? "L" : "l", args);
        return this;
}, hLineTo:function () {
        var args = [];
        this._collectArgs(args, arguments);
        this._pushSegment(this.absolute ? "H" : "h", args);
        return this;
}, vLineTo:function () {
        var args = [];
        this._collectArgs(args, arguments);
        this._pushSegment(this.absolute ? "V" : "v", args);
        return this;
}, curveTo:function () {
        var args = [];
        this._collectArgs(args, arguments);
        this._pushSegment(this.absolute ? "C" : "c", args);
        return this;
}, smoothCurveTo:function () {
        var args = [];
        this._collectArgs(args, arguments);
        this._pushSegment(this.absolute ? "S" : "s", args);
        return this;
}, qCurveTo:function () {
        var args = [];
        this._collectArgs(args, arguments);
        this._pushSegment(this.absolute ? "Q" : "q", args);
        return this;
}, qSmoothCurveTo:function () {
        var args = [];
        this._collectArgs(args, arguments);
        this._pushSegment(this.absolute ? "T" : "t", args);
        return this;
}, arcTo:function () {
        var args = [];
        this._collectArgs(args, arguments);
        for (var i = 2; i < args.length; i += 7) {
                args[i] = -args[i];
        }
        this._pushSegment(this.absolute ? "A" : "a", args);
        return this;
}, closePath:function () {
        this._pushSegment("Z", []);
        return this;
}, _setPath:function (path) {
        var p = path.match(dojo.gfx.pathRegExp);
        this.segments = [];
        this.absolute = true;
        this.bbox = {};
        this.last = {};
        if (!p) {
                return;
        }
        var action = "";
        var args = [];
        for (var i = 0; i < p.length; ++i) {
                var t = p[i];
                var 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) {
        this.shape = dojo.gfx.makeParameters(this.shape, typeof (newShape) == "string" ? {path:newShape} : newShape);
        var path = this.shape.path;
        this.shape.path = [];
        this._setPath(path);
        this.shape.path = this.shape.path.join("");
        return this;
}, _2PI:Math.PI * 2});