PageSourceSearch

https://empoweringamerica.org/wp-content/themes/tea/assets/js/raphael.js?ver=7.1.1

js empoweringamerica.org collected 2026-09-26 02:34:05 UTC 203,134 bytes, 5,381 lines download raw bytes

1// ┌─────────────────────────────────────────────────────────────────────┐ \\
2// │ Raphaël 2.0 - JavaScript Vector Library                             │ \\
3// ├─────────────────────────────────────────────────────────────────────┤ \\
4// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\
5// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\
6// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
7// └─────────────────────────────────────────────────────────────────────┘ \\
8
9// ┌──────────────────────────────────────────────────────────────────────────────────────┐ \\
10// │ Eve 0.3.0 - JavaScript Events Library                                                │ \\
11// ├──────────────────────────────────────────────────────────────────────────────────────┤ \\
12// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/)          │ \\
13// │ Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. │ \\
14// └──────────────────────────────────────────────────────────────────────────────────────┘ \\
15
16(function (glob) {
17    var version = "0.3.0",
18        has = "hasOwnProperty",
19        separator = /[\.\/]/,
20        wildcard = "*",
21        fun = function () {},
22        numsort = function (a, b) {
23            return a - b;
24        },
25        current_event,
26        stop,
27        events = {n: {}},
28    
29        eve = function (name, scope) {
30            var e = events,
31                args = Array.prototype.slice.call(arguments, 2),
32                listeners = eve.listeners(name),
33                z = 0,
34                f = false,
35                l,
36                indexed = [],
37                queue = {},
38                out = [],
39                errors = [];
40            current_event = name;
41            stop = 0;
42            for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) {
43                indexed.push(listeners[i].zIndex);
44                if (listeners[i].zIndex < 0) {
45                    queue[listeners[i].zIndex] = listeners[i];
46                }
47            }
48            indexed.sort(numsort);
49            while (indexed[z] < 0) {
50                l = queue[indexed[z++]];
51                out.push(l.apply(scope, args));
52                if (stop) {
53                    return out;
54                }
55            }
56            for (i = 0; i < ii; i++) {
57                l = listeners[i];
58                if ("zIndex" in l) {
59                    if (l.zIndex == indexed[z]) {
60                        out.push(l.apply(scope, args));
61                        if (stop) {
62                            return out;
63                        }
64                        do {
65                            z++;
66                            l = queue[indexed[z]];
67                            l && out.push(l.apply(scope, args));
68                            if (stop) {
69                                return out;
70                            }
71                        } while (l)
72                    } else {
73                        queue[l.zIndex] = l;
74                    }
75                } else {
76                    out.push(l.apply(scope, args));
77                    if (stop) {
78                        return out;
79                    }
80                }
81            }
82            return out.length ? out : null;
83        };
84    
85    eve.listeners = function (name) {
86        var names = name.split(separator),
87            e = events,
88            item,
89            items,
90            k,
91            i,
92            ii,
93            j,
94            jj,
95            nes,
96            es = [e],
97            out = [];
98        for (i = 0, ii = names.length; i < ii; i++) {
99            nes = [];
100            for (j = 0, jj = es.length; j < jj; j++) {
101                e = es[j].n;
102                items = [e[names[i]], e[wildcard]];
103                k = 2;
104                while (k--) {
105                    item = items[k];
106                    if (item) {
107                        nes.push(item);
108                        out = out.concat(item.f || []);
109                    }
110                }
111            }
112            es = nes;
113        }
114        return out;
115    };
116    
117    
118    eve.on = function (name, f) {
119        var names = name.split(separator),
120            e = events;
121        for (var i = 0, ii = names.length; i < ii; i++) {
122            e = e.n;
123            !e[names[i]] && (e[names[i]] = {n: {}});
124            e = e[names[i]];
125        }
126        e.f = e.f || [];
127        for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {
128            return fun;
129        }
130        e.f.push(f);
131        return function (zIndex) {
132            if (+zIndex == +zIndex) {
133                f.zIndex = +zIndex;
134            }
135        };
136    };
137    
138    eve.stop = function () {
139        stop = 1;
140    };
141    
142    eve.nt = function (subname) {
143        if (subname) {
144            return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(current_event);
145        }
146        return current_event;
147    };
148    
149    eve.unbind = function (name, f) {
150        var names = name.split(separator),
151            e,
152            key,
153            splice,
154            cur = [events];
155        for (var i = 0, ii = names.length; i < ii; i++) {
156            for (var j = 0; j < cur.length; j += splice.length - 2) {
157                splice = [j, 1];
158                e = cur[j].n;
159                if (names[i] != wildcard) {
160                    if (e[names[i]]) {
161                        splice.push(e[names[i]]);
162                    }
163                } else {
164                    for (key in e) if (e[has](key)) {
165                        splice.push(e[key]);
166                    }
167                }
168                cur.splice.apply(cur, splice);
169            }
170        }
171        for (i = 0, ii = cur.length; i < ii; i++) {
172            e = cur[i];
173            while (e.n) {
174                if (f) {
175                    if (e.f) {
176                        for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {
177                            e.f.splice(i, 1);
178                            break;
179                        }
180                        !e.f.length && delete e.f;
181                    }
182                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {
183                        var funcs = e.n[key].f;
184                        for (i = 0, ii = funcs.length; i < ii; i++) if (funcs[i] == f) {
185                            funcs.splice(i, 1);
186                            break;
187                        }
188                        !funcs.length && delete e.n[key].f;
189                    }
190                } else {
191                    delete e.f;
192                    for (key in e.n) if (e.n[has](key) && e.n[key].f) {
193                        delete e.n[key].f;
194                    }
195                }
196                e = e.n;
197            }
198        }
199    };
200    
201    eve.version = version;
202    eve.toString = function () {
203        return "You are running Eve " + version;
204    };
205    (typeof module != "undefined" && module.exports) ? (module.exports = eve) : (glob.eve = eve);
206})(this);
207
208// ┌─────────────────────────────────────────────────────────────────────┐ \\
209// │ "Raphaël 2.0" - JavaScript Vector Library                           │ \\
210// ├─────────────────────────────────────────────────────────────────────┤ \\
211// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\
212// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\
213// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
214// └─────────────────────────────────────────────────────────────────────┘ \\
215(function () {
216    
217    function R(first) {
218        if (R.is(first, "function")) {
219            return loaded ? first() : eve.on("DOMload", first);
220        } else if (R.is(first, array)) {
221            var a = first,
222                cnv = R._engine.create[apply](R, a.splice(0, 3 + R.is(a[0], nu))),
223                res = cnv.set(),
224                i = 0,
225                ii = a.length,
226                j;
227            for (; i < ii; i++) {
228                j = a[i] || {};
229                elements[has](j.type) && res.push(cnv[j.type]().attr(j));
230            }
231            return res;
232        } else {
233            var args = Array.prototype.slice.call(arguments, 0);
234            if (R.is(args[args.length - 1], "function")) {
235                var f = args.pop();
236                return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on("DOMload", function () {
vendor: 56,194 bytes, lines 237-1785
237                    f.call(R._engine.create[apply](R, args));
238                });
239            } else {
240                return R._engine.create[apply](R, arguments);
241            }
242        }
243    }
244    R.version = "2.0.0";
245    R.eve = eve;
246    var loaded,
247        separator = /[, ]+/,
248        elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},
249        formatrg = /\{(\d+)\}/g,
250        proto = "prototype",
251        has = "hasOwnProperty",
252        g = {
253            doc: document,
254            win: window
255        },
256        oldRaphael = {
257            was: Object.prototype[has].call(g.win, "Raphael"),
258            is: g.win.Raphael
259        },
260        Paper = function () {
261            
262            this.customAttributes = {};
263        },
264        paperproto,
265        appendChild = "appendChild",
266        apply = "apply",
267        concat = "concat",
268        supportsTouch = "createTouch" in g.doc,
269        E = "",
270        S = " ",
271        Str = String,
272        split = "split",
273        events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel".split(S),
274        touchMap = {
275            mousedown: "touchstart",
276            mousemove: "touchmove",
277            mouseup: "touchend"
278        },
279        lowerCase = Str.prototype.toLowerCase,
280        math = Math,
281        mmax = math.max,
282        mmin = math.min,
283        abs = math.abs,
284        pow = math.pow,
285        PI = math.PI,
286        nu = "number",
287        string = "string",
288        array = "array",
289        toString = "toString",
290        fillString = "fill",
291        objectToString = Object.prototype.toString,
292        paper = {},
293        push = "push",
294        ISURL = R._ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i,
295        colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,
296        isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1},
297        bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
298        round = math.round,
299        setAttribute = "setAttribute",
300        toFloat = parseFloat,
301        toInt = parseInt,
302        upperCase = Str.prototype.toUpperCase,
303        availableAttrs = R._availableAttrs = {
304            "arrow-end": "none",
305            "arrow-start": "none",
306            blur: 0,
307            "clip-rect": "0 0 1e9 1e9",
308            cursor: "default",
309            cx: 0,
310            cy: 0,
311            fill: "#fff",
312            "fill-opacity": 1,
313            font: '10px "Arial"',
314            "font-family": '"Arial"',
315            "font-size": "10",
316            "font-style": "normal",
317            "font-weight": 400,
318            gradient: 0,
319            height: 0,
320            href: "http://raphaeljs.com/",
321            opacity: 1,
322            path: "M0,0",
323            r: 0,
324            rx: 0,
325            ry: 0,
326            src: "",
327            stroke: "#000",
328            "stroke-dasharray": "",
329            "stroke-linecap": "butt",
330            "stroke-linejoin": "butt",
331            "stroke-miterlimit": 0,
332            "stroke-opacity": 1,
333            "stroke-width": 1,
334            target: "_blank",
335            "text-anchor": "middle",
336            title: "Raphael",
337            transform: "",
338            width: 0,
339            x: 0,
340            y: 0
341        },
342        availableAnimAttrs = R._availableAnimAttrs = {
343            blur: nu,
344            "clip-rect": "csv",
345            cx: nu,
346            cy: nu,
347            fill: "colour",
348            "fill-opacity": nu,
349            "font-size": nu,
350            height: nu,
351            opacity: nu,
352            path: "path",
353            r: nu,
354            rx: nu,
355            ry: nu,
356            stroke: "colour",
357            "stroke-opacity": nu,
358            "stroke-width": nu,
359            transform: "transform",
360            width: nu,
361            x: nu,
362            y: nu
363        },
364        commaSpaces = /\s*,\s*/,
365        hsrg = {hs: 1, rg: 1},
366        p2s = /,?([achlmqrstvxz]),?/gi,
367        pathCommand = /([achlmrqstvz])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?\s*,?\s*)+)/ig,
368        tCommand = /([rstm])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?\s*,?\s*)+)/ig,
369        pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)\s*,?\s*/ig,
370        radial_gradient = R._radial_gradient = /^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/,
371        eldata = {},
372        sortByKey = function (a, b) {
373            return a.key - b.key;
374        },
375        sortByNumber = function (a, b) {
376            return toFloat(a) - toFloat(b);
377        },
378        fun = function () {},
379        pipe = function (x) {
380            return x;
381        },
382        rectPath = R._rectPath = function (x, y, w, h, r) {
383            if (r) {
384                return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]];
385            }
386            return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]];
387        },
388        ellipsePath = function (x, y, rx, ry) {
389            if (ry == null) {
390                ry = rx;
391            }
392            return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]];
393        },
394        getPath = R._getPath = {
395            path: function (el) {
396                return el.attr("path");
397            },
398            circle: function (el) {
399                var a = el.attrs;
400                return ellipsePath(a.cx, a.cy, a.r);
401            },
402            ellipse: function (el) {
403                var a = el.attrs;
404                return ellipsePath(a.cx, a.cy, a.rx, a.ry);
405            },
406            rect: function (el) {
407                var a = el.attrs;
408                return rectPath(a.x, a.y, a.width, a.height, a.r);
409            },
410            image: function (el) {
411                var a = el.attrs;
412                return rectPath(a.x, a.y, a.width, a.height);
413            },
414            text: function (el) {
415                var bbox = el._getBBox();
416                return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
417            }
418        },
419        mapPath = R.mapPath = function (path, matrix) {
420            if (!matrix) {
421                return path;
422            }
423            var x, y, i, j, pathi;
424            path = path2curve(path);
425            for (i = 0, ii = path.length; i < ii; i++) {
426                pathi = path[i];
427                for (j = 1, jj = pathi.length; j < jj; j += 2) {
428                    x = matrix.x(pathi[j], pathi[j + 1]);
429                    y = matrix.y(pathi[j], pathi[j + 1]);
430                    pathi[j] = x;
431                    pathi[j + 1] = y;
432                }
433            }
434            return path;
435        };
436
437    R._g = g;
438    
439    R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML");
440    if (R.type == "VML") {
441        var d = g.doc.createElement("div"),
442            b;
443        d.innerHTML = '<v:shape adj="1"/>';
444        b = d.firstChild;
445        b.style.behavior = "url(#default#VML)";
446        if (!(b && typeof b.adj == "object")) {
447            return (R.type = E);
448        }
449        d = null;
450    }
451    
452    
453    R.svg = !(R.vml = R.type == "VML");
454    R._Paper = Paper;
455    
456    R.fn = paperproto = Paper.prototype = R.prototype;
457    R._id = 0;
458    R._oid = 0;
459    
460    R.is = function (o, type) {
461        type = lowerCase.call(type);
462        if (type == "finite") {
463            return !isnan[has](+o);
464        }
465        if (type == "array") {
466            return o instanceof Array;
467        }
468        return  (type == "null" && o === null) ||
469                (type == typeof o) ||
470                (type == "object" && o === Object(o)) ||
471                (type == "array" && Array.isArray && Array.isArray(o)) ||
472                objectToString.call(o).slice(8, -1).toLowerCase() == type;
473    };
474    
475    R.angle = function (x1, y1, x2, y2, x3, y3) {
476        if (x3 == null) {
477            var x = x1 - x2,
478                y = y1 - y2;
479            if (!x && !y) {
480                return 0;
481            }
482            return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;
483        } else {
484            return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);
485        }
486    };
487    
488    R.rad = function (deg) {
489        return deg % 360 * PI / 180;
490    };
491    
492    R.deg = function (rad) {
493        return rad * 180 / PI % 360;
494    };
495    
496    R.snapTo = function (values, value, tolerance) {
497        tolerance = R.is(tolerance, "finite") ? tolerance : 10;
498        if (R.is(values, array)) {
499            var i = values.length;
500            while (i--) if (abs(values[i] - value) <= tolerance) {
501                return values[i];
502            }
503        } else {
504            values = +values;
505            var rem = value % values;
506            if (rem < tolerance) {
507                return value - rem;
508            }
509            if (rem > values - tolerance) {
510                return value - rem + values;
511            }
512        }
513        return value;
514    };
515    
516    
517    var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) {
518        return function () {
519            return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase();
520        };
521    })(/[xy]/g, function (c) {
522        var r = math.random() * 16 | 0,
523            v = c == "x" ? r : (r & 3 | 8);
524        return v.toString(16);
525    });
526
527    
528    R.setWindow = function (newwin) {
529        eve("setWindow", R, g.win, newwin);
530        g.win = newwin;
531        g.doc = g.win.document;
532        if (initWin) {
533            initWin(g.win);
534        }
535    };
536    var toHex = function (color) {
537        if (R.vml) {
538            // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/
539            var trim = /^\s+|\s+$/g;
540            var bod;
541            try {
542                var docum = new ActiveXObject("htmlfile");
543                docum.write("<body>");
544                docum.close();
545                bod = docum.body;
546            } catch(e) {
547                bod = createPopup().document.body;
548            }
549            var range = bod.createTextRange();
550            toHex = cacher(function (color) {
551                try {
552                    bod.style.color = Str(color).replace(trim, E);
553                    var value = range.queryCommandValue("ForeColor");
554                    value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);
555                    return "#" + ("000000" + value.toString(16)).slice(-6);
556                } catch(e) {
557                    return "none";
558                }
559            });
560        } else {
561            var i = g.doc.createElement("i");
562            i.title = "Rapha\xebl Colour Picker";
563            i.style.display = "none";
564            g.doc.body.appendChild(i);
565            toHex = cacher(function (color) {
566                i.style.color = color;
567                return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color");
568            });
569        }
570        return toHex(color);
571    },
572    hsbtoString = function () {
573        return "hsb(" + [this.h, this.s, this.b] + ")";
574    },
575    hsltoString = function () {
576        return "hsl(" + [this.h, this.s, this.l] + ")";
577    },
578    rgbtoString = function () {
579        return this.hex;
580    },
581    prepareRGB = function (r, g, b) {
582        if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) {
583            b = r.b;
584            g = r.g;
585            r = r.r;
586        }
587        if (g == null && R.is(r, string)) {
588            var clr = R.getRGB(r);
589            r = clr.r;
590            g = clr.g;
591            b = clr.b;
592        }
593        if (r > 1 || g > 1 || b > 1) {
594            r /= 255;
595            g /= 255;
596            b /= 255;
597        }
598        
599        return [r, g, b];
600    },
601    packageRGB = function (r, g, b, o) {
602        r *= 255;
603        g *= 255;
604        b *= 255;
605        var rgb = {
606            r: r,
607            g: g,
608            b: b,
609            hex: R.rgb(r, g, b),
610            toString: rgbtoString
611        };
612        R.is(o, "finite") && (rgb.opacity = o);
613        return rgb;
614    };
615    
616    
617    R.color = function (clr) {
618        var rgb;
619        if (R.is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) {
620            rgb = R.hsb2rgb(clr);
621            clr.r = rgb.r;
622            clr.g = rgb.g;
623            clr.b = rgb.b;
624            clr.hex = rgb.hex;
625        } else if (R.is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) {
626            rgb = R.hsl2rgb(clr);
627            clr.r = rgb.r;
628            clr.g = rgb.g;
629            clr.b = rgb.b;
630            clr.hex = rgb.hex;
631        } else {
632            if (R.is(clr, "string")) {
633                clr = R.getRGB(clr);
634            }
635            if (R.is(clr, "object") && "r" in clr && "g" in clr && "b" in clr) {
636                rgb = R.rgb2hsl(clr);
637                clr.h = rgb.h;
638                clr.s = rgb.s;
639                clr.l = rgb.l;
640                rgb = R.rgb2hsb(clr);
641                clr.v = rgb.b;
642            } else {
643                clr = {hex: "none"};
644                crl.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;
645            }
646        }
647        clr.toString = rgbtoString;
648        return clr;
649    };
650    
651    R.hsb2rgb = function (h, s, v, o) {
652        if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) {
653            v = h.b;
654            s = h.s;
655            h = h.h;
656            o = h.o;
657        }
658        h *= 360;
659        var R, G, B, X, C;
660        h = (h % 360) / 60;
661        C = v * s;
662        X = C * (1 - abs(h % 2 - 1));
663        R = G = B = v - C;
664
665        h = ~~h;
666        R += [C, X, 0, 0, X, C][h];
667        G += [X, C, C, X, 0, 0][h];
668        B += [0, 0, X, C, C, X][h];
669        return packageRGB(R, G, B, o);
670    };
671    
672    R.hsl2rgb = function (h, s, l, o) {
673        if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) {
674            l = h.l;
675            s = h.s;
676            h = h.h;
677        }
678        if (h > 1 || s > 1 || l > 1) {
679            h /= 360;
680            s /= 100;
681            l /= 100;
682        }
683        h *= 360;
684        var R, G, B, X, C;
685        h = (h % 360) / 60;
686        C = 2 * s * (l < .5 ? l : 1 - l);
687        X = C * (1 - abs(h % 2 - 1));
688        R = G = B = l - C / 2;
689
690        h = ~~h;
691        R += [C, X, 0, 0, X, C][h];
692        G += [X, C, C, X, 0, 0][h];
693        B += [0, 0, X, C, C, X][h];
694        return packageRGB(R, G, B, o);
695    };
696    
697    R.rgb2hsb = function (r, g, b) {
698        b = prepareRGB(r, g, b);
699        r = b[0];
700        g = b[1];
701        b = b[2];
702
703        var H, S, V, C;
704        V = mmax(r, g, b);
705        C = V - mmin(r, g, b);
706        H = (C == 0 ? null :
707             V == r ? (g - b) / C :
708             V == g ? (b - r) / C + 2 :
709                      (r - g) / C + 4
710            );
711        H = ((H + 360) % 6) * 60 / 360;
712        S = C == 0 ? 0 : C / V;
713        return {h: H, s: S, b: V, toString: hsbtoString};
714    };
715    
716    R.rgb2hsl = function (r, g, b) {
717        b = prepareRGB(r, g, b);
718        r = b[0];
719        g = b[1];
720        b = b[2];
721
722        var H, S, L, M, m, C;
723        M = mmax(r, g, b);
724        m = mmin(r, g, b);
725        C = M - m;
726        H = (C == 0 ? null :
727             M == r ? (g - b) / C :
728             M == g ? (b - r) / C + 2 :
729                      (r - g) / C + 4);
730        H = ((H + 360) % 6) * 60 / 360;
731        L = (M + m) / 2;
732        S = (C == 0 ? 0 :
733             L < .5 ? C / (2 * L) :
734                      C / (2 - 2 * L));
735        return {h: H, s: S, l: L, toString: hsltoString};
736    };
737    R._path2string = function () {
738        return this.join(",").replace(p2s, "$1");
739    };
740    function repush(array, item) {
741        for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {
742            return array.push(array.splice(i, 1)[0]);
743        }
744    }
745    function cacher(f, scope, postprocessor) {
746        function newf() {
747            var arg = Array.prototype.slice.call(arguments, 0),
748                args = arg.join("\u2400"),
749                cache = newf.cache = newf.cache || {},
750                count = newf.count = newf.count || [];
751            if (cache[has](args)) {
752                repush(count, args);
753                return postprocessor ? postprocessor(cache[args]) : cache[args];
754            }
755            count.length >= 1e3 && delete cache[count.shift()];
756            count.push(args);
757            cache[args] = f[apply](scope, arg);
758            return postprocessor ? postprocessor(cache[args]) : cache[args];
759        }
760        return newf;
761    }
762
763    var preload = R._preload = function (src, f) {
764        var img = g.doc.createElement("img");
765        img.style.cssText = "position:absolute;left:-9999em;top-9999em";
766        img.onload = function () {
767            f.call(this);
768            this.onload = null;
769            g.doc.body.removeChild(this);
770        };
771        img.onerror = function () {
772            g.doc.body.removeChild(this);
773        };
774        g.doc.body.appendChild(img);
775        img.src = src;
776    };
777    
778    function clrToString() {
779        return this.hex;
780    }
781
782    
783    R.getRGB = cacher(function (colour) {
784        if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) {
785            return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
786        }
787        if (colour == "none") {
788            return {r: -1, g: -1, b: -1, hex: "none", toString: clrToString};
789        }
790        !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour));
791        var res,
792            red,
793            green,
794            blue,
795            opacity,
796            t,
797            values,
798            rgb = colour.match(colourRegExp);
799        if (rgb) {
800            if (rgb[2]) {
801                blue = toInt(rgb[2].substring(5), 16);
802                green = toInt(rgb[2].substring(3, 5), 16);
803                red = toInt(rgb[2].substring(1, 3), 16);
804            }
805            if (rgb[3]) {
806                blue = toInt((t = rgb[3].charAt(3)) + t, 16);
807                green = toInt((t = rgb[3].charAt(2)) + t, 16);
808                red = toInt((t = rgb[3].charAt(1)) + t, 16);
809            }
810            if (rgb[4]) {
811                values = rgb[4].split(commaSpaces);
812                red = toFloat(values[0]);
813                values[0].slice(-1) == "%" && (red *= 2.55);
814                green = toFloat(values[1]);
815                values[1].slice(-1) == "%" && (green *= 2.55);
816                blue = toFloat(values[2]);
817                values[2].slice(-1) == "%" && (blue *= 2.55);
818                rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3]));
819                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
820            }
821            if (rgb[5]) {
822                values = rgb[5].split(commaSpaces);
823                red = toFloat(values[0]);
824                values[0].slice(-1) == "%" && (red *= 2.55);
825                green = toFloat(values[1]);
826                values[1].slice(-1) == "%" && (green *= 2.55);
827                blue = toFloat(values[2]);
828                values[2].slice(-1) == "%" && (blue *= 2.55);
829                (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
830                rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3]));
831                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
832                return R.hsb2rgb(red, green, blue, opacity);
833            }
834            if (rgb[6]) {
835                values = rgb[6].split(commaSpaces);
836                red = toFloat(values[0]);
837                values[0].slice(-1) == "%" && (red *= 2.55);
838                green = toFloat(values[1]);
839                values[1].slice(-1) == "%" && (green *= 2.55);
840                blue = toFloat(values[2]);
841                values[2].slice(-1) == "%" && (blue *= 2.55);
842                (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
843                rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3]));
844                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
845                return R.hsl2rgb(red, green, blue, opacity);
846            }
847            rgb = {r: red, g: green, b: blue, toString: clrToString};
848            rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);
849            R.is(opacity, "finite") && (rgb.opacity = opacity);
850            return rgb;
851        }
852        return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
853    }, R);
854    
855    R.hsb = cacher(function (h, s, b) {
856        return R.hsb2rgb(h, s, b).hex;
857    });
858    
859    R.hsl = cacher(function (h, s, l) {
860        return R.hsl2rgb(h, s, l).hex;
861    });
862    
863    R.rgb = cacher(function (r, g, b) {
864        return "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1);
865    });
866    
867    R.getColor = function (value) {
868        var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},
869            rgb = this.hsb2rgb(start.h, start.s, start.b);
870        start.h += .075;
871        if (start.h > 1) {
872            start.h = 0;
873            start.s -= .2;
874            start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});
875        }
876        return rgb.hex;
877    };
878    
879    R.getColor.reset = function () {
880        delete this.start;
881    };
882
883    // http://schepers.cc/getting-to-the-point
884    function catmullRom2bezier(crp) {
885        var d = [];
886        for (var i = 0, iLen = crp.length; iLen - 2 > i; i += 2) {
887            var p = [{x: +crp[i],     y: +crp[i + 1]},
888                     {x: +crp[i],     y: +crp[i + 1]},
889                     {x: +crp[i + 2], y: +crp[i + 3]},
890                     {x: +crp[i + 4], y: +crp[i + 5]}];
891            if (iLen - 4 == i) {
892                p[0] = {x: +crp[i - 2], y: +crp[i - 1]};
893                p[3] = p[2];
894            } else if (i) {
895                p[0] = {x: +crp[i - 2], y: +crp[i - 1]};
896            }
897            d.push(["C",
898                (-p[0].x + 6 * p[1].x + p[2].x) / 6,
899                (-p[0].y + 6 * p[1].y + p[2].y) / 6,
900                (p[1].x + 6 * p[2].x - p[3].x) / 6,
901                (p[1].y + 6*p[2].y - p[3].y) / 6,
902                p[2].x,
903                p[2].y
904            ]);
905        }
906
907        return d;
908    }
909    
910    R.parsePathString = cacher(function (pathString) {
911        if (!pathString) {
912            return null;
913        }
914        var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0},
915            data = [];
916        if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption
917            data = pathClone(pathString);
918        }
919        if (!data.length) {
920            Str(pathString).replace(pathCommand, function (a, b, c) {
921                var params = [],
922                    name = b.toLowerCase();
923                c.replace(pathValues, function (a, b) {
924                    b && params.push(+b);
925                });
926                if (name == "m" && params.length > 2) {
927                    data.push([b][concat](params.splice(0, 2)));
928                    name = "l";
929                    b = b == "m" ? "l" : "L";
930                }
931                if (name == "r") {
932                    data.push([b][concat](params));
933                } else while (params.length >= paramCounts[name]) {
934                    data.push([b][concat](params.splice(0, paramCounts[name])));
935                    if (!paramCounts[name]) {
936                        break;
937                    }
938                }
939            });
940        }
941        data.toString = R._path2string;
942        return data;
943    });
944    
945    R.parseTransformString = cacher(function (TString) {
946        if (!TString) {
947            return null;
948        }
949        var paramCounts = {r: 3, s: 4, t: 2, m: 6},
950            data = [];
951        if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption
952            data = pathClone(TString);
953        }
954        if (!data.length) {
955            Str(TString).replace(tCommand, function (a, b, c) {
956                var params = [],
957                    name = lowerCase.call(b);
958                c.replace(pathValues, function (a, b) {
959                    b && params.push(+b);
960                });
961                data.push([name][concat](params));
962            });
963        }
964        data.toString = R._path2string;
965        return data;
966    });
967    
968    R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
969        var t1 = 1 - t,
970            t13 = pow(t1, 3),
971            t12 = pow(t1, 2),
972            t2 = t * t,
973            t3 = t2 * t,
974            x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
975            y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,
976            mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),
977            my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),
978            nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),
979            ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),
980            ax = t1 * p1x + t * c1x,
981            ay = t1 * p1y + t * c1y,
982            cx = t1 * c2x + t * p2x,
983            cy = t1 * c2y + t * p2y,
984            alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);
985        (mx > nx || my < ny) && (alpha += 180);
986        return {
987            x: x,
988            y: y,
989            m: {x: mx, y: my},
990            n: {x: nx, y: ny},
991            start: {x: ax, y: ay},
992            end: {x: cx, y: cy},
993            alpha: alpha
994        };
995    };
996    var pathDimensions = cacher(function (path) {
997        if (!path) {
998            return {x: 0, y: 0, width: 0, height: 0};
999        }
1000        path = path2curve(path);
1001        var x = 0, 
1002            y = 0,
1003            X = [],
1004            Y = [],
1005            p;
1006        for (var i = 0, ii = path.length; i < ii; i++) {
1007            p = path[i];
1008            if (p[0] == "M") {
1009                x = p[1];
1010                y = p[2];
1011                X.push(x);
1012                Y.push(y);
1013            } else {
1014                var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
1015                X = X[concat](dim.min.x, dim.max.x);
1016                Y = Y[concat](dim.min.y, dim.max.y);
1017                x = p[5];
1018                y = p[6];
1019            }
1020        }
1021        var xmin = mmin[apply](0, X),
1022            ymin = mmin[apply](0, Y);
1023        return {
1024            x: xmin,
1025            y: ymin,
1026            width: mmax[apply](0, X) - xmin,
1027            height: mmax[apply](0, Y) - ymin
1028        };
1029    }, null, function (o) {
1030        return {
1031            x: o.x,
1032            y: o.y,
1033            width: o.width,
1034            height: o.height
1035        };
1036    }),
1037        pathClone = function (pathArray) {
1038            var res = [];
1039            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
1040                pathArray = R.parsePathString(pathArray);
1041            }
1042            for (var i = 0, ii = pathArray.length; i < ii; i++) {
1043                res[i] = [];
1044                for (var j = 0, jj = pathArray[i].length; j < jj; j++) {
1045                    res[i][j] = pathArray[i][j];
1046                }
1047            }
1048            res.toString = R._path2string;
1049            return res;
1050        },
1051        pathToRelative = R._pathToRelative = cacher(function (pathArray) {
1052            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
1053                pathArray = R.parsePathString(pathArray);
1054            }
1055            var res = [],
1056                x = 0,
1057                y = 0,
1058                mx = 0,
1059                my = 0,
1060                start = 0;
1061            if (pathArray[0][0] == "M") {
1062                x = pathArray[0][1];
1063                y = pathArray[0][2];
1064                mx = x;
1065                my = y;
1066                start++;
1067                res.push(["M", x, y]);
1068            }
1069            for (var i = start, ii = pathArray.length; i < ii; i++) {
1070                var r = res[i] = [],
1071                    pa = pathArray[i];
1072                if (pa[0] != lowerCase.call(pa[0])) {
1073                    r[0] = lowerCase.call(pa[0]);
1074                    switch (r[0]) {
1075                        case "a":
1076                            r[1] = pa[1];
1077                            r[2] = pa[2];
1078                            r[3] = pa[3];
1079                            r[4] = pa[4];
1080                            r[5] = pa[5];
1081                            r[6] = +(pa[6] - x).toFixed(3);
1082                            r[7] = +(pa[7] - y).toFixed(3);
1083                            break;
1084                        case "v":
1085                            r[1] = +(pa[1] - y).toFixed(3);
1086                            break;
1087                        case "m":
1088                            mx = pa[1];
1089                            my = pa[2];
1090                        default:
1091                            for (var j = 1, jj = pa.length; j < jj; j++) {
1092                                r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
1093                            }
1094                    }
1095                } else {
1096                    r = res[i] = [];
1097                    if (pa[0] == "m") {
1098                        mx = pa[1] + x;
1099                        my = pa[2] + y;
1100                    }
1101                    for (var k = 0, kk = pa.length; k < kk; k++) {
1102                        res[i][k] = pa[k];
1103                    }
1104                }
1105                var len = res[i].length;
1106                switch (res[i][0]) {
1107                    case "z":
1108                        x = mx;
1109                        y = my;
1110                        break;
1111                    case "h":
1112                        x += +res[i][len - 1];
1113                        break;
1114                    case "v":
1115                        y += +res[i][len - 1];
1116                        break;
1117                    default:
1118                        x += +res[i][len - 2];
1119                        y += +res[i][len - 1];
1120                }
1121            }
1122            res.toString = R._path2string;
1123            return res;
1124        }, 0, pathClone),
1125        pathToAbsolute = R._pathToAbsolute = cacher(function (pathArray) {
1126            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
1127                pathArray = R.parsePathString(pathArray);
1128            }
1129            if (!pathArray || !pathArray.length) {
1130                return [["M", 0, 0]];
1131            }
1132            var res = [],
1133                x = 0,
1134                y = 0,
1135                mx = 0,
1136                my = 0,
1137                start = 0;
1138            if (pathArray[0][0] == "M") {
1139                x = +pathArray[0][1];
1140                y = +pathArray[0][2];
1141                mx = x;
1142                my = y;
1143                start++;
1144                res[0] = ["M", x, y];
1145            }
1146            for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
1147                res.push(r = []);
1148                pa = pathArray[i];
1149                if (pa[0] != upperCase.call(pa[0])) {
1150                    r[0] = upperCase.call(pa[0]);
1151                    switch (r[0]) {
1152                        case "A":
1153                            r[1] = pa[1];
1154                            r[2] = pa[2];
1155                            r[3] = pa[3];
1156                            r[4] = pa[4];
1157                            r[5] = pa[5];
1158                            r[6] = +(pa[6] + x);
1159                            r[7] = +(pa[7] + y);
1160                            break;
1161                        case "V":
1162                            r[1] = +pa[1] + y;
1163                            break;
1164                        case "H":
1165                            r[1] = +pa[1] + x;
1166                            break;
1167                        case "R":
1168                            var dots = [x, y][concat](pa.slice(1));
1169                            for (var j = 2, jj = dots.length; j < jj; j++) {
1170                                dots[j] = +dots[j] + x;
1171                                dots[++j] = +dots[j] + y;
1172                            }
1173                            res.pop();
1174                            res = res[concat](catmullRom2bezier(dots));
1175                            break;
1176                        case "M":
1177                            mx = +pa[1] + x;
1178                            my = +pa[2] + y;
1179                        default:
1180                            for (j = 1, jj = pa.length; j < jj; j++) {
1181                                r[j] = +pa[j] + ((j % 2) ? x : y);
1182                            }
1183                    }
1184                } else if (pa[0] == "R") {
1185                    dots = [x, y][concat](pa.slice(1));
1186                    res.pop();
1187                    res = res[concat](catmullRom2bezier(dots));
1188                    r = ["R"][concat](pa.slice(-2));
1189                } else {
1190                    for (var k = 0, kk = pa.length; k < kk; k++) {
1191                        r[k] = pa[k];
1192                    }
1193                }
1194                switch (r[0]) {
1195                    case "Z":
1196                        x = mx;
1197                        y = my;
1198                        break;
1199                    case "H":
1200                        x = r[1];
1201                        break;
1202                    case "V":
1203                        y = r[1];
1204                        break;
1205                    case "M":
1206                        mx = r[r.length - 2];
1207                        my = r[r.length - 1];
1208                    default:
1209                        x = r[r.length - 2];
1210                        y = r[r.length - 1];
1211                }
1212            }
1213            res.toString = R._path2string;
1214            return res;
1215        }, null, pathClone),
1216        l2c = function (x1, y1, x2, y2) {
1217            return [x1, y1, x2, y2, x2, y2];
1218        },
1219        q2c = function (x1, y1, ax, ay, x2, y2) {
1220            var _13 = 1 / 3,
1221                _23 = 2 / 3;
1222            return [
1223                    _13 * x1 + _23 * ax,
1224                    _13 * y1 + _23 * ay,
1225                    _13 * x2 + _23 * ax,
1226                    _13 * y2 + _23 * ay,
1227                    x2,
1228                    y2
1229                ];
1230        },
1231        a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
1232            // for more information of where this math came from visit:
1233            // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
1234            var _120 = PI * 120 / 180,
1235                rad = PI / 180 * (+angle || 0),
1236                res = [],
1237                xy,
1238                rotate = cacher(function (x, y, rad) {
1239                    var X = x * math.cos(rad) - y * math.sin(rad),
1240                        Y = x * math.sin(rad) + y * math.cos(rad);
1241                    return {x: X, y: Y};
1242                });
1243            if (!recursive) {
1244                xy = rotate(x1, y1, -rad);
1245                x1 = xy.x;
1246                y1 = xy.y;
1247                xy = rotate(x2, y2, -rad);
1248                x2 = xy.x;
1249                y2 = xy.y;
1250                var cos = math.cos(PI / 180 * angle),
1251                    sin = math.sin(PI / 180 * angle),
1252                    x = (x1 - x2) / 2,
1253                    y = (y1 - y2) / 2;
1254                var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
1255                if (h > 1) {
1256                    h = math.sqrt(h);
1257                    rx = h * rx;
1258                    ry = h * ry;
1259                }
1260                var rx2 = rx * rx,
1261                    ry2 = ry * ry,
1262                    k = (large_arc_flag == sweep_flag ? -1 : 1) *
1263                        math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
1264                    cx = k * rx * y / ry + (x1 + x2) / 2,
1265                    cy = k * -ry * x / rx + (y1 + y2) / 2,
1266                    f1 = math.asin(((y1 - cy) / ry).toFixed(9)),
1267                    f2 = math.asin(((y2 - cy) / ry).toFixed(9));
1268
1269                f1 = x1 < cx ? PI - f1 : f1;
1270                f2 = x2 < cx ? PI - f2 : f2;
1271                f1 < 0 && (f1 = PI * 2 + f1);
1272                f2 < 0 && (f2 = PI * 2 + f2);
1273                if (sweep_flag && f1 > f2) {
1274                    f1 = f1 - PI * 2;
1275                }
1276                if (!sweep_flag && f2 > f1) {
1277                    f2 = f2 - PI * 2;
1278                }
1279            } else {
1280                f1 = recursive[0];
1281                f2 = recursive[1];
1282                cx = recursive[2];
1283                cy = recursive[3];
1284            }
1285            var df = f2 - f1;
1286            if (abs(df) > _120) {
1287                var f2old = f2,
1288                    x2old = x2,
1289                    y2old = y2;
1290                f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
1291                x2 = cx + rx * math.cos(f2);
1292                y2 = cy + ry * math.sin(f2);
1293                res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
1294            }
1295            df = f2 - f1;
1296            var c1 = math.cos(f1),
1297                s1 = math.sin(f1),
1298                c2 = math.cos(f2),
1299                s2 = math.sin(f2),
1300                t = math.tan(df / 4),
1301                hx = 4 / 3 * rx * t,
1302                hy = 4 / 3 * ry * t,
1303                m1 = [x1, y1],
1304                m2 = [x1 + hx * s1, y1 - hy * c1],
1305                m3 = [x2 + hx * s2, y2 - hy * c2],
1306                m4 = [x2, y2];
1307            m2[0] = 2 * m1[0] - m2[0];
1308            m2[1] = 2 * m1[1] - m2[1];
1309            if (recursive) {
1310                return [m2, m3, m4][concat](res);
1311            } else {
1312                res = [m2, m3, m4][concat](res).join().split(",");
1313                var newres = [];
1314                for (var i = 0, ii = res.length; i < ii; i++) {
1315                    newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
1316                }
1317                return newres;
1318            }
1319        },
1320        findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
1321            var t1 = 1 - t;
1322            return {
1323                x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,
1324                y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y
1325            };
1326        },
1327        curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
1328            var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
1329                b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
1330                c = p1x - c1x,
1331                t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,
1332                t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,
1333                y = [p1y, p2y],
1334                x = [p1x, p2x],
1335                dot;
1336            abs(t1) > "1e12" && (t1 = .5);
1337            abs(t2) > "1e12" && (t2 = .5);
1338            if (t1 > 0 && t1 < 1) {
1339                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
1340                x.push(dot.x);
1341                y.push(dot.y);
1342            }
1343            if (t2 > 0 && t2 < 1) {
1344                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
1345                x.push(dot.x);
1346                y.push(dot.y);
1347            }
1348            a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
1349            b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
1350            c = p1y - c1y;
1351            t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;
1352            t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;
1353            abs(t1) > "1e12" && (t1 = .5);
1354            abs(t2) > "1e12" && (t2 = .5);
1355            if (t1 > 0 && t1 < 1) {
1356                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
1357                x.push(dot.x);
1358                y.push(dot.y);
1359            }
1360            if (t2 > 0 && t2 < 1) {
1361                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
1362                x.push(dot.x);
1363                y.push(dot.y);
1364            }
1365            return {
1366                min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},
1367                max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}
1368            };
1369        }),
1370        path2curve = R._path2curve = cacher(function (path, path2) {
1371            var p = pathToAbsolute(path),
1372                p2 = path2 && pathToAbsolute(path2),
1373                attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
1374                attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
1375                processPath = function (path, d) {
1376                    var nx, ny;
1377                    if (!path) {
1378                        return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
1379                    }
1380                    !(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null);
1381                    switch (path[0]) {
1382                        case "M":
1383                            d.X = path[1];
1384                            d.Y = path[2];
1385                            break;
1386                        case "A":
1387                            path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));
1388                            break;
1389                        case "S":
1390                            nx = d.x + (d.x - (d.bx || d.x));
1391                            ny = d.y + (d.y - (d.by || d.y));
1392                            path = ["C", nx, ny][concat](path.slice(1));
1393                            break;
1394                        case "T":
1395                            d.qx = d.x + (d.x - (d.qx || d.x));
1396                            d.qy = d.y + (d.y - (d.qy || d.y));
1397                            path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
1398                            break;
1399                        case "Q":
1400                            d.qx = path[1];
1401                            d.qy = path[2];
1402                            path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));
1403                            break;
1404                        case "L":
1405                            path = ["C"][concat](l2c(d.x, d.y, path[1], path[2]));
1406                            break;
1407                        case "H":
1408                            path = ["C"][concat](l2c(d.x, d.y, path[1], d.y));
1409                            break;
1410                        case "V":
1411                            path = ["C"][concat](l2c(d.x, d.y, d.x, path[1]));
1412                            break;
1413                        case "Z":
1414                            path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y));
1415                            break;
1416                    }
1417                    return path;
1418                },
1419                fixArc = function (pp, i) {
1420                    if (pp[i].length > 7) {
1421                        pp[i].shift();
1422                        var pi = pp[i];
1423                        while (pi.length) {
1424                            pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6)));
1425                        }
1426                        pp.splice(i, 1);
1427                        ii = mmax(p.length, p2 && p2.length || 0);
1428                    }
1429                },
1430                fixM = function (path1, path2, a1, a2, i) {
1431                    if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
1432                        path2.splice(i, 0, ["M", a2.x, a2.y]);
1433                        a1.bx = 0;
1434                        a1.by = 0;
1435                        a1.x = path1[i][1];
1436                        a1.y = path1[i][2];
1437                        ii = mmax(p.length, p2 && p2.length || 0);
1438                    }
1439                };
1440            for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) {
1441                p[i] = processPath(p[i], attrs);
1442                fixArc(p, i);
1443                p2 && (p2[i] = processPath(p2[i], attrs2));
1444                p2 && fixArc(p2, i);
1445                fixM(p, p2, attrs, attrs2, i);
1446                fixM(p2, p, attrs2, attrs, i);
1447                var seg = p[i],
1448                    seg2 = p2 && p2[i],
1449                    seglen = seg.length,
1450                    seg2len = p2 && seg2.length;
1451                attrs.x = seg[seglen - 2];
1452                attrs.y = seg[seglen - 1];
1453                attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;
1454                attrs.by = toFloat(seg[seglen - 3]) || attrs.y;
1455                attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);
1456                attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);
1457                attrs2.x = p2 && seg2[seg2len - 2];
1458                attrs2.y = p2 && seg2[seg2len - 1];
1459            }
1460            return p2 ? [p, p2] : p;
1461        }, null, pathClone),
1462        parseDots = R._parseDots = cacher(function (gradient) {
1463            var dots = [];
1464            for (var i = 0, ii = gradient.length; i < ii; i++) {
1465                var dot = {},
1466                    par = gradient[i].match(/^([^:]*):?([\d\.]*)/);
1467                dot.color = R.getRGB(par[1]);
1468                if (dot.color.error) {
1469                    return null;
1470                }
1471                dot.color = dot.color.hex;
1472                par[2] && (dot.offset = par[2] + "%");
1473                dots.push(dot);
1474            }
1475            for (i = 1, ii = dots.length - 1; i < ii; i++) {
1476                if (!dots[i].offset) {
1477                    var start = toFloat(dots[i - 1].offset || 0),
1478                        end = 0;
1479                    for (var j = i + 1; j < ii; j++) {
1480                        if (dots[j].offset) {
1481                            end = dots[j].offset;
1482                            break;
1483                        }
1484                    }
1485                    if (!end) {
1486                        end = 100;
1487                        j = ii;
1488                    }
1489                    end = toFloat(end);
1490                    var d = (end - start) / (j - i + 1);
1491                    for (; i < j; i++) {
1492                        start += d;
1493                        dots[i].offset = start + "%";
1494                    }
1495                }
1496            }
1497            return dots;
1498        }),
1499        tear = R._tear = function (el, paper) {
1500            el == paper.top && (paper.top = el.prev);
1501            el == paper.bottom && (paper.bottom = el.next);
1502            el.next && (el.next.prev = el.prev);
1503            el.prev && (el.prev.next = el.next);
1504        },
1505        tofront = R._tofront = function (el, paper) {
1506            if (paper.top === el) {
1507                return;
1508            }
1509            tear(el, paper);
1510            el.next = null;
1511            el.prev = paper.top;
1512            paper.top.next = el;
1513            paper.top = el;
1514        },
1515        toback = R._toback = function (el, paper) {
1516            if (paper.bottom === el) {
1517                return;
1518            }
1519            tear(el, paper);
1520            el.next = paper.bottom;
1521            el.prev = null;
1522            paper.bottom.prev = el;
1523            paper.bottom = el;
1524        },
1525        insertafter = R._insertafter = function (el, el2, paper) {
1526            tear(el, paper);
1527            el2 == paper.top && (paper.top = el);
1528            el2.next && (el2.next.prev = el);
1529            el.next = el2.next;
1530            el.prev = el2;
1531            el2.next = el;
1532        },
1533        insertbefore = R._insertbefore = function (el, el2, paper) {
1534            tear(el, paper);
1535            el2 == paper.bottom && (paper.bottom = el);
1536            el2.prev && (el2.prev.next = el);
1537            el.prev = el2.prev;
1538            el2.prev = el;
1539            el.next = el2;
1540        },
1541        removed = function (methodname) {
1542            return function () {
1543                throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object");
1544            };
1545        },
1546        extractTransform = R._extractTransform = function (el, tstr) {
1547            if (tstr == null) {
1548                return el._.transform;
1549            }
1550            tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E);
1551            var tdata = R.parseTransformString(tstr),
1552                deg = 0,
1553                dx = 0,
1554                dy = 0,
1555                sx = 1,
1556                sy = 1,
1557                _ = el._,
1558                m = new Matrix;
1559            _.transform = tdata || [];
1560            if (tdata) {
1561                for (var i = 0, ii = tdata.length; i < ii; i++) {
1562                    var t = tdata[i],
1563                        tlen = t.length,
1564                        bb;
1565                    t[0] = Str(t[0]).toLowerCase();
1566                    if (t[0] == "t" && tlen == 3) {
1567                        m.translate(t[1], t[2]);
1568                    } else if (t[0] == "r") {
1569                        if (tlen == 2) {
1570                            bb = bb || el.getBBox(1);
1571                            m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);
1572                            deg += t[1];
1573                        } else if (tlen == 4) {
1574                            m.rotate(t[1], t[2], t[3]);
1575                            deg += t[1];
1576                        }
1577                    } else if (t[0] == "s") {
1578                        if (tlen == 2 || tlen == 3) {
1579                            bb = bb || el.getBBox(1);
1580                            m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);
1581                            sx *= t[1];
1582                            sy *= t[tlen - 1];
1583                        } else if (tlen == 5) {
1584                            m.scale(t[1], t[2], t[3], t[4]);
1585                            sx *= t[1];
1586                            sy *= t[2];
1587                        }
1588                    } else if (t[0] == "m" && tlen == 7) {
1589                        m.add(t[1], t[2], t[3], t[4], t[5], t[6]);
1590                    }
1591                    _.dirtyT = 1;
1592                    el.matrix = m;
1593                }
1594            }
1595
1596            el.matrix = m;
1597
1598            _.sx = sx;
1599            _.sy = sy;
1600            _.deg = deg;
1601            _.dx = dx = m.e;
1602            _.dy = dy = m.f;
1603
1604            if (sx == 1 && sy == 1 && !deg && _.bbox) {
1605                _.bbox.x += +dx;
1606                _.bbox.y += +dy;
1607            } else {
1608                _.dirtyT = 1;
1609            }
1610        },
1611        getEmpty = function (item) {
1612            switch (item[0]) {
1613                case "t": return ["t", 0, 0];
1614                case "m": return ["m", 1, 0, 0, 1, 0, 0];
1615                case "r": if (item.length == 4) {
1616                    return ["r", 0, item[2], item[3]];
1617                } else {
1618                    return ["r", 0];
1619                }
1620                case "s": if (item.length == 5) {
1621                    return ["s", 1, 1, item[3], item[4]];
1622                } else if (item.length == 3) {
1623                    return ["s", 1, 1];
1624                } else {
1625                    return ["s", 1];
1626                }
1627            }
1628        },
1629        equaliseTransform = R._equaliseTransform = function (t1, t2) {
1630            t2 = Str(t2).replace(/\.{3}|\u2026/g, t1);
1631            t1 = R.parseTransformString(t1) || [];
1632            t2 = R.parseTransformString(t2) || [];
1633            var maxlength = mmax(t1.length, t2.length),
1634                from = [],
1635                to = [],
1636                i = 0, j, jj,
1637                tt1, tt2;
1638            for (; i < maxlength; i++) {
1639                tt1 = t1[i] || getEmpty(t2[i]);
1640                tt2 = t2[i] || getEmpty(tt1);
1641                if ((tt1[0] != tt2[0]) ||
1642                    (tt1[0] == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
1643                    (tt1[0] == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
1644                    ) {
1645                    return;
1646                }
1647                from[i] = [];
1648                to[i] = [];
1649                for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) {
1650                    j in tt1 && (from[i][j] = tt1[j]);
1651                    j in tt2 && (to[i][j] = tt2[j]);
1652                }
1653            }
1654            return {
1655                from: from,
1656                to: to
1657            };
1658        };
1659    R._getContainer = function (x, y, w, h) {
1660        var container;
1661        container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x;
1662        if (container == null) {
1663            return;
1664        }
1665        if (container.tagName) {
1666            if (y == null) {
1667                return {
1668                    container: container,
1669                    width: container.style.pixelWidth || container.offsetWidth,
1670                    height: container.style.pixelHeight || container.offsetHeight
1671                };
1672            } else {
1673                return {
1674                    container: container,
1675                    width: y,
1676                    height: w
1677                };
1678            }
1679        }
1680        return {
1681            container: 1,
1682            x: x,
1683            y: y,
1684            width: w,
1685            height: h
1686        };
1687    };
1688    
1689    R.pathToRelative = pathToRelative;
1690    R._engine = {};
1691    
1692    R.path2curve = path2curve;
1693    
1694    R.matrix = function (a, b, c, d, e, f) {
1695        return new Matrix(a, b, c, d, e, f);
1696    };
1697    function Matrix(a, b, c, d, e, f) {
1698        if (a != null) {
1699            this.a = +a;
1700            this.b = +b;
1701            this.c = +c;
1702            this.d = +d;
1703            this.e = +e;
1704            this.f = +f;
1705        } else {
1706            this.a = 1;
1707            this.b = 0;
1708            this.c = 0;
1709            this.d = 1;
1710            this.e = 0;
1711            this.f = 0;
1712        }
1713    }
1714    (function (matrixproto) {
1715        
1716        matrixproto.add = function (a, b, c, d, e, f) {
1717            var out = [[], [], []],
1718                m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],
1719                matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
1720                x, y, z, res;
1721
1722            if (a && a instanceof Matrix) {
1723                matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];
1724            }
1725
1726            for (x = 0; x < 3; x++) {
1727                for (y = 0; y < 3; y++) {
1728                    res = 0;
1729                    for (z = 0; z < 3; z++) {
1730                        res += m[x][z] * matrix[z][y];
1731                    }
1732                    out[x][y] = res;
1733                }
1734            }
1735            this.a = out[0][0];
1736            this.b = out[1][0];
1737            this.c = out[0][1];
1738            this.d = out[1][1];
1739            this.e = out[0][2];
1740            this.f = out[1][2];
1741        };
1742        
1743        matrixproto.invert = function () {
1744            var me = this,
1745                x = me.a * me.d - me.b * me.c;
1746            return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);
1747        };
1748        
1749        matrixproto.clone = function () {
1750            return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);
1751        };
1752        
1753        matrixproto.translate = function (x, y) {
1754            this.add(1, 0, 0, 1, x, y);
1755        };
1756        
1757        matrixproto.scale = function (x, y, cx, cy) {
1758            y == null && (y = x);
1759            (cx || cy) && this.add(1, 0, 0, 1, cx, cy);
1760            this.add(x, 0, 0, y, 0, 0);
1761            (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);
1762        };
1763        
1764        matrixproto.rotate = function (a, x, y) {
1765            a = R.rad(a);
1766            x = x || 0;
1767            y = y || 0;
1768            var cos = +math.cos(a).toFixed(9),
1769                sin = +math.sin(a).toFixed(9);
1770            this.add(cos, sin, -sin, cos, x, y);
1771            this.add(1, 0, 0, 1, -x, -y);
1772        };
1773        
1774        matrixproto.x = function (x, y) {
1775            return x * this.a + y * this.c + this.e;
1776        };
1777        
1778        matrixproto.y = function (x, y) {
1779            return x * this.b + y * this.d + this.f;
1780        };
1781        matrixproto.get = function (i) {
1782            return +this[Str.fromCharCode(97 + i)].toFixed(4);
1783        };
1784        matrixproto.toString = function () {
1785            return R.svg ?
1786                "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")" :
1787                [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();
1788        };
1789        matrixproto.toFilter = function () {
1790            return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) +
1791                ", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) +
1792                ", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')";
1793        };
1794        matrixproto.offset = function () {
1795            return [this.e.toFixed(4), this.f.toFixed(4)];
1796        };
1797        function norm(a) {
1798            return a[0] * a[0] + a[1] * a[1];
1799        }
1800        function normalize(a) {
1801            var mag = math.sqrt(norm(a));
1802            a[0] && (a[0] /= mag);
1803            a[1] && (a[1] /= mag);
1804        }
1805        
1806        matrixproto.split = function () {
1807            var out = {};
1808            // translation
1809            out.dx = this.e;
1810            out.dy = this.f;
1811
1812            // scale and shear
1813            var row = [[this.a, this.c], [this.b, this.d]];
1814            out.scalex = math.sqrt(norm(row[0]));
1815            normalize(row[0]);
1816
1817            out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
1818            row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
1819
1820            out.scaley = math.sqrt(norm(row[1]));
1821            normalize(row[1]);
1822            out.shear /= out.scaley;
1823
1824            // rotation
1825            var sin = -row[0][1],
1826                cos = row[1][1];
1827            if (cos < 0) {
1828                out.rotate = R.deg(math.acos(cos));
1829                if (sin < 0) {
1830                    out.rotate = 360 - out.rotate;
1831                }
1832            } else {
1833                out.rotate = R.deg(math.asin(sin));
1834            }
1835
1836            out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);
1837            out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;
1838            out.noRotation = !+out.shear.toFixed(9) && !out.rotate;
1839            return out;
1840        };
1841        
1842        matrixproto.toTransformString = function () {
1843            var s = this.split();
1844            if (s.isSimple) {
1845                return "t" + [s.dx, s.dy] + "s" + [s.scalex, s.scaley, 0, 0] + "r" + [s.rotate, 0, 0];
1846            } else {
1847                return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];
1848            }
1849        };
1850    })(Matrix.prototype);
1851
1852    // WebKit rendering bug workaround method
1853    var version = navigator.userAgent.match(/Version\/(.*?)\s/) || navigator.userAgent.match(/Chrome\/(\d+)/);
1854    if ((navigator.vendor == "Apple Computer, Inc.") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == "iP") ||
1855        (navigator.vendor == "Google Inc." && version && version[1] < 8)) {
1856        
1857        paperproto.safari = function () {
1858            var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"});
1859            setTimeout(function () {rect.remove();});
1860        };
1861    } else {
1862        paperproto.safari = fun;
1863    }
1864 
1865    var preventDefault = function () {
1866        this.returnValue = false;
1867    },
1868    preventTouch = function () {
1869        return this.originalEvent.preventDefault();
1870    },
1871    stopPropagation = function () {
1872        this.cancelBubble = true;
1873    },
1874    stopTouch = function () {
1875        return this.originalEvent.stopPropagation();
1876    },
1877    addEvent = (function () {
1878        if (g.doc.addEventListener) {
1879            return function (obj, type, fn, element) {
1880                var realName = supportsTouch && touchMap[type] ? touchMap[type] : type,
1881                    f = function (e) {
1882                        var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
1883                            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
1884                            x = e.clientX + scrollX,
1885                            y = e.clientY + scrollY;
1886                    if (supportsTouch && touchMap[has](type)) {
1887                        for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {
1888                            if (e.targetTouches[i].target == obj) {
1889                                var olde = e;
1890                                e = e.targetTouches[i];
1891                                e.originalEvent = olde;
1892                                e.preventDefault = preventTouch;
1893                                e.stopPropagation = stopTouch;
1894                                break;
1895                            }
1896                        }
1897                    }
vendor: 12,100 bytes, lines 1898-2258
1898                    return fn.call(element, e, x, y);
1899                };
1900                obj.addEventListener(realName, f, false);
1901                return function () {
1902                    obj.removeEventListener(realName, f, false);
1903                    return true;
1904                };
1905            };
1906        } else if (g.doc.attachEvent) {
1907            return function (obj, type, fn, element) {
1908                var f = function (e) {
1909                    e = e || g.win.event;
1910                    var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
1911                        scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
1912                        x = e.clientX + scrollX,
1913                        y = e.clientY + scrollY;
1914                    e.preventDefault = e.preventDefault || preventDefault;
1915                    e.stopPropagation = e.stopPropagation || stopPropagation;
1916                    return fn.call(element, e, x, y);
1917                };
1918                obj.attachEvent("on" + type, f);
1919                var detacher = function () {
1920                    obj.detachEvent("on" + type, f);
1921                    return true;
1922                };
1923                return detacher;
1924            };
1925        }
1926    })(),
1927    drag = [],
1928    dragMove = function (e) {
1929        var x = e.clientX,
1930            y = e.clientY,
1931            scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
1932            scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
1933            dragi,
1934            j = drag.length;
1935        while (j--) {
1936            dragi = drag[j];
1937            if (supportsTouch) {
1938                var i = e.touches.length,
1939                    touch;
1940                while (i--) {
1941                    touch = e.touches[i];
1942                    if (touch.identifier == dragi.el._drag.id) {
1943                        x = touch.clientX;
1944                        y = touch.clientY;
1945                        (e.originalEvent ? e.originalEvent : e).preventDefault();
1946                        break;
1947                    }
1948                }
1949            } else {
1950                e.preventDefault();
1951            }
1952            var node = dragi.el.node,
1953                o,
1954                next = node.nextSibling,
1955                parent = node.parentNode,
1956                display = node.style.display;
1957            g.win.opera && parent.removeChild(node);
1958            node.style.display = "none";
1959            o = dragi.el.paper.getElementByPoint(x, y);
1960            node.style.display = display;
1961            g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));
1962            o && eve("drag.over." + dragi.el.id, dragi.el, o);
1963            x += scrollX;
1964            y += scrollY;
1965            eve("drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);
1966        }
1967    },
1968    dragUp = function (e) {
1969        R.unmousemove(dragMove).unmouseup(dragUp);
1970        var i = drag.length,
1971            dragi;
1972        while (i--) {
1973            dragi = drag[i];
1974            dragi.el._drag = {};
1975            eve("drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);
1976        }
1977        drag = [];
1978    },
1979    
1980    elproto = R.el = {};
1981    
1982    
1983    
1984    
1985    
1986    
1987    
1988    
1989    
1990    
1991    
1992    
1993    
1994    
1995    
1996    
1997    
1998    
1999    
2000    
2001    
2002    
2003    
2004    
2005    
2006    
2007    
2008    
2009    
2010    
2011    
2012    
2013    for (var i = events.length; i--;) {
2014        (function (eventName) {
2015            R[eventName] = elproto[eventName] = function (fn, scope) {
2016                if (R.is(fn, "function")) {
2017                    this.events = this.events || [];
2018                    this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)});
2019                }
2020                return this;
2021            };
2022            R["un" + eventName] = elproto["un" + eventName] = function (fn) {
2023                var events = this.events,
2024                    l = events.length;
2025                while (l--) if (events[l].name == eventName && events[l].f == fn) {
2026                    events[l].unbind();
2027                    events.splice(l, 1);
2028                    !events.length && delete this.events;
2029                    return this;
2030                }
2031                return this;
2032            };
2033        })(events[i]);
2034    }
2035    
2036    
2037    elproto.data = function (key, value) {
2038        var data = eldata[this.id] = eldata[this.id] || {};
2039        if (arguments.length == 1) {
2040            if (R.is(key, "object")) {
2041                for (var i in key) if (key[has](i)) {
2042                    this.data(i, key[i]);
2043                }
2044                return this;
2045            }
2046            eve("data.get." + this.id, this, data[key], key);
2047            return data[key];
2048        }
2049        data[key] = value;
2050        eve("data.set." + this.id, this, value, key);
2051        return this;
2052    };
2053    
2054    elproto.removeData = function (key) {
2055        if (key == null) {
2056            eldata[this.id] = {};
2057        } else {
2058            eldata[this.id] && delete eldata[this.id][key];
2059        }
2060        return this;
2061    };
2062    
2063    elproto.hover = function (f_in, f_out, scope_in, scope_out) {
2064        return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);
2065    };
2066    
2067    elproto.unhover = function (f_in, f_out) {
2068        return this.unmouseover(f_in).unmouseout(f_out);
2069    };
2070    
2071    elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {
2072        function start(e) {
2073            (e.originalEvent || e).preventDefault();
2074            var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
2075                scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;
2076            this._drag.x = e.clientX + scrollX;
2077            this._drag.y = e.clientY + scrollY;
2078            this._drag.id = e.identifier;
2079            !drag.length && R.mousemove(dragMove).mouseup(dragUp);
2080            drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});
2081            onstart && eve.on("drag.start." + this.id, onstart);
2082            onmove && eve.on("drag.move." + this.id, onmove);
2083            onend && eve.on("drag.end." + this.id, onend);
2084            eve("drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e);
2085        }
2086        this._drag = {};
2087        this.mousedown(start);
2088        return this;
2089    };
2090    
2091    elproto.onDragOver = function (f) {
2092        f ? eve.on("drag.over." + this.id, f) : eve.unbind("drag.over." + this.id);
2093    };
2094    
2095    elproto.undrag = function () {
2096        var i = drag.length;
2097        while (i--) if (drag[i].el == this) {
2098            R.unmousedown(drag[i].start);
2099            drag.splice(i++, 1);
2100            eve.unbind("drag.*." + this.id);
2101        }
2102        !drag.length && R.unmousemove(dragMove).unmouseup(dragUp);
2103    };
2104    
2105    paperproto.circle = function (x, y, r) {
2106        var out = R._engine.circle(this, x || 0, y || 0, r || 0);
2107        this.__set__ && this.__set__.push(out);
2108        return out;
2109    };
2110    
2111    paperproto.rect = function (x, y, w, h, r) {
2112        var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0);
2113        this.__set__ && this.__set__.push(out);
2114        return out;
2115    };
2116    
2117    paperproto.ellipse = function (x, y, rx, ry) {
2118        var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0);
2119        this.__set__ && this.__set__.push(out);
2120        return out;
2121    };
2122    
2123    paperproto.path = function (pathString) {
2124        pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);
2125        var out = R._engine.path(R.format[apply](R, arguments), this);
2126        this.__set__ && this.__set__.push(out);
2127        return out;
2128    };
2129    
2130    paperproto.image = function (src, x, y, w, h) {
2131        var out = R._engine.image(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0);
2132        this.__set__ && this.__set__.push(out);
2133        return out;
2134    };
2135    
2136    paperproto.text = function (x, y, text) {
2137        var out = R._engine.text(this, x || 0, y || 0, Str(text));
2138        this.__set__ && this.__set__.push(out);
2139        return out;
2140    };
2141    
2142    paperproto.set = function (itemsArray) {
2143        !R.is(itemsArray, "array") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length));
2144        var out = new Set(itemsArray);
2145        this.__set__ && this.__set__.push(out);
2146        return out;
2147    };
2148    
2149    paperproto.setStart = function (set) {
2150        this.__set__ = set || this.set();
2151    };
2152    
2153    paperproto.setFinish = function (set) {
2154        var out = this.__set__;
2155        delete this.__set__;
2156        return out;
2157    };
2158    
2159    paperproto.setSize = function (width, height) {
2160        return R._engine.setSize.call(this, width, height);
2161    };
2162    
2163    paperproto.setViewBox = function (x, y, w, h, fit) {
2164        return R._engine.setViewBox.call(this, x, y, w, h, fit);
2165    };
2166    
2167    
2168    paperproto.top = paperproto.bottom = null;
2169    
2170    paperproto.raphael = R;
2171    var getOffset = function (elem) {
2172        var box = elem.getBoundingClientRect(),
2173            doc = elem.ownerDocument,
2174            body = doc.body,
2175            docElem = doc.documentElement,
2176            clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
2177            top  = box.top  + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop,
2178            left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft;
2179        return {
2180            y: top,
2181            x: left
2182        };
2183    };
2184    
2185    paperproto.getElementByPoint = function (x, y) {
2186        var paper = this,
2187            svg = paper.canvas,
2188            target = g.doc.elementFromPoint(x, y);
2189        if (g.win.opera && target.tagName == "svg") {
2190            var so = getOffset(svg),
2191                sr = svg.createSVGRect();
2192            sr.x = x - so.x;
2193            sr.y = y - so.y;
2194            sr.width = sr.height = 1;
2195            var hits = svg.getIntersectionList(sr, null);
2196            if (hits.length) {
2197                target = hits[hits.length - 1];
2198            }
2199        }
2200        if (!target) {
2201            return null;
2202        }
2203        while (target.parentNode && target != svg.parentNode && !target.raphael) {
2204            target = target.parentNode;
2205        }
2206        target == paper.canvas.parentNode && (target = svg);
2207        target = target && target.raphael ? paper.getById(target.raphaelid) : null;
2208        return target;
2209    };
2210    
2211    paperproto.getById = function (id) {
2212        var bot = this.bottom;
2213        while (bot) {
2214            if (bot.id == id) {
2215                return bot;
2216            }
2217            bot = bot.next;
2218        }
2219        return null;
2220    };
2221    
2222    paperproto.forEach = function (callback, thisArg) {
2223        var bot = this.bottom;
2224        while (bot) {
2225            if (callback.call(thisArg, bot) === false) {
2226                return this;
2227            }
2228            bot = bot.next;
2229        }
2230        return this;
2231    };
2232    function x_y() {
2233        return this.x + S + this.y;
2234    }
2235    function x_y_w_h() {
2236        return this.x + S + this.y + S + this.width + " \xd7 " + this.height;
2237    }
2238    
2239    elproto.getBBox = function (isWithoutTransform) {
2240        if (this.removed) {
2241            return {};
2242        }
2243        var _ = this._;
2244        if (isWithoutTransform) {
2245            if (_.dirty || !_.bboxwt) {
2246                this.realPath = getPath[this.type](this);
2247                _.bboxwt = pathDimensions(this.realPath);
2248                _.bboxwt.toString = x_y_w_h;
2249                _.dirty = 0;
2250            }
2251            return _.bboxwt;
2252        }
2253        if (_.dirty || _.dirtyT || !_.bbox) {
2254            if (_.dirty || !this.realPath) {
2255                _.bboxwt = 0;
2256                this.realPath = getPath[this.type](this);
2257            }
2258            _.bbox = pathDimensions(mapPath(this.realPath, this.matrix
2258));
2259            _.bbox.toString = x_y_w_h;
2260            _.dirty = _.dirtyT = 0;
2261        }
2262        return _.bbox;
2263    };
2264    
2265    elproto.clone = function () {
2266        if (this.removed) {
2267            return null;
2268        }
2269        return this.paper[this.type]().attr(this.attr());
2270    };
2271    
2272    elproto.glow = function (glow) {
2273        if (this.type == "text") {
2274            return null;
2275        }
2276        glow = glow || {};
2277        var s = {
2278            width: (glow.width || 10) + (+this.attr("stroke-width") || 1),
2279            fill: glow.fill || false,
2280            opacity: glow.opacity || .5,
2281            offsetx: glow.offsetx || 0,
2282            offsety: glow.offsety || 0,
2283            color: glow.color || "#000"
2284        },
2285            c = s.width / 2,
2286            r = this.paper,
2287            out = r.set(),
2288            path = this.realPath || getPath[this.type](this);
2289        path = this.matrix ? mapPath(path, this.matrix) : path;
2290        for (var i = 1; i < c + 1; i++) {
2291            out.push(r.path(path).attr({
2292                stroke: s.color,
2293                fill: s.fill ? s.color : "none",
2294                "stroke-linejoin": "round",
2295                "stroke-linecap": "round",
2296                "stroke-width": +(s.width / c * i).toFixed(3),
2297                opacity: +(s.opacity / c).toFixed(3)
2298            }));
2299        }
2300        return out.insertBefore(this).translate(s.offsetx, s.offsety);
2301    };
2302    var curveslengths = {},
2303    getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
2304        var len = 0,
2305            precision = 100,
2306            name = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y].join(),
2307            cache = curveslengths[name],
2308            old, dot;
2309        !cache && (curveslengths[name] = cache = {data: []});
2310        cache.timer && clearTimeout(cache.timer);
2311        cache.timer = setTimeout(function () {delete curveslengths[name];}, 2e3);
2312        if (length != null && !cache.precision) {
2313            var total = getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
2314            cache.precision = ~~total * 10;
2315            cache.data = [];
2316        }
2317        precision = cache.precision || precision;
2318        for (var i = 0; i < precision + 1; i++) {
2319            if (cache.data[i * precision]) {
2320                dot = cache.data[i * precision];
2321            } else {
2322                dot = R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i / precision);
2323                cache.data[i * precision] = dot;
2324            }
2325            i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5));
2326            if (length != null && len >= length) {
2327                return dot;
2328            }
2329            old = dot;
2330        }
2331        if (length == null) {
2332            return len;
2333        }
2334    },
2335    getLengthFactory = function (istotal, subpath) {
2336        return function (path, length, onlystart) {
2337            path = path2curve(path);
2338            var x, y, p, l, sp = "", subpaths = {}, point,
2339                len = 0;
2340            for (var i = 0, ii = path.length; i < ii; i++) {
2341                p = path[i];
2342                if (p[0] == "M") {
2343                    x = +p[1];
2344                    y = +p[2];
2345                } else {
2346                    l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
2347                    if (len + l > length) {
2348                        if (subpath && !subpaths.start) {
2349                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
2350                            sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];
2351                            if (onlystart) {return sp;}
2352                            subpaths.start = sp;
2353                            sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();
2354                            len += l;
2355                            x = +p[5];
2356                            y = +p[6];
2357                            continue;
2358                        }
2359                        if (!istotal && !subpath) {
2360                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
2361                            return {x: point.x, y: point.y, alph
vendor: 32,561 bytes, lines 2361-3219
2361a: point.alpha};
2362                        }
2363                    }
2364                    len += l;
2365                    x = +p[5];
2366                    y = +p[6];
2367                }
2368                sp += p.shift() + p;
2369            }
2370            subpaths.end = sp;
2371            point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
2372            point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});
2373            return point;
2374        };
2375    };
2376    var getTotalLength = getLengthFactory(1),
2377        getPointAtLength = getLengthFactory(),
2378        getSubpathsAtLength = getLengthFactory(0, 1);
2379    
2380    R.getTotalLength = getTotalLength;
2381    
2382    R.getPointAtLength = getPointAtLength;
2383    
2384    R.getSubpath = function (path, from, to) {
2385        if (this.getTotalLength(path) - to < 1e-6) {
2386            return getSubpathsAtLength(path, from).end;
2387        }
2388        var a = getSubpathsAtLength(path, to, 1);
2389        return from ? getSubpathsAtLength(a, from).end : a;
2390    };
2391    
2392    elproto.getTotalLength = function () {
2393        if (this.type != "path") {return;}
2394        if (this.node.getTotalLength) {
2395            return this.node.getTotalLength();
2396        }
2397        return getTotalLength(this.attrs.path);
2398    };
2399    
2400    elproto.getPointAtLength = function (length) {
2401        if (this.type != "path") {return;}
2402        return getPointAtLength(this.attrs.path, length);
2403    };
2404    
2405    elproto.getSubpath = function (from, to) {
2406        if (this.type != "path") {return;}
2407        return R.getSubpath(this.attrs.path, from, to);
2408    };
2409    
2410    var ef = R.easing_formulas = {
2411        linear: function (n) {
2412            return n;
2413        },
2414        "<": function (n) {
2415            return pow(n, 1.7);
2416        },
2417        ">": function (n) {
2418            return pow(n, .48);
2419        },
2420        "<>": function (n) {
2421            var q = .48 - n / 1.04,
2422                Q = math.sqrt(.1734 + q * q),
2423                x = Q - q,
2424                X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),
2425                y = -Q - q,
2426                Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),
2427                t = X + Y + .5;
2428            return (1 - t) * 3 * t * t + t * t * t;
2429        },
2430        backIn: function (n) {
2431            var s = 1.70158;
2432            return n * n * ((s + 1) * n - s);
2433        },
2434        backOut: function (n) {
2435            n = n - 1;
2436            var s = 1.70158;
2437            return n * n * ((s + 1) * n + s) + 1;
2438        },
2439        elastic: function (n) {
2440            if (n == !!n) {
2441                return n;
2442            }
2443            return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;
2444        },
2445        bounce: function (n) {
2446            var s = 7.5625,
2447                p = 2.75,
2448                l;
2449            if (n < (1 / p)) {
2450                l = s * n * n;
2451            } else {
2452                if (n < (2 / p)) {
2453                    n -= (1.5 / p);
2454                    l = s * n * n + .75;
2455                } else {
2456                    if (n < (2.5 / p)) {
2457                        n -= (2.25 / p);
2458                        l = s * n * n + .9375;
2459                    } else {
2460                        n -= (2.625 / p);
2461                        l = s * n * n + .984375;
2462                    }
2463                }
2464            }
2465            return l;
2466        }
2467    };
2468    ef.easeIn = ef["ease-in"] = ef["<"];
2469    ef.easeOut = ef["ease-out"] = ef[">"];
2470    ef.easeInOut = ef["ease-in-out"] = ef["<>"];
2471    ef["back-in"] = ef.backIn;
2472    ef["back-out"] = ef.backOut;
2473
2474    var animationElements = [],
2475        requestAnimFrame = window.requestAnimationFrame       ||
2476                           window.webkitRequestAnimationFrame ||
2477                           window.mozRequestAnimationFrame    ||
2478                           window.oRequestAnimationFrame      ||
2479                           window.msRequestAnimationFrame     ||
2480                           function (callback) {
2481                               setTimeout(callback, 16);
2482                           },
2483        animation = function () {
2484            var Now = +new Date,
2485                l = 0;
2486            for (; l < animationElements.length; l++) {
2487                var e = animationElements[l];
2488                if (e.el.removed || e.paused) {
2489                    continue;
2490                }
2491                var time = Now - e.start,
2492                    ms = e.ms,
2493                    easing = e.easing,
2494                    from = e.from,
2495                    diff = e.diff,
2496                    to = e.to,
2497                    t = e.t,
2498                    that = e.el,
2499                    set = {},
2500                    now;
2501                if (e.initstatus) {
2502                    time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms;
2503                    e.status = e.initstatus;
2504                    delete e.initstatus;
2505                    e.stop && animationElements.splice(l--, 1);
2506                } else {
2507                    e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top;
2508                }
2509                if (time < 0) {
2510                    continue;
2511                }
2512                if (time < ms) {
2513                    var pos = easing(time / ms);
2514                    for (var attr in from) if (from[has](attr)) {
2515                        switch (availableAnimAttrs[attr]) {
2516                            case nu:
2517                                now = +from[attr] + pos * ms * diff[attr];
2518                                break;
2519                            case "colour":
2520                                now = "rgb(" + [
2521                                    upto255(round(from[attr].r + pos * ms * diff[attr].r)),
2522                                    upto255(round(from[attr].g + pos * ms * diff[attr].g)),
2523                                    upto255(round(from[attr].b + pos * ms * diff[attr].b))
2524                                ].join(",") + ")";
2525                                break;
2526                            case "path":
2527                                now = [];
2528                                for (var i = 0, ii = from[attr].length; i < ii; i++) {
2529                                    now[i] = [from[attr][i][0]];
2530                                    for (var j = 1, jj = from[attr][i].length; j < jj; j++) {
2531                                        now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];
2532                                    }
2533                                    now[i] = now[i].join(S);
2534                                }
2535                                now = now.join(S);
2536                                break;
2537                            case "transform":
2538                                if (diff[attr].real) {
2539                                    now = [];
2540                                    for (i = 0, ii = from[attr].length; i < ii; i++) {
2541                                        now[i] = [from[attr][i][0]];
2542                                        for (j = 1, jj = from[attr][i].length; j < jj; j++) {
2543                                            now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j];
2544                                        }
2545                                    }
2546                                } else {
2547                                    var get = function (i) {
2548                                        return +from[attr][i] + pos * ms * diff[attr][i];
2549                                    };
2550                                    // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]];
2551                                    now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]];
2552                                }
2553                                break;
2554                            case "csv":
2555                                if (attr == "clip-rect") {
2556                                    now = [];
2557                                    i = 4;
2558                                    while (i--) {
2559                                        now[i] = +from[attr][i] + pos * ms * diff[attr][i];
2560                                    }
2561                                }
2562                                break;
2563                            default:
2564                                var from2 = [].concat(from[attr]);
2565                                now = [];
2566                                i = that.paper.customAttributes[attr].length;
2567                                while (i--) {
2568                                    now[i] = +from2[i] + pos * ms * diff[attr][i];
2569                                }
2570                                break;
2571                        }
2572                        set[attr] = now;
2573                    }
2574                    that.attr(set);
2575                    (function (id, that, anim) {
2576                        setTimeout(function () {
2577                            eve("anim.frame." + id, that, anim);
2578                        });
2579                    })(that.id, that, e.anim);
2580                } else {
2581                    (function(f, el, a) {
2582                        setTimeout(function() {
2583                            eve("anim.frame." + el.id, el, a);
2584                            eve("anim.finish." + el.id, el, a);
2585                            R.is(f, "function") && f.call(el);
2586                        });
2587                    })(e.callback, that, e.anim);
2588                    that.attr(to);
2589                    animationElements.splice(l--, 1);
2590                    if (e.repeat > 1 && !e.next) {
2591                        runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);
2592                    }
2593                    if (e.next && !e.stop) {
2594                        runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat);
2595                    }
2596                }
2597            }
2598            R.svg && that && that.paper && that.paper.safari();
2599            animationElements.length && requestAnimFrame(animation);
2600        },
2601        upto255 = function (color) {
2602            return color > 255 ? 255 : color < 0 ? 0 : color;
2603        };
2604    
2605    elproto.animateWith = function (element, anim, params, ms, easing, callback) {
2606        var a = params ? R.animation(params, ms, easing, callback) : anim;
2607            status = element.status(anim);
2608        return this.animate(a).status(a, status * anim.ms / a.ms);
2609    };
2610    function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {
2611        var cx = 3 * p1x,
2612            bx = 3 * (p2x - p1x) - cx,
2613            ax = 1 - cx - bx,
2614            cy = 3 * p1y,
2615            by = 3 * (p2y - p1y) - cy,
2616            ay = 1 - cy - by;
2617        function sampleCurveX(t) {
2618            return ((ax * t + bx) * t + cx) * t;
2619        }
2620        function solve(x, epsilon) {
2621            var t = solveCurveX(x, epsilon);
2622            return ((ay * t + by) * t + cy) * t;
2623        }
2624        function solveCurveX(x, epsilon) {
2625            var t0, t1, t2, x2, d2, i;
2626            for(t2 = x, i = 0; i < 8; i++) {
2627                x2 = sampleCurveX(t2) - x;
2628                if (abs(x2) < epsilon) {
2629                    return t2;
2630                }
2631                d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
2632                if (abs(d2) < 1e-6) {
2633                    break;
2634                }
2635                t2 = t2 - x2 / d2;
2636            }
2637            t0 = 0;
2638            t1 = 1;
2639            t2 = x;
2640            if (t2 < t0) {
2641                return t0;
2642            }
2643            if (t2 > t1) {
2644                return t1;
2645            }
2646            while (t0 < t1) {
2647                x2 = sampleCurveX(t2);
2648                if (abs(x2 - x) < epsilon) {
2649                    return t2;
2650                }
2651                if (x > x2) {
2652                    t0 = t2;
2653                } else {
2654                    t1 = t2;
2655                }
2656                t2 = (t1 - t0) / 2 + t0;
2657            }
2658            return t2;
2659        }
2660        return solve(t, 1 / (200 * duration));
2661    }
2662    elproto.onAnimation = function (f) {
2663        f ? eve.on("anim.frame." + this.id, f) : eve.unbind("anim.frame." + this.id);
2664        return this;
2665    };
2666    function Animation(anim, ms) {
2667        var percents = [],
2668            newAnim = {};
2669        this.ms = ms;
2670        this.times = 1;
2671        if (anim) {
2672            for (var attr in anim) if (anim[has](attr)) {
2673                newAnim[toFloat(attr)] = anim[attr];
2674                percents.push(toFloat(attr));
2675            }
2676            percents.sort(sortByNumber);
2677        }
2678        this.anim = newAnim;
2679        this.top = percents[percents.length - 1];
2680        this.percents = percents;
2681    }
2682    
2683    Animation.prototype.delay = function (delay) {
2684        var a = new Animation(this.anim, this.ms);
2685        a.times = this.times;
2686        a.del = +delay || 0;
2687        return a;
2688    };
2689    
2690    Animation.prototype.repeat = function (times) { 
2691        var a = new Animation(this.anim, this.ms);
2692        a.del = this.del;
2693        a.times = math.floor(mmax(times, 0)) || 1;
2694        return a;
2695    };
2696    function runAnimation(anim, element, percent, status, totalOrigin, times) {
2697        percent = toFloat(percent);
2698        var params,
2699            isInAnim,
2700            isInAnimSet,
2701            percents = [],
2702            next,
2703            prev,
2704            timestamp,
2705            ms = anim.ms,
2706            from = {},
2707            to = {},
2708            diff = {};
2709        if (status) {
2710            for (i = 0, ii = animationElements.length; i < ii; i++) {
2711                var e = animationElements[i];
2712                if (e.el.id == element.id && e.anim == anim) {
2713                    if (e.percent != percent) {
2714                        animationElements.splice(i, 1);
2715                        isInAnimSet = 1;
2716                    } else {
2717                        isInAnim = e;
2718                    }
2719                    element.attr(e.totalOrigin);
2720                    break;
2721                }
2722            }
2723        } else {
2724            status = +to; // NaN
2725        }
2726        for (var i = 0, ii = anim.percents.length; i < ii; i++) {
2727            if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) {
2728                percent = anim.percents[i];
2729                prev = anim.percents[i - 1] || 0;
2730                ms = ms / anim.top * (percent - prev);
2731                next = anim.percents[i + 1];
2732                params = anim.anim[percent];
2733                break;
2734            } else if (status) {
2735                element.attr(anim.anim[anim.percents[i]]);
2736            }
2737        }
2738        if (!params) {
2739            return;
2740        }
2741        if (!isInAnim) {
2742            for (attr in params) if (params[has](attr)) {
2743                if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {
2744                    from[attr] = element.attr(attr);
2745                    (from[attr] == null) && (from[attr] = availableAttrs[attr]);
2746                    to[attr] = params[attr];
2747                    switch (availableAnimAttrs[attr]) {
2748                        case nu:
2749                            diff[attr] = (to[attr] - from[attr]) / ms;
2750                            break;
2751                        case "colour":
2752                            from[attr] = R.getRGB(from[attr]);
2753                            var toColour = R.getRGB(to[attr]);
2754                            diff[attr] = {
2755                                r: (toColour.r - from[attr].r) / ms,
2756                                g: (toColour.g - from[attr].g) / ms,
2757                                b: (toColour.b - from[attr].b) / ms
2758                            };
2759                            break;
2760                        case "path":
2761                            var pathes = path2curve(from[attr], to[attr]),
2762                                toPath = pathes[1];
2763                            from[attr] = pathes[0];
2764                            diff[attr] = [];
2765                            for (i = 0, ii = from[attr].length; i < ii; i++) {
2766                                diff[attr][i] = [0];
2767                                for (var j = 1, jj = from[attr][i].length; j < jj; j++) {
2768                                    diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;
2769                                }
2770                            }
2771                            break;
2772                        case "transform":
2773                            var _ = element._,
2774                                eq = equaliseTransform(_[attr], to[attr]);
2775                            if (eq) {
2776                                from[attr] = eq.from;
2777                                to[attr] = eq.to;
2778                                diff[attr] = [];
2779                                diff[attr].real = true;
2780                                for (i = 0, ii = from[attr].length; i < ii; i++) {
2781                                    diff[attr][i] = [from[attr][i][0]];
2782                                    for (j = 1, jj = from[attr][i].length; j < jj; j++) {
2783                                        diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms;
2784                                    }
2785                                }
2786                            } else {
2787                                var m = (element.matrix || new Matrix),
2788                                    to2 = {
2789                                        _: {transform: _.transform},
2790                                        getBBox: function () {
2791                                            return element.getBBox(1);
2792                                        }
2793                                    };
2794                                from[attr] = [
2795                                    m.a,
2796                                    m.b,
2797                                    m.c,
2798                                    m.d,
2799                                    m.e,
2800                                    m.f
2801                                ];
2802                                extractTransform(to2, to[attr]);
2803                                to[attr] = to2._.transform;
2804                                diff[attr] = [
2805                                    (to2.matrix.a - m.a) / ms,
2806                                    (to2.matrix.b - m.b) / ms,
2807                                    (to2.matrix.c - m.c) / ms,
2808                                    (to2.matrix.d - m.d) / ms,
2809                                    (to2.matrix.e - m.e) / ms,
2810                                    (to2.matrix.e - m.f) / ms
2811                                ];
2812                                // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];
2813                                // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};
2814                                // extractTransform(to2, to[attr]);
2815                                // diff[attr] = [
2816                                //     (to2._.sx - _.sx) / ms,
2817                                //     (to2._.sy - _.sy) / ms,
2818                                //     (to2._.deg - _.deg) / ms,
2819                                //     (to2._.dx - _.dx) / ms,
2820                                //     (to2._.dy - _.dy) / ms
2821                                // ];
2822                            }
2823                            break;
2824                        case "csv":
2825                            var values = Str(params[attr]).split(separator),
2826                                from2 = Str(from[attr]).split(separator);
2827                            if (attr == "clip-rect") {
2828                                from[attr] = from2;
2829                                diff[attr] = [];
2830                                i = from2.length;
2831                                while (i--) {
2832                                    diff[attr][i] = (values[i] - from[attr][i]) / ms;
2833                                }
2834                            }
2835                            to[attr] = values;
2836                            break;
2837                        default:
2838                            values = [].concat(params[attr]);
2839                            from2 = [].concat(from[attr]);
2840                            diff[attr] = [];
2841                            i = element.paper.customAttributes[attr].length;
2842                            while (i--) {
2843                                diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;
2844                            }
2845                            break;
2846                    }
2847                }
2848            }
2849            var easing = params.easing,
2850                easyeasy = R.easing_formulas[easing];
2851            if (!easyeasy) {
2852                easyeasy = Str(easing).match(bezierrg);
2853                if (easyeasy && easyeasy.length == 5) {
2854                    var curve = easyeasy;
2855                    easyeasy = function (t) {
2856                        return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);
2857                    };
2858                } else {
2859                    easyeasy = pipe;
2860                }
2861            }
2862            timestamp = params.start || anim.start || +new Date;
2863            e = {
2864                anim: anim,
2865                percent: percent,
2866                timestamp: timestamp,
2867                start: timestamp + (anim.del || 0),
2868                status: 0,
2869                initstatus: status || 0,
2870                stop: false,
2871                ms: ms,
2872                easing: easyeasy,
2873                from: from,
2874                diff: diff,
2875                to: to,
2876                el: element,
2877                callback: params.callback,
2878                prev: prev,
2879                next: next,
2880                repeat: times || anim.times,
2881                origin: element.attr(),
2882                totalOrigin: totalOrigin
2883            };
2884            animationElements.push(e);
2885            if (status && !isInAnim && !isInAnimSet) {
2886                e.stop = true;
2887                e.start = new Date - ms * status;
2888                if (animationElements.length == 1) {
2889                    return animation();
2890                }
2891            }
2892            if (isInAnimSet) {
2893                e.start = new Date - e.ms * status;
2894            }
2895            animationElements.length == 1 && requestAnimFrame(animation);
2896        } else {
2897            isInAnim.initstatus = status;
2898            isInAnim.start = new Date - isInAnim.ms * status;
2899        }
2900        eve("anim.start." + element.id, element, anim);
2901    }
2902    
2903    R.animation = function (params, ms, easing, callback) {
2904        if (params instanceof Animation) {
2905            return params;
2906        }
2907        if (R.is(easing, "function") || !easing) {
2908            callback = callback || easing || null;
2909            easing = null;
2910        }
2911        params = Object(params);
2912        ms = +ms || 0;
2913        var p = {},
2914            json,
2915            attr;
2916        for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat(attr) + "%" != attr) {
2917            json = true;
2918            p[attr] = params[attr];
2919        }
2920        if (!json) {
2921            return new Animation(params, ms);
2922        } else {
2923            easing && (p.easing = easing);
2924            callback && (p.callback = callback);
2925            return new Animation({100: p}, ms);
2926        }
2927    };
2928    
2929    elproto.animate = function (params, ms, easing, callback) {
2930        var element = this;
2931        if (element.removed) {
2932            callback && callback.call(element);
2933            return element;
2934        }
2935        var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback);
2936        runAnimation(anim, element, anim.percents[0], null, element.attr());
2937        return element;
2938    };
2939    
2940    elproto.setTime = function (anim, value) {
2941        if (anim && value != null) {
2942            this.status(anim, mmin(value, anim.ms) / anim.ms);
2943        }
2944        return this;
2945    };
2946    
2947    elproto.status = function (anim, value) {
2948        var out = [],
2949            i = 0,
2950            len,
2951            e;
2952        if (value != null) {
2953            runAnimation(anim, this, -1, mmin(value, 1));
2954            return this;
2955        } else {
2956            len = animationElements.length;
2957            for (; i < len; i++) {
2958                e = animationElements[i];
2959                if (e.el.id == this.id && (!anim || e.anim == anim)) {
2960                    if (anim) {
2961                        return e.status;
2962                    }
2963                    out.push({
2964                        anim: e.anim,
2965                        status: e.status
2966                    });
2967                }
2968            }
2969            if (anim) {
2970                return 0;
2971            }
2972            return out;
2973        }
2974    };
2975    
2976    elproto.pause = function (anim) {
2977        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
2978            if (eve("anim.pause." + this.id, this, animationElements[i].anim) !== false) {
2979                animationElements[i].paused = true;
2980            }
2981        }
2982        return this;
2983    };
2984    
2985    elproto.resume = function (anim) {
2986        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
2987            var e = animationElements[i];
2988            if (eve("anim.resume." + this.id, this, e.anim) !== false) {
2989                delete e.paused;
2990                this.status(e.anim, e.status);
2991            }
2992        }
2993        return this;
2994    };
2995    
2996    elproto.stop = function (anim) {
2997        for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
2998            if (eve("anim.stop." + this.id, this, animationElements[i].anim) !== false) {
2999                animationElements.splice(i--, 1);
3000            }
3001        }
3002        return this;
3003    };
3004    elproto.toString = function () {
3005        return "Rapha\xebl\u2019s object";
3006    };
3007
3008    // Set
3009    var Set = function (items) {
3010        this.items = [];
3011        this.length = 0;
3012        this.type = "set";
3013        if (items) {
3014            for (var i = 0, ii = items.length; i < ii; i++) {
3015                if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) {
3016                    this[this.items.length] = this.items[this.items.length] = items[i];
3017                    this.length++;
3018                }
3019            }
3020        }
3021    },
3022    setproto = Set.prototype;
3023    
3024    setproto.push = function () {
3025        var item,
3026            len;
3027        for (var i = 0, ii = arguments.length; i < ii; i++) {
3028            item = arguments[i];
3029            if (item && (item.constructor == elproto.constructor || item.constructor == Set)) {
3030                len = this.items.length;
3031                this[len] = this.items[len] = item;
3032                this.length++;
3033            }
3034        }
3035        return this;
3036    };
3037    
3038    setproto.pop = function () {
3039        this.length && delete this[this.length--];
3040        return this.items.pop();
3041    };
3042    
3043    setproto.forEach = function (callback, thisArg) {
3044        for (var i = 0, ii = this.items.length; i < ii; i++) {
3045            if (callback.call(thisArg, this.items[i]) === false) {
3046                return this;
3047            }
3048        }
3049        return this;
3050    };
3051    for (var method in elproto) if (elproto[has](method)) {
3052        setproto[method] = (function (methodname) {
3053            return function () {
3054                var arg = arguments;
3055                return this.forEach(function (el) {
3056                    el[methodname][apply](el, arg);
3057                });
3058            };
3059        })(method);
3060    }
3061    setproto.attr = function (name, value) {
3062        if (name && R.is(name, array) && R.is(name[0], "object")) {
3063            for (var j = 0, jj = name.length; j < jj; j++) {
3064                this.items[j].attr(name[j]);
3065            }
3066        } else {
3067            for (var i = 0, ii = this.items.length; i < ii; i++) {
3068                this.items[i].attr(name, value);
3069            }
3070        }
3071        return this;
3072    };
3073    
3074    setproto.clear = function () {
3075        while (this.length) {
3076            this.pop();
3077        }
3078    };
3079    
3080    setproto.splice = function (index, count, insertion) {
3081        index = index < 0 ? mmax(this.length + index, 0) : index;
3082        count = mmax(0, mmin(this.length - index, count));
3083        var tail = [],
3084            todel = [],
3085            args = [],
3086            i;
3087        for (i = 2; i < arguments.length; i++) {
3088            args.push(arguments[i]);
3089        }
3090        for (i = 0; i < count; i++) {
3091            todel.push(this[index + i]);
3092        }
3093        for (; i < this.length - index; i++) {
3094            tail.push(this[index + i]);
3095        }
3096        var arglen = args.length;
3097        for (i = 0; i < arglen + tail.length; i++) {
3098            this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen];
3099        }
3100        i = this.items.length = this.length -= count - arglen;
3101        while (this[i]) {
3102            delete this[i++];
3103        }
3104        return new Set(todel);
3105    };
3106    
3107    setproto.exclude = function (el) {
3108        for (var i = 0, ii = this.length, found; i < ii; i++) if (found || this[i] == el) {
3109            this[i] = this[i + 1];
3110            found = 1;
3111        }
3112        if (found) {
3113            this.length--;
3114            delete this[i];
3115            return true;
3116        }
3117    };
3118    setproto.animate = function (params, ms, easing, callback) {
3119        (R.is(easing, "function") || !easing) && (callback = easing || null);
3120        var len = this.items.length,
3121            i = len,
3122            item,
3123            set = this,
3124            collector;
3125        if (!len) {
3126            return this;
3127        }
3128        callback && (collector = function () {
3129            !--len && callback.call(set);
3130        });
3131        easing = R.is(easing, string) ? easing : collector;
3132        var anim = R.animation(params, ms, easing, collector);
3133        item = this.items[--i].animate(anim);
3134        while (i--) {
3135            this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim);
3136        }
3137        return this;
3138    };
3139    setproto.insertAfter = function (el) {
3140        var i = this.items.length;
3141        while (i--) {
3142            this.items[i].insertAfter(el);
3143        }
3144        return this;
3145    };
3146    setproto.getBBox = function () {
3147        var x = [],
3148            y = [],
3149            w = [],
3150            h = [];
3151        for (var i = this.items.length; i--;) if (!this.items[i].removed) {
3152            var box = this.items[i].getBBox();
3153            x.push(box.x);
3154            y.push(box.y);
3155            w.push(box.x + box.width);
3156            h.push(box.y + box.height);
3157        }
3158        x = mmin[apply](0, x);
3159        y = mmin[apply](0, y);
3160        return {
3161            x: x,
3162            y: y,
3163            width: mmax[apply](0, w) - x,
3164            height: mmax[apply](0, h) - y
3165        };
3166    };
3167    setproto.clone = function (s) {
3168        s = new Set;
3169        for (var i = 0, ii = this.items.length; i < ii; i++) {
3170            s.push(this.items[i].clone());
3171        }
3172        return s;
3173    };
3174    setproto.toString = function () {
3175        return "Rapha\xebl\u2018s set";
3176    };
3177
3178    
3179    R.registerFont = function (font) {
3180        if (!font.face) {
3181            return font;
3182        }
3183        this.fonts = this.fonts || {};
3184        var fontcopy = {
3185                w: font.w,
3186                face: {},
3187                glyphs: {}
3188            },
3189            family = font.face["font-family"];
3190        for (var prop in font.face) if (font.face[has](prop)) {
3191            fontcopy.face[prop] = font.face[prop];
3192        }
3193        if (this.fonts[family]) {
3194            this.fonts[family].push(fontcopy);
3195        } else {
3196            this.fonts[family] = [fontcopy];
3197        }
3198        if (!font.svg) {
3199            fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10);
3200            for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {
3201                var path = font.glyphs[glyph];
3202                fontcopy.glyphs[glyph] = {
3203                    w: path.w,
3204                    k: {},
3205                    d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) {
3206                            return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M";
3207                        }) + "z"
3208                };
3209                if (path.k) {
3210                    for (var k in path.k) if (path[has](k)) {
3211                        fontcopy.glyphs[glyph].k[k] = path.k[k];
3212                    }
3213                }
3214            }
3215        }
3216        return font;
3217    };
3218    
3219    paperproto.getFont = function (family, weight, style, stretch) {
3220        stretch = stretch || "normal";
3221        style = style || "normal";
3222        weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;
3223        if (!R.fonts) {
3224            return;
3225        }
3226        var font = R.fonts[family];
3227        if (!font) {
3228            var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i");
3229            for (var fontName in R.fonts) if (R.fonts[has](fontName)) {
3230                if (name.test(fontName)) {
3231                    font = R.fonts[fontName];
3232                    break;
3233                }
3234            }
3235        }
3236        var thefont;
3237        if (font) {
3238            for (var i = 0, ii = font.length; i < ii; i++) {
3239                thefont = font[i];
3240                if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) {
3241                    break;
3242                }
3243            }
3244        }
3245        return thefont;
3246    };
3247    
3248    paperproto.print = function (x, y, string, font, size, origin, letter_spacing) {
3249        origin = origin || "middle"; // baseline|middle
3250        letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);
3251        var out = this.set(),
3252            letters = Str(string).split(E),
3253            shift = 0,
3254            path = E,
3255            scale;
3256        R.is(font, string) && (font = this.getFont(font));
3257        if (font) {
3258            scale = (size || 16) / font.face["units-per-em"];
3259            var bb = font.face.bbox.split(separator),
3260                top = +bb[0],
3261                height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2);
3262            for (var i = 0, ii = letters.length; i < ii; i++) {
3263                var prev = i && font.glyphs[letters[i - 1]] || {},
3264                    curr = font.glyphs[letters[i]];
3265                shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;
3266                curr && curr.d && out.push(this.path(curr.d).attr({
3267                    fill: "#000",
3268                    stroke: "none",
3269                    transform: [["t", shift * scale, 0]]
3270                }));
3271            }
3272            out.transform(["...s", scale, scale, top, height, "t", (x - top) / scale, (y - height) / scale]);
3273        }
3274        return out;
3275    };
3276
3277    
3278    R.format = function (token, params) {
3279        var args = R.is(params, array) ? [0][concat](params) : arguments;
3280        token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) {
3281            return args[++i] == null ? E : args[i];
3282        }));
3283        return token || E;
3284    };
3285    
3286    R.fullfill = (function () {
3287        var tokenRegex = /\{([^\}]+)\}/g,
3288            objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties
3289            replacer = function (all, key, obj) {
3290                var res = obj;
3291                key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {
3292                    name = name || quotedName;
3293                    if (res) {
3294                        if (name in res) {
3295                            res = res[name];
3296                        }
3297                        typeof res == "function" && isFunc && (res = res());
3298                    }
3299                });
3300                res = (res == null || res == obj ? all : res) + "";
3301                return res;
3302            };
3303        return function (str, obj) {
3304            return String(str).replace(tokenRegex, function (all, key) {
3305                return replacer(all, key, obj);
3306            });
3307        };
3308    })();
3309    
3310    R.ninja = function () {
3311        oldRaphael.was ? (g.win.Raphael = oldRaphael.is) : delete Raphael;
3312        return R;
3313    };
3314    
3315    R.st = setproto;
3316    // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
3317    (function (doc, loaded, f) {
3318        if (doc.readyState == null && doc.addEventListener){
3319            doc.addEventListener(loaded, f = function () {
3320                doc.removeEventListener(loaded, f, false);
3321                doc.readyState = "complete";
3322            }, false);
3323            doc.readyState = "loading";
3324        }
3325        function isLoaded() {
3326            (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve("DOMload");
3327        }
3328        isLoaded();
3329    })(document, "DOMContentLoaded");
3330
3331    oldRaphael.was ? (g.win.Raphael = R) : (Raphael = R);
3332    
3333    eve.on("DOMload", function () {
3334        loaded = true;
3335    });
3336})();
3337
3338// ┌─────────────────────────────────────────────────────────────────────┐ \\
3339// │ Raphaël 2 - JavaScript Vector Library                               │ \\
3340// ├─────────────────────────────────────────────────────────────────────┤ \\
3341// │ SVG Module                                                          │ \\
3342// ├─────────────────────────────────────────────────────────────────────┤ \\
3343// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\
3344// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\
3345// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
3346// └─────────────────────────────────────────────────────────────────────┘ \\
3347window.Raphael.svg && function (R) {
3348    var has = "hasOwnProperty",
3349        Str = String,
3350        toFloat = parseFloat,
3351        toInt = parseInt,
3352        math = Math,
3353        mmax = math.max,
3354        abs = math.abs,
3355        pow = math.pow,
3356        separator = /[, ]+/,
3357        eve = R.eve,
3358        E = "",
3359        S = " ";
3360    var xlink = "http://www.w3.org/1999/xlink",
3361        markers = {
3362            block: "M5,0 0,2.5 5,5z",
3363            classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z",
3364            diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z",
3365            open: "M6,1 1,3.5 6,6",
3366            oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"
3367        },
3368        markerCounter = {};
3369    R.toString = function () {
3370        return  "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version;
3371    };
3372    var $ = function (el, attr) {
3373        if (attr) {
3374            if (typeof el == "string") {
3375                el = $(el);
3376            }
3377            for (var key in attr) if (attr[has](key)) {
3378                if (key.substring(0, 6) == "xlink:") {
3379                    el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));
3380                } else {
3381                    el.setAttribute(key, Str(attr[key]));
3382                }
3383            }
3384        } else {
3385            el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el);
3386            el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)");
3387        }
3388        return el;
3389    },
3390    gradients = {},
3391    rgGrad = /^url\(#(.*)\)$/,
3392    removeGradientFill = function (node, paper) {
3393        var oid = node.getAttribute("fill");
3394        oid = oid && oid.match(rgGrad);
3395        if (oid && !--gradients[oid[1]]) {
3396            delete gradients[oid[1]];
3397            paper.defs.removeChild(R._g.doc.getElementById(oid[1]));
3398        }
3399    },
3400    addGradientFill = function (element, gradient) {
3401        var type = "linear",
vendor: 30,788 bytes, lines 3402-4194
3402            id = element.id + gradient,
3403            fx = .5, fy = .5,
3404            o = element.node,
3405            SVG = element.paper,
3406            s = o.style,
3407            el = R._g.doc.getElementById(id);
3408        if (!el) {
3409            gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) {
3410                type = "radial";
3411                if (_fx && _fy) {
3412                    fx = toFloat(_fx);
3413                    fy = toFloat(_fy);
3414                    var dir = ((fy > .5) * 2 - 1);
3415                    pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&
3416                        (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&
3417                        fy != .5 &&
3418                        (fy = fy.toFixed(5) - 1e-5 * dir);
3419                }
3420                return E;
3421            });
3422            gradient = gradient.split(/\s*\-\s*/);
3423            if (type == "linear") {
3424                var angle = gradient.shift();
3425                angle = -toFloat(angle);
3426                if (isNaN(angle)) {
3427                    return null;
3428                }
3429                var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))],
3430                    max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);
3431                vector[2] *= max;
3432                vector[3] *= max;
3433                if (vector[2] < 0) {
3434                    vector[0] = -vector[2];
3435                    vector[2] = 0;
3436                }
3437                if (vector[3] < 0) {
3438                    vector[1] = -vector[3];
3439                    vector[3] = 0;
3440                }
3441            }
3442            var dots = R._parseDots(gradient);
3443            if (!dots) {
3444                return null;
3445            }
3446            if (element.gradient) {
3447                SVG.defs.removeChild(element.gradient);
3448                delete element.gradient;
3449            }
3450
3451            id = id.replace(/[\(\)\s,\xb0#]/g, "-");
3452            el = $(type + "Gradient", {id: id});
3453            element.gradient = el;
3454            $(el, type == "radial" ? {
3455                fx: fx,
3456                fy: fy
3457            } : {
3458                x1: vector[0],
3459                y1: vector[1],
3460                x2: vector[2],
3461                y2: vector[3],
3462                gradientTransform: element.matrix.invert()
3463            });
3464            SVG.defs.appendChild(el);
3465            for (var i = 0, ii = dots.length; i < ii; i++) {
3466                el.appendChild($("stop", {
3467                    offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%",
3468                    "stop-color": dots[i].color || "#fff"
3469                }));
3470            }
3471        }
3472        $(o, {
3473            fill: "url(#" + id + ")",
3474            opacity: 1,
3475            "fill-opacity": 1
3476        });
3477        s.fill = E;
3478        s.opacity = 1;
3479        s.fillOpacity = 1;
3480        return 1;
3481    },
3482    updatePosition = function (o) {
3483        var bbox = o.getBBox(1);
3484        $(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"});
3485    },
3486    addArrow = function (o, value, isEnd) {
3487        if (o.type == "path") {
3488            var values = Str(value).toLowerCase().split("-"),
3489                p = o.paper,
3490                se = isEnd ? "end" : "start",
3491                node = o.node,
3492                attrs = o.attrs,
3493                stroke = attrs["stroke-width"],
3494                i = values.length,
3495                type = "classic",
3496                from,
3497                to,
3498                dx,
3499                refX,
3500                attr,
3501                w = 3,
3502                h = 3,
3503                t = 5;
3504            while (i--) {
3505                switch (values[i]) {
3506                    case "block":
3507                    case "classic":
3508                    case "oval":
3509                    case "diamond":
3510                    case "open":
3511                    case "none":
3512                        type = values[i];
3513                        break;
3514                    case "wide": h = 5; break;
3515                    case "narrow": h = 2; break;
3516                    case "long": w = 5; break;
3517                    case "short": w = 2; break;
3518                }
3519            }
3520            if (type == "open") {
3521                w += 2;
3522                h += 2;
3523                t += 2;
3524                dx = 1;
3525                refX = isEnd ? 4 : 1;
3526                attr = {
3527                    fill: "none",
3528                    stroke: attrs.stroke
3529                };
3530            } else {
3531                refX = dx = w / 2;
3532                attr = {
3533                    fill: attrs.stroke,
3534                    stroke: "none"
3535                };
3536            }
3537            if (o._.arrows) {
3538                if (isEnd) {
3539                    o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;
3540                    o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;
3541                } else {
3542                    o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;
3543                    o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;
3544                }
3545            } else {
3546                o._.arrows = {};
3547            }
3548            if (type != "none") {
3549                var pathId = "raphael-marker-" + type,
3550                    markerId = "raphael-marker-" + se + type + w + h;
3551                if (!R._g.doc.getElementById(pathId)) {
3552                    p.defs.appendChild($($("path"), {
3553                        "stroke-linecap": "round",
3554                        d: markers[type],
3555                        id: pathId
3556                    }));
3557                    markerCounter[pathId] = 1;
3558                } else {
3559                    markerCounter[pathId]++;
3560                }
3561                var marker = R._g.doc.getElementById(markerId),
3562                    use;
3563                if (!marker) {
3564                    marker = $($("marker"), {
3565                        id: markerId,
3566                        markerHeight: h,
3567                        markerWidth: w,
3568                        orient: "auto",
3569                        refX: refX,
3570                        refY: h / 2
3571                    });
3572                    use = $($("use"), {
3573                        "xlink:href": "#" + pathId,
3574                        transform: (isEnd ? " rotate(180 " + w / 2 + " " + h / 2 + ") " : S) + "scale(" + w / t + "," + h / t + ")",
3575                        "stroke-width": 1 / ((w / t + h / t) / 2)
3576                    });
3577                    marker.appendChild(use);
3578                    p.defs.appendChild(marker);
3579                    markerCounter[markerId] = 1;
3580                } else {
3581                    markerCounter[markerId]++;
3582                    use = marker.getElementsByTagName("use")[0];
3583                }
3584                $(use, attr);
3585                var delta = dx * (type != "diamond" && type != "oval");
3586                if (isEnd) {
3587                    from = o._.arrows.startdx * stroke || 0;
3588                    to = R.getTotalLength(attrs.path) - delta * stroke;
3589                } else {
3590                    from = delta * stroke;
3591                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
3592                }
3593                attr = {};
3594                attr["marker-" + se] = "url(#" + markerId + ")";
3595                if (to || from) {
3596                    attr.d = Raphael.getSubpath(attrs.path, from, to);
3597                }
3598                $(node, attr);
3599                o._.arrows[se + "Path"] = pathId;
3600                o._.arrows[se + "Marker"] = markerId;
3601                o._.arrows[se + "dx"] = delta;
3602                o._.arrows[se + "Type"] = type;
3603                o._.arrows[se + "String"] = value;
3604            } else {
3605                if (isEnd) {
3606                    from = o._.arrows.startdx * stroke || 0;
3607                    to = R.getTotalLength(attrs.path) - from;
3608                } else {
3609                    from = 0;
3610                    to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
3611                }
3612                o._.arrows[se + "Path"] && $(node, {d: Raphael.getSubpath(attrs.path, from, to)});
3613                delete o._.arrows[se + "Path"];
3614                delete o._.arrows[se + "Marker"];
3615                delete o._.arrows[se + "dx"];
3616                delete o._.arrows[se + "Type"];
3617                delete o._.arrows[se + "String"];
3618            }
3619            for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) {
3620                var item = R._g.doc.getElementById(attr);
3621                item && item.parentNode.removeChild(item);
3622            }
3623        }
3624    },
3625    dasharray = {
3626        "": [0],
3627        "none": [0],
3628        "-": [3, 1],
3629        ".": [1, 1],
3630        "-.": [3, 1, 1, 1],
3631        "-..": [3, 1, 1, 1, 1, 1],
3632        ". ": [1, 3],
3633        "- ": [4, 3],
3634        "--": [8, 3],
3635        "- .": [4, 3, 1, 3],
3636        "--.": [8, 3, 1, 3],
3637        "--..": [8, 3, 1, 3, 1, 3]
3638    },
3639    addDashes = function (o, value, params) {
3640        value = dasharray[Str(value).toLowerCase()];
3641        if (value) {
3642            var width = o.attrs["stroke-width"] || "1",
3643                butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0,
3644                dashes = [],
3645                i = value.length;
3646            while (i--) {
3647                dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;
3648            }
3649            $(o.node, {"stroke-dasharray": dashes.join(",")});
3650        }
3651    },
3652    setFillAndStroke = function (o, params) {
3653        var node = o.node,
3654            attrs = o.attrs,
3655            vis = node.style.visibility;
3656        node.style.visibility = "hidden";
3657        for (var att in params) {
3658            if (params[has](att)) {
3659                if (!R._availableAttrs[has](att)) {
3660                    continue;
3661                }
3662                var value = params[att];
3663                attrs[att] = value;
3664                switch (att) {
3665                    case "blur":
3666                        o.blur(value);
3667                        break;
3668                    case "href":
3669                    case "title":
3670                    case "target":
3671                        var pn = node.parentNode;
3672                        if (pn.tagName.toLowerCase() != "a") {
3673                            var hl = $("a");
3674                            pn.insertBefore(hl, node);
3675                            hl.appendChild(node);
3676                            pn = hl;
3677                        }
3678                        if (att == "target" && value == "blank") {
3679                            pn.setAttributeNS(xlink, "show", "new");
3680                        } else {
3681                            pn.setAttributeNS(xlink, att, value);
3682                        }
3683                        break;
3684                    case "cursor":
3685                        node.style.cursor = value;
3686                        break;
3687                    case "transform":
3688                        o.transform(value);
3689                        break;
3690                    case "arrow-start":
3691                        addArrow(o, value);
3692                        break;
3693                    case "arrow-end":
3694                        addArrow(o, value, 1);
3695                        break;
3696                    case "clip-rect":
3697                        var rect = Str(value).split(separator);
3698                        if (rect.length == 4) {
3699                            o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);
3700                            var el = $("clipPath"),
3701                                rc = $("rect");
3702                            el.id = R.createUUID();
3703                            $(rc, {
3704                                x: rect[0],
3705                                y: rect[1],
3706                                width: rect[2],
3707                                height: rect[3]
3708                            });
3709                            el.appendChild(rc);
3710                            o.paper.defs.appendChild(el);
3711                            $(node, {"clip-path": "url(#" + el.id + ")"});
3712                            o.clip = rc;
3713                        }
3714                        if (!value) {
3715                            var clip = R._g.doc.getElementById(node.getAttribute("clip-path").replace(/(^url\(#|\)$)/g, E));
3716                            clip && clip.parentNode.removeChild(clip);
3717                            $(node, {"clip-path": E});
3718                            delete o.clip;
3719                        }
3720                    break;
3721                    case "path":
3722                        if (o.type == "path") {
3723                            $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : "M0,0"});
3724                            o._.dirty = 1;
3725                            if (o._.arrows) {
3726                                "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
3727                                "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
3728                            }
3729                        }
3730                        break;
3731                    case "width":
3732                        node.setAttribute(att, value);
3733                        o._.dirty = 1;
3734                        if (attrs.fx) {
3735                            att = "x";
3736                            value = attrs.x;
3737                        } else {
3738                            break;
3739                        }
3740                    case "x":
3741                        if (attrs.fx) {
3742                            value = -attrs.x - (attrs.width || 0);
3743                        }
3744                    case "rx":
3745                        if (att == "rx" && o.type == "rect") {
3746                            break;
3747                        }
3748                    case "cx":
3749                        node.setAttribute(att, value);
3750                        o.pattern && updatePosition(o);
3751                        o._.dirty = 1;
3752                        break;
3753                    case "height":
3754                        node.setAttribute(att, value);
3755                        o._.dirty = 1;
3756                        if (attrs.fy) {
3757                            att = "y";
3758                            value = attrs.y;
3759                        } else {
3760                            break;
3761                        }
3762                    case "y":
3763                        if (attrs.fy) {
3764                            value = -attrs.y - (attrs.height || 0);
3765                        }
3766                    case "ry":
3767                        if (att == "ry" && o.type == "rect") {
3768                            break;
3769                        }
3770                    case "cy":
3771                        node.setAttribute(att, value);
3772                        o.pattern && updatePosition(o);
3773                        o._.dirty = 1;
3774                        break;
3775                    case "r":
3776                        if (o.type == "rect") {
3777                            $(node, {rx: value, ry: value});
3778                        } else {
3779                            node.setAttribute(att, value);
3780                        }
3781                        o._.dirty = 1;
3782                        break;
3783                    case "src":
3784                        if (o.type == "image") {
3785                            node.setAttributeNS(xlink, "href", value);
3786                        }
3787                        break;
3788                    case "stroke-width":
3789                        if (o._.sx != 1 || o._.sy != 1) {
3790                            value /= mmax(abs(o._.sx), abs(o._.sy)) || 1;
3791                        }
3792                        if (o.paper._vbSize) {
3793                            value *= o.paper._vbSize;
3794                        }
3795                        node.setAttribute(att, value);
3796                        if (attrs["stroke-dasharray"]) {
3797                            addDashes(o, attrs["stroke-dasharray"], params);
3798                        }
3799                        if (o._.arrows) {
3800                            "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
3801                            "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
3802                        }
3803                        break;
3804                    case "stroke-dasharray":
3805                        addDashes(o, value, params);
3806                        break;
3807                    case "fill":
3808                        var isURL = Str(value).match(R._ISURL);
3809                        if (isURL) {
3810                            el = $("pattern");
3811                            var ig = $("image");
3812                            el.id = R.createUUID();
3813                            $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1});
3814                            $(ig, {x: 0, y: 0, "xlink:href": isURL[1]});
3815                            el.appendChild(ig);
3816
3817                            (function (el) {
3818                                R._preload(isURL[1], function () {
3819                                    var w = this.offsetWidth,
3820                                        h = this.offsetHeight;
3821                                    $(el, {width: w, height: h});
3822                                    $(ig, {width: w, height: h});
3823                                    o.paper.safari();
3824                                });
3825                            })(el);
3826                            o.paper.defs.appendChild(el);
3827                            node.style.fill = "url(#" + el.id + ")";
3828                            $(node, {fill: "url(#" + el.id + ")"});
3829                            o.pattern = el;
3830                            o.pattern && updatePosition(o);
3831                            break;
3832                        }
3833                        var clr = R.getRGB(value);
3834                        if (!clr.error) {
3835                            delete params.gradient;
3836                            delete attrs.gradient;
3837                            !R.is(attrs.opacity, "undefined") &&
3838                                R.is(params.opacity, "undefined") &&
3839                                $(node, {opacity: attrs.opacity});
3840                            !R.is(attrs["fill-opacity"], "undefined") &&
3841                                R.is(params["fill-opacity"], "undefined") &&
3842                                $(node, {"fill-opacity": attrs["fill-opacity"]});
3843                        } else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) {
3844                            if ("opacity" in attrs || "fill-opacity" in attrs) {
3845                                var gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
3846                                if (gradient) {
3847                                    var stops = gradient.getElementsByTagName("stop");
3848                                    $(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)});
3849                                }
3850                            }
3851                            attrs.gradient = value;
3852                            attrs.fill = "none";
3853                            break;
3854                        }
3855                        clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
3856                    case "stroke":
3857                        clr = R.getRGB(value);
3858                        node.setAttribute(att, clr.hex);
3859                        att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
3860                        if (att == "stroke" && o._.arrows) {
3861                            "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
3862                            "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
3863                        }
3864                        break;
3865                    case "gradient":
3866                        (o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value);
3867                        break;
3868                    case "opacity":
3869                        if (attrs.gradient && !attrs[has]("stroke-opacity")) {
3870                            $(node, {"stroke-opacity": value > 1 ? value / 100 : value});
3871                        }
3872                        // fall
3873                    case "fill-opacity":
3874                        if (attrs.gradient) {
3875                            gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
3876                            if (gradient) {
3877                                stops = gradient.getElementsByTagName("stop");
3878                                $(stops[stops.length - 1], {"stop-opacity": value});
3879                            }
3880                            break;
3881                        }
3882                    default:
3883                        att == "font-size" && (value = toInt(value, 10) + "px");
3884                        var cssrule = att.replace(/(\-.)/g, function (w) {
3885                            return w.substring(1).toUpperCase();
3886                        });
3887                        node.style[cssrule] = value;
3888                        o._.dirty = 1;
3889                        node.setAttribute(att, value);
3890                        break;
3891                }
3892            }
3893        }
3894
3895        tuneText(o, params);
3896        node.style.visibility = vis;
3897    },
3898    leading = 1.2,
3899    tuneText = function (el, params) {
3900        if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) {
3901            return;
3902        }
3903        var a = el.attrs,
3904            node = el.node,
3905            fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10;
3906
3907        if (params[has]("text")) {
3908            a.text = params.text;
3909            while (node.firstChild) {
3910                node.removeChild(node.firstChild);
3911            }
3912            var texts = Str(params.text).split("\n"),
3913                tspans = [],
3914                tspan;
3915            for (var i = 0, ii = texts.length; i < ii; i++) {
3916                tspan = $("tspan");
3917                i && $(tspan, {dy: fontSize * leading, x: a.x});
3918                tspan.appendChild(R._g.doc.createTextNode(texts[i]));
3919                node.appendChild(tspan);
3920                tspans[i] = tspan;
3921            }
3922        } else {
3923            tspans = node.getElementsByTagName("tspan");
3924            for (i = 0, ii = tspans.length; i < ii; i++) if (i) {
3925                $(tspans[i], {dy: fontSize * leading, x: a.x});
3926            } else {
3927                $(tspans[0], {dy: 0});
3928            }
3929        }
3930        $(node, {x: a.x, y: a.y});
3931        el._.dirty = 1;
3932        var bb = el._getBBox(),
3933            dif = a.y - (bb.y + bb.height / 2);
3934        dif && R.is(dif, "finite") && $(tspans[0], {dy: dif});
3935    },
3936    Element = function (node, svg) {
3937        var X = 0,
3938            Y = 0;
3939        
3940        this[0] = this.node = node;
3941        
3942        node.raphael = true;
3943        
3944        this.id = R._oid++;
3945        node.raphaelid = this.id;
3946        this.matrix = R.matrix();
3947        this.realPath = null;
3948        
3949        this.paper = svg;
3950        this.attrs = this.attrs || {};
3951        this._ = {
3952            transform: [],
3953            sx: 1,
3954            sy: 1,
3955            deg: 0,
3956            dx: 0,
3957            dy: 0,
3958            dirty: 1
3959        };
3960        !svg.bottom && (svg.bottom = this);
3961        
3962        this.prev = svg.top;
3963        svg.top && (svg.top.next = this);
3964        svg.top = this;
3965        
3966        this.next = null;
3967    },
3968    elproto = R.el;
3969
3970    Element.prototype = elproto;
3971    elproto.constructor = Element;
3972
3973    R._engine.path = function (pathString, SVG) {
3974        var el = $("path");
3975        SVG.canvas && SVG.canvas.appendChild(el);
3976        var p = new Element(el, SVG);
3977        p.type = "path";
3978        setFillAndStroke(p, {
3979            fill: "none",
3980            stroke: "#000",
3981            path: pathString
3982        });
3983        return p;
3984    };
3985    
3986    elproto.rotate = function (deg, cx, cy) {
3987        if (this.removed) {
3988            return this;
3989        }
3990        deg = Str(deg).split(separator);
3991        if (deg.length - 1) {
3992            cx = toFloat(deg[1]);
3993            cy = toFloat(deg[2]);
3994        }
3995        deg = toFloat(deg[0]);
3996        (cy == null) && (cx = cy);
3997        if (cx == null || cy == null) {
3998            var bbox = this.getBBox(1);
3999            cx = bbox.x + bbox.width / 2;
4000            cy = bbox.y + bbox.height / 2;
4001        }
4002        this.transform(this._.transform.concat([["r", deg, cx, cy]]));
4003        return this;
4004    };
4005    
4006    elproto.scale = function (sx, sy, cx, cy) {
4007        if (this.removed) {
4008            return this;
4009        }
4010        sx = Str(sx).split(separator);
4011        if (sx.length - 1) {
4012            sy = toFloat(sx[1]);
4013            cx = toFloat(sx[2]);
4014            cy = toFloat(sx[3]);
4015        }
4016        sx = toFloat(sx[0]);
4017        (sy == null) && (sy = sx);
4018        (cy == null) && (cx = cy);
4019        if (cx == null || cy == null) {
4020            var bbox = this.getBBox(1);
4021        }
4022        cx = cx == null ? bbox.x + bbox.width / 2 : cx;
4023        cy = cy == null ? bbox.y + bbox.height / 2 : cy;
4024        this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
4025        return this;
4026    };
4027    
4028    elproto.translate = function (dx, dy) {
4029        if (this.removed) {
4030            return this;
4031        }
4032        dx = Str(dx).split(separator);
4033        if (dx.length - 1) {
4034            dy = toFloat(dx[1]);
4035        }
4036        dx = toFloat(dx[0]) || 0;
4037        dy = +dy || 0;
4038        this.transform(this._.transform.concat([["t", dx, dy]]));
4039        return this;
4040    };
4041    
4042    elproto.transform = function (tstr) {
4043        var _ = this._;
4044        if (tstr == null) {
4045            return _.transform;
4046        }
4047        R._extractTransform(this, tstr);
4048
4049        this.clip && $(this.clip, {transform: this.matrix.invert()});
4050        this.pattern && updatePosition(this);
4051        this.node && $(this.node, {transform: this.matrix});
4052    
4053        if (_.sx != 1 || _.sy != 1) {
4054            var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1;
4055            this.attr({"stroke-width": sw});
4056        }
4057
4058        return this;
4059    };
4060    
4061    elproto.hide = function () {
4062        !this.removed && this.paper.safari(this.node.style.display = "none");
4063        return this;
4064    };
4065    
4066    elproto.show = function () {
4067        !this.removed && this.paper.safari(this.node.style.display = "");
4068        return this;
4069    };
4070    
4071    elproto.remove = function () {
4072        if (this.removed) {
4073            return;
4074        }
4075        eve.unbind("*.*." + this.id);
4076        R._tear(this, this.paper);
4077        this.node.parentNode.removeChild(this.node);
4078        for (var i in this) {
4079            delete this[i];
4080        }
4081        this.removed = true;
4082    };
4083    elproto._getBBox = function () {
4084        if (this.node.style.display == "none") {
4085            this.show();
4086            var hide = true;
4087        }
4088        var bbox = {};
4089        try {
4090            bbox = this.node.getBBox();
4091        } catch(e) {
4092            // Firefox 3.0.x plays badly here
4093        } finally {
4094            bbox = bbox || {};
4095        }
4096        hide && this.hide();
4097        return bbox;
4098    };
4099    
4100    elproto.attr = function (name, value) {
4101        if (this.removed) {
4102            return this;
4103        }
4104        if (name == null) {
4105            var res = {};
4106            for (var a in this.attrs) if (this.attrs[has](a)) {
4107                res[a] = this.attrs[a];
4108            }
4109            res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
4110            res.transform = this._.transform;
4111            return res;
4112        }
4113        if (value == null && R.is(name, "string")) {
4114            if (name == "fill" && this.attrs.fill == "none" && this.attrs.gradient) {
4115                return this.attrs.gradient;
4116            }
4117            if (name == "transform") {
4118                return this._.transform;
4119            }
4120            var names = name.split(separator),
4121                out = {};
4122            for (var i = 0, ii = names.length; i < ii; i++) {
4123                name = names[i];
4124                if (name in this.attrs) {
4125                    out[name] = this.attrs[name];
4126                } else if (R.is(this.paper.customAttributes[name], "function")) {
4127                    out[name] = this.paper.customAttributes[name].def;
4128                } else {
4129                    out[name] = R._availableAttrs[name];
4130                }
4131            }
4132            return ii - 1 ? out : out[names[0]];
4133        }
4134        if (value == null && R.is(name, "array")) {
4135            out = {};
4136            for (i = 0, ii = name.length; i < ii; i++) {
4137                out[name[i]] = this.attr(name[i]);
4138            }
4139            return out;
4140        }
4141        if (value != null) {
4142            var params = {};
4143            params[name] = value;
4144        } else if (name != null && R.is(name, "object")) {
4145            params = name;
4146        }
4147        for (var key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
4148            var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));
4149            this.attrs[key] = params[key];
4150            for (var subkey in par) if (par[has](subkey)) {
4151                params[subkey] = par[subkey];
4152            }
4153        }
4154        setFillAndStroke(this, params);
4155        return this;
4156    };
4157    
4158    elproto.toFront = function () {
4159        if (this.removed) {
4160            return this;
4161        }
4162        this.node.parentNode.appendChild(this.node);
4163        var svg = this.paper;
4164        svg.top != this && R._tofront(this, svg);
4165        return this;
4166    };
4167    
4168    elproto.toBack = function () {
4169        if (this.removed) {
4170            return this;
4171        }
4172        if (this.node.parentNode.firstChild != this.node) {
4173            this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
4174            R._toback(this, this.paper);
4175            var svg = this.paper;
4176        }
4177        return this;
4178    };
4179    
4180    elproto.insertAfter = function (element) {
4181        if (this.removed) {
4182            return this;
4183        }
4184        var node = element.node || element[element.length - 1].node;
4185        if (node.nextSibling) {
4186            node.parentNode.insertBefore(this.node, node.nextSibling);
4187        } else {
4188            node.parentNode.appendChild(this.node);
4189        }
4190        R._insertafter(this, element, this.paper);
4191        return this;
4192    };
4193    
4194    elproto.insertBefore = function (eleme
4194nt) {
4195        if (this.removed) {
4196            return this;
4197        }
4198        var node = element.node || element[0].node;
4199        node.parentNode.insertBefore(this.node, node);
4200        R._insertbefore(this, element, this.paper);
4201        return this;
4202    };
4203    elproto.blur = function (size) {
4204        // Experimental. No Safari support. Use it on your own risk.
4205        var t = this;
4206        if (+size !== 0) {
4207            var fltr = $("filter"),
4208                blur = $("feGaussianBlur");
4209            t.attrs.blur = size;
4210            fltr.id = R.createUUID();
4211            $(blur, {stdDeviation: +size || 1.5});
4212            fltr.appendChild(blur);
4213            t.paper.defs.appendChild(fltr);
4214            t._blur = fltr;
4215            $(t.node, {filter: "url(#" + fltr.id + ")"});
4216        } else {
4217            if (t._blur) {
4218                t._blur.parentNode.removeChild(t._blur);
4219                delete t._blur;
4220                delete t.attrs.blur;
4221            }
4222            t.node.removeAttribute("filter");
4223        }
4224    };
4225    R._engine.circle = function (svg, x, y, r) {
4226        var el = $("circle");
4227        svg.canvas && svg.canvas.appendChild(el);
4228        var res = new Element(el, svg);
4229        res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"};
4230        res.type = "circle";
4231        $(el, res.attrs);
4232        return res;
4233    };
4234    R._engine.rect = function (svg, x, y, w, h, r) {
4235        var el = $("rect");
4236        svg.canvas && svg.canvas.appendChild(el);
4237        var res = new Element(el, svg);
4238        res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"};
4239        res.type = "rect";
4240        $(el, res.attrs);
4241        return res;
4242    };
4243    R._engine.ellipse = function (svg, x, y, rx, ry) {
4244        var el = $("ellipse");
4245        svg.canvas && svg.canvas.appendChild(el);
4246        var res = new Element(el, svg);
4247        res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"};
4248        res.type = "ellipse";
4249        $(el, res.attrs);
4250        return res;
4251    };
4252    R._engine.image = function (svg, src, x, y, w, h) {
4253        var el = $("image");
4254        $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"});
4255        el.setAttributeNS(xlink, "href", src);
4256        svg.canvas && svg.canvas.appendChild(el);
4257        var res = new Element(el, svg);
4258        res.attrs = {x: x, y: y, width: w, height: h, src: src};
4259        res.type = "image";
4260        return res;
4261    };
4262    R._engine.text = function (svg, x, y, text) {
4263        var el = $("text");
4264        // $(el, {x: x, y: y, "text-anchor": "middle"});
4265        svg.canvas && svg.canvas.appendChild(el);
4266        var res = new Element(el, svg);
4267        res.attrs = {
4268            x: x,
4269            y: y,
4270            "text-anchor": "middle",
4271            text: text,
4272            font: R._availableAttrs.font,
4273            stroke: "none",
4274            fill: "#000"
4275        };
4276        res.type = "text";
4277        setFillAndStroke(res, res.attrs);
4278        return res;
4279    };
4280    R._engine.setSize = function (width, height) {
4281        this.width = width || this.width;
4282        this.height = height || this.height;
4283        this.canvas.setAttribute("width", this.width);
4284        this.canvas.setAttribute("height", this.height);
4285        if (this._viewBox) {
4286            this.setViewBox.apply(this, this._viewBox);
4287        }
4288        return this;
4289    };
4290    R._engine.create = function () {
4291        var con = R._getContainer.apply(0, arguments),
4292            container = con && con.container,
4293            x = con.x,
4294            y = con.y,
4295            width = con.width,
4296            height = con.height;
4297        if (!container) {
4298            throw new Error("SVG container not found.");
4299        }
4300        var cnvs = $("svg"),
4301            css = "overflow:hidden;",
4302            isFloating;
4303        x = x || 0;
4304        y = y || 0;
4305        width = width || 512;
4306        height = height || 342;
4307        $(cnvs, {
4308            height: height,
4309            version: 1.1,
4310            width: width,
4311            xmlns: "http://www.w3.org/2000/svg"
4312        });
4313        if (container == 1) {
4314            cnvs.style.cssText = css + "position:absolute;
4314left:" + x + "px;top:" + y + "px";
4315            R._g.doc.body.appendChild(cnvs);
4316            isFloating = 1;
4317        } else {
4318            cnvs.style.cssText = css + "position:relative";
4319            if (container.firstChild) {
4320                container.insertBefore(cnvs, container.firstChild);
4321            } else {
4322                container.appendChild(cnvs);
4323            }
4324        }
4325        container = new R._Paper;
4326        container.width = width;
4327        container.height = height;
4328        container.canvas = cnvs;
4329        // plugins.call(container, container, R.fn);
4330        container.clear();
4331        container._left = container._top = 0;
4332        isFloating && (container.renderfix = function () {});
4333        container.renderfix();
4334        return container;
4335    };
4336    R._engine.setViewBox = function (x, y, w, h, fit) {
4337        eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]);
4338        var size = mmax(w / this.width, h / this.height),
4339            top = this.top,
4340            aspectRatio = fit ? "meet" : "xMinYMin",
4341            vb,
4342            sw;
4343        if (x == null) {
4344            if (this._vbSize) {
4345                size = 1;
4346            }
4347            delete this._vbSize;
4348            vb = "0 0 " + this.width + S + this.height;
4349        } else {
4350            this._vbSize = size;
4351            vb = x + S + y + S + w + S + h;
4352        }
4353        $(this.canvas, {
vendor: 37,689 bytes, lines 4354-5346
4354            viewBox: vb,
4355            preserveAspectRatio: aspectRatio
4356        });
4357        while (size && top) {
4358            sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1;
4359            top.attr({"stroke-width": sw});
4360            top._.dirty = 1;
4361            top._.dirtyT = 1;
4362            top = top.prev;
4363        }
4364        this._viewBox = [x, y, w, h, !!fit];
4365        return this;
4366    };
4367    
4368    R.prototype.renderfix = function () {
4369        var cnvs = this.canvas,
4370            s = cnvs.style,
4371            pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix(),
4372            left = -pos.e % 1,
4373            top = -pos.f % 1;
4374        if (left || top) {
4375            if (left) {
4376                this._left = (this._left + left) % 1;
4377                s.left = this._left + "px";
4378            }
4379            if (top) {
4380                this._top = (this._top + top) % 1;
4381                s.top = this._top + "px";
4382            }
4383        }
4384    };
4385    
4386    R.prototype.clear = function () {
4387        R.eve("clear", this);
4388        var c = this.canvas;
4389        while (c.firstChild) {
4390            c.removeChild(c.firstChild);
4391        }
4392        this.bottom = this.top = null;
4393        (this.desc = $("desc")).appendChild(R._g.doc.createTextNode("Created with Rapha\xebl " + R.version));
4394        c.appendChild(this.desc);
4395        c.appendChild(this.defs = $("defs"));
4396    };
4397    
4398    R.prototype.remove = function () {
4399        eve("remove", this);
4400        this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
4401        for (var i in this) {
4402            this[i] = removed(i);
4403        }
4404    };
4405    var setproto = R.st;
4406    for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
4407        setproto[method] = (function (methodname) {
4408            return function () {
4409                var arg = arguments;
4410                return this.forEach(function (el) {
4411                    el[methodname].apply(el, arg);
4412                });
4413            };
4414        })(method);
4415    }
4416}(window.Raphael);
4417
4418// ┌─────────────────────────────────────────────────────────────────────┐ \\
4419// │ Raphaël 2 - JavaScript Vector Library                               │ \\
4420// ├─────────────────────────────────────────────────────────────────────┤ \\
4421// │ VML Module                                                          │ \\
4422// ├─────────────────────────────────────────────────────────────────────┤ \\
4423// │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com)   │ \\
4424// │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com)             │ \\
4425// │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
4426// └─────────────────────────────────────────────────────────────────────┘ \\
4427window.Raphael.vml && function (R) {
4428    var has = "hasOwnProperty",
4429        Str = String,
4430        toFloat = parseFloat,
4431        math = Math,
4432        round = math.round,
4433        mmax = math.max,
4434        mmin = math.min,
4435        abs = math.abs,
4436        fillString = "fill",
4437        separator = /[, ]+/,
4438        eve = R.eve,
4439        ms = " progid:DXImageTransform.Microsoft",
4440        S = " ",
4441        E = "",
4442        map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
4443        bites = /([clmz]),?([^clmz]*)/gi,
4444        blurregexp = / progid:\S+Blur\([^\)]+\)/g,
4445        val = /-?[^,\s-]+/g,
4446        cssDot = "position:absolute;left:0;top:0;width:1px;height:1px",
4447        zoom = 21600,
4448        pathTypes = {path: 1, rect: 1, image: 1},
4449        ovalTypes = {circle: 1, ellipse: 1},
4450        path2vml = function (path) {
4451            var total =  /[ahqstv]/ig,
4452                command = R._pathToAbsolute;
4453            Str(path).match(total) && (command = R._path2curve);
4454            total = /[clmz]/g;
4455            if (command == R._pathToAbsolute && !Str(path).match(total)) {
4456                var res = Str(path).replace(bites, function (all, command, args) {
4457                    var vals = [],
4458                        isMove = command.toLowerCase() == "m",
4459                        res = map[command];
4460                    args.replace(val, function (value) {
4461                        if (isMove && vals.length == 2) {
4462                            res += vals + map[command == "m" ? "l" : "L"];
4463                            vals = [];
4464                        }
4465                        vals.push(round(value * zoom));
4466                    });
4467                    return res + vals;
4468                });
4469                return res;
4470            }
4471            var pa = command(path), p, r;
4472            res = [];
4473            for (var i = 0, ii = pa.length; i < ii; i++) {
4474                p = pa[i];
4475                r = pa[i][0].toLowerCase();
4476                r == "z" && (r = "x");
4477                for (var j = 1, jj = p.length; j < jj; j++) {
4478                    r += round(p[j] * zoom) + (j != jj - 1 ? "," : E);
4479                }
4480                res.push(r);
4481            }
4482            return res.join(S);
4483        },
4484        compensation = function (deg, dx, dy) {
4485            var m = R.matrix();
4486            m.rotate(-deg, .5, .5);
4487            return {
4488                dx: m.x(dx, dy),
4489                dy: m.y(dx, dy)
4490            };
4491        },
4492        setCoords = function (p, sx, sy, dx, dy, deg) {
4493            var _ = p._,
4494                m = p.matrix,
4495                fillpos = _.fillpos,
4496                o = p.node,
4497                s = o.style,
4498                y = 1,
4499                flip = "",
4500                dxdy,
4501                kx = zoom / sx,
4502                ky = zoom / sy;
4503            s.visibility = "hidden";
4504            if (!sx || !sy) {
4505                return;
4506            }
4507            o.coordsize = abs(kx) + S + abs(ky);
4508            s.rotation = deg * (sx * sy < 0 ? -1 : 1);
4509            if (deg) {
4510                var c = compensation(deg, dx, dy);
4511                dx = c.dx;
4512                dy = c.dy;
4513            }
4514            sx < 0 && (flip += "x");
4515            sy < 0 && (flip += " y") && (y = -1);
4516            s.flip = flip;
4517            o.coordorigin = (dx * -kx) + S + (dy * -ky);
4518            if (fillpos || _.fillsize) {
4519                var fill = o.getElementsByTagName(fillString);
4520                fill = fill && fill[0];
4521                o.removeChild(fill);
4522                if (fillpos) {
4523                    c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));
4524                    fill.position = c.dx * y + S + c.dy * y;
4525                }
4526                if (_.fillsize) {
4527                    fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);
4528                }
4529                o.appendChild(fill);
4530            }
4531            s.visibility = "visible";
4532        };
4533    R.toString = function () {
4534        return  "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version;
4535    };
4536    addArrow = function (o, value, isEnd) {
4537        var values = Str(value).toLowerCase().split("-"),
4538            se = isEnd ? "end" : "start",
4539            i = values.length,
4540            type = "classic",
4541            w = "medium",
4542            h = "medium";
4543        while (i--) {
4544            switch (values[i]) {
4545                case "block":
4546                case "classic":
4547                case "oval":
4548                case "diamond":
4549                case "open":
4550                case "none":
4551                    type = values[i];
4552                    break;
4553                case "wide":
4554                case "narrow": h = values[i]; break;
4555                case "long":
4556                case "short": w = values[i]; break;
4557            }
4558        }
4559        var stroke = o.node.getElementsByTagName("stroke")[0];
4560        stroke[se + "arrow"] = type;
4561        stroke[se + "arrowlength"] = w;
4562        stroke[se + "arrowwidth"] = h;
4563    };
4564    setFillAndStroke = function (o, params) {
4565        // o.paper.canvas.style.display = "none";
4566        o.attrs = o.attrs || {};
4567        var node = o.node,
4568            a = o.attrs,
4569            s = node.style,
4570            xy,
4571            newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r),
4572            isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),
4573            res = o;
4574
4575
4576        for (var par in params) if (params[has](par)) {
4577            a[par] = params[par];
4578        }
4579        if (newpath) {
4580            a.path = R._getPath[o.type](o);
4581            o._.dirty = 1;
4582        }
4583        params.href && (node.href = params.href);
4584        params.title && (node.title = params.title);
4585        params.target && (node.target = params.target);
4586        params.cursor && (s.cursor = params.cursor);
4587        "blur" in params && o.blur(params.blur);
4588        if (params.path && o.type == "path" || newpath) {
4589            node.path = path2vml(~Str(a.path).toLowerCase().indexOf("r") ? R._pathToAbsolute(a.path) : a.path);
4590            if (o.type == "image") {
4591                o._.fillpos = [a.x, a.y];
4592                o._.fillsize = [a.width, a.height];
4593                setCoords(o, 1, 1, 0, 0, 0);
4594            }
4595        }
4596        "transform" in params && o.transform(params.transform);
4597        if (isOval) {
4598            var cx = +a.cx,
4599                cy = +a.cy,
4600                rx = +a.rx || +a.r || 0,
4601                ry = +a.ry || +a.r || 0;
4602            node.path = R.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom));
4603        }
4604        if ("clip-rect" in params) {
4605            var rect = Str(params["clip-rect"]).split(separator);
4606            if (rect.length == 4) {
4607                rect[2] = +rect[2] + (+rect[0]);
4608                rect[3] = +rect[3] + (+rect[1]);
4609                var div = node.clipRect || R._g.doc.createElement("div"),
4610                    dstyle = div.style;
4611                dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect);
4612                if (!node.clipRect) {
4613                    dstyle.position = "absolute";
4614                    dstyle.top = 0;
4615                    dstyle.left = 0;
4616                    dstyle.width = o.paper.width + "px";
4617                    dstyle.height = o.paper.height + "px";
4618                    node.parentNode.insertBefore(div, node);
4619                    div.appendChild(node);
4620                    node.clipRect = div;
4621                }
4622            }
4623            if (!params["clip-rect"]) {
4624                node.clipRect && (node.clipRect.style.clip = E);
4625            }
4626        }
4627        if (o.textpath) {
4628            var textpathStyle = o.textpath.style;
4629            params.font && (textpathStyle.font = params.font);
4630            params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"');
4631            params["font-size"] && (textpathStyle.fontSize = params["font-size"]);
4632            params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]);
4633            params["font-style"] && (textpathStyle.fontStyle = params["font-style"]);
4634        }
4635        if ("arrow-start" in params) {
4636            addArrow(res, params["arrow-start"]);
4637        }
4638        if ("arrow-end" in params) {
4639            addArrow(res, params["arrow-end"], 1);
4640        }
4641        if (params.opacity != null || 
4642            params["stroke-width"] != null ||
4643            params.fill != null ||
4644            params.src != null ||
4645            params.stroke != null ||
4646            params["stroke-width"] != null ||
4647            params["stroke-opacity"] != null ||
4648            params["fill-opacity"] != null ||
4649            params["stroke-dasharray"] != null ||
4650            params["stroke-miterlimit"] != null ||
4651            params["stroke-linejoin"] != null ||
4652            params["stroke-linecap"] != null) {
4653            var fill = node.getElementsByTagName(fillString),
4654                newfill = false;
4655            fill = fill && fill[0];
4656            !fill && (newfill = fill = createNode(fillString));
4657            if (o.type == "image" && params.src) {
4658                fill.src = params.src;
4659            }
4660            params.fill && (fill.on = true);
4661            if (fill.on == null || params.fill == "none" || params.fill === null) {
4662                fill.on = false;
4663            }
4664            if (fill.on && params.fill) {
4665                var isURL = Str(params.fill).match(R._ISURL);
4666                if (isURL) {
4667                    fill.parentNode == node && node.removeChild(fill);
4668                    fill.rotate = true;
4669                    fill.src = isURL[1];
4670                    fill.type = "tile";
4671                    var bbox = o.getBBox(1);
4672                    fill.position = bbox.x + S + bbox.y;
4673                    o._.fillpos = [bbox.x, bbox.y];
4674
4675                    R._preload(isURL[1], function () {
4676                        o._.fillsize = [this.offsetWidth, this.offsetHeight];
4677                    });
4678                } else {
4679                    fill.color = R.getRGB(params.fill).hex;
4680                    fill.src = E;
4681                    fill.type = "solid";
4682                    if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) {
4683                        a.fill = "none";
4684                        a.gradient = params.fill;
4685                        fill.rotate = false;
4686                    }
4687                }
4688            }
4689            if ("fill-opacity" in params || "opacity" in params) {
4690                var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);
4691                opacity = mmin(mmax(opacity, 0), 1);
4692                fill.opacity = opacity;
4693                if (fill.src) {
4694                    fill.color = "none";
4695                }
4696            }
4697            node.appendChild(fill);
4698            var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]),
4699            newstroke = false;
4700            !stroke && (newstroke = stroke = createNode("stroke"));
4701            if ((params.stroke && params.stroke != "none") ||
4702                params["stroke-width"] ||
4703                params["stroke-opacity"] != null ||
4704                params["stroke-dasharray"] ||
4705                params["stroke-miterlimit"] ||
4706                params["stroke-linejoin"] ||
4707                params["stroke-linecap"]) {
4708                stroke.on = true;
4709            }
4710            (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false);
4711            var strokeColor = R.getRGB(params.stroke);
4712            stroke.on && params.stroke && (stroke.color = strokeColor.hex);
4713            opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);
4714            var width = (toFloat(params["stroke-width"]) || 1) * .75;
4715            opacity = mmin(mmax(opacity, 0), 1);
4716            params["stroke-width"] == null && (width = a["stroke-width"]);
4717            params["stroke-width"] && (stroke.weight = width);
4718            width && width < 1 && (opacity *= width) && (stroke.weight = 1);
4719            stroke.opacity = opacity;
4720        
4721            params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter");
4722            stroke.miterlimit = params["stroke-miterlimit"] || 8;
4723            params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round");
4724            if (params["stroke-dasharray"]) {
4725                var dasharray = {
4726                    "-": "shortdash",
4727                    ".": "shortdot",
4728                    "-.": "shortdashdot",
4729                    "-..": "shortdashdotdot",
4730                    ". ": "dot",
4731                    "- ": "dash",
4732                    "--": "longdash",
4733                    "- .": "dashdot",
4734                    "--.": "longdashdot",
4735                    "--..": "longdashdotdot"
4736                };
4737                stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E;
4738            }
4739            newstroke && node.appendChild(stroke);
4740        }
4741        if (res.type == "text") {
4742            res.paper.canvas.style.display = E;
4743            var span = res.paper.span,
4744                m = 100,
4745                fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/);
4746            s = span.style;
4747            a.font && (s.font = a.font);
4748            a["font-family"] && (s.fontFamily = a["font-family"]);
4749            a["font-weight"] && (s.fontWeight = a["font-weight"]);
4750            a["font-style"] && (s.fontStyle = a["font-style"]);
4751            fontSize = toFloat(fontSize ? fontSize[0] : a["font-size"]);
4752            s.fontSize = fontSize * m + "px";
4753            res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>"));
4754            var brect = span.getBoundingClientRect();
4755            res.W = a.w = (brect.right - brect.left) / m;
4756            res.H = a.h = (brect.bottom - brect.top) / m;
4757            // res.paper.canvas.style.display = "none";
4758            res.X = a.x;
4759            res.Y = a.y + res.H / 2;
4760
4761            ("x" in params || "y" in params) && (res.path.v = R.format("m{0},{1}l{2},{1}", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1));
4762            var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"];
4763            for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {
4764                res._.dirty = 1;
4765                break;
4766            }
4767        
4768            // text-anchor emulation
4769            switch (a["text-anchor"]) {
4770                case "start":
4771                    res.textpath.style["v-text-align"] = "left";
4772                    res.bbx = res.W / 2;
4773                break;
4774                case "end":
4775                    res.textpath.style["v-text-align"] = "right";
4776                    res.bbx = -res.W / 2;
4777                break;
4778                default:
4779                    res.textpath.style["v-text-align"] = "center";
4780                    res.bbx = 0;
4781                break;
4782            }
4783            res.textpath.style["v-text-kern"] = true;
4784        }
4785        // res.paper.canvas.style.display = E;
4786    };
4787    addGradientFill = function (o, gradient, fill) {
4788        o.attrs = o.attrs || {};
4789        var attrs = o.attrs,
4790            opacity,
4791            oindex,
4792            type = "linear",
4793            fxfy = ".5 .5";
4794        o.attrs.gradient = gradient;
4795        gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {
4796            type = "radial";
4797            if (fx && fy) {
4798                fx = toFloat(fx);
4799                fy = toFloat(fy);
4800                pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);
4801                fxfy = fx + S + fy;
4802            }
4803            return E;
4804        });
4805        gradient = gradient.split(/\s*\-\s*/);
4806        if (type == "linear") {
4807            var angle = gradient.shift();
4808            angle = -toFloat(angle);
4809            if (isNaN(angle)) {
4810                return null;
4811            }
4812        }
4813        var dots = R._parseDots(gradient);
4814        if (!dots) {
4815            return null;
4816        }
4817        o = o.shape || o.node;
4818        if (dots.length) {
4819            o.removeChild(fill);
4820            fill.on = true;
4821            fill.method = "none";
4822            fill.color = dots[0].color;
4823            fill.color2 = dots[dots.length - 1].color;
4824            var clrs = [];
4825            for (var i = 0, ii = dots.length; i < ii; i++) {
4826                dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);
4827            }
4828            fill.colors = clrs.length ? clrs.join() : "0% " + fill.color;
4829            if (type == "radial") {
4830                fill.type = "gradientTitle";
4831                fill.focus = "100%";
4832                fill.focussize = "0 0";
4833                fill.focusposition = fxfy;
4834                fill.angle = 0;
4835            } else {
4836                // fill.rotate= true;
4837                fill.type = "gradient";
4838                fill.angle = (270 - angle) % 360;
4839            }
4840            o.appendChild(fill);
4841        }
4842        return 1;
4843    };
4844    Element = function (node, vml) {
4845        this[0] = this.node = node;
4846        node.raphael = true;
4847        this.id = R._oid++;
4848        node.raphaelid = this.id;
4849        this.X = 0;
4850        this.Y = 0;
4851        this.attrs = {};
4852        this.paper = vml;
4853        this.matrix = R.matrix();
4854        this._ = {
4855            transform: [],
4856            sx: 1,
4857            sy: 1,
4858            dx: 0,
4859            dy: 0,
4860            deg: 0,
4861            dirty: 1,
4862            dirtyT: 1
4863        };
4864        !vml.bottom && (vml.bottom = this);
4865        this.prev = vml.top;
4866        vml.top && (vml.top.next = this);
4867        vml.top = this;
4868        this.next = null;
4869    };
4870    var elproto = R.el;
4871
4872    Element.prototype = elproto;
4873    elproto.constructor = Element;
4874    elproto.transform = function (tstr) {
4875        if (tstr == null) {
4876            return this._.transform;
4877        }
4878        var vbs = this.paper._viewBoxShift,
4879            vbt = vbs ? "s" + [vbs.scale, vbs.scale] + "-1-1t" + [vbs.dx, vbs.dy] : E,
4880            oldt;
4881        if (vbs) {
4882            oldt = tstr = Str(tstr).replace(/\.{3}|\u2026/g, this._.transform || E);
4883        }
4884        R._extractTransform(this, vbt + tstr);
4885        var matrix = this.matrix.clone(),
4886            skew = this.skew,
4887            o = this.node,
4888            split,
4889            isGrad = ~Str(this.attrs.fill).indexOf("-"),
4890            isPatt = !Str(this.attrs.fill).indexOf("url(");
4891        matrix.translate(-.5, -.5);
4892        if (isPatt || isGrad || this.type == "image") {
4893            skew.matrix = "1 0 0 1";
4894            skew.offset = "0 0";
4895            split = matrix.split();
4896            if ((isGrad && split.noRotation) || !split.isSimple) {
4897                o.style.filter = matrix.toFilter();
4898                var bb = this.getBBox(),
4899                    bbt = this.getBBox(1),
4900                    dx = bb.x - bbt.x,
4901                    dy = bb.y - bbt.y;
4902                o.coordorigin = (dx * -zoom) + S + (dy * -zoom);
4903                setCoords(this, 1, 1, dx, dy, 0);
4904            } else {
4905                o.style.filter = E;
4906                setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);
4907            }
4908        } else {
4909            o.style.filter = E;
4910            skew.matrix = Str(matrix);
4911            skew.offset = matrix.offset();
4912        }
4913        oldt && (this._.transform = oldt);
4914        return this;
4915    };
4916    elproto.rotate = function (deg, cx, cy) {
4917        if (this.removed) {
4918            return this;
4919        }
4920        if (deg == null) {
4921            return;
4922        }
4923        deg = Str(deg).split(separator);
4924        if (deg.length - 1) {
4925            cx = toFloat(deg[1]);
4926            cy = toFloat(deg[2]);
4927        }
4928        deg = toFloat(deg[0]);
4929        (cy == null) && (cx = cy);
4930        if (cx == null || cy == null) {
4931            var bbox = this.getBBox(1);
4932            cx = bbox.x + bbox.width / 2;
4933            cy = bbox.y + bbox.height / 2;
4934        }
4935        this._.dirtyT = 1;
4936        this.transform(this._.transform.concat([["r", deg, cx, cy]]));
4937        return this;
4938    };
4939    elproto.translate = function (dx, dy) {
4940        if (this.removed) {
4941            return this;
4942        }
4943        dx = Str(dx).split(separator);
4944        if (dx.length - 1) {
4945            dy = toFloat(dx[1]);
4946        }
4947        dx = toFloat(dx[0]) || 0;
4948        dy = +dy || 0;
4949        if (this._.bbox) {
4950            this._.bbox.x += dx;
4951            this._.bbox.y += dy;
4952        }
4953        this.transform(this._.transform.concat([["t", dx, dy]]));
4954        return this;
4955    };
4956    elproto.scale = function (sx, sy, cx, cy) {
4957        if (this.removed) {
4958            return this;
4959        }
4960        sx = Str(sx).split(separator);
4961        if (sx.length - 1) {
4962            sy = toFloat(sx[1]);
4963            cx = toFloat(sx[2]);
4964            cy = toFloat(sx[3]);
4965            isNaN(cx) && (cx = null);
4966            isNaN(cy) && (cy = null);
4967        }
4968        sx = toFloat(sx[0]);
4969        (sy == null) && (sy = sx);
4970        (cy == null) && (cx = cy);
4971        if (cx == null || cy == null) {
4972            var bbox = this.getBBox(1);
4973        }
4974        cx = cx == null ? bbox.x + bbox.width / 2 : cx;
4975        cy = cy == null ? bbox.y + bbox.height / 2 : cy;
4976    
4977        this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
4978        this._.dirtyT = 1;
4979        return this;
4980    };
4981    elproto.hide = function () {
4982        !this.removed && (this.node.style.display = "none");
4983        return this;
4984    };
4985    elproto.show = function () {
4986        !this.removed && (this.node.style.display = E);
4987        return this;
4988    };
4989    elproto._getBBox = function () {
4990        if (this.removed) {
4991            return {};
4992        }
4993        if (this.type == "text") {
4994            return {
4995                x: this.X + (this.bbx || 0) - this.W / 2,
4996                y: this.Y - this.H,
4997                width: this.W,
4998                height: this.H
4999            };
5000        } else {
5001            return pathDimensions(this.attrs.path);
5002        }
5003    };
5004    elproto.remove = function () {
5005        if (this.removed) {
5006            return;
5007        }
5008        R.eve.unbind("*.*." + this.id);
5009        R._tear(this, this.paper);
5010        this.node.parentNode.removeChild(this.node);
5011        this.shape && this.shape.parentNode.removeChild(this.shape);
5012        for (var i in this) {
5013            delete this[i];
5014        }
5015        this.removed = true;
5016    };
5017    elproto.attr = function (name, value) {
5018        if (this.removed) {
5019            return this;
5020        }
5021        if (name == null) {
5022            var res = {};
5023            for (var a in this.attrs) if (this.attrs[has](a)) {
5024                res[a] = this.attrs[a];
5025            }
5026            res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
5027            res.transform = this._.transform;
5028            return res;
5029        }
5030        if (value == null && R.is(name, "string")) {
5031            if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {
5032                return this.attrs.gradient;
5033            }
5034            var names = name.split(separator),
5035                out = {};
5036            for (var i = 0, ii = names.length; i < ii; i++) {
5037                name = names[i];
5038                if (name in this.attrs) {
5039                    out[name] = this.attrs[name];
5040                } else if (R.is(this.paper.customAttributes[name], "function")) {
5041                    out[name] = this.paper.customAttributes[name].def;
5042                } else {
5043                    out[name] = R._availableAttrs[name];
5044                }
5045            }
5046            return ii - 1 ? out : out[names[0]];
5047        }
5048        if (this.attrs && value == null && R.is(name, "array")) {
5049            out = {};
5050            for (i = 0, ii = name.length; i < ii; i++) {
5051                out[name[i]] = this.attr(name[i]);
5052            }
5053            return out;
5054        }
5055        var params;
5056        if (value != null) {
5057            params = {};
5058            params[name] = value;
5059        }
5060        value == null && R.is(name, "object") && (params = name);
5061        for (var key in params) {
5062            R.eve("attr." + key + "." + this.id, this, params[key]);
5063        }
5064        if (params) {
5065            for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
5066                var par = this.paper.customAttributes[key].apply(this, [][concat](params[key]));
5067                this.attrs[key] = params[key];
5068                for (var subkey in par) if (par[has](subkey)) {
5069                    params[subkey] = par[subkey];
5070                }
5071            }
5072            // this.paper.canvas.style.display = "none";
5073            if (params.text && this.type == "text") {
5074                this.textpath.string = params.text;
5075            }
5076            setFillAndStroke(this, params);
5077            // this.paper.canvas.style.display = E;
5078        }
5079        return this;
5080    };
5081    elproto.toFront = function () {
5082        !this.removed && this.node.parentNode.appendChild(this.node);
5083        this.paper && this.paper.top != this && R._tofront(this, this.paper);
5084        return this;
5085    };
5086    elproto.toBack = function () {
5087        if (this.removed) {
5088            return this;
5089        }
5090        if (this.node.parentNode.firstChild != this.node) {
5091            this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
5092            R._toback(this, this.paper);
5093        }
5094        return this;
5095    };
5096    elproto.insertAfter = function (element) {
5097        if (this.removed) {
5098            return this;
5099        }
5100        if (element.constructor == R.st.constructor) {
5101            element = element[element.length - 1];
5102        }
5103        if (element.node.nextSibling) {
5104            element.node.parentNode.insertBefore(this.node, element.node.nextSibling);
5105        } else {
5106            element.node.parentNode.appendChild(this.node);
5107        }
5108        R._insertafter(this, element, this.paper);
5109        return this;
5110    };
5111    elproto.insertBefore = function (element) {
5112        if (this.removed) {
5113            return this;
5114        }
5115        if (element.constructor == R.st.constructor) {
5116            element = element[0];
5117        }
5118        element.node.parentNode.insertBefore(this.node, element.node);
5119        R._insertbefore(this, element, this.paper);
5120        return this;
5121    };
5122    elproto.blur = function (size) {
5123        var s = this.node.runtimeStyle,
5124            f = s.filter;
5125        f = f.replace(blurregexp, E);
5126        if (+size !== 0) {
5127            this.attrs.blur = size;
5128            s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")";
5129            s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5));
5130        } else {
5131            s.filter = f;
5132            s.margin = 0;
5133            delete this.attrs.blur;
5134        }
5135    };
5136
5137    R._engine.path = function (pathString, vml) {
5138        var el = createNode("shape");
5139        el.style.cssText = cssDot;
5140        el.coordsize = zoom + S + zoom;
5141        el.coordorigin = vml.coordorigin;
5142        var p = new Element(el, vml),
5143            attr = {fill: "none", stroke: "#000"};
5144        pathString && (attr.path = pathString);
5145        p.type = "path";
5146        p.path = [];
5147        p.Path = E;
5148        setFillAndStroke(p, attr);
5149        vml.canvas.appendChild(el);
5150        var skew = createNode("skew");
5151        skew.on = true;
5152        el.appendChild(skew);
5153        p.skew = skew;
5154        p.transform(E);
5155        return p;
5156    };
5157    R._engine.rect = function (vml, x, y, w, h, r) {
5158        var path = R._rectPath(x, y, w, h, r),
5159            res = vml.path(path),
5160            a = res.attrs;
5161        res.X = a.x = x;
5162        res.Y = a.y = y;
5163        res.W = a.width = w;
5164        res.H = a.height = h;
5165        a.r = r;
5166        a.path = path;
5167        res.type = "rect";
5168        return res;
5169    };
5170    R._engine.ellipse = function (vml, x, y, rx, ry) {
5171        var res = vml.path(),
5172            a = res.attrs;
5173        res.X = x - rx;
5174        res.Y = y - ry;
5175        res.W = rx * 2;
5176        res.H = ry * 2;
5177        res.type = "ellipse";
5178        setFillAndStroke(res, {
5179            cx: x,
5180            cy: y,
5181            rx: rx,
5182            ry: ry
5183        });
5184        return res;
5185    };
5186    R._engine.circle = function (vml, x, y, r) {
5187        var res = vml.path(),
5188            a = res.attrs;
5189        res.X = x - r;
5190        res.Y = y - r;
5191        res.W = res.H = r * 2;
5192        res.type = "circle";
5193        setFillAndStroke(res, {
5194            cx: x,
5195            cy: y,
5196            r: r
5197        });
5198        return res;
5199    };
5200    R._engine.image = function (vml, src, x, y, w, h) {
5201        var path = R._rectPath(x, y, w, h),
5202            res = vml.path(path).attr({stroke: "none"}),
5203            a = res.attrs,
5204            node = res.node,
5205            fill = node.getElementsByTagName(fillString)[0];
5206        a.src = src;
5207        res.X = a.x = x;
5208        res.Y = a.y = y;
5209        res.W = a.width = w;
5210        res.H = a.height = h;
5211        a.path = path;
5212        res.type = "image";
5213        fill.parentNode == node && node.removeChild(fill);
5214        fill.rotate = true;
5215        fill.src = src;
5216        fill.type = "tile";
5217        res._.fillpos = [x, y];
5218        res._.fillsize = [w, h];
5219        node.appendChild(fill);
5220        setCoords(res, 1, 1, 0, 0, 0);
5221        return res;
5222    };
5223    R._engine.text = function (vml, x, y, text) {
5224        var el = createNode("shape"),
5225            path = createNode("path"),
5226            o = createNode("textpath");
5227        x = x || 0;
5228        y = y || 0;
5229        text = text || "";
5230        path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1);
5231        path.textpathok = true;
5232        o.string = Str(text);
5233        o.on = true;
5234        el.style.cssText = "position:absolute;left:0;top:0;width:1px;height:1px";
5235        el.coordsize = zoom + S + zoom;
5236        el.coordorigin = "0 0";
5237        var p = new Element(el, vml),
5238            attr = {
5239                fill: "#000",
5240                stroke: "none",
5241                font: R._availableAttrs.font,
5242                text: text
5243            };
5244        p.shape = el;
5245        p.path = path;
5246        p.textpath = o;
5247        p.type = "text";
5248        p.attrs.text = Str(text);
5249        p.attrs.x = x;
5250        p.attrs.y = y;
5251        p.attrs.w = 1;
5252        p.attrs.h = 1;
5253        setFillAndStroke(p, attr);
5254        el.appendChild(o);
5255        el.appendChild(path);
5256        vml.canvas.appendChild(el);
5257        var skew = createNode("skew");
5258        skew.on = true;
5259        el.appendChild(skew);
5260        p.skew = skew;
5261        p.transform(E);
5262        return p;
5263    };
5264    R._engine.setSize = function (width, height) {
5265        var cs = this.canvas.style;
5266        this.width = width;
5267        this.height = height;
5268        width == +width && (width += "px");
5269        height == +height && (height += "px");
5270        cs.width = width;
5271        cs.height = height;
5272        cs.clip = "rect(0 " + width + " " + height + " 0)";
5273        if (this._viewBox) {
5274            setViewBox.apply(this, this._viewBox);
5275        }
5276        return this;
5277    };
5278    R._engine.setViewBox = function (x, y, w, h, fit) {
5279        R.eve("setViewBox", this, this._viewBox, [x, y, w, h, fit]);
5280        var width = this.width,
5281            height = this.height,
5282            size = 1 / mmax(w / width, h / height),
5283            H, W;
5284        if (fit) {
5285            H = height / h;
5286            W = width / w;
5287            if (w * H < width) {
5288                x -= (width - w * H) / 2 / H;
5289            }
5290            if (h * W < height) {
5291                y -= (height - h * W) / 2 / W;
5292            }
5293        }
5294        this._viewBox = [x, y, w, h, !!fit];
5295        this._viewBoxShift = {
5296            dx: -x,
5297            dy: -y,
5298            scale: size
5299        };
5300        this.forEach(function (el) {
5301            el.transform("...");
5302        });
5303        return this;
5304    };
5305    var createNode,
5306        initWin = function (win) {
5307            var doc = win.document;
5308            doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
5309            try {
5310                !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
5311                createNode = function (tagName) {
5312                    return doc.createElement('<rvml:' + tagName + ' class="rvml">');
5313                };
5314            } catch (e) {
5315                createNode = function (tagName) {
5316                    return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
5317                };
5318            }
5319        };
5320    initWin(R._g.win);
5321    R._engine.create = function () {
5322        var con = R._getContainer.apply(0, arguments),
5323            container = con.container,
5324            height = con.height,
5325            s,
5326            width = con.width,
5327            x = con.x,
5328            y = con.y;
5329        if (!container) {
5330            throw new Error("VML container not found.");
5331        }
5332        var res = new R._Paper,
5333            c = res.canvas = R._g.doc.createElement("div"),
5334            cs = c.style;
5335        x = x || 0;
5336        y = y || 0;
5337        width = width || 512;
5338        height = height || 342;
5339        res.width = width;
5340        res.height = height;
5341        width == +width && (width += "px");
5342        height == +height && (height += "px");
5343        res.coordsize = zoom * 1e3 + S + zoom * 1e3;
5344        res.coordorigin = "0 0";
5345        res.span = R._g.doc.createElement("span");
5346        res.span.style.cssText = "position:absolute;
5346left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;";
5347        c.appendChild(res.span);
5348        cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height);
5349        if (container == 1) {
5350            R._g.doc.body.appendChild(c);
5351            cs.left = x + "px";
5352            cs.top = y + "px";
5353            cs.position = "absolute";
5354        } else {
5355            if (container.firstChild) {
5356                container.insertBefore(c, container.firstChild);
5357            } else {
5358                container.appendChild(c);
5359            }
5360        }
5361        // plugins.call(res, res, R.fn);
5362        res.renderfix = function () {};
5363        return res;
5364    };
5365    R.prototype.clear = function () {
5366        R.eve("clear", this);
5367        this.canvas.innerHTML = E;
5368        this.span = R._g.doc.createElement("span");
5369        this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
5370        this.canvas.appendChild(this.span);
5371        this.bottom = this.top = null;
5372    };
5373    R.prototype.remove = function () {
5374        R.eve("remove", this);
5375        this.canvas.parentNode.removeChild(this.canvas);
5376        for (var i in this) {
5377            this[i] = removed(i);
5378        }
5379        return true;
5380    };
5381}(window.Raphael);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.