~therp-nl/openerp-web/7.0-lp1013636-x2m_honour_required_attribute

« back to all changes in this revision

Viewing changes to addons/web_diagram/static/lib/js/raphael.js

[MERGE] from trunk

Show diffs side-by-side

added added

removed removed

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