1 // ┌─────────────────────────────────────────────────────────────────────┐ \\
2 // │ Raphaël 2.0.1 - JavaScript Vector Library │ \\
3 // ├─────────────────────────────────────────────────────────────────────┤ \\
4 // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
5 // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\
6 // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
7 // └─────────────────────────────────────────────────────────────────────┘ \\
9 // ┌──────────────────────────────────────────────────────────────────────────────────────┐ \\
10 // │ Eve 0.4.0 - JavaScript Events Library │ \\
11 // ├──────────────────────────────────────────────────────────────────────────────────────┤ \\
12 // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/) │ \\
13 // │ Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. │ \\
14 // └──────────────────────────────────────────────────────────────────────────────────────┘ \\
17 var version
= "0.4.0",
18 has
= "hasOwnProperty",
22 numsort = function (a
, b
) {
29 eve = function (name
, scope
) {
32 args
= Array
.prototype.slice
.call(arguments
, 2),
33 listeners
= eve
.listeners(name
),
43 for (var i
= 0, ii
= listeners
.length
; i
< ii
; i
++) if ("zIndex" in listeners
[i
]) {
44 indexed
.push(listeners
[i
].zIndex
);
45 if (listeners
[i
].zIndex
< 0) {
46 queue
[listeners
[i
].zIndex
] = listeners
[i
];
49 indexed
.sort(numsort
);
50 while (indexed
[z
] < 0) {
51 l
= queue
[indexed
[z
++]];
52 out
.push(l
.apply(scope
, args
));
58 for (i
= 0; i
< ii
; i
++) {
61 if (l
.zIndex
== indexed
[z
]) {
62 out
.push(l
.apply(scope
, args
));
69 l
= queue
[indexed
[z
]];
70 l
&& out
.push(l
.apply(scope
, args
));
80 out
.push(l
.apply(scope
, args
));
88 return out
.length
? out
: null;
91 eve
.listeners = function (name
) {
92 var names
= name
.split(separator
),
104 for (i
= 0, ii
= names
.length
; i
< ii
; i
++) {
106 for (j
= 0, jj
= es
.length
; j
< jj
; j
++) {
108 items
= [e
[names
[i
]], e
[wildcard
]];
114 out
= out
.concat(item
.f
|| []);
124 eve
.on = function (name
, f
) {
125 var names
= name
.split(separator
),
127 for (var i
= 0, ii
= names
.length
; i
< ii
; i
++) {
129 !e
[names
[i
]] && (e
[names
[i
]] = {n
: {}});
133 for (i
= 0, ii
= e
.f
.length
; i
< ii
; i
++) if (e
.f
[i
] == f
) {
137 return function (zIndex
) {
138 if (+zIndex
== +zIndex
) {
144 eve
.stop = function () {
148 eve
.nt = function (subname
) {
150 return new RegExp("(?:\\.|\\/|^)" + subname
+ "(?:\\.|\\/|$)").test(current_event
);
152 return current_event
;
155 eve
.unbind = function (name
, f
) {
156 var names
= name
.split(separator
),
162 for (i
= 0, ii
= names
.length
; i
< ii
; i
++) {
163 for (j
= 0; j
< cur
.length
; j
+= splice
.length
- 2) {
166 if (names
[i
] != wildcard
) {
168 splice
.push(e
[names
[i
]]);
171 for (key
in e
) if (e
[has
](key
)) {
175 cur
.splice
.apply(cur
, splice
);
178 for (i
= 0, ii
= cur
.length
; i
< ii
; i
++) {
183 for (j
= 0, jj
= e
.f
.length
; j
< jj
; j
++) if (e
.f
[j
] == f
) {
187 !e
.f
.length
&& delete e
.f
;
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
) {
195 !funcs
.length
&& delete e
.n
[key
].f
;
199 for (key
in e
.n
) if (e
.n
[has
](key
) && e
.n
[key
].f
) {
208 eve
.once = function (name
, f
) {
209 var f2 = function () {
210 f
.apply(this, arguments
);
211 eve
.unbind(name
, f2
);
213 return eve
.on(name
, f2
);
216 eve
.version
= version
;
217 eve
.toString = function () {
218 return "You are running Eve " + version
;
220 (typeof module
!= "undefined" && module
.exports
) ? (module
.exports
= eve
) : (glob
.eve
= eve
);
223 // ┌─────────────────────────────────────────────────────────────────────┐ \\
224 // │ "Raphaël 2.0.1" - JavaScript Vector Library │ \\
225 // ├─────────────────────────────────────────────────────────────────────┤ \\
226 // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
227 // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\
228 // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
229 // └─────────────────────────────────────────────────────────────────────┘ \\
233 if (R
.is(first
, "function")) {
234 return loaded
? first() : eve
.on("DOMload", first
);
235 } else if (R
.is(first
, array
)) {
236 return R
._engine
.create
[apply
](R
, first
.splice(0, 3 + R
.is(first
[0], nu
))).add(first
);
238 var args
= Array
.prototype.slice
.call(arguments
, 0);
239 if (R
.is(args
[args
.length
- 1], "function")) {
241 return loaded
? f
.call(R
._engine
.create
[apply
](R
, args
)) : eve
.on("DOMload", function () {
242 f
.call(R
._engine
.create
[apply
](R
, args
));
245 return R
._engine
.create
[apply
](R
, arguments
);
253 elements
= {circle
: 1, rect
: 1, path
: 1, ellipse
: 1, text
: 1, image
: 1},
254 formatrg
= /\{(\d+)\}/g,
256 has
= "hasOwnProperty",
262 was
: Object
.prototype[has
].call(g
.win
, "Raphael"),
265 Paper = function () {
268 this.ca
= this.customAttributes
= {};
271 appendChild
= "appendChild",
274 //supportsTouch = "createTouch" in g.doc,
275 supportsTouch
= false,
280 events
= "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[split
](S
),
282 mousedown
: "touchstart",
283 mousemove
: "touchmove",
286 lowerCase
= Str
.prototype.toLowerCase
,
296 toString
= "toString",
298 objectToString
= Object
.prototype.toString
,
301 ISURL
= R
._ISURL
= /^url\(['"]?([^\)]+?)['"]?\)$/i,
302 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,
303 isnan
= {"NaN": 1, "Infinity": 1, "-Infinity": 1},
304 bezierrg
= /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
306 setAttribute
= "setAttribute",
307 toFloat
= parseFloat
,
309 upperCase
= Str
.prototype.toUpperCase
,
310 availableAttrs
= R
._availableAttrs
= {
312 "arrow-start": "none",
314 "clip-rect": "0 0 1e9 1e9",
320 font
: '10px "Arial"',
321 "font-family": '"Arial"',
323 "font-style": "normal",
327 href
: "http://raphaeljs.com/",
336 "stroke-dasharray": "",
337 "stroke-linecap": "butt",
338 "stroke-linejoin": "butt",
339 "stroke-miterlimit": 0,
343 "text-anchor": "middle",
350 availableAnimAttrs
= R
._availableAnimAttrs
= {
365 "stroke-opacity": nu
,
367 transform
: "transform",
372 commaSpaces
= /\s*,\s*/,
373 hsrg
= {hs
: 1, rg
: 1},
374 p2s
= /,?([achlmqrstvxz]),?/gi,
375 pathCommand
= /([achlmrqstvz])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?\s*,?\s*)+)/ig,
376 tCommand
= /([rstm])[\s,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?\s*,?\s*)+)/ig,
377 pathValues
= /(-?\d*\.?\d*(?:e[\-+]?\d+)?)\s*,?\s*/ig,
378 radial_gradient
= R
._radial_gradient
= /^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/,
380 sortByKey = function (a
, b
) {
381 return a
.key
- b
.key
;
383 sortByNumber = function (a
, b
) {
384 return toFloat(a
) - toFloat(b
);
386 fun = function () {},
387 pipe = function (x
) {
390 rectPath
= R
._rectPath = function (x
, y
, w
, h
, r
) {
392 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"]];
394 return [["M", x
, y
], ["l", w
, 0], ["l", 0, h
], ["l", -w
, 0], ["z"]];
396 ellipsePath = function (x
, y
, rx
, ry
) {
400 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"]];
402 getPath
= R
._getPath
= {
403 path: function (el
) {
404 return el
.attr("path");
406 circle: function (el
) {
408 return ellipsePath(a
.cx
, a
.cy
, a
.r
);
410 ellipse: function (el
) {
412 return ellipsePath(a
.cx
, a
.cy
, a
.rx
, a
.ry
);
414 rect: function (el
) {
416 return rectPath(a
.x
, a
.y
, a
.width
, a
.height
, a
.r
);
418 image: function (el
) {
420 return rectPath(a
.x
, a
.y
, a
.width
, a
.height
);
422 text: function (el
) {
423 var bbox
= el
._getBBox();
424 return rectPath(bbox
.x
, bbox
.y
, bbox
.width
, bbox
.height
);
427 mapPath
= R
.mapPath = function (path
, matrix
) {
431 var x
, y
, i
, j
, ii
, jj
, pathi
;
432 path
= path2curve(path
);
433 for (i
= 0, ii
= path
.length
; i
< ii
; i
++) {
435 for (j
= 1, jj
= pathi
.length
; j
< jj
; j
+= 2) {
436 x
= matrix
.x(pathi
[j
], pathi
[j
+ 1]);
437 y
= matrix
.y(pathi
[j
], pathi
[j
+ 1]);
447 R
.type
= (g
.win
.SVGAngle
|| g
.doc
.implementation
.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML");
448 if (R
.type
== "VML") {
449 var d
= g
.doc
.createElement("div"),
451 d
.innerHTML
= '<v:shape adj="1"/>';
453 b
.style
.behavior
= "url(#default#VML)";
454 if (!(b
&& typeof b
.adj
== "object")) {
461 R
.svg
= !(R
.vml
= R
.type
== "VML");
464 R
.fn
= paperproto
= Paper
.prototype = R
.prototype;
468 R
.is = function (o
, type
) {
469 type
= lowerCase
.call(type
);
470 if (type
== "finite") {
471 return !isnan
[has
](+o
);
473 if (type
== "array") {
474 return o
instanceof Array
;
476 return (type
== "null" && o
=== null) ||
477 (type
== typeof o
&& o
!== null) ||
478 (type
== "object" && o
=== Object(o
)) ||
479 (type
== "array" && Array
.isArray
&& Array
.isArray(o
)) ||
480 objectToString
.call(o
).slice(8, -1).toLowerCase() == type
;
483 R
.angle = function (x1
, y1
, x2
, y2
, x3
, y3
) {
490 return (180 + math
.atan2(-y
, -x
) * 180 / PI
+ 360) % 360;
492 return R
.angle(x1
, y1
, x3
, y3
) - R
.angle(x2
, y2
, x3
, y3
);
496 R
.rad = function (deg
) {
497 return deg
% 360 * PI
/ 180;
500 R
.deg = function (rad
) {
501 return rad
* 180 / PI
% 360;
504 R
.snapTo = function (values
, value
, tolerance
) {
505 tolerance
= R
.is(tolerance
, "finite") ? tolerance
: 10;
506 if (R
.is(values
, array
)) {
507 var i
= values
.length
;
508 while (i
--) if (abs(values
[i
] - value
) <= tolerance
) {
513 var rem
= value
% values
;
514 if (rem
< tolerance
) {
517 if (rem
> values
- tolerance
) {
518 return value
- rem
+ values
;
525 var createUUID
= R
.createUUID
= (function (uuidRegEx
, uuidReplacer
) {
527 return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx
, uuidReplacer
).toUpperCase();
529 })(/[xy]/g, function (c
) {
530 var r
= math
.random() * 16 | 0,
531 v
= c
== "x" ? r
: (r
& 3 | 8);
532 return v
.toString(16);
536 R
.setWindow = function (newwin
) {
537 eve("setWindow", R
, g
.win
, newwin
);
539 g
.doc
= g
.win
.document
;
540 if (R
._engine
.initWin
) {
541 R
._engine
.initWin(g
.win
);
544 var toHex = function (color
) {
546 // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/
547 var trim
= /^\s+|\s+$/g;
550 var docum
= new ActiveXObject("htmlfile");
551 docum
.write("<body>");
555 bod
= createPopup().document
.body
;
557 var range
= bod
.createTextRange();
558 toHex
= cacher(function (color
) {
560 bod
.style
.color
= Str(color
).replace(trim
, E
);
561 var value
= range
.queryCommandValue("ForeColor");
562 value
= ((value
& 255) << 16) | (value
& 65280) | ((value
& 16711680) >>> 16);
563 return "#" + ("000000" + value
.toString(16)).slice(-6);
569 var i
= g
.doc
.createElement("i");
570 i
.title
= "Rapha\xebl Colour Picker";
571 i
.style
.display
= "none";
572 g
.doc
.body
.appendChild(i
);
573 toHex
= cacher(function (color
) {
574 i
.style
.color
= color
;
575 return g
.doc
.defaultView
.getComputedStyle(i
, E
).getPropertyValue("color");
580 hsbtoString = function () {
581 return "hsb(" + [this.h
, this.s
, this.b
] + ")";
583 hsltoString = function () {
584 return "hsl(" + [this.h
, this.s
, this.l
] + ")";
586 rgbtoString = function () {
589 prepareRGB = function (r
, g
, b
) {
590 if (g
== null && R
.is(r
, "object") && "r" in r
&& "g" in r
&& "b" in r
) {
595 if (g
== null && R
.is(r
, string
)) {
596 var clr
= R
.getRGB(r
);
601 if (r
> 1 || g
> 1 || b
> 1) {
609 packageRGB = function (r
, g
, b
, o
) {
618 toString
: rgbtoString
620 R
.is(o
, "finite") && (rgb
.opacity
= o
);
625 R
.color = function (clr
) {
627 if (R
.is(clr
, "object") && "h" in clr
&& "s" in clr
&& "b" in clr
) {
628 rgb
= R
.hsb2rgb(clr
);
633 } else if (R
.is(clr
, "object") && "h" in clr
&& "s" in clr
&& "l" in clr
) {
634 rgb
= R
.hsl2rgb(clr
);
640 if (R
.is(clr
, "string")) {
643 if (R
.is(clr
, "object") && "r" in clr
&& "g" in clr
&& "b" in clr
) {
644 rgb
= R
.rgb2hsl(clr
);
648 rgb
= R
.rgb2hsb(clr
);
652 clr
.r
= clr
.g
= clr
.b
= clr
.h
= clr
.s
= clr
.v
= clr
.l
= -1;
655 clr
.toString
= rgbtoString
;
659 R
.hsb2rgb = function (h
, s
, v
, o
) {
660 if (this.is(h
, "object") && "h" in h
&& "s" in h
&& "b" in h
) {
670 X
= C
* (1 - abs(h
% 2 - 1));
674 R
+= [C
, X
, 0, 0, X
, C
][h
];
675 G
+= [X
, C
, C
, X
, 0, 0][h
];
676 B
+= [0, 0, X
, C
, C
, X
][h
];
677 return packageRGB(R
, G
, B
, o
);
680 R
.hsl2rgb = function (h
, s
, l
, o
) {
681 if (this.is(h
, "object") && "h" in h
&& "s" in h
&& "l" in h
) {
686 if (h
> 1 || s
> 1 || l
> 1) {
694 C
= 2 * s
* (l
< .5 ? l
: 1 - l
);
695 X
= C
* (1 - abs(h
% 2 - 1));
696 R
= G
= B
= l
- C
/ 2;
699 R
+= [C
, X
, 0, 0, X
, C
][h
];
700 G
+= [X
, C
, C
, X
, 0, 0][h
];
701 B
+= [0, 0, X
, C
, C
, X
][h
];
702 return packageRGB(R
, G
, B
, o
);
705 R
.rgb2hsb = function (r
, g
, b
) {
706 b
= prepareRGB(r
, g
, b
);
713 C
= V
- mmin(r
, g
, b
);
715 V
== r
? (g
- b
) / C
:
716 V
== g
? (b
- r
) / C
+ 2 :
719 H
= ((H
+ 360) % 6) * 60 / 360;
720 S
= C
== 0 ? 0 : C
/ V
;
721 return {h
: H
, s
: S
, b
: V
, toString
: hsbtoString
};
724 R
.rgb2hsl = function (r
, g
, b
) {
725 b
= prepareRGB(r
, g
, b
);
730 var H
, S
, L
, M
, m
, C
;
735 M
== r
? (g
- b
) / C
:
736 M
== g
? (b
- r
) / C
+ 2 :
738 H
= ((H
+ 360) % 6) * 60 / 360;
741 L
< .5 ? C
/ (2 * L
) :
743 return {h
: H
, s
: S
, l
: L
, toString
: hsltoString
};
745 R
._path2string = function () {
746 return this.join(",").replace(p2s
, "$1");
748 function repush(array
, item
) {
749 for (var i
= 0, ii
= array
.length
; i
< ii
; i
++) if (array
[i
] === item
) {
750 return array
.push(array
.splice(i
, 1)[0]);
753 function cacher(f
, scope
, postprocessor
) {
755 var arg
= Array
.prototype.slice
.call(arguments
, 0),
756 args
= arg
.join("\u2400"),
757 cache
= newf
.cache
= newf
.cache
|| {},
758 count
= newf
.count
= newf
.count
|| [];
759 if (cache
[has
](args
)) {
761 return postprocessor
? postprocessor(cache
[args
]) : cache
[args
];
763 count
.length
>= 1e3
&& delete cache
[count
.shift()];
765 cache
[args
] = f
[apply
](scope
, arg
);
766 return postprocessor
? postprocessor(cache
[args
]) : cache
[args
];
771 var preload
= R
._preload = function (src
, f
) {
772 var img
= g
.doc
.createElement("img");
773 img
.style
.cssText
= "position:absolute;left:-9999em;top:-9999em";
774 img
.onload = function () {
777 g
.doc
.body
.removeChild(this);
779 img
.onerror = function () {
780 g
.doc
.body
.removeChild(this);
782 g
.doc
.body
.appendChild(img
);
786 function clrToString() {
791 R
.getRGB
= cacher(function (colour
) {
792 if (!colour
|| !!((colour
= Str(colour
)).indexOf("-") + 1)) {
793 return {r
: -1, g
: -1, b
: -1, hex
: "none", error
: 1, toString
: clrToString
};
795 if (colour
== "none") {
796 return {r
: -1, g
: -1, b
: -1, hex
: "none", toString
: clrToString
};
798 !(hsrg
[has
](colour
.toLowerCase().substring(0, 2)) || colour
.charAt() == "#") && (colour
= toHex(colour
));
806 rgb
= colour
.match(colourRegExp
);
809 blue
= toInt(rgb
[2].substring(5), 16);
810 green
= toInt(rgb
[2].substring(3, 5), 16);
811 red
= toInt(rgb
[2].substring(1, 3), 16);
814 blue
= toInt((t
= rgb
[3].charAt(3)) + t
, 16);
815 green
= toInt((t
= rgb
[3].charAt(2)) + t
, 16);
816 red
= toInt((t
= rgb
[3].charAt(1)) + t
, 16);
819 values
= rgb
[4][split
](commaSpaces
);
820 red
= toFloat(values
[0]);
821 values
[0].slice(-1) == "%" && (red
*= 2.55);
822 green
= toFloat(values
[1]);
823 values
[1].slice(-1) == "%" && (green
*= 2.55);
824 blue
= toFloat(values
[2]);
825 values
[2].slice(-1) == "%" && (blue
*= 2.55);
826 rgb
[1].toLowerCase().slice(0, 4) == "rgba" && (opacity
= toFloat(values
[3]));
827 values
[3] && values
[3].slice(-1) == "%" && (opacity
/= 100);
830 values
= rgb
[5][split
](commaSpaces
);
831 red
= toFloat(values
[0]);
832 values
[0].slice(-1) == "%" && (red
*= 2.55);
833 green
= toFloat(values
[1]);
834 values
[1].slice(-1) == "%" && (green
*= 2.55);
835 blue
= toFloat(values
[2]);
836 values
[2].slice(-1) == "%" && (blue
*= 2.55);
837 (values
[0].slice(-3) == "deg" || values
[0].slice(-1) == "\xb0") && (red
/= 360);
838 rgb
[1].toLowerCase().slice(0, 4) == "hsba" && (opacity
= toFloat(values
[3]));
839 values
[3] && values
[3].slice(-1) == "%" && (opacity
/= 100);
840 return R
.hsb2rgb(red
, green
, blue
, opacity
);
843 values
= rgb
[6][split
](commaSpaces
);
844 red
= toFloat(values
[0]);
845 values
[0].slice(-1) == "%" && (red
*= 2.55);
846 green
= toFloat(values
[1]);
847 values
[1].slice(-1) == "%" && (green
*= 2.55);
848 blue
= toFloat(values
[2]);
849 values
[2].slice(-1) == "%" && (blue
*= 2.55);
850 (values
[0].slice(-3) == "deg" || values
[0].slice(-1) == "\xb0") && (red
/= 360);
851 rgb
[1].toLowerCase().slice(0, 4) == "hsla" && (opacity
= toFloat(values
[3]));
852 values
[3] && values
[3].slice(-1) == "%" && (opacity
/= 100);
853 return R
.hsl2rgb(red
, green
, blue
, opacity
);
855 rgb
= {r
: red
, g
: green
, b
: blue
, toString
: clrToString
};
856 rgb
.hex
= "#" + (16777216 | blue
| (green
<< 8) | (red
<< 16)).toString(16).slice(1);
857 R
.is(opacity
, "finite") && (rgb
.opacity
= opacity
);
860 return {r
: -1, g
: -1, b
: -1, hex
: "none", error
: 1, toString
: clrToString
};
863 R
.hsb
= cacher(function (h
, s
, b
) {
864 return R
.hsb2rgb(h
, s
, b
).hex
;
867 R
.hsl
= cacher(function (h
, s
, l
) {
868 return R
.hsl2rgb(h
, s
, l
).hex
;
871 R
.rgb
= cacher(function (r
, g
, b
) {
872 return "#" + (16777216 | b
| (g
<< 8) | (r
<< 16)).toString(16).slice(1);
875 R
.getColor = function (value
) {
876 var start
= this.getColor
.start
= this.getColor
.start
|| {h
: 0, s
: 1, b
: value
|| .75},
877 rgb
= this.hsb2rgb(start
.h
, start
.s
, start
.b
);
882 start
.s
<= 0 && (this.getColor
.start
= {h
: 0, s
: 1, b
: start
.b
});
887 R
.getColor
.reset = function () {
891 // http://schepers.cc/getting-to-the-point
892 function catmullRom2bezier(crp
) {
894 for (var i
= 0, iLen
= crp
.length
; iLen
- 2 > i
; i
+= 2) {
895 var p
= [{x
: +crp
[i
], y
: +crp
[i
+ 1]},
896 {x
: +crp
[i
], y
: +crp
[i
+ 1]},
897 {x
: +crp
[i
+ 2], y
: +crp
[i
+ 3]},
898 {x
: +crp
[i
+ 4], y
: +crp
[i
+ 5]}];
900 p
[0] = {x
: +crp
[i
- 2], y
: +crp
[i
- 1]};
903 p
[0] = {x
: +crp
[i
- 2], y
: +crp
[i
- 1]};
906 (-p
[0].x
+ 6 * p
[1].x
+ p
[2].x
) / 6,
907 (-p
[0].y
+ 6 * p
[1].y
+ p
[2].y
) / 6,
908 (p
[1].x
+ 6 * p
[2].x
- p
[3].x
) / 6,
909 (p
[1].y
+ 6*p
[2].y
- p
[3].y
) / 6,
918 R
.parsePathString
= cacher(function (pathString
) {
922 var paramCounts
= {a
: 7, c
: 6, h
: 1, l
: 2, m
: 2, r
: 4, q
: 4, s
: 4, t
: 2, v
: 1, z
: 0},
924 if (R
.is(pathString
, array
) && R
.is(pathString
[0], array
)) { // rough assumption
925 data
= pathClone(pathString
);
928 Str(pathString
).replace(pathCommand
, function (a
, b
, c
) {
930 name
= b
.toLowerCase();
931 c
.replace(pathValues
, function (a
, b
) {
932 b
&& params
.push(+b
);
934 if (name
== "m" && params
.length
> 2) {
935 data
.push([b
][concat
](params
.splice(0, 2)));
937 b
= b
== "m" ? "l" : "L";
940 data
.push([b
][concat
](params
));
941 } else while (params
.length
>= paramCounts
[name
]) {
942 data
.push([b
][concat
](params
.splice(0, paramCounts
[name
])));
943 if (!paramCounts
[name
]) {
949 data
.toString
= R
._path2string
;
953 R
.parseTransformString
= cacher(function (TString
) {
957 var paramCounts
= {r
: 3, s
: 4, t
: 2, m
: 6},
959 if (R
.is(TString
, array
) && R
.is(TString
[0], array
)) { // rough assumption
960 data
= pathClone(TString
);
963 Str(TString
).replace(tCommand
, function (a
, b
, c
) {
965 name
= lowerCase
.call(b
);
966 c
.replace(pathValues
, function (a
, b
) {
967 b
&& params
.push(+b
);
969 data
.push([b
][concat
](params
));
972 data
.toString
= R
._path2string
;
976 R
.findDotsAtSegment = function (p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
, t
) {
982 x
= t13
* p1x
+ t12
* 3 * t
* c1x
+ t1
* 3 * t
* t
* c2x
+ t3
* p2x
,
983 y
= t13
* p1y
+ t12
* 3 * t
* c1y
+ t1
* 3 * t
* t
* c2y
+ t3
* p2y
,
984 mx
= p1x
+ 2 * t
* (c1x
- p1x
) + t2
* (c2x
- 2 * c1x
+ p1x
),
985 my
= p1y
+ 2 * t
* (c1y
- p1y
) + t2
* (c2y
- 2 * c1y
+ p1y
),
986 nx
= c1x
+ 2 * t
* (c2x
- c1x
) + t2
* (p2x
- 2 * c2x
+ c1x
),
987 ny
= c1y
+ 2 * t
* (c2y
- c1y
) + t2
* (p2y
- 2 * c2y
+ c1y
),
988 ax
= t1
* p1x
+ t
* c1x
,
989 ay
= t1
* p1y
+ t
* c1y
,
990 cx
= t1
* c2x
+ t
* p2x
,
991 cy
= t1
* c2y
+ t
* p2y
,
992 alpha
= (90 - math
.atan2(mx
- nx
, my
- ny
) * 180 / PI
);
993 (mx
> nx
|| my
< ny
) && (alpha
+= 180);
999 start
: {x
: ax
, y
: ay
},
1000 end
: {x
: cx
, y
: cy
},
1004 R
._removedFactory = function (methodname
) {
1005 return function () {
1006 throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname
+ "\u201d of removed object");
1009 var pathDimensions
= cacher(function (path
) {
1011 return {x
: 0, y
: 0, width
: 0, height
: 0};
1013 path
= path2curve(path
);
1019 for (var i
= 0, ii
= path
.length
; i
< ii
; i
++) {
1027 var dim
= curveDim(x
, y
, p
[1], p
[2], p
[3], p
[4], p
[5], p
[6]);
1028 X
= X
[concat
](dim
.min
.x
, dim
.max
.x
);
1029 Y
= Y
[concat
](dim
.min
.y
, dim
.max
.y
);
1034 var xmin
= mmin
[apply
](0, X
),
1035 ymin
= mmin
[apply
](0, Y
);
1039 width
: mmax
[apply
](0, X
) - xmin
,
1040 height
: mmax
[apply
](0, Y
) - ymin
1042 }, null, function (o
) {
1050 pathClone = function (pathArray
) {
1052 if (!R
.is(pathArray
, array
) || !R
.is(pathArray
&& pathArray
[0], array
)) { // rough assumption
1053 pathArray
= R
.parsePathString(pathArray
);
1055 for (var i
= 0, ii
= pathArray
.length
; i
< ii
; i
++) {
1057 for (var j
= 0, jj
= pathArray
[i
].length
; j
< jj
; j
++) {
1058 res
[i
][j
] = pathArray
[i
][j
];
1061 res
.toString
= R
._path2string
;
1064 pathToRelative
= R
._pathToRelative
= cacher(function (pathArray
) {
1065 if (!R
.is(pathArray
, array
) || !R
.is(pathArray
&& pathArray
[0], array
)) { // rough assumption
1066 pathArray
= R
.parsePathString(pathArray
);
1074 if (pathArray
[0][0] == "M") {
1075 x
= pathArray
[0][1];
1076 y
= pathArray
[0][2];
1080 res
.push(["M", x
, y
]);
1082 for (var i
= start
, ii
= pathArray
.length
; i
< ii
; i
++) {
1083 var r
= res
[i
] = [],
1085 if (pa
[0] != lowerCase
.call(pa
[0])) {
1086 r
[0] = lowerCase
.call(pa
[0]);
1094 r
[6] = +(pa
[6] - x
).toFixed(3);
1095 r
[7] = +(pa
[7] - y
).toFixed(3);
1098 r
[1] = +(pa
[1] - y
).toFixed(3);
1104 for (var j
= 1, jj
= pa
.length
; j
< jj
; j
++) {
1105 r
[j
] = +(pa
[j
] - ((j
% 2) ? x
: y
)).toFixed(3);
1114 for (var k
= 0, kk
= pa
.length
; k
< kk
; k
++) {
1118 var len
= res
[i
].length
;
1119 switch (res
[i
][0]) {
1125 x
+= +res
[i
][len
- 1];
1128 y
+= +res
[i
][len
- 1];
1131 x
+= +res
[i
][len
- 2];
1132 y
+= +res
[i
][len
- 1];
1135 res
.toString
= R
._path2string
;
1138 pathToAbsolute
= R
._pathToAbsolute
= cacher(function (pathArray
) {
1139 if (!R
.is(pathArray
, array
) || !R
.is(pathArray
&& pathArray
[0], array
)) { // rough assumption
1140 pathArray
= R
.parsePathString(pathArray
);
1142 if (!pathArray
|| !pathArray
.length
) {
1143 return [["M", 0, 0]];
1151 if (pathArray
[0][0] == "M") {
1152 x
= +pathArray
[0][1];
1153 y
= +pathArray
[0][2];
1157 res
[0] = ["M", x
, y
];
1159 for (var r
, pa
, i
= start
, ii
= pathArray
.length
; i
< ii
; i
++) {
1162 if (pa
[0] != upperCase
.call(pa
[0])) {
1163 r
[0] = upperCase
.call(pa
[0]);
1171 r
[6] = +(pa
[6] + x
);
1172 r
[7] = +(pa
[7] + y
);
1181 var dots
= [x
, y
][concat
](pa
.slice(1));
1182 for (var j
= 2, jj
= dots
.length
; j
< jj
; j
++) {
1183 dots
[j
] = +dots
[j
] + x
;
1184 dots
[++j
] = +dots
[j
] + y
;
1187 res
= res
[concat
](catmullRom2bezier(dots
));
1193 for (j
= 1, jj
= pa
.length
; j
< jj
; j
++) {
1194 r
[j
] = +pa
[j
] + ((j
% 2) ? x
: y
);
1197 } else if (pa
[0] == "R") {
1198 dots
= [x
, y
][concat
](pa
.slice(1));
1200 res
= res
[concat
](catmullRom2bezier(dots
));
1201 r
= ["R"][concat
](pa
.slice(-2));
1203 for (var k
= 0, kk
= pa
.length
; k
< kk
; k
++) {
1219 mx
= r
[r
.length
- 2];
1220 my
= r
[r
.length
- 1];
1222 x
= r
[r
.length
- 2];
1223 y
= r
[r
.length
- 1];
1226 res
.toString
= R
._path2string
;
1228 }, null, pathClone
),
1229 l2c = function (x1
, y1
, x2
, y2
) {
1230 return [x1
, y1
, x2
, y2
, x2
, y2
];
1232 q2c = function (x1
, y1
, ax
, ay
, x2
, y2
) {
1236 _13
* x1
+ _23
* ax
,
1237 _13
* y1
+ _23
* ay
,
1238 _13
* x2
+ _23
* ax
,
1239 _13
* y2
+ _23
* ay
,
1244 a2c = function (x1
, y1
, rx
, ry
, angle
, large_arc_flag
, sweep_flag
, x2
, y2
, recursive
) {
1245 // for more information of where this math came from visit:
1246 // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
1247 var _120
= PI
* 120 / 180,
1248 rad
= PI
/ 180 * (+angle
|| 0),
1251 rotate
= cacher(function (x
, y
, rad
) {
1252 var X
= x
* math
.cos(rad
) - y
* math
.sin(rad
),
1253 Y
= x
* math
.sin(rad
) + y
* math
.cos(rad
);
1254 return {x
: X
, y
: Y
};
1257 xy
= rotate(x1
, y1
, -rad
);
1260 xy
= rotate(x2
, y2
, -rad
);
1263 var cos
= math
.cos(PI
/ 180 * angle
),
1264 sin
= math
.sin(PI
/ 180 * angle
),
1267 var h
= (x
* x
) / (rx
* rx
) + (y
* y
) / (ry
* ry
);
1275 k
= (large_arc_flag
== sweep_flag
? -1 : 1) *
1276 math
.sqrt(abs((rx2
* ry2
- rx2
* y
* y
- ry2
* x
* x
) / (rx2
* y
* y
+ ry2
* x
* x
))),
1277 cx
= k
* rx
* y
/ ry
+ (x1
+ x2
) / 2,
1278 cy
= k
* -ry
* x
/ rx
+ (y1
+ y2
) / 2,
1279 f1
= math
.asin(((y1
- cy
) / ry
).toFixed(9)),
1280 f2
= math
.asin(((y2
- cy
) / ry
).toFixed(9));
1282 f1
= x1
< cx
? PI
- f1
: f1
;
1283 f2
= x2
< cx
? PI
- f2
: f2
;
1284 f1
< 0 && (f1
= PI
* 2 + f1
);
1285 f2
< 0 && (f2
= PI
* 2 + f2
);
1286 if (sweep_flag
&& f1
> f2
) {
1289 if (!sweep_flag
&& f2
> f1
) {
1299 if (abs(df
) > _120
) {
1303 f2
= f1
+ _120
* (sweep_flag
&& f2
> f1
? 1 : -1);
1304 x2
= cx
+ rx
* math
.cos(f2
);
1305 y2
= cy
+ ry
* math
.sin(f2
);
1306 res
= a2c(x2
, y2
, rx
, ry
, angle
, 0, sweep_flag
, x2old
, y2old
, [f2
, f2old
, cx
, cy
]);
1309 var c1
= math
.cos(f1
),
1313 t
= math
.tan(df
/ 4),
1314 hx
= 4 / 3 * rx
* t
,
1315 hy
= 4 / 3 * ry
* t
,
1317 m2
= [x1
+ hx
* s1
, y1
- hy
* c1
],
1318 m3
= [x2
+ hx
* s2
, y2
- hy
* c2
],
1320 m2
[0] = 2 * m1
[0] - m2
[0];
1321 m2
[1] = 2 * m1
[1] - m2
[1];
1323 return [m2
, m3
, m4
][concat
](res
);
1325 res
= [m2
, m3
, m4
][concat
](res
).join()[split
](",");
1327 for (var i
= 0, ii
= res
.length
; i
< ii
; i
++) {
1328 newres
[i
] = i
% 2 ? rotate(res
[i
- 1], res
[i
], rad
).y
: rotate(res
[i
], res
[i
+ 1], rad
).x
;
1333 findDotAtSegment = function (p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
, t
) {
1336 x
: pow(t1
, 3) * p1x
+ pow(t1
, 2) * 3 * t
* c1x
+ t1
* 3 * t
* t
* c2x
+ pow(t
, 3) * p2x
,
1337 y
: pow(t1
, 3) * p1y
+ pow(t1
, 2) * 3 * t
* c1y
+ t1
* 3 * t
* t
* c2y
+ pow(t
, 3) * p2y
1340 curveDim
= cacher(function (p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
) {
1341 var a
= (c2x
- 2 * c1x
+ p1x
) - (p2x
- 2 * c2x
+ c1x
),
1342 b
= 2 * (c1x
- p1x
) - 2 * (c2x
- c1x
),
1344 t1
= (-b
+ math
.sqrt(b
* b
- 4 * a
* c
)) / 2 / a
,
1345 t2
= (-b
- math
.sqrt(b
* b
- 4 * a
* c
)) / 2 / a
,
1349 abs(t1
) > "1e12" && (t1
= .5);
1350 abs(t2
) > "1e12" && (t2
= .5);
1351 if (t1
> 0 && t1
< 1) {
1352 dot
= findDotAtSegment(p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
, t1
);
1356 if (t2
> 0 && t2
< 1) {
1357 dot
= findDotAtSegment(p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
, t2
);
1361 a
= (c2y
- 2 * c1y
+ p1y
) - (p2y
- 2 * c2y
+ c1y
);
1362 b
= 2 * (c1y
- p1y
) - 2 * (c2y
- c1y
);
1364 t1
= (-b
+ math
.sqrt(b
* b
- 4 * a
* c
)) / 2 / a
;
1365 t2
= (-b
- math
.sqrt(b
* b
- 4 * a
* c
)) / 2 / a
;
1366 abs(t1
) > "1e12" && (t1
= .5);
1367 abs(t2
) > "1e12" && (t2
= .5);
1368 if (t1
> 0 && t1
< 1) {
1369 dot
= findDotAtSegment(p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
, t1
);
1373 if (t2
> 0 && t2
< 1) {
1374 dot
= findDotAtSegment(p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
, t2
);
1379 min
: {x
: mmin
[apply
](0, x
), y
: mmin
[apply
](0, y
)},
1380 max
: {x
: mmax
[apply
](0, x
), y
: mmax
[apply
](0, y
)}
1383 path2curve
= R
._path2curve
= cacher(function (path
, path2
) {
1384 var p
= pathToAbsolute(path
),
1385 p2
= path2
&& pathToAbsolute(path2
),
1386 attrs
= {x
: 0, y
: 0, bx
: 0, by
: 0, X
: 0, Y
: 0, qx
: null, qy
: null},
1387 attrs2
= {x
: 0, y
: 0, bx
: 0, by
: 0, X
: 0, Y
: 0, qx
: null, qy
: null},
1388 processPath = function (path
, d
) {
1391 return ["C", d
.x
, d
.y
, d
.x
, d
.y
, d
.x
, d
.y
];
1393 !(path
[0] in {T
:1, Q
:1}) && (d
.qx
= d
.qy
= null);
1400 path
= ["C"][concat
](a2c
[apply
](0, [d
.x
, d
.y
][concat
](path
.slice(1))));
1403 nx
= d
.x
+ (d
.x
- (d
.bx
|| d
.x
));
1404 ny
= d
.y
+ (d
.y
- (d
.by
|| d
.y
));
1405 path
= ["C", nx
, ny
][concat
](path
.slice(1));
1408 d
.qx
= d
.x
+ (d
.x
- (d
.qx
|| d
.x
));
1409 d
.qy
= d
.y
+ (d
.y
- (d
.qy
|| d
.y
));
1410 path
= ["C"][concat
](q2c(d
.x
, d
.y
, d
.qx
, d
.qy
, path
[1], path
[2]));
1415 path
= ["C"][concat
](q2c(d
.x
, d
.y
, path
[1], path
[2], path
[3], path
[4]));
1418 path
= ["C"][concat
](l2c(d
.x
, d
.y
, path
[1], path
[2]));
1421 path
= ["C"][concat
](l2c(d
.x
, d
.y
, path
[1], d
.y
));
1424 path
= ["C"][concat
](l2c(d
.x
, d
.y
, d
.x
, path
[1]));
1427 path
= ["C"][concat
](l2c(d
.x
, d
.y
, d
.X
, d
.Y
));
1432 fixArc = function (pp
, i
) {
1433 if (pp
[i
].length
> 7) {
1437 pp
.splice(i
++, 0, ["C"][concat
](pi
.splice(0, 6)));
1440 ii
= mmax(p
.length
, p2
&& p2
.length
|| 0);
1443 fixM = function (path1
, path2
, a1
, a2
, i
) {
1444 if (path1
&& path2
&& path1
[i
][0] == "M" && path2
[i
][0] != "M") {
1445 path2
.splice(i
, 0, ["M", a2
.x
, a2
.y
]);
1450 ii
= mmax(p
.length
, p2
&& p2
.length
|| 0);
1453 for (var i
= 0, ii
= mmax(p
.length
, p2
&& p2
.length
|| 0); i
< ii
; i
++) {
1454 p
[i
] = processPath(p
[i
], attrs
);
1456 p2
&& (p2
[i
] = processPath(p2
[i
], attrs2
));
1457 p2
&& fixArc(p2
, i
);
1458 fixM(p
, p2
, attrs
, attrs2
, i
);
1459 fixM(p2
, p
, attrs2
, attrs
, i
);
1462 seglen
= seg
.length
,
1463 seg2len
= p2
&& seg2
.length
;
1464 attrs
.x
= seg
[seglen
- 2];
1465 attrs
.y
= seg
[seglen
- 1];
1466 attrs
.bx
= toFloat(seg
[seglen
- 4]) || attrs
.x
;
1467 attrs
.by
= toFloat(seg
[seglen
- 3]) || attrs
.y
;
1468 attrs2
.bx
= p2
&& (toFloat(seg2
[seg2len
- 4]) || attrs2
.x
);
1469 attrs2
.by
= p2
&& (toFloat(seg2
[seg2len
- 3]) || attrs2
.y
);
1470 attrs2
.x
= p2
&& seg2
[seg2len
- 2];
1471 attrs2
.y
= p2
&& seg2
[seg2len
- 1];
1473 return p2
? [p
, p2
] : p
;
1474 }, null, pathClone
),
1475 parseDots
= R
._parseDots
= cacher(function (gradient
) {
1477 for (var i
= 0, ii
= gradient
.length
; i
< ii
; i
++) {
1479 par
= gradient
[i
].match(/^([^:]*):?([\d\.]*)/);
1480 dot
.color
= R
.getRGB(par
[1]);
1481 if (dot
.color
.error
) {
1484 dot
.color
= dot
.color
.hex
;
1485 par
[2] && (dot
.offset
= par
[2] + "%");
1488 for (i
= 1, ii
= dots
.length
- 1; i
< ii
; i
++) {
1489 if (!dots
[i
].offset
) {
1490 var start
= toFloat(dots
[i
- 1].offset
|| 0),
1492 for (var j
= i
+ 1; j
< ii
; j
++) {
1493 if (dots
[j
].offset
) {
1494 end
= dots
[j
].offset
;
1503 var d
= (end
- start
) / (j
- i
+ 1);
1504 for (; i
< j
; i
++) {
1506 dots
[i
].offset
= start
+ "%";
1512 tear
= R
._tear = function (el
, paper
) {
1513 el
== paper
.top
&& (paper
.top
= el
.prev
);
1514 el
== paper
.bottom
&& (paper
.bottom
= el
.next
);
1515 el
.next
&& (el
.next
.prev
= el
.prev
);
1516 el
.prev
&& (el
.prev
.next
= el
.next
);
1518 tofront
= R
._tofront = function (el
, paper
) {
1519 if (paper
.top
=== el
) {
1524 el
.prev
= paper
.top
;
1525 paper
.top
.next
= el
;
1528 toback
= R
._toback = function (el
, paper
) {
1529 if (paper
.bottom
=== el
) {
1533 el
.next
= paper
.bottom
;
1535 paper
.bottom
.prev
= el
;
1538 insertafter
= R
._insertafter = function (el
, el2
, paper
) {
1540 el2
== paper
.top
&& (paper
.top
= el
);
1541 el2
.next
&& (el2
.next
.prev
= el
);
1546 insertbefore
= R
._insertbefore = function (el
, el2
, paper
) {
1548 el2
== paper
.bottom
&& (paper
.bottom
= el
);
1549 el2
.prev
&& (el2
.prev
.next
= el
);
1554 extractTransform
= R
._extractTransform = function (el
, tstr
) {
1556 return el
._
.transform
;
1558 tstr
= Str(tstr
).replace(/\.{3}|\u2026/g, el
._
.transform
|| E
);
1559 var tdata
= R
.parseTransformString(tstr
),
1567 _
.transform
= tdata
|| [];
1569 for (var i
= 0, ii
= tdata
.length
; i
< ii
; i
++) {
1572 command
= Str(t
[0]).toLowerCase(),
1573 absolute
= t
[0] != command
,
1574 inver
= absolute
? m
.invert() : 0,
1580 if (command
== "t" && tlen
== 3) {
1584 x2
= inver
.x(t
[1], t
[2]);
1585 y2
= inver
.y(t
[1], t
[2]);
1586 m
.translate(x2
- x1
, y2
- y1
);
1588 m
.translate(t
[1], t
[2]);
1590 } else if (command
== "r") {
1592 bb
= bb
|| el
.getBBox(1);
1593 m
.rotate(t
[1], bb
.x
+ bb
.width
/ 2, bb
.y
+ bb
.height
/ 2);
1595 } else if (tlen
== 4) {
1597 x2
= inver
.x(t
[2], t
[3]);
1598 y2
= inver
.y(t
[2], t
[3]);
1599 m
.rotate(t
[1], x2
, y2
);
1601 m
.rotate(t
[1], t
[2], t
[3]);
1605 } else if (command
== "s") {
1606 if (tlen
== 2 || tlen
== 3) {
1607 bb
= bb
|| el
.getBBox(1);
1608 m
.scale(t
[1], t
[tlen
- 1], bb
.x
+ bb
.width
/ 2, bb
.y
+ bb
.height
/ 2);
1611 } else if (tlen
== 5) {
1613 x2
= inver
.x(t
[3], t
[4]);
1614 y2
= inver
.y(t
[3], t
[4]);
1615 m
.scale(t
[1], t
[2], x2
, y2
);
1617 m
.scale(t
[1], t
[2], t
[3], t
[4]);
1622 } else if (command
== "m" && tlen
== 7) {
1623 m
.add(t
[1], t
[2], t
[3], t
[4], t
[5], t
[6]);
1638 if (sx
== 1 && sy
== 1 && !deg
&& _
.bbox
) {
1645 getEmpty = function (item
) {
1647 switch (l
.toLowerCase()) {
1648 case "t": return [l
, 0, 0];
1649 case "m": return [l
, 1, 0, 0, 1, 0, 0];
1650 case "r": if (item
.length
== 4) {
1651 return [l
, 0, item
[2], item
[3]];
1655 case "s": if (item
.length
== 5) {
1656 return [l
, 1, 1, item
[3], item
[4]];
1657 } else if (item
.length
== 3) {
1664 equaliseTransform
= R
._equaliseTransform = function (t1
, t2
) {
1665 t2
= Str(t2
).replace(/\.{3}|\u2026/g, t1
);
1666 t1
= R
.parseTransformString(t1
) || [];
1667 t2
= R
.parseTransformString(t2
) || [];
1668 var maxlength
= mmax(t1
.length
, t2
.length
),
1673 for (; i
< maxlength
; i
++) {
1674 tt1
= t1
[i
] || getEmpty(t2
[i
]);
1675 tt2
= t2
[i
] || getEmpty(tt1
);
1676 if ((tt1
[0] != tt2
[0]) ||
1677 (tt1
[0].toLowerCase() == "r" && (tt1
[2] != tt2
[2] || tt1
[3] != tt2
[3])) ||
1678 (tt1
[0].toLowerCase() == "s" && (tt1
[3] != tt2
[3] || tt1
[4] != tt2
[4]))
1684 for (j
= 0, jj
= mmax(tt1
.length
, tt2
.length
); j
< jj
; j
++) {
1685 j
in tt1
&& (from[i
][j
] = tt1
[j
]);
1686 j
in tt2
&& (to
[i
][j
] = tt2
[j
]);
1694 R
._getContainer = function (x
, y
, w
, h
) {
1696 container
= h
== null && !R
.is(x
, "object") ? g
.doc
.getElementById(x
) : x
;
1697 if (container
== null) {
1700 if (container
.tagName
) {
1703 container
: container
,
1704 width
: container
.style
.pixelWidth
|| container
.offsetWidth
,
1705 height
: container
.style
.pixelHeight
|| container
.offsetHeight
1709 container
: container
,
1724 R
.pathToRelative
= pathToRelative
;
1727 R
.path2curve
= path2curve
;
1729 R
.matrix = function (a
, b
, c
, d
, e
, f
) {
1730 return new Matrix(a
, b
, c
, d
, e
, f
);
1732 function Matrix(a
, b
, c
, d
, e
, f
) {
1749 (function (matrixproto
) {
1751 matrixproto
.add = function (a
, b
, c
, d
, e
, f
) {
1752 var out
= [[], [], []],
1753 m
= [[this.a
, this.c
, this.e
], [this.b
, this.d
, this.f
], [0, 0, 1]],
1754 matrix
= [[a
, c
, e
], [b
, d
, f
], [0, 0, 1]],
1757 if (a
&& a
instanceof Matrix
) {
1758 matrix
= [[a
.a
, a
.c
, a
.e
], [a
.b
, a
.d
, a
.f
], [0, 0, 1]];
1761 for (x
= 0; x
< 3; x
++) {
1762 for (y
= 0; y
< 3; y
++) {
1764 for (z
= 0; z
< 3; z
++) {
1765 res
+= m
[x
][z
] * matrix
[z
][y
];
1778 matrixproto
.invert = function () {
1780 x
= me
.a
* me
.d
- me
.b
* me
.c
;
1781 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
);
1784 matrixproto
.clone = function () {
1785 return new Matrix(this.a
, this.b
, this.c
, this.d
, this.e
, this.f
);
1788 matrixproto
.translate = function (x
, y
) {
1789 this.add(1, 0, 0, 1, x
, y
);
1792 matrixproto
.scale = function (x
, y
, cx
, cy
) {
1793 y
== null && (y
= x
);
1794 (cx
|| cy
) && this.add(1, 0, 0, 1, cx
, cy
);
1795 this.add(x
, 0, 0, y
, 0, 0);
1796 (cx
|| cy
) && this.add(1, 0, 0, 1, -cx
, -cy
);
1799 matrixproto
.rotate = function (a
, x
, y
) {
1803 var cos
= +math
.cos(a
).toFixed(9),
1804 sin
= +math
.sin(a
).toFixed(9);
1805 this.add(cos
, sin
, -sin
, cos
, x
, y
);
1806 this.add(1, 0, 0, 1, -x
, -y
);
1809 matrixproto
.x = function (x
, y
) {
1810 return x
* this.a
+ y
* this.c
+ this.e
;
1813 matrixproto
.y = function (x
, y
) {
1814 return x
* this.b
+ y
* this.d
+ this.f
;
1816 matrixproto
.get = function (i
) {
1817 return +this[Str
.fromCharCode(97 + i
)].toFixed(4);
1819 matrixproto
.toString = function () {
1821 "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")" :
1822 [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();
1824 matrixproto
.toFilter = function () {
1825 return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) +
1826 ", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) +
1827 ", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')";
1829 matrixproto
.offset = function () {
1830 return [this.e
.toFixed(4), this.f
.toFixed(4)];
1833 return a
[0] * a
[0] + a
[1] * a
[1];
1835 function normalize(a
) {
1836 var mag
= math
.sqrt(norm(a
));
1837 a
[0] && (a
[0] /= mag
);
1838 a
[1] && (a
[1] /= mag
);
1841 matrixproto
.split = function () {
1848 var row
= [[this.a
, this.c
], [this.b
, this.d
]];
1849 out
.scalex
= math
.sqrt(norm(row
[0]));
1852 out
.shear
= row
[0][0] * row
[1][0] + row
[0][1] * row
[1][1];
1853 row
[1] = [row
[1][0] - row
[0][0] * out
.shear
, row
[1][1] - row
[0][1] * out
.shear
];
1855 out
.scaley
= math
.sqrt(norm(row
[1]));
1857 out
.shear
/= out
.scaley
;
1860 var sin
= -row
[0][1],
1863 out
.rotate
= R
.deg(math
.acos(cos
));
1865 out
.rotate
= 360 - out
.rotate
;
1868 out
.rotate
= R
.deg(math
.asin(sin
));
1871 out
.isSimple
= !+out
.shear
.toFixed(9) && (out
.scalex
.toFixed(9) == out
.scaley
.toFixed(9) || !out
.rotate
);
1872 out
.isSuperSimple
= !+out
.shear
.toFixed(9) && out
.scalex
.toFixed(9) == out
.scaley
.toFixed(9) && !out
.rotate
;
1873 out
.noRotation
= !+out
.shear
.toFixed(9) && !out
.rotate
;
1877 matrixproto
.toTransformString = function (shorter
) {
1878 var s
= shorter
|| this[split
]();
1880 s
.scalex
= +s
.scalex
.toFixed(4);
1881 s
.scaley
= +s
.scaley
.toFixed(4);
1882 s
.rotate
= +s
.rotate
.toFixed(4);
1883 return (s
.dx
&& s
.dy
? "t" + [s
.dx
, s
.dy
] : E
) +
1884 (s
.scalex
!= 1 || s
.scaley
!= 1 ? "s" + [s
.scalex
, s
.scaley
, 0, 0] : E
) +
1885 (s
.rotate
? "r" + [s
.rotate
, 0, 0] : E
);
1887 return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];
1890 })(Matrix
.prototype);
1892 // WebKit rendering bug workaround method
1893 var version
= navigator
.userAgent
.match(/Version\/(.*?)\s/) || navigator
.userAgent
.match(/Chrome\/(\d+)/);
1894 if ((navigator
.vendor
== "Apple Computer, Inc.") && (version
&& version
[1] < 4 || navigator
.platform
.slice(0, 2) == "iP") ||
1895 (navigator
.vendor
== "Google Inc." && version
&& version
[1] < 8)) {
1897 paperproto
.safari = function () {
1898 var rect
= this.rect(-99, -99, this.width
+ 99, this.height
+ 99).attr({stroke
: "none"});
1899 setTimeout(function () {rect
.remove();});
1902 paperproto
.safari
= fun
;
1905 var preventDefault = function () {
1906 this.returnValue
= false;
1908 preventTouch = function () {
1909 return this.originalEvent
.preventDefault();
1911 stopPropagation = function () {
1912 this.cancelBubble
= true;
1914 stopTouch = function () {
1915 return this.originalEvent
.stopPropagation();
1917 addEvent
= (function () {
1918 if (g
.doc
.addEventListener
) {
1919 return function (obj
, type
, fn
, element
) {
1920 var realName
= supportsTouch
&& touchMap
[type
] ? touchMap
[type
] : type
,
1922 var scrollY
= g
.doc
.documentElement
.scrollTop
|| g
.doc
.body
.scrollTop
,
1923 scrollX
= g
.doc
.documentElement
.scrollLeft
|| g
.doc
.body
.scrollLeft
,
1924 x
= e
.clientX
+ scrollX
,
1925 y
= e
.clientY
+ scrollY
;
1926 if (supportsTouch
&& touchMap
[has
](type
)) {
1927 for (var i
= 0, ii
= e
.targetTouches
&& e
.targetTouches
.length
; i
< ii
; i
++) {
1928 if (e
.targetTouches
[i
].target
== obj
) {
1930 e
= e
.targetTouches
[i
];
1931 e
.originalEvent
= olde
;
1932 e
.preventDefault
= preventTouch
;
1933 e
.stopPropagation
= stopTouch
;
1938 return fn
.call(element
, e
, x
, y
);
1940 obj
.addEventListener(realName
, f
, false);
1941 return function () {
1942 obj
.removeEventListener(realName
, f
, false);
1946 } else if (g
.doc
.attachEvent
) {
1947 return function (obj
, type
, fn
, element
) {
1948 var f = function (e
) {
1949 e
= e
|| g
.win
.event
;
1950 var scrollY
= g
.doc
.documentElement
.scrollTop
|| g
.doc
.body
.scrollTop
,
1951 scrollX
= g
.doc
.documentElement
.scrollLeft
|| g
.doc
.body
.scrollLeft
,
1952 x
= e
.clientX
+ scrollX
,
1953 y
= e
.clientY
+ scrollY
;
1954 e
.preventDefault
= e
.preventDefault
|| preventDefault
;
1955 e
.stopPropagation
= e
.stopPropagation
|| stopPropagation
;
1956 return fn
.call(element
, e
, x
, y
);
1958 obj
.attachEvent("on" + type
, f
);
1959 var detacher = function () {
1960 obj
.detachEvent("on" + type
, f
);
1968 dragMove = function (e
) {
1971 scrollY
= g
.doc
.documentElement
.scrollTop
|| g
.doc
.body
.scrollTop
,
1972 scrollX
= g
.doc
.documentElement
.scrollLeft
|| g
.doc
.body
.scrollLeft
,
1977 if (supportsTouch
) {
1978 var i
= e
.touches
.length
,
1981 touch
= e
.touches
[i
];
1982 if (touch
.identifier
== dragi
.el
._drag
.id
) {
1985 (e
.originalEvent
? e
.originalEvent
: e
).preventDefault();
1992 var node
= dragi
.el
.node
,
1994 next
= node
.nextSibling
,
1995 parent
= node
.parentNode
,
1996 display
= node
.style
.display
;
1997 g
.win
.opera
&& parent
.removeChild(node
);
1998 node
.style
.display
= "none";
1999 o
= dragi
.el
.paper
.getElementByPoint(x
, y
);
2000 node
.style
.display
= display
;
2001 g
.win
.opera
&& (next
? parent
.insertBefore(node
, next
) : parent
.appendChild(node
));
2002 o
&& eve("drag.over." + dragi
.el
.id
, dragi
.el
, o
);
2005 eve("drag.move." + dragi
.el
.id
, dragi
.move_scope
|| dragi
.el
, x
- dragi
.el
._drag
.x
, y
- dragi
.el
._drag
.y
, x
, y
, e
);
2008 dragUp = function (e
) {
2009 R
.unmousemove(dragMove
).unmouseup(dragUp
);
2010 var i
= drag
.length
,
2014 dragi
.el
._drag
= {};
2015 eve("drag.end." + dragi
.el
.id
, dragi
.end_scope
|| dragi
.start_scope
|| dragi
.move_scope
|| dragi
.el
, e
);
2020 elproto
= R
.el
= {};
2053 for (var i
= events
.length
; i
--;) {
2054 (function (eventName
) {
2055 R
[eventName
] = elproto
[eventName
] = function (fn
, scope
) {
2056 if (R
.is(fn
, "function")) {
2057 this.events
= this.events
|| [];
2058 this.events
.push({name
: eventName
, f
: fn
, unbind
: addEvent(this.shape
|| this.node
|| g
.doc
, eventName
, fn
, scope
|| this)});
2062 R
["un" + eventName
] = elproto
["un" + eventName
] = function (fn
) {
2063 var events
= this.events
,
2065 while (l
--) if (events
[l
].name
== eventName
&& events
[l
].f
== fn
) {
2067 events
.splice(l
, 1);
2068 !events
.length
&& delete this.events
;
2077 elproto
.data = function (key
, value
) {
2078 var data
= eldata
[this.id
] = eldata
[this.id
] || {};
2079 if (arguments
.length
== 1) {
2080 if (R
.is(key
, "object")) {
2081 for (var i
in key
) if (key
[has
](i
)) {
2082 this.data(i
, key
[i
]);
2086 eve("data.get." + this.id
, this, data
[key
], key
);
2090 eve("data.set." + this.id
, this, value
, key
);
2094 elproto
.removeData = function (key
) {
2096 eldata
[this.id
] = {};
2098 eldata
[this.id
] && delete eldata
[this.id
][key
];
2103 elproto
.hover = function (f_in
, f_out
, scope_in
, scope_out
) {
2104 return this.mouseover(f_in
, scope_in
).mouseout(f_out
, scope_out
|| scope_in
);
2107 elproto
.unhover = function (f_in
, f_out
) {
2108 return this.unmouseover(f_in
).unmouseout(f_out
);
2112 elproto
.drag = function (onmove
, onstart
, onend
, move_scope
, start_scope
, end_scope
) {
2114 (e
.originalEvent
|| e
).preventDefault();
2115 var scrollY
= g
.doc
.documentElement
.scrollTop
|| g
.doc
.body
.scrollTop
,
2116 scrollX
= g
.doc
.documentElement
.scrollLeft
|| g
.doc
.body
.scrollLeft
;
2117 this._drag
.x
= e
.clientX
+ scrollX
;
2118 this._drag
.y
= e
.clientY
+ scrollY
;
2119 this._drag
.id
= e
.identifier
;
2120 !drag
.length
&& R
.mousemove(dragMove
).mouseup(dragUp
);
2121 drag
.push({el
: this, move_scope
: move_scope
, start_scope
: start_scope
, end_scope
: end_scope
});
2122 onstart
&& eve
.on("drag.start." + this.id
, onstart
);
2123 onmove
&& eve
.on("drag.move." + this.id
, onmove
);
2124 onend
&& eve
.on("drag.end." + this.id
, onend
);
2125 eve("drag.start." + this.id
, start_scope
|| move_scope
|| this, e
.clientX
+ scrollX
, e
.clientY
+ scrollY
, e
);
2128 draggable
.push({el
: this, start
: start
});
2129 this.mousedown(start
);
2133 elproto
.onDragOver = function (f
) {
2134 f
? eve
.on("drag.over." + this.id
, f
) : eve
.unbind("drag.over." + this.id
);
2137 elproto
.undrag = function () {
2138 var i
= draggable
.length
;
2139 while (i
--) if (draggable
[i
].el
== this) {
2140 this.unmousedown(draggable
[i
].start
);
2141 draggable
.splice(i
, 1);
2142 eve
.unbind("drag.*." + this.id
);
2144 !draggable
.length
&& R
.unmousemove(dragMove
).unmouseup(dragUp
);
2147 paperproto
.circle = function (x
, y
, r
) {
2148 var out
= R
._engine
.circle(this, x
|| 0, y
|| 0, r
|| 0);
2149 this.__set__
&& this.__set__
.push(out
);
2153 paperproto
.rect = function (x
, y
, w
, h
, r
) {
2154 var out
= R
._engine
.rect(this, x
|| 0, y
|| 0, w
|| 0, h
|| 0, r
|| 0);
2155 this.__set__
&& this.__set__
.push(out
);
2159 paperproto
.ellipse = function (x
, y
, rx
, ry
) {
2160 var out
= R
._engine
.ellipse(this, x
|| 0, y
|| 0, rx
|| 0, ry
|| 0);
2161 this.__set__
&& this.__set__
.push(out
);
2165 paperproto
.path = function (pathString
) {
2166 pathString
&& !R
.is(pathString
, string
) && !R
.is(pathString
[0], array
) && (pathString
+= E
);
2167 var out
= R
._engine
.path(R
.format
[apply
](R
, arguments
), this);
2168 this.__set__
&& this.__set__
.push(out
);
2172 paperproto
.image = function (src
, x
, y
, w
, h
) {
2173 var out
= R
._engine
.image(this, src
|| "about:blank", x
|| 0, y
|| 0, w
|| 0, h
|| 0);
2174 this.__set__
&& this.__set__
.push(out
);
2178 paperproto
.text = function (x
, y
, text
) {
2179 var out
= R
._engine
.text(this, x
|| 0, y
|| 0, Str(text
));
2180 this.__set__
&& this.__set__
.push(out
);
2184 paperproto
.set = function (itemsArray
) {
2185 !R
.is(itemsArray
, "array") && (itemsArray
= Array
.prototype.splice
.call(arguments
, 0, arguments
.length
));
2186 var out
= new Set(itemsArray
);
2187 this.__set__
&& this.__set__
.push(out
);
2191 paperproto
.setStart = function (set) {
2192 this.__set__
= set || this.set();
2195 paperproto
.setFinish = function (set) {
2196 var out
= this.__set__
;
2197 delete this.__set__
;
2201 paperproto
.setSize = function (width
, height
) {
2202 return R
._engine
.setSize
.call(this, width
, height
);
2205 paperproto
.setViewBox = function (x
, y
, w
, h
, fit
) {
2206 return R
._engine
.setViewBox
.call(this, x
, y
, w
, h
, fit
);
2210 paperproto
.top
= paperproto
.bottom
= null;
2212 paperproto
.raphael
= R
;
2213 var getOffset = function (elem
) {
2214 var box
= elem
.getBoundingClientRect(),
2215 doc
= elem
.ownerDocument
,
2217 docElem
= doc
.documentElement
,
2218 clientTop
= docElem
.clientTop
|| body
.clientTop
|| 0, clientLeft
= docElem
.clientLeft
|| body
.clientLeft
|| 0,
2219 top
= box
.top
+ (g
.win
.pageYOffset
|| docElem
.scrollTop
|| body
.scrollTop
) - clientTop
,
2220 left
= box
.left
+ (g
.win
.pageXOffset
|| docElem
.scrollLeft
|| body
.scrollLeft
) - clientLeft
;
2227 paperproto
.getElementByPoint = function (x
, y
) {
2230 target
= g
.doc
.elementFromPoint(x
, y
);
2231 if (g
.win
.opera
&& target
.tagName
== "svg") {
2232 var so
= getOffset(svg
),
2233 sr
= svg
.createSVGRect();
2236 sr
.width
= sr
.height
= 1;
2237 var hits
= svg
.getIntersectionList(sr
, null);
2239 target
= hits
[hits
.length
- 1];
2245 while (target
.parentNode
&& target
!= svg
.parentNode
&& !target
.raphael
) {
2246 target
= target
.parentNode
;
2248 target
== paper
.canvas
.parentNode
&& (target
= svg
);
2249 target
= target
&& target
.raphael
? paper
.getById(target
.raphaelid
) : null;
2253 paperproto
.getById = function (id
) {
2254 var bot
= this.bottom
;
2264 paperproto
.forEach = function (callback
, thisArg
) {
2265 var bot
= this.bottom
;
2267 if (callback
.call(thisArg
, bot
) === false) {
2275 return this.x
+ S
+ this.y
;
2277 function x_y_w_h() {
2278 return this.x
+ S
+ this.y
+ S
+ this.width
+ " \xd7 " + this.height
;
2281 elproto
.getBBox = function (isWithoutTransform
) {
2286 if (isWithoutTransform
) {
2287 if (_
.dirty
|| !_
.bboxwt
) {
2288 this.realPath
= getPath
[this.type
](this);
2289 _
.bboxwt
= pathDimensions(this.realPath
);
2290 _
.bboxwt
.toString
= x_y_w_h
;
2295 if (_
.dirty
|| _
.dirtyT
|| !_
.bbox
) {
2296 if (_
.dirty
|| !this.realPath
) {
2298 this.realPath
= getPath
[this.type
](this);
2300 _
.bbox
= pathDimensions(mapPath(this.realPath
, this.matrix
));
2301 _
.bbox
.toString
= x_y_w_h
;
2302 _
.dirty
= _
.dirtyT
= 0;
2307 elproto
.clone = function () {
2311 var out
= this.paper
[this.type
]().attr(this.attr());
2312 this.__set__
&& this.__set__
.push(out
);
2316 elproto
.glow = function (glow
) {
2317 if (this.type
== "text") {
2322 width
: (glow
.width
|| 10) + (+this.attr("stroke-width") || 1),
2323 fill
: glow
.fill
|| false,
2324 opacity
: glow
.opacity
|| .5,
2325 offsetx
: glow
.offsetx
|| 0,
2326 offsety
: glow
.offsety
|| 0,
2327 color
: glow
.color
|| "#000"
2332 path
= this.realPath
|| getPath
[this.type
](this);
2333 path
= this.matrix
? mapPath(path
, this.matrix
) : path
;
2334 for (var i
= 1; i
< c
+ 1; i
++) {
2335 out
.push(r
.path(path
).attr({
2337 fill
: s
.fill
? s
.color
: "none",
2338 "stroke-linejoin": "round",
2339 "stroke-linecap": "round",
2340 "stroke-width": +(s
.width
/ c
* i
).toFixed(3),
2341 opacity
: +(s
.opacity
/ c
).toFixed(3)
2344 return out
.insertBefore(this).translate(s
.offsetx
, s
.offsety
);
2346 var curveslengths
= {},
2347 getPointAtSegmentLength = function (p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
, length
) {
2350 name
= [p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
].join(),
2351 cache
= curveslengths
[name
],
2353 !cache
&& (curveslengths
[name
] = cache
= {data
: []});
2354 cache
.timer
&& clearTimeout(cache
.timer
);
2355 cache
.timer
= setTimeout(function () {delete curveslengths
[name
];}, 2e3
);
2356 if (length
!= null && !cache
.precision
) {
2357 var total
= getPointAtSegmentLength(p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
);
2358 cache
.precision
= ~~total
* 10;
2361 precision
= cache
.precision
|| precision
;
2362 for (var i
= 0; i
< precision
+ 1; i
++) {
2363 if (cache
.data
[i
* precision
]) {
2364 dot
= cache
.data
[i
* precision
];
2366 dot
= R
.findDotsAtSegment(p1x
, p1y
, c1x
, c1y
, c2x
, c2y
, p2x
, p2y
, i
/ precision
);
2367 cache
.data
[i
* precision
] = dot
;
2369 i
&& (len
+= pow(pow(old
.x
- dot
.x
, 2) + pow(old
.y
- dot
.y
, 2), .5));
2370 if (length
!= null && len
>= length
) {
2375 if (length
== null) {
2379 getLengthFactory = function (istotal
, subpath
) {
2380 return function (path
, length
, onlystart
) {
2381 path
= path2curve(path
);
2382 var x
, y
, p
, l
, sp
= "", subpaths
= {}, point
,
2384 for (var i
= 0, ii
= path
.length
; i
< ii
; i
++) {
2390 l
= getPointAtSegmentLength(x
, y
, p
[1], p
[2], p
[3], p
[4], p
[5], p
[6]);
2391 if (len
+ l
> length
) {
2392 if (subpath
&& !subpaths
.start
) {
2393 point
= getPointAtSegmentLength(x
, y
, p
[1], p
[2], p
[3], p
[4], p
[5], p
[6], length
- len
);
2394 sp
+= ["C" + point
.start
.x
, point
.start
.y
, point
.m
.x
, point
.m
.y
, point
.x
, point
.y
];
2395 if (onlystart
) {return sp
;}
2396 subpaths
.start
= sp
;
2397 sp
= ["M" + point
.x
, point
.y
+ "C" + point
.n
.x
, point
.n
.y
, point
.end
.x
, point
.end
.y
, p
[5], p
[6]].join();
2403 if (!istotal
&& !subpath
) {
2404 point
= getPointAtSegmentLength(x
, y
, p
[1], p
[2], p
[3], p
[4], p
[5], p
[6], length
- len
);
2405 return {x
: point
.x
, y
: point
.y
, alpha
: point
.alpha
};
2412 sp
+= p
.shift() + p
;
2415 point
= istotal
? len
: subpath
? subpaths
: R
.findDotsAtSegment(x
, y
, p
[0], p
[1], p
[2], p
[3], p
[4], p
[5], 1);
2416 point
.alpha
&& (point
= {x
: point
.x
, y
: point
.y
, alpha
: point
.alpha
});
2420 var getTotalLength
= getLengthFactory(1),
2421 getPointAtLength
= getLengthFactory(),
2422 getSubpathsAtLength
= getLengthFactory(0, 1);
2424 R
.getTotalLength
= getTotalLength
;
2426 R
.getPointAtLength
= getPointAtLength
;
2428 R
.getSubpath = function (path
, from, to
) {
2429 if (this.getTotalLength(path
) - to
< 1e-6) {
2430 return getSubpathsAtLength(path
, from).end
;
2432 var a
= getSubpathsAtLength(path
, to
, 1);
2433 return from ? getSubpathsAtLength(a
, from).end
: a
;
2436 elproto
.getTotalLength = function () {
2437 if (this.type
!= "path") {return;}
2438 if (this.node
.getTotalLength
) {
2439 return this.node
.getTotalLength();
2441 return getTotalLength(this.attrs
.path
);
2444 elproto
.getPointAtLength = function (length
) {
2445 if (this.type
!= "path") {return;}
2446 return getPointAtLength(this.attrs
.path
, length
);
2449 elproto
.getSubpath = function (from, to
) {
2450 if (this.type
!= "path") {return;}
2451 return R
.getSubpath(this.attrs
.path
, from, to
);
2454 var ef
= R
.easing_formulas
= {
2455 linear: function (n
) {
2464 "<>": function (n
) {
2465 var q
= .48 - n
/ 1.04,
2466 Q
= math
.sqrt(.1734 + q
* q
),
2468 X
= pow(abs(x
), 1 / 3) * (x
< 0 ? -1 : 1),
2470 Y
= pow(abs(y
), 1 / 3) * (y
< 0 ? -1 : 1),
2472 return (1 - t
) * 3 * t
* t
+ t
* t
* t
;
2474 backIn: function (n
) {
2476 return n
* n
* ((s
+ 1) * n
- s
);
2478 backOut: function (n
) {
2481 return n
* n
* ((s
+ 1) * n
+ s
) + 1;
2483 elastic: function (n
) {
2487 return pow(2, -10 * n
) * math
.sin((n
- .075) * (2 * PI
) / .3) + 1;
2489 bounce: function (n
) {
2498 l
= s
* n
* n
+ .75;
2500 if (n
< (2.5 / p
)) {
2502 l
= s
* n
* n
+ .9375;
2505 l
= s
* n
* n
+ .984375;
2512 ef
.easeIn
= ef
["ease-in"] = ef
["<"];
2513 ef
.easeOut
= ef
["ease-out"] = ef
[">"];
2514 ef
.easeInOut
= ef
["ease-in-out"] = ef
["<>"];
2515 ef
["back-in"] = ef
.backIn
;
2516 ef
["back-out"] = ef
.backOut
;
2518 var animationElements
= [],
2519 requestAnimFrame
= window
.requestAnimationFrame
||
2520 window
.webkitRequestAnimationFrame
||
2521 window
.mozRequestAnimationFrame
||
2522 window
.oRequestAnimationFrame
||
2523 window
.msRequestAnimationFrame
||
2524 function (callback
) {
2525 setTimeout(callback
, 16);
2527 animation = function () {
2528 var Now
= +new Date
,
2530 for (; l
< animationElements
.length
; l
++) {
2531 var e
= animationElements
[l
];
2532 if (e
.el
.removed
|| e
.paused
) {
2535 var time
= Now
- e
.start
,
2548 time
= (e
.initstatus
* e
.anim
.top
- e
.prev
) / (e
.percent
- e
.prev
) * ms
;
2549 e
.status
= e
.initstatus
;
2550 delete e
.initstatus
;
2551 e
.stop
&& animationElements
.splice(l
--, 1);
2553 e
.status
= (e
.prev
+ (e
.percent
- e
.prev
) * (time
/ ms
)) / e
.anim
.top
;
2559 var pos
= easing(time
/ ms
);
2560 for (var attr
in from) if (from[has
](attr
)) {
2561 switch (availableAnimAttrs
[attr
]) {
2563 now
= +from[attr
] + pos
* ms
* diff
[attr
];
2567 upto255(round(from[attr
].r
+ pos
* ms
* diff
[attr
].r
)),
2568 upto255(round(from[attr
].g
+ pos
* ms
* diff
[attr
].g
)),
2569 upto255(round(from[attr
].b
+ pos
* ms
* diff
[attr
].b
))
2574 for (var i
= 0, ii
= from[attr
].length
; i
< ii
; i
++) {
2575 now
[i
] = [from[attr
][i
][0]];
2576 for (var j
= 1, jj
= from[attr
][i
].length
; j
< jj
; j
++) {
2577 now
[i
][j
] = +from[attr
][i
][j
] + pos
* ms
* diff
[attr
][i
][j
];
2579 now
[i
] = now
[i
].join(S
);
2584 if (diff
[attr
].real
) {
2586 for (i
= 0, ii
= from[attr
].length
; i
< ii
; i
++) {
2587 now
[i
] = [from[attr
][i
][0]];
2588 for (j
= 1, jj
= from[attr
][i
].length
; j
< jj
; j
++) {
2589 now
[i
][j
] = from[attr
][i
][j
] + pos
* ms
* diff
[attr
][i
][j
];
2593 var get = function (i
) {
2594 return +from[attr
][i
] + pos
* ms
* diff
[attr
][i
];
2596 // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]];
2597 now
= [["m", get(0), get(1), get(2), get(3), get(4), get(5)]];
2601 if (attr
== "clip-rect") {
2605 now
[i
] = +from[attr
][i
] + pos
* ms
* diff
[attr
][i
];
2610 var from2
= [][concat
](from[attr
]);
2612 i
= that
.paper
.customAttributes
[attr
].length
;
2614 now
[i
] = +from2
[i
] + pos
* ms
* diff
[attr
][i
];
2621 (function (id
, that
, anim
) {
2622 setTimeout(function () {
2623 eve("anim.frame." + id
, that
, anim
);
2625 })(that
.id
, that
, e
.anim
);
2627 (function(f
, el
, a
) {
2628 setTimeout(function() {
2629 eve("anim.frame." + el
.id
, el
, a
);
2630 eve("anim.finish." + el
.id
, el
, a
);
2631 R
.is(f
, "function") && f
.call(el
);
2633 })(e
.callback
, that
, e
.anim
);
2635 animationElements
.splice(l
--, 1);
2636 if (e
.repeat
> 1 && !e
.next
) {
2637 for (key
in to
) if (to
[has
](key
)) {
2638 init
[key
] = e
.totalOrigin
[key
];
2641 runAnimation(e
.anim
, e
.el
, e
.anim
.percents
[0], null, e
.totalOrigin
, e
.repeat
- 1);
2643 if (e
.next
&& !e
.stop
) {
2644 runAnimation(e
.anim
, e
.el
, e
.next
, null, e
.totalOrigin
, e
.repeat
);
2648 R
.svg
&& that
&& that
.paper
&& that
.paper
.safari();
2649 animationElements
.length
&& requestAnimFrame(animation
);
2651 upto255 = function (color
) {
2652 return color
> 255 ? 255 : color
< 0 ? 0 : color
;
2655 elproto
.animateWith = function (element
, anim
, params
, ms
, easing
, callback
) {
2656 var a
= params
? R
.animation(params
, ms
, easing
, callback
) : anim
,
2657 status
= element
.status(anim
);
2658 return this.animate(a
).status(a
, status
* anim
.ms
/ a
.ms
);
2660 function CubicBezierAtTime(t
, p1x
, p1y
, p2x
, p2y
, duration
) {
2662 bx
= 3 * (p2x
- p1x
) - cx
,
2665 by
= 3 * (p2y
- p1y
) - cy
,
2667 function sampleCurveX(t
) {
2668 return ((ax
* t
+ bx
) * t
+ cx
) * t
;
2670 function solve(x
, epsilon
) {
2671 var t
= solveCurveX(x
, epsilon
);
2672 return ((ay
* t
+ by
) * t
+ cy
) * t
;
2674 function solveCurveX(x
, epsilon
) {
2675 var t0
, t1
, t2
, x2
, d2
, i
;
2676 for(t2
= x
, i
= 0; i
< 8; i
++) {
2677 x2
= sampleCurveX(t2
) - x
;
2678 if (abs(x2
) < epsilon
) {
2681 d2
= (3 * ax
* t2
+ 2 * bx
) * t2
+ cx
;
2682 if (abs(d2
) < 1e-6) {
2697 x2
= sampleCurveX(t2
);
2698 if (abs(x2
- x
) < epsilon
) {
2706 t2
= (t1
- t0
) / 2 + t0
;
2710 return solve(t
, 1 / (200 * duration
));
2712 elproto
.onAnimation = function (f
) {
2713 f
? eve
.on("anim.frame." + this.id
, f
) : eve
.unbind("anim.frame." + this.id
);
2716 function Animation(anim
, ms
) {
2722 for (var attr
in anim
) if (anim
[has
](attr
)) {
2723 newAnim
[toFloat(attr
)] = anim
[attr
];
2724 percents
.push(toFloat(attr
));
2726 percents
.sort(sortByNumber
);
2728 this.anim
= newAnim
;
2729 this.top
= percents
[percents
.length
- 1];
2730 this.percents
= percents
;
2733 Animation
.prototype.delay = function (delay
) {
2734 var a
= new Animation(this.anim
, this.ms
);
2735 a
.times
= this.times
;
2736 a
.del
= +delay
|| 0;
2740 Animation
.prototype.repeat = function (times
) {
2741 var a
= new Animation(this.anim
, this.ms
);
2743 a
.times
= math
.floor(mmax(times
, 0)) || 1;
2746 function runAnimation(anim
, element
, percent
, status
, totalOrigin
, times
) {
2747 percent
= toFloat(percent
);
2760 for (i
= 0, ii
= animationElements
.length
; i
< ii
; i
++) {
2761 var e
= animationElements
[i
];
2762 if (e
.el
.id
== element
.id
&& e
.anim
== anim
) {
2763 if (e
.percent
!= percent
) {
2764 animationElements
.splice(i
, 1);
2769 element
.attr(e
.totalOrigin
);
2774 status
= +to
; // NaN
2776 for (var i
= 0, ii
= anim
.percents
.length
; i
< ii
; i
++) {
2777 if (anim
.percents
[i
] == percent
|| anim
.percents
[i
] > status
* anim
.top
) {
2778 percent
= anim
.percents
[i
];
2779 prev
= anim
.percents
[i
- 1] || 0;
2780 ms
= ms
/ anim
.top
* (percent
- prev
);
2781 next
= anim
.percents
[i
+ 1];
2782 params
= anim
.anim
[percent
];
2784 } else if (status
) {
2785 element
.attr(anim
.anim
[anim
.percents
[i
]]);
2792 for (var attr
in params
) if (params
[has
](attr
)) {
2793 if (availableAnimAttrs
[has
](attr
) || element
.paper
.customAttributes
[has
](attr
)) {
2794 from[attr
] = element
.attr(attr
);
2795 (from[attr
] == null) && (from[attr
] = availableAttrs
[attr
]);
2796 to
[attr
] = params
[attr
];
2797 switch (availableAnimAttrs
[attr
]) {
2799 diff
[attr
] = (to
[attr
] - from[attr
]) / ms
;
2802 from[attr
] = R
.getRGB(from[attr
]);
2803 var toColour
= R
.getRGB(to
[attr
]);
2805 r
: (toColour
.r
- from[attr
].r
) / ms
,
2806 g
: (toColour
.g
- from[attr
].g
) / ms
,
2807 b
: (toColour
.b
- from[attr
].b
) / ms
2811 var pathes
= path2curve(from[attr
], to
[attr
]),
2813 from[attr
] = pathes
[0];
2815 for (i
= 0, ii
= from[attr
].length
; i
< ii
; i
++) {
2816 diff
[attr
][i
] = [0];
2817 for (var j
= 1, jj
= from[attr
][i
].length
; j
< jj
; j
++) {
2818 diff
[attr
][i
][j
] = (toPath
[i
][j
] - from[attr
][i
][j
]) / ms
;
2824 eq
= equaliseTransform(_
[attr
], to
[attr
]);
2826 from[attr
] = eq
.from;
2829 diff
[attr
].real
= true;
2830 for (i
= 0, ii
= from[attr
].length
; i
< ii
; i
++) {
2831 diff
[attr
][i
] = [from[attr
][i
][0]];
2832 for (j
= 1, jj
= from[attr
][i
].length
; j
< jj
; j
++) {
2833 diff
[attr
][i
][j
] = (to
[attr
][i
][j
] - from[attr
][i
][j
]) / ms
;
2837 var m
= (element
.matrix
|| new Matrix
),
2839 _
: {transform
: _
.transform
},
2840 getBBox: function () {
2841 return element
.getBBox(1);
2852 extractTransform(to2
, to
[attr
]);
2853 to
[attr
] = to2
._
.transform
;
2855 (to2
.matrix
.a
- m
.a
) / ms
,
2856 (to2
.matrix
.b
- m
.b
) / ms
,
2857 (to2
.matrix
.c
- m
.c
) / ms
,
2858 (to2
.matrix
.d
- m
.d
) / ms
,
2859 (to2
.matrix
.e
- m
.e
) / ms
,
2860 (to2
.matrix
.e
- m
.f
) / ms
2862 // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];
2863 // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};
2864 // extractTransform(to2, to[attr]);
2866 // (to2._.sx - _.sx) / ms,
2867 // (to2._.sy - _.sy) / ms,
2868 // (to2._.deg - _.deg) / ms,
2869 // (to2._.dx - _.dx) / ms,
2870 // (to2._.dy - _.dy) / ms
2875 var values
= Str(params
[attr
])[split
](separator
),
2876 from2
= Str(from[attr
])[split
](separator
);
2877 if (attr
== "clip-rect") {
2882 diff
[attr
][i
] = (values
[i
] - from[attr
][i
]) / ms
;
2888 values
= [][concat
](params
[attr
]);
2889 from2
= [][concat
](from[attr
]);
2891 i
= element
.paper
.customAttributes
[attr
].length
;
2893 diff
[attr
][i
] = ((values
[i
] || 0) - (from2
[i
] || 0)) / ms
;
2899 var easing
= params
.easing
,
2900 easyeasy
= R
.easing_formulas
[easing
];
2902 easyeasy
= Str(easing
).match(bezierrg
);
2903 if (easyeasy
&& easyeasy
.length
== 5) {
2904 var curve
= easyeasy
;
2905 easyeasy = function (t
) {
2906 return CubicBezierAtTime(t
, +curve
[1], +curve
[2], +curve
[3], +curve
[4], ms
);
2912 timestamp
= params
.start
|| anim
.start
|| +new Date
;
2916 timestamp
: timestamp
,
2917 start
: timestamp
+ (anim
.del
|| 0),
2919 initstatus
: status
|| 0,
2927 callback
: params
.callback
,
2930 repeat
: times
|| anim
.times
,
2931 origin
: element
.attr(),
2932 totalOrigin
: totalOrigin
2934 animationElements
.push(e
);
2935 if (status
&& !isInAnim
&& !isInAnimSet
) {
2937 e
.start
= new Date
- ms
* status
;
2938 if (animationElements
.length
== 1) {
2943 e
.start
= new Date
- e
.ms
* status
;
2945 animationElements
.length
== 1 && requestAnimFrame(animation
);
2947 isInAnim
.initstatus
= status
;
2948 isInAnim
.start
= new Date
- isInAnim
.ms
* status
;
2950 eve("anim.start." + element
.id
, element
, anim
);
2953 R
.animation = function (params
, ms
, easing
, callback
) {
2954 if (params
instanceof Animation
) {
2957 if (R
.is(easing
, "function") || !easing
) {
2958 callback
= callback
|| easing
|| null;
2961 params
= Object(params
);
2966 for (attr
in params
) if (params
[has
](attr
) && toFloat(attr
) != attr
&& toFloat(attr
) + "%" != attr
) {
2968 p
[attr
] = params
[attr
];
2971 return new Animation(params
, ms
);
2973 easing
&& (p
.easing
= easing
);
2974 callback
&& (p
.callback
= callback
);
2975 return new Animation({100: p
}, ms
);
2979 elproto
.animate = function (params
, ms
, easing
, callback
) {
2981 if (element
.removed
) {
2982 callback
&& callback
.call(element
);
2985 var anim
= params
instanceof Animation
? params
: R
.animation(params
, ms
, easing
, callback
);
2986 runAnimation(anim
, element
, anim
.percents
[0], null, element
.attr());
2990 elproto
.setTime = function (anim
, value
) {
2991 if (anim
&& value
!= null) {
2992 this.status(anim
, mmin(value
, anim
.ms
) / anim
.ms
);
2997 elproto
.status = function (anim
, value
) {
3002 if (value
!= null) {
3003 runAnimation(anim
, this, -1, mmin(value
, 1));
3006 len
= animationElements
.length
;
3007 for (; i
< len
; i
++) {
3008 e
= animationElements
[i
];
3009 if (e
.el
.id
== this.id
&& (!anim
|| e
.anim
== anim
)) {
3026 elproto
.pause = function (anim
) {
3027 for (var i
= 0; i
< animationElements
.length
; i
++) if (animationElements
[i
].el
.id
== this.id
&& (!anim
|| animationElements
[i
].anim
== anim
)) {
3028 if (eve("anim.pause." + this.id
, this, animationElements
[i
].anim
) !== false) {
3029 animationElements
[i
].paused
= true;
3035 elproto
.resume = function (anim
) {
3036 for (var i
= 0; i
< animationElements
.length
; i
++) if (animationElements
[i
].el
.id
== this.id
&& (!anim
|| animationElements
[i
].anim
== anim
)) {
3037 var e
= animationElements
[i
];
3038 if (eve("anim.resume." + this.id
, this, e
.anim
) !== false) {
3040 this.status(e
.anim
, e
.status
);
3046 elproto
.stop = function (anim
) {
3047 for (var i
= 0; i
< animationElements
.length
; i
++) if (animationElements
[i
].el
.id
== this.id
&& (!anim
|| animationElements
[i
].anim
== anim
)) {
3048 if (eve("anim.stop." + this.id
, this, animationElements
[i
].anim
) !== false) {
3049 animationElements
.splice(i
--, 1);
3054 elproto
.toString = function () {
3055 return "Rapha\xebl\u2019s object";
3059 var Set = function (items
) {
3064 for (var i
= 0, ii
= items
.length
; i
< ii
; i
++) {
3065 if (items
[i
] && (items
[i
].constructor == elproto
.constructor || items
[i
].constructor == Set
)) {
3066 this[this.items
.length
] = this.items
[this.items
.length
] = items
[i
];
3072 setproto
= Set
.prototype;
3074 setproto
.push = function () {
3077 for (var i
= 0, ii
= arguments
.length
; i
< ii
; i
++) {
3078 item
= arguments
[i
];
3079 if (item
&& (item
.constructor == elproto
.constructor || item
.constructor == Set
)) {
3080 len
= this.items
.length
;
3081 this[len
] = this.items
[len
] = item
;
3088 setproto
.pop = function () {
3089 this.length
&& delete this[this.length
--];
3090 return this.items
.pop();
3093 setproto
.forEach = function (callback
, thisArg
) {
3094 for (var i
= 0, ii
= this.items
.length
; i
< ii
; i
++) {
3095 if (callback
.call(thisArg
, this.items
[i
], i
) === false) {
3101 for (var method
in elproto
) if (elproto
[has
](method
)) {
3102 setproto
[method
] = (function (methodname
) {
3103 return function () {
3104 var arg
= arguments
;
3105 return this.forEach(function (el
) {
3106 el
[methodname
][apply
](el
, arg
);
3111 setproto
.attr = function (name
, value
) {
3112 if (name
&& R
.is(name
, array
) && R
.is(name
[0], "object")) {
3113 for (var j
= 0, jj
= name
.length
; j
< jj
; j
++) {
3114 this.items
[j
].attr(name
[j
]);
3117 for (var i
= 0, ii
= this.items
.length
; i
< ii
; i
++) {
3118 this.items
[i
].attr(name
, value
);
3124 setproto
.clear = function () {
3125 while (this.length
) {
3130 setproto
.splice = function (index
, count
, insertion
) {
3131 index
= index
< 0 ? mmax(this.length
+ index
, 0) : index
;
3132 count
= mmax(0, mmin(this.length
- index
, count
));
3137 for (i
= 2; i
< arguments
.length
; i
++) {
3138 args
.push(arguments
[i
]);
3140 for (i
= 0; i
< count
; i
++) {
3141 todel
.push(this[index
+ i
]);
3143 for (; i
< this.length
- index
; i
++) {
3144 tail
.push(this[index
+ i
]);
3146 var arglen
= args
.length
;
3147 for (i
= 0; i
< arglen
+ tail
.length
; i
++) {
3148 this.items
[index
+ i
] = this[index
+ i
] = i
< arglen
? args
[i
] : tail
[i
- arglen
];
3150 i
= this.items
.length
= this.length
-= count
- arglen
;
3154 return new Set(todel
);
3157 setproto
.exclude = function (el
) {
3158 for (var i
= 0, ii
= this.length
; i
< ii
; i
++) if (this[i
] == el
) {
3163 setproto
.animate = function (params
, ms
, easing
, callback
) {
3164 (R
.is(easing
, "function") || !easing
) && (callback
= easing
|| null);
3165 var len
= this.items
.length
,
3173 callback
&& (collector = function () {
3174 !--len
&& callback
.call(set);
3176 easing
= R
.is(easing
, string
) ? easing
: collector
;
3177 var anim
= R
.animation(params
, ms
, easing
, collector
);
3178 item
= this.items
[--i
].animate(anim
);
3180 this.items
[i
] && !this.items
[i
].removed
&& this.items
[i
].animateWith(item
, anim
);
3184 setproto
.insertAfter = function (el
) {
3185 var i
= this.items
.length
;
3187 this.items
[i
].insertAfter(el
);
3191 setproto
.getBBox = function () {
3196 for (var i
= this.items
.length
; i
--;) if (!this.items
[i
].removed
) {
3197 var box
= this.items
[i
].getBBox();
3200 w
.push(box
.x
+ box
.width
);
3201 h
.push(box
.y
+ box
.height
);
3203 x
= mmin
[apply
](0, x
);
3204 y
= mmin
[apply
](0, y
);
3208 width
: mmax
[apply
](0, w
) - x
,
3209 height
: mmax
[apply
](0, h
) - y
3212 setproto
.clone = function (s
) {
3214 for (var i
= 0, ii
= this.items
.length
; i
< ii
; i
++) {
3215 s
.push(this.items
[i
].clone());
3219 setproto
.toString = function () {
3220 return "Rapha\xebl\u2018s set";
3224 R
.registerFont = function (font
) {
3228 this.fonts
= this.fonts
|| {};
3234 family
= font
.face
["font-family"];
3235 for (var prop
in font
.face
) if (font
.face
[has
](prop
)) {
3236 fontcopy
.face
[prop
] = font
.face
[prop
];
3238 if (this.fonts
[family
]) {
3239 this.fonts
[family
].push(fontcopy
);
3241 this.fonts
[family
] = [fontcopy
];
3244 fontcopy
.face
["units-per-em"] = toInt(font
.face
["units-per-em"], 10);
3245 for (var glyph
in font
.glyphs
) if (font
.glyphs
[has
](glyph
)) {
3246 var path
= font
.glyphs
[glyph
];
3247 fontcopy
.glyphs
[glyph
] = {
3250 d
: path
.d
&& "M" + path
.d
.replace(/[mlcxtrv]/g, function (command
) {
3251 return {l
: "L", c
: "C", x
: "z", t
: "m", r
: "l", v
: "c"}[command
] || "M";
3255 for (var k
in path
.k
) if (path
[has
](k
)) {
3256 fontcopy
.glyphs
[glyph
].k
[k
] = path
.k
[k
];
3264 paperproto
.getFont = function (family
, weight
, style
, stretch
) {
3265 stretch
= stretch
|| "normal";
3266 style
= style
|| "normal";
3267 weight
= +weight
|| {normal
: 400, bold
: 700, lighter
: 300, bolder
: 800}[weight
] || 400;
3271 var font
= R
.fonts
[family
];
3273 var name
= new RegExp("(^|\\s)" + family
.replace(/[^\w\d\s+!~.:_-]/g, E
) + "(\\s|$)", "i");
3274 for (var fontName
in R
.fonts
) if (R
.fonts
[has
](fontName
)) {
3275 if (name
.test(fontName
)) {
3276 font
= R
.fonts
[fontName
];
3283 for (var i
= 0, ii
= font
.length
; i
< ii
; i
++) {
3285 if (thefont
.face
["font-weight"] == weight
&& (thefont
.face
["font-style"] == style
|| !thefont
.face
["font-style"]) && thefont
.face
["font-stretch"] == stretch
) {
3293 paperproto
.print = function (x
, y
, string
, font
, size
, origin
, letter_spacing
) {
3294 origin
= origin
|| "middle"; // baseline|middle
3295 letter_spacing
= mmax(mmin(letter_spacing
|| 0, 1), -1);
3296 var out
= this.set(),
3297 letters
= Str(string
)[split
](E
),
3301 R
.is(font
, string
) && (font
= this.getFont(font
));
3303 scale
= (size
|| 16) / font
.face
["units-per-em"];
3304 var bb
= font
.face
.bbox
[split
](separator
),
3306 height
= +bb
[1] + (origin
== "baseline" ? bb
[3] - bb
[1] + (+font
.face
.descent
) : (bb
[3] - bb
[1]) / 2);
3307 for (var i
= 0, ii
= letters
.length
; i
< ii
; i
++) {
3308 var prev
= i
&& font
.glyphs
[letters
[i
- 1]] || {},
3309 curr
= font
.glyphs
[letters
[i
]];
3310 shift
+= i
? (prev
.w
|| font
.w
) + (prev
.k
&& prev
.k
[letters
[i
]] || 0) + (font
.w
* letter_spacing
) : 0;
3311 curr
&& curr
.d
&& out
.push(this.path(curr
.d
).attr({
3314 transform
: [["t", shift
* scale
, 0]]
3317 out
.transform(["...s", scale
, scale
, top
, height
, "t", (x
- top
) / scale
, (y
- height
) / scale
]);
3323 paperproto
.add = function (json
) {
3324 if (R
.is(json
, "array")) {
3325 var res
= this.set(),
3329 for (; i
< ii
; i
++) {
3331 elements
[has
](j
.type
) && res
.push(this[j
.type
]().attr(j
));
3338 R
.format = function (token
, params
) {
3339 var args
= R
.is(params
, array
) ? [0][concat
](params
) : arguments
;
3340 token
&& R
.is(token
, string
) && args
.length
- 1 && (token
= token
.replace(formatrg
, function (str
, i
) {
3341 return args
[++i
] == null ? E
: args
[i
];
3346 R
.fullfill
= (function () {
3347 var tokenRegex
= /\{([^\}]+)\}/g,
3348 objNotationRegex
= /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties
3349 replacer = function (all
, key
, obj
) {
3351 key
.replace(objNotationRegex
, function (all
, name
, quote
, quotedName
, isFunc
) {
3352 name
= name
|| quotedName
;
3357 typeof res
== "function" && isFunc
&& (res
= res());
3360 res
= (res
== null || res
== obj
? all
: res
) + "";
3363 return function (str
, obj
) {
3364 return String(str
).replace(tokenRegex
, function (all
, key
) {
3365 return replacer(all
, key
, obj
);
3370 R
.ninja = function () {
3371 oldRaphael
.was
? (g
.win
.Raphael
= oldRaphael
.is
) : delete Raphael
;
3376 // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
3377 (function (doc
, loaded
, f
) {
3378 if (doc
.readyState
== null && doc
.addEventListener
){
3379 doc
.addEventListener(loaded
, f = function () {
3380 doc
.removeEventListener(loaded
, f
, false);
3381 doc
.readyState
= "complete";
3383 doc
.readyState
= "loading";
3385 function isLoaded() {
3386 (/in/).test(doc
.readyState
) ? setTimeout(isLoaded
, 9) : R
.eve("DOMload");
3389 })(document
, "DOMContentLoaded");
3391 oldRaphael
.was
? (g
.win
.Raphael
= R
) : (Raphael
= R
);
3393 eve
.on("DOMload", function () {
3399 // ┌─────────────────────────────────────────────────────────────────────┐ \\
3400 // │ Raphaël - JavaScript Vector Library │ \\
3401 // ├─────────────────────────────────────────────────────────────────────┤ \\
3402 // │ SVG Module │ \\
3403 // ├─────────────────────────────────────────────────────────────────────┤ \\
3404 // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
3405 // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\
3406 // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
3407 // └─────────────────────────────────────────────────────────────────────┘ \\
3408 window
.Raphael
.svg
&& function (R
) {
3409 var has
= "hasOwnProperty",
3411 toFloat
= parseFloat
,
3417 separator
= /[, ]+/,
3421 var xlink
= "http://www.w3.org/1999/xlink",
3423 block
: "M5,0 0,2.5 5,5z",
3424 classic
: "M5,0 0,2.5 5,5 3.5,3 3.5,2z",
3425 diamond
: "M2.5,0 5,2.5 2.5,5 0,2.5z",
3426 open
: "M6,1 1,3.5 6,6",
3427 oval
: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"
3430 R
.toString = function () {
3431 return "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version
;
3433 var $ = function (el
, attr
) {
3435 if (typeof el
== "string") {
3438 for (var key
in attr
) if (attr
[has
](key
)) {
3439 if (key
.substring(0, 6) == "xlink:") {
3440 el
.setAttributeNS(xlink
, key
.substring(6), Str(attr
[key
]));
3442 el
.setAttribute(key
, Str(attr
[key
]));
3446 el
= R
._g
.doc
.createElementNS("http://www.w3.org/2000/svg", el
);
3447 el
.style
&& (el
.style
.webkitTapHighlightColor
= "rgba(0,0,0,0)");
3451 addGradientFill = function (element
, gradient
) {
3452 var type
= "linear",
3453 id
= element
.id
+ gradient
,
3456 SVG
= element
.paper
,
3458 el
= R
._g
.doc
.getElementById(id
);
3460 gradient
= Str(gradient
).replace(R
._radial_gradient
, function (all
, _fx
, _fy
) {
3465 var dir
= ((fy
> .5) * 2 - 1);
3466 pow(fx
- .5, 2) + pow(fy
- .5, 2) > .25 &&
3467 (fy
= math
.sqrt(.25 - pow(fx
- .5, 2)) * dir
+ .5) &&
3469 (fy
= fy
.toFixed(5) - 1e-5 * dir
);
3473 gradient
= gradient
.split(/\s*\-\s*/);
3474 if (type
== "linear") {
3475 var angle
= gradient
.shift();
3476 angle
= -toFloat(angle
);
3480 var vector
= [0, 0, math
.cos(R
.rad(angle
)), math
.sin(R
.rad(angle
))],
3481 max
= 1 / (mmax(abs(vector
[2]), abs(vector
[3])) || 1);
3484 if (vector
[2] < 0) {
3485 vector
[0] = -vector
[2];
3488 if (vector
[3] < 0) {
3489 vector
[1] = -vector
[3];
3493 var dots
= R
._parseDots(gradient
);
3497 id
= id
.replace(/[\(\)\s,\xb0#]/g, "_");
3499 if (element
.gradient
&& id
!= element
.gradient
.id
) {
3500 SVG
.defs
.removeChild(element
.gradient
);
3501 delete element
.gradient
;
3504 if (!element
.gradient
) {
3505 el
= $(type
+ "Gradient", {id
: id
});
3506 element
.gradient
= el
;
3507 $(el
, type
== "radial" ? {
3515 gradientTransform
: element
.matrix
.invert()
3517 SVG
.defs
.appendChild(el
);
3518 for (var i
= 0, ii
= dots
.length
; i
< ii
; i
++) {
3519 el
.appendChild($("stop", {
3520 offset
: dots
[i
].offset
? dots
[i
].offset
: i
? "100%" : "0%",
3521 "stop-color": dots
[i
].color
|| "#fff"
3527 fill
: "url(#" + id
+ ")",
3536 updatePosition = function (o
) {
3537 var bbox
= o
.getBBox(1);
3538 $(o
.pattern
, {patternTransform
: o
.matrix
.invert() + " translate(" + bbox
.x
+ "," + bbox
.y
+ ")"});
3540 addArrow = function (o
, value
, isEnd
) {
3541 if (o
.type
== "path") {
3542 var values
= Str(value
).toLowerCase().split("-"),
3544 se
= isEnd
? "end" : "start",
3547 stroke
= attrs
["stroke-width"],
3559 switch (values
[i
]) {
3568 case "wide": h
= 5; break;
3569 case "narrow": h
= 2; break;
3570 case "long": w
= 5; break;
3571 case "short": w
= 2; break;
3574 if (type
== "open") {
3579 refX
= isEnd
? 4 : 1;
3582 stroke
: attrs
.stroke
3593 o
._
.arrows
.endPath
&& markerCounter
[o
._
.arrows
.endPath
]--;
3594 o
._
.arrows
.endMarker
&& markerCounter
[o
._
.arrows
.endMarker
]--;
3596 o
._
.arrows
.startPath
&& markerCounter
[o
._
.arrows
.startPath
]--;
3597 o
._
.arrows
.startMarker
&& markerCounter
[o
._
.arrows
.startMarker
]--;
3602 if (type
!= "none") {
3603 var pathId
= "raphael-marker-" + type
,
3604 markerId
= "raphael-marker-" + se
+ type
+ w
+ h
;
3605 if (!R
._g
.doc
.getElementById(pathId
)) {
3606 p
.defs
.appendChild($($("path"), {
3607 "stroke-linecap": "round",
3611 markerCounter
[pathId
] = 1;
3613 markerCounter
[pathId
]++;
3615 var marker
= R
._g
.doc
.getElementById(markerId
),
3618 marker
= $($("marker"), {
3627 "xlink:href": "#" + pathId
,
3628 transform
: (isEnd
? " rotate(180 " + w
/ 2 + " " + h
/ 2 + ") " : S
) + "scale(" + w
/ t
+ "," + h
/ t
+ ")",
3629 "stroke-width": 1 / ((w
/ t
+ h
/ t
) / 2)
3631 marker
.appendChild(use);
3632 p
.defs
.appendChild(marker
);
3633 markerCounter
[markerId
] = 1;
3635 markerCounter
[markerId
]++;
3636 use = marker
.getElementsByTagName("use")[0];
3639 var delta
= dx
* (type
!= "diamond" && type
!= "oval");
3641 from = o
._
.arrows
.startdx
* stroke
|| 0;
3642 to
= R
.getTotalLength(attrs
.path
) - delta
* stroke
;
3644 from = delta
* stroke
;
3645 to
= R
.getTotalLength(attrs
.path
) - (o
._
.arrows
.enddx
* stroke
|| 0);
3648 attr
["marker-" + se
] = "url(#" + markerId
+ ")";
3650 attr
.d
= Raphael
.getSubpath(attrs
.path
, from, to
);
3653 o
._
.arrows
[se
+ "Path"] = pathId
;
3654 o
._
.arrows
[se
+ "Marker"] = markerId
;
3655 o
._
.arrows
[se
+ "dx"] = delta
;
3656 o
._
.arrows
[se
+ "Type"] = type
;
3657 o
._
.arrows
[se
+ "String"] = value
;
3660 from = o
._
.arrows
.startdx
* stroke
|| 0;
3661 to
= R
.getTotalLength(attrs
.path
) - from;
3664 to
= R
.getTotalLength(attrs
.path
) - (o
._
.arrows
.enddx
* stroke
|| 0);
3666 o
._
.arrows
[se
+ "Path"] && $(node
, {d
: Raphael
.getSubpath(attrs
.path
, from, to
)});
3667 delete o
._
.arrows
[se
+ "Path"];
3668 delete o
._
.arrows
[se
+ "Marker"];
3669 delete o
._
.arrows
[se
+ "dx"];
3670 delete o
._
.arrows
[se
+ "Type"];
3671 delete o
._
.arrows
[se
+ "String"];
3673 for (attr
in markerCounter
) if (markerCounter
[has
](attr
) && !markerCounter
[attr
]) {
3674 var item
= R
._g
.doc
.getElementById(attr
);
3675 item
&& item
.parentNode
.removeChild(item
);
3685 "-..": [3, 1, 1, 1, 1, 1],
3689 "- .": [4, 3, 1, 3],
3690 "--.": [8, 3, 1, 3],
3691 "--..": [8, 3, 1, 3, 1, 3]
3693 addDashes = function (o
, value
, params
) {
3694 value
= dasharray
[Str(value
).toLowerCase()];
3696 var width
= o
.attrs
["stroke-width"] || "1",
3697 butt
= {round
: width
, square
: width
, butt
: 0}[o
.attrs
["stroke-linecap"] || params
["stroke-linecap"]] || 0,
3701 dashes
[i
] = value
[i
] * width
+ ((i
% 2) ? 1 : -1) * butt
;
3703 $(o
.node
, {"stroke-dasharray": dashes
.join(",")});
3706 setFillAndStroke = function (o
, params
) {
3709 vis
= node
.style
.visibility
;
3710 node
.style
.visibility
= "hidden";
3711 for (var att
in params
) {
3712 if (params
[has
](att
)) {
3713 if (!R
._availableAttrs
[has
](att
)) {
3716 var value
= params
[att
];
3725 var pn
= node
.parentNode
;
3726 if (pn
.tagName
.toLowerCase() != "a") {
3728 pn
.insertBefore(hl
, node
);
3729 hl
.appendChild(node
);
3732 if (att
== "target" && value
== "blank") {
3733 pn
.setAttributeNS(xlink
, "show", "new");
3735 pn
.setAttributeNS(xlink
, att
, value
);
3739 node
.style
.cursor
= value
;
3748 addArrow(o
, value
, 1);
3751 var rect
= Str(value
).split(separator
);
3752 if (rect
.length
== 4) {
3753 o
.clip
&& o
.clip
.parentNode
.parentNode
.removeChild(o
.clip
.parentNode
);
3754 var el
= $("clipPath"),
3756 el
.id
= R
.createUUID();
3764 o
.paper
.defs
.appendChild(el
);
3765 $(node
, {"clip-path": "url(#" + el
.id
+ ")"});
3769 var path
= node
.getAttribute("clip-path");
3771 var clip
= R
._g
.doc
.getElementById(path
.replace(/(^url\(#|\)$)/g, E
));
3772 clip
&& clip
.parentNode
.removeChild(clip
);
3773 $(node
, {"clip-path": E
});
3779 if (o
.type
== "path") {
3780 $(node
, {d
: value
? attrs
.path
= R
._pathToAbsolute(value
) : "M0,0"});
3783 "startString" in o
._
.arrows
&& addArrow(o
, o
._
.arrows
.startString
);
3784 "endString" in o
._
.arrows
&& addArrow(o
, o
._
.arrows
.endString
, 1);
3789 node
.setAttribute(att
, value
);
3799 value
= -attrs
.x
- (attrs
.width
|| 0);
3802 if (att
== "rx" && o
.type
== "rect") {
3806 node
.setAttribute(att
, value
);
3807 o
.pattern
&& updatePosition(o
);
3811 node
.setAttribute(att
, value
);
3821 value
= -attrs
.y
- (attrs
.height
|| 0);
3824 if (att
== "ry" && o
.type
== "rect") {
3828 node
.setAttribute(att
, value
);
3829 o
.pattern
&& updatePosition(o
);
3833 if (o
.type
== "rect") {
3834 $(node
, {rx
: value
, ry
: value
});
3836 node
.setAttribute(att
, value
);
3841 if (o
.type
== "image") {
3842 node
.setAttributeNS(xlink
, "href", value
);
3845 case "stroke-width":
3846 if (o
._
.sx
!= 1 || o
._
.sy
!= 1) {
3847 value
/= mmax(abs(o
._
.sx
), abs(o
._
.sy
)) || 1;
3849 if (o
.paper
._vbSize
) {
3850 value
*= o
.paper
._vbSize
;
3852 node
.setAttribute(att
, value
);
3853 if (attrs
["stroke-dasharray"]) {
3854 addDashes(o
, attrs
["stroke-dasharray"], params
);
3857 "startString" in o
._
.arrows
&& addArrow(o
, o
._
.arrows
.startString
);
3858 "endString" in o
._
.arrows
&& addArrow(o
, o
._
.arrows
.endString
, 1);
3861 case "stroke-dasharray":
3862 addDashes(o
, value
, params
);
3865 var isURL
= Str(value
).match(R
._ISURL
);
3868 var ig
= $("image");
3869 el
.id
= R
.createUUID();
3870 $(el
, {x
: 0, y
: 0, patternUnits
: "userSpaceOnUse", height
: 1, width
: 1});
3871 $(ig
, {x
: 0, y
: 0, "xlink:href": isURL
[1]});
3875 R
._preload(isURL
[1], function () {
3876 var w
= this.offsetWidth
,
3877 h
= this.offsetHeight
;
3878 $(el
, {width
: w
, height
: h
});
3879 $(ig
, {width
: w
, height
: h
});
3883 o
.paper
.defs
.appendChild(el
);
3884 node
.style
.fill
= "url(#" + el
.id
+ ")";
3885 $(node
, {fill
: "url(#" + el
.id
+ ")"});
3887 o
.pattern
&& updatePosition(o
);
3890 var clr
= R
.getRGB(value
);
3892 delete params
.gradient
;
3893 delete attrs
.gradient
;
3894 !R
.is(attrs
.opacity
, "undefined") &&
3895 R
.is(params
.opacity
, "undefined") &&
3896 $(node
, {opacity
: attrs
.opacity
});
3897 !R
.is(attrs
["fill-opacity"], "undefined") &&
3898 R
.is(params
["fill-opacity"], "undefined") &&
3899 $(node
, {"fill-opacity": attrs
["fill-opacity"]});
3900 } else if ((o
.type
== "circle" || o
.type
== "ellipse" || Str(value
).charAt() != "r") && addGradientFill(o
, value
)) {
3901 if ("opacity" in attrs
|| "fill-opacity" in attrs
) {
3902 var gradient
= R
._g
.doc
.getElementById(node
.getAttribute("fill").replace(/^url\(#|\)$/g, E
));
3904 var stops
= gradient
.getElementsByTagName("stop");
3905 $(stops
[stops
.length
- 1], {"stop-opacity": ("opacity" in attrs
? attrs
.opacity
: 1) * ("fill-opacity" in attrs
? attrs
["fill-opacity"] : 1)});
3908 attrs
.gradient
= value
;
3909 attrs
.fill
= "none";
3912 clr
[has
]("opacity") && $(node
, {"fill-opacity": clr
.opacity
> 1 ? clr
.opacity
/ 100 : clr
.opacity
});
3914 clr
= R
.getRGB(value
);
3915 node
.setAttribute(att
, clr
.hex
);
3916 att
== "stroke" && clr
[has
]("opacity") && $(node
, {"stroke-opacity": clr
.opacity
> 1 ? clr
.opacity
/ 100 : clr
.opacity
});
3917 if (att
== "stroke" && o
._
.arrows
) {
3918 "startString" in o
._
.arrows
&& addArrow(o
, o
._
.arrows
.startString
);
3919 "endString" in o
._
.arrows
&& addArrow(o
, o
._
.arrows
.endString
, 1);
3923 (o
.type
== "circle" || o
.type
== "ellipse" || Str(value
).charAt() != "r") && addGradientFill(o
, value
);
3926 if (attrs
.gradient
&& !attrs
[has
]("stroke-opacity")) {
3927 $(node
, {"stroke-opacity": value
> 1 ? value
/ 100 : value
});
3930 case "fill-opacity":
3931 if (attrs
.gradient
) {
3932 gradient
= R
._g
.doc
.getElementById(node
.getAttribute("fill").replace(/^url\(#|\)$/g, E
));
3934 stops
= gradient
.getElementsByTagName("stop");
3935 $(stops
[stops
.length
- 1], {"stop-opacity": value
});
3940 att
== "font-size" && (value
= toInt(value
, 10) + "px");
3941 var cssrule
= att
.replace(/(\-.)/g, function (w
) {
3942 return w
.substring(1).toUpperCase();
3944 node
.style
[cssrule
] = value
;
3946 node
.setAttribute(att
, value
);
3952 tuneText(o
, params
);
3953 node
.style
.visibility
= vis
;
3956 tuneText = function (el
, params
) {
3957 if (el
.type
!= "text" || !(params
[has
]("text") || params
[has
]("font") || params
[has
]("font-size") || params
[has
]("x") || params
[has
]("y"))) {
3962 fontSize
= node
.firstChild
? toInt(R
._g
.doc
.defaultView
.getComputedStyle(node
.firstChild
, E
).getPropertyValue("font-size"), 10) : 10;
3964 if (params
[has
]("text")) {
3965 a
.text
= params
.text
;
3966 while (node
.firstChild
) {
3967 node
.removeChild(node
.firstChild
);
3969 var texts
= Str(params
.text
).split("\n"),
3972 for (var i
= 0, ii
= texts
.length
; i
< ii
; i
++) {
3974 i
&& $(tspan
, {dy
: fontSize
* leading
, x
: a
.x
});
3975 tspan
.appendChild(R
._g
.doc
.createTextNode(texts
[i
]));
3976 node
.appendChild(tspan
);
3980 tspans
= node
.getElementsByTagName("tspan");
3981 for (i
= 0, ii
= tspans
.length
; i
< ii
; i
++) if (i
) {
3982 $(tspans
[i
], {dy
: fontSize
* leading
, x
: a
.x
});
3984 $(tspans
[0], {dy
: 0});
3987 $(node
, {x
: a
.x
, y
: a
.y
});
3989 var bb
= el
._getBBox(),
3990 dif
= a
.y
- (bb
.y
+ bb
.height
/ 2);
3991 dif
&& R
.is(dif
, "finite") && $(tspans
[0], {dy
: dif
});
3993 Element = function (node
, svg
) {
3997 this[0] = this.node
= node
;
3999 node
.raphael
= true;
4002 node
.raphaelid
= this.id
;
4003 this.matrix
= R
.matrix();
4004 this.realPath
= null;
4007 this.attrs
= this.attrs
|| {};
4017 !svg
.bottom
&& (svg
.bottom
= this);
4019 this.prev
= svg
.top
;
4020 svg
.top
&& (svg
.top
.next
= this);
4027 Element
.prototype = elproto
;
4028 elproto
.constructor = Element
;
4030 R
._engine
.path = function (pathString
, SVG
) {
4032 SVG
.canvas
&& SVG
.canvas
.appendChild(el
);
4033 var p
= new Element(el
, SVG
);
4035 setFillAndStroke(p
, {
4043 elproto
.rotate = function (deg
, cx
, cy
) {
4047 deg
= Str(deg
).split(separator
);
4048 if (deg
.length
- 1) {
4049 cx
= toFloat(deg
[1]);
4050 cy
= toFloat(deg
[2]);
4052 deg
= toFloat(deg
[0]);
4053 (cy
== null) && (cx
= cy
);
4054 if (cx
== null || cy
== null) {
4055 var bbox
= this.getBBox(1);
4056 cx
= bbox
.x
+ bbox
.width
/ 2;
4057 cy
= bbox
.y
+ bbox
.height
/ 2;
4059 this.transform(this._
.transform
.concat([["r", deg
, cx
, cy
]]));
4063 elproto
.scale = function (sx
, sy
, cx
, cy
) {
4067 sx
= Str(sx
).split(separator
);
4068 if (sx
.length
- 1) {
4069 sy
= toFloat(sx
[1]);
4070 cx
= toFloat(sx
[2]);
4071 cy
= toFloat(sx
[3]);
4073 sx
= toFloat(sx
[0]);
4074 (sy
== null) && (sy
= sx
);
4075 (cy
== null) && (cx
= cy
);
4076 if (cx
== null || cy
== null) {
4077 var bbox
= this.getBBox(1);
4079 cx
= cx
== null ? bbox
.x
+ bbox
.width
/ 2 : cx
;
4080 cy
= cy
== null ? bbox
.y
+ bbox
.height
/ 2 : cy
;
4081 this.transform(this._
.transform
.concat([["s", sx
, sy
, cx
, cy
]]));
4085 elproto
.translate = function (dx
, dy
) {
4089 dx
= Str(dx
).split(separator
);
4090 if (dx
.length
- 1) {
4091 dy
= toFloat(dx
[1]);
4093 dx
= toFloat(dx
[0]) || 0;
4095 this.transform(this._
.transform
.concat([["t", dx
, dy
]]));
4099 elproto
.transform = function (tstr
) {
4104 R
._extractTransform(this, tstr
);
4106 this.clip
&& $(this.clip
, {transform
: this.matrix
.invert()});
4107 this.pattern
&& updatePosition(this);
4108 this.node
&& $(this.node
, {transform
: this.matrix
});
4110 if (_
.sx
!= 1 || _
.sy
!= 1) {
4111 var sw
= this.attrs
[has
]("stroke-width") ? this.attrs
["stroke-width"] : 1;
4112 this.attr({"stroke-width": sw
});
4118 elproto
.hide = function () {
4119 !this.removed
&& this.paper
.safari(this.node
.style
.display
= "none");
4123 elproto
.show = function () {
4124 !this.removed
&& this.paper
.safari(this.node
.style
.display
= "");
4128 elproto
.remove = function () {
4132 var paper
= this.paper
;
4133 paper
.__set__
&& paper
.__set__
.exclude(this);
4134 eve
.unbind("*.*." + this.id
);
4135 if (this.gradient
) {
4136 paper
.defs
.removeChild(this.gradient
);
4138 R
._tear(this, paper
);
4139 this.node
.parentNode
.removeChild(this.node
);
4140 for (var i
in this) {
4141 this[i
] = typeof this[i
] == "function" ? R
._removedFactory(i
) : null;
4143 this.removed
= true;
4145 elproto
._getBBox = function () {
4146 if (this.node
.style
.display
== "none") {
4152 bbox
= this.node
.getBBox();
4154 // Firefox 3.0.x plays badly here
4158 hide
&& this.hide();
4162 elproto
.attr = function (name
, value
) {
4168 for (var a
in this.attrs
) if (this.attrs
[has
](a
)) {
4169 res
[a
] = this.attrs
[a
];
4171 res
.gradient
&& res
.fill
== "none" && (res
.fill
= res
.gradient
) && delete res
.gradient
;
4172 res
.transform
= this._
.transform
;
4175 if (value
== null && R
.is(name
, "string")) {
4176 if (name
== "fill" && this.attrs
.fill
== "none" && this.attrs
.gradient
) {
4177 return this.attrs
.gradient
;
4179 if (name
== "transform") {
4180 return this._
.transform
;
4182 var names
= name
.split(separator
),
4184 for (var i
= 0, ii
= names
.length
; i
< ii
; i
++) {
4186 if (name
in this.attrs
) {
4187 out
[name
] = this.attrs
[name
];
4188 } else if (R
.is(this.paper
.customAttributes
[name
], "function")) {
4189 out
[name
] = this.paper
.customAttributes
[name
].def
;
4191 out
[name
] = R
._availableAttrs
[name
];
4194 return ii
- 1 ? out
: out
[names
[0]];
4196 if (value
== null && R
.is(name
, "array")) {
4198 for (i
= 0, ii
= name
.length
; i
< ii
; i
++) {
4199 out
[name
[i
]] = this.attr(name
[i
]);
4203 if (value
!= null) {
4205 params
[name
] = value
;
4206 } else if (name
!= null && R
.is(name
, "object")) {
4209 for (var key
in params
) {
4210 eve("attr." + key
+ "." + this.id
, this, params
[key
]);
4212 for (key
in this.paper
.customAttributes
) if (this.paper
.customAttributes
[has
](key
) && params
[has
](key
) && R
.is(this.paper
.customAttributes
[key
], "function")) {
4213 var par
= this.paper
.customAttributes
[key
].apply(this, [].concat(params
[key
]));
4214 this.attrs
[key
] = params
[key
];
4215 for (var subkey
in par
) if (par
[has
](subkey
)) {
4216 params
[subkey
] = par
[subkey
];
4219 setFillAndStroke(this, params
);
4223 elproto
.toFront = function () {
4227 if (this.node
.parentNode
.tagName
.toLowerCase() == "a") {
4228 this.node
.parentNode
.parentNode
.appendChild(this.node
.parentNode
);
4230 this.node
.parentNode
.appendChild(this.node
);
4232 var svg
= this.paper
;
4233 svg
.top
!= this && R
._tofront(this, svg
);
4237 elproto
.toBack = function () {
4241 var parent
= this.node
.parentNode
;
4242 if (parent
.tagName
.toLowerCase() == "a") {
4243 parent
.parentNode
.insertBefore(this.node
.parentNode
, this.node
.parentNode
.parentNode
.firstChild
);
4244 } else if (parent
.firstChild
!= this.node
) {
4245 parent
.insertBefore(this.node
, this.node
.parentNode
.firstChild
);
4247 R
._toback(this, this.paper
);
4248 var svg
= this.paper
;
4252 elproto
.insertAfter = function (element
) {
4256 var node
= element
.node
|| element
[element
.length
- 1].node
;
4257 if (node
.nextSibling
) {
4258 node
.parentNode
.insertBefore(this.node
, node
.nextSibling
);
4260 node
.parentNode
.appendChild(this.node
);
4262 R
._insertafter(this, element
, this.paper
);
4266 elproto
.insertBefore = function (element
) {
4270 var node
= element
.node
|| element
[0].node
;
4271 node
.parentNode
.insertBefore(this.node
, node
);
4272 R
._insertbefore(this, element
, this.paper
);
4275 elproto
.blur = function (size
) {
4276 // Experimental. No Safari support. Use it on your own risk.
4279 var fltr
= $("filter"),
4280 blur
= $("feGaussianBlur");
4281 t
.attrs
.blur
= size
;
4282 fltr
.id
= R
.createUUID();
4283 $(blur
, {stdDeviation
: +size
|| 1.5});
4284 fltr
.appendChild(blur
);
4285 t
.paper
.defs
.appendChild(fltr
);
4287 $(t
.node
, {filter
: "url(#" + fltr
.id
+ ")"});
4290 t
._blur
.parentNode
.removeChild(t
._blur
);
4292 delete t
.attrs
.blur
;
4294 t
.node
.removeAttribute("filter");
4297 R
._engine
.circle = function (svg
, x
, y
, r
) {
4298 var el
= $("circle");
4299 svg
.canvas
&& svg
.canvas
.appendChild(el
);
4300 var res
= new Element(el
, svg
);
4301 res
.attrs
= {cx
: x
, cy
: y
, r
: r
, fill
: "none", stroke
: "#000"};
4302 res
.type
= "circle";
4306 R
._engine
.rect = function (svg
, x
, y
, w
, h
, r
) {
4308 svg
.canvas
&& svg
.canvas
.appendChild(el
);
4309 var res
= new Element(el
, svg
);
4310 res
.attrs
= {x
: x
, y
: y
, width
: w
, height
: h
, r
: r
|| 0, rx
: r
|| 0, ry
: r
|| 0, fill
: "none", stroke
: "#000"};
4315 R
._engine
.ellipse = function (svg
, x
, y
, rx
, ry
) {
4316 var el
= $("ellipse");
4317 svg
.canvas
&& svg
.canvas
.appendChild(el
);
4318 var res
= new Element(el
, svg
);
4319 res
.attrs
= {cx
: x
, cy
: y
, rx
: rx
, ry
: ry
, fill
: "none", stroke
: "#000"};
4320 res
.type
= "ellipse";
4324 R
._engine
.image = function (svg
, src
, x
, y
, w
, h
) {
4325 var el
= $("image");
4326 $(el
, {x
: x
, y
: y
, width
: w
, height
: h
, preserveAspectRatio
: "none"});
4327 el
.setAttributeNS(xlink
, "href", src
);
4328 svg
.canvas
&& svg
.canvas
.appendChild(el
);
4329 var res
= new Element(el
, svg
);
4330 res
.attrs
= {x
: x
, y
: y
, width
: w
, height
: h
, src
: src
};
4334 R
._engine
.text = function (svg
, x
, y
, text
) {
4336 // $(el, {x: x, y: y, "text-anchor": "middle"});
4337 svg
.canvas
&& svg
.canvas
.appendChild(el
);
4338 var res
= new Element(el
, svg
);
4342 "text-anchor": "middle",
4344 font
: R
._availableAttrs
.font
,
4349 setFillAndStroke(res
, res
.attrs
);
4352 R
._engine
.setSize = function (width
, height
) {
4353 this.width
= width
|| this.width
;
4354 this.height
= height
|| this.height
;
4355 this.canvas
.setAttribute("width", this.width
);
4356 this.canvas
.setAttribute("height", this.height
);
4357 if (this._viewBox
) {
4358 this.setViewBox
.apply(this, this._viewBox
);
4362 R
._engine
.create = function () {
4363 var con
= R
._getContainer
.apply(0, arguments
),
4364 container
= con
&& con
.container
,
4368 height
= con
.height
;
4370 throw new Error("SVG container not found.");
4372 var cnvs
= $("svg"),
4373 css
= "overflow:hidden;",
4377 width
= width
|| 512;
4378 height
= height
|| 342;
4383 xmlns
: "http://www.w3.org/2000/svg"
4385 if (container
== 1) {
4386 cnvs
.style
.cssText
= css
+ "position:absolute;left:" + x
+ "px;top:" + y
+ "px";
4387 R
._g
.doc
.body
.appendChild(cnvs
);
4390 cnvs
.style
.cssText
= css
+ "position:relative";
4391 if (container
.firstChild
) {
4392 container
.insertBefore(cnvs
, container
.firstChild
);
4394 container
.appendChild(cnvs
);
4397 container
= new R
._Paper
;
4398 container
.width
= width
;
4399 container
.height
= height
;
4400 container
.canvas
= cnvs
;
4401 // plugins.call(container, container, R.fn);
4403 container
._left
= container
._top
= 0;
4404 isFloating
&& (container
.renderfix = function () {});
4405 container
.renderfix();
4408 R
._engine
.setViewBox = function (x
, y
, w
, h
, fit
) {
4409 eve("setViewBox", this, this._viewBox
, [x
, y
, w
, h
, fit
]);
4410 var size
= mmax(w
/ this.width
, h
/ this.height
),
4412 aspectRatio
= fit
? "meet" : "xMinYMin",
4419 delete this._vbSize
;
4420 vb
= "0 0 " + this.width
+ S
+ this.height
;
4422 this._vbSize
= size
;
4423 vb
= x
+ S
+ y
+ S
+ w
+ S
+ h
;
4427 preserveAspectRatio
: aspectRatio
4429 while (size
&& top
) {
4430 sw
= "stroke-width" in top
.attrs
? top
.attrs
["stroke-width"] : 1;
4431 top
.attr({"stroke-width": sw
});
4436 this._viewBox
= [x
, y
, w
, h
, !!fit
];
4440 R
.prototype.renderfix = function () {
4441 var cnvs
= this.canvas
,
4443 pos
= cnvs
.getScreenCTM() || cnvs
.createSVGMatrix(),
4448 this._left
= (this._left
+ left
) % 1;
4449 s
.left
= this._left
+ "px";
4452 this._top
= (this._top
+ top
) % 1;
4453 s
.top
= this._top
+ "px";
4458 R
.prototype.clear = function () {
4459 R
.eve("clear", this);
4460 var c
= this.canvas
;
4461 while (c
.firstChild
) {
4462 c
.removeChild(c
.firstChild
);
4464 this.bottom
= this.top
= null;
4465 (this.desc
= $("desc")).appendChild(R
._g
.doc
.createTextNode("Created with Rapha\xebl " + R
.version
));
4466 c
.appendChild(this.desc
);
4467 c
.appendChild(this.defs
= $("defs"));
4470 R
.prototype.remove = function () {
4471 eve("remove", this);
4472 this.canvas
.parentNode
&& this.canvas
.parentNode
.removeChild(this.canvas
);
4473 for (var i
in this) {
4474 this[i
] = typeof this[i
] == "function" ? R
._removedFactory(i
) : null;
4477 var setproto
= R
.st
;
4478 for (var method
in elproto
) if (elproto
[has
](method
) && !setproto
[has
](method
)) {
4479 setproto
[method
] = (function (methodname
) {
4480 return function () {
4481 var arg
= arguments
;
4482 return this.forEach(function (el
) {
4483 el
[methodname
].apply(el
, arg
);
4490 // ┌─────────────────────────────────────────────────────────────────────┐ \\
4491 // │ Raphaël - JavaScript Vector Library │ \\
4492 // ├─────────────────────────────────────────────────────────────────────┤ \\
4493 // │ VML Module │ \\
4494 // ├─────────────────────────────────────────────────────────────────────┤ \\
4495 // │ Copyright (c) 2008-2011 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
4496 // │ Copyright (c) 2008-2011 Sencha Labs (http://sencha.com) │ \\
4497 // │ Licensed under the MIT (http://raphaeljs.com/license.html) license. │ \\
4498 // └─────────────────────────────────────────────────────────────────────┘ \\
4499 window
.Raphael
.vml
&& function (R
) {
4500 var has
= "hasOwnProperty",
4502 toFloat
= parseFloat
,
4508 fillString
= "fill",
4509 separator
= /[, ]+/,
4511 ms
= " progid:DXImageTransform.Microsoft",
4514 map
= {M
: "m", L
: "l", C
: "c", Z
: "x", m
: "t", l
: "r", c
: "v", z
: "x"},
4515 bites
= /([clmz]),?([^clmz]*)/gi,
4516 blurregexp
= / progid
:\S
+Blur
\([^\)]+\)/g
,
4517 val
= /-?[^,\s-]+/g,
4518 cssDot
= "position:absolute;left:0;top:0;width:1px;height:1px",
4520 pathTypes
= {path
: 1, rect
: 1, image
: 1},
4521 ovalTypes
= {circle
: 1, ellipse
: 1},
4522 path2vml = function (path
) {
4523 var total
= /[ahqstv]/ig,
4524 command
= R
._pathToAbsolute
;
4525 Str(path
).match(total
) && (command
= R
._path2curve
);
4527 if (command
== R
._pathToAbsolute
&& !Str(path
).match(total
)) {
4528 var res
= Str(path
).replace(bites
, function (all
, command
, args
) {
4530 isMove
= command
.toLowerCase() == "m",
4532 args
.replace(val
, function (value
) {
4533 if (isMove
&& vals
.length
== 2) {
4534 res
+= vals
+ map
[command
== "m" ? "l" : "L"];
4537 vals
.push(round(value
* zoom
));
4543 var pa
= command(path
), p
, r
;
4545 for (var i
= 0, ii
= pa
.length
; i
< ii
; i
++) {
4547 r
= pa
[i
][0].toLowerCase();
4548 r
== "z" && (r
= "x");
4549 for (var j
= 1, jj
= p
.length
; j
< jj
; j
++) {
4550 r
+= round(p
[j
] * zoom
) + (j
!= jj
- 1 ? "," : E
);
4556 compensation = function (deg
, dx
, dy
) {
4558 m
.rotate(-deg
, .5, .5);
4564 setCoords = function (p
, sx
, sy
, dx
, dy
, deg
) {
4567 fillpos
= _
.fillpos
,
4575 s
.visibility
= "hidden";
4579 o
.coordsize
= abs(kx
) + S
+ abs(ky
);
4580 s
.rotation
= deg
* (sx
* sy
< 0 ? -1 : 1);
4582 var c
= compensation(deg
, dx
, dy
);
4586 sx
< 0 && (flip
+= "x");
4587 sy
< 0 && (flip
+= " y") && (y
= -1);
4589 o
.coordorigin
= (dx
* -kx
) + S
+ (dy
* -ky
);
4590 if (fillpos
|| _
.fillsize
) {
4591 var fill
= o
.getElementsByTagName(fillString
);
4592 fill
= fill
&& fill
[0];
4593 o
.removeChild(fill
);
4595 c
= compensation(deg
, m
.x(fillpos
[0], fillpos
[1]), m
.y(fillpos
[0], fillpos
[1]));
4596 fill
.position
= c
.dx
* y
+ S
+ c
.dy
* y
;
4599 fill
.size
= _
.fillsize
[0] * abs(sx
) + S
+ _
.fillsize
[1] * abs(sy
);
4601 o
.appendChild(fill
);
4603 s
.visibility
= "visible";
4605 R
.toString = function () {
4606 return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version
;
4608 var addArrow = function (o
, value
, isEnd
) {
4609 var values
= Str(value
).toLowerCase().split("-"),
4610 se
= isEnd
? "end" : "start",
4616 switch (values
[i
]) {
4626 case "narrow": h
= values
[i
]; break;
4628 case "short": w
= values
[i
]; break;
4631 var stroke
= o
.node
.getElementsByTagName("stroke")[0];
4632 stroke
[se
+ "arrow"] = type
;
4633 stroke
[se
+ "arrowlength"] = w
;
4634 stroke
[se
+ "arrowwidth"] = h
;
4636 setFillAndStroke = function (o
, params
) {
4637 // o.paper.canvas.style.display = "none";
4638 o
.attrs
= o
.attrs
|| {};
4643 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
),
4644 isOval
= ovalTypes
[o
.type
] && (a
.cx
!= params
.cx
|| a
.cy
!= params
.cy
|| a
.r
!= params
.r
|| a
.rx
!= params
.rx
|| a
.ry
!= params
.ry
),
4648 for (var par
in params
) if (params
[has
](par
)) {
4649 a
[par
] = params
[par
];
4652 a
.path
= R
._getPath
[o
.type
](o
);
4655 params
.href
&& (node
.href
= params
.href
);
4656 params
.title
&& (node
.title
= params
.title
);
4657 params
.target
&& (node
.target
= params
.target
);
4658 params
.cursor
&& (s
.cursor
= params
.cursor
);
4659 "blur" in params
&& o
.blur(params
.blur
);
4660 if (params
.path
&& o
.type
== "path" || newpath
) {
4661 node
.path
= path2vml(~Str(a
.path
).toLowerCase().indexOf("r") ? R
._pathToAbsolute(a
.path
) : a
.path
);
4662 if (o
.type
== "image") {
4663 o
._
.fillpos
= [a
.x
, a
.y
];
4664 o
._
.fillsize
= [a
.width
, a
.height
];
4665 setCoords(o
, 1, 1, 0, 0, 0);
4668 "transform" in params
&& o
.transform(params
.transform
);
4672 rx
= +a
.rx
|| +a
.r
|| 0,
4673 ry
= +a
.ry
|| +a
.r
|| 0;
4674 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
));
4676 if ("clip-rect" in params
) {
4677 var rect
= Str(params
["clip-rect"]).split(separator
);
4678 if (rect
.length
== 4) {
4679 rect
[2] = +rect
[2] + (+rect
[0]);
4680 rect
[3] = +rect
[3] + (+rect
[1]);
4681 var div
= node
.clipRect
|| R
._g
.doc
.createElement("div"),
4683 dstyle
.clip
= R
.format("rect({1}px {2}px {3}px {0}px)", rect
);
4684 if (!node
.clipRect
) {
4685 dstyle
.position
= "absolute";
4688 dstyle
.width
= o
.paper
.width
+ "px";
4689 dstyle
.height
= o
.paper
.height
+ "px";
4690 node
.parentNode
.insertBefore(div
, node
);
4691 div
.appendChild(node
);
4692 node
.clipRect
= div
;
4695 if (!params
["clip-rect"]) {
4696 node
.clipRect
&& (node
.clipRect
.style
.clip
= "auto");
4700 var textpathStyle
= o
.textpath
.style
;
4701 params
.font
&& (textpathStyle
.font
= params
.font
);
4702 params
["font-family"] && (textpathStyle
.fontFamily
= '"' + params
["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E
) + '"');
4703 params
["font-size"] && (textpathStyle
.fontSize
= params
["font-size"]);
4704 params
["font-weight"] && (textpathStyle
.fontWeight
= params
["font-weight"]);
4705 params
["font-style"] && (textpathStyle
.fontStyle
= params
["font-style"]);
4707 if ("arrow-start" in params
) {
4708 addArrow(res
, params
["arrow-start"]);
4710 if ("arrow-end" in params
) {
4711 addArrow(res
, params
["arrow-end"], 1);
4713 if (params
.opacity
!= null ||
4714 params
["stroke-width"] != null ||
4715 params
.fill
!= null ||
4716 params
.src
!= null ||
4717 params
.stroke
!= null ||
4718 params
["stroke-width"] != null ||
4719 params
["stroke-opacity"] != null ||
4720 params
["fill-opacity"] != null ||
4721 params
["stroke-dasharray"] != null ||
4722 params
["stroke-miterlimit"] != null ||
4723 params
["stroke-linejoin"] != null ||
4724 params
["stroke-linecap"] != null) {
4725 var fill
= node
.getElementsByTagName(fillString
),
4727 fill
= fill
&& fill
[0];
4728 !fill
&& (newfill
= fill
= createNode(fillString
));
4729 if (o
.type
== "image" && params
.src
) {
4730 fill
.src
= params
.src
;
4732 params
.fill
&& (fill
.on
= true);
4733 if (fill
.on
== null || params
.fill
== "none" || params
.fill
=== null) {
4736 if (fill
.on
&& params
.fill
) {
4737 var isURL
= Str(params
.fill
).match(R
._ISURL
);
4739 fill
.parentNode
== node
&& node
.removeChild(fill
);
4741 fill
.src
= isURL
[1];
4743 var bbox
= o
.getBBox(1);
4744 fill
.position
= bbox
.x
+ S
+ bbox
.y
;
4745 o
._
.fillpos
= [bbox
.x
, bbox
.y
];
4747 R
._preload(isURL
[1], function () {
4748 o
._
.fillsize
= [this.offsetWidth
, this.offsetHeight
];
4751 fill
.color
= R
.getRGB(params
.fill
).hex
;
4753 fill
.type
= "solid";
4754 if (R
.getRGB(params
.fill
).error
&& (res
.type
in {circle
: 1, ellipse
: 1} || Str(params
.fill
).charAt() != "r") && addGradientFill(res
, params
.fill
, fill
)) {
4756 a
.gradient
= params
.fill
;
4757 fill
.rotate
= false;
4761 if ("fill-opacity" in params
|| "opacity" in params
) {
4762 var opacity
= ((+a
["fill-opacity"] + 1 || 2) - 1) * ((+a
.opacity
+ 1 || 2) - 1) * ((+R
.getRGB(params
.fill
).o
+ 1 || 2) - 1);
4763 opacity
= mmin(mmax(opacity
, 0), 1);
4764 fill
.opacity
= opacity
;
4766 fill
.color
= "none";
4769 node
.appendChild(fill
);
4770 var stroke
= (node
.getElementsByTagName("stroke") && node
.getElementsByTagName("stroke")[0]),
4772 !stroke
&& (newstroke
= stroke
= createNode("stroke"));
4773 if ((params
.stroke
&& params
.stroke
!= "none") ||
4774 params
["stroke-width"] ||
4775 params
["stroke-opacity"] != null ||
4776 params
["stroke-dasharray"] ||
4777 params
["stroke-miterlimit"] ||
4778 params
["stroke-linejoin"] ||
4779 params
["stroke-linecap"]) {
4782 (params
.stroke
== "none" || params
.stroke
=== null || stroke
.on
== null || params
.stroke
== 0 || params
["stroke-width"] == 0) && (stroke
.on
= false);
4783 var strokeColor
= R
.getRGB(params
.stroke
);
4784 stroke
.on
&& params
.stroke
&& (stroke
.color
= strokeColor
.hex
);
4785 opacity
= ((+a
["stroke-opacity"] + 1 || 2) - 1) * ((+a
.opacity
+ 1 || 2) - 1) * ((+strokeColor
.o
+ 1 || 2) - 1);
4786 var width
= (toFloat(params
["stroke-width"]) || 1) * .75;
4787 opacity
= mmin(mmax(opacity
, 0), 1);
4788 params
["stroke-width"] == null && (width
= a
["stroke-width"]);
4789 params
["stroke-width"] && (stroke
.weight
= width
);
4790 width
&& width
< 1 && (opacity
*= width
) && (stroke
.weight
= 1);
4791 stroke
.opacity
= opacity
;
4793 params
["stroke-linejoin"] && (stroke
.joinstyle
= params
["stroke-linejoin"] || "miter");
4794 stroke
.miterlimit
= params
["stroke-miterlimit"] || 8;
4795 params
["stroke-linecap"] && (stroke
.endcap
= params
["stroke-linecap"] == "butt" ? "flat" : params
["stroke-linecap"] == "square" ? "square" : "round");
4796 if (params
["stroke-dasharray"]) {
4800 "-.": "shortdashdot",
4801 "-..": "shortdashdotdot",
4806 "--.": "longdashdot",
4807 "--..": "longdashdotdot"
4809 stroke
.dashstyle
= dasharray
[has
](params
["stroke-dasharray"]) ? dasharray
[params
["stroke-dasharray"]] : E
;
4811 newstroke
&& node
.appendChild(stroke
);
4813 if (res
.type
== "text") {
4814 res
.paper
.canvas
.style
.display
= E
;
4815 var span
= res
.paper
.span
,
4817 fontSize
= a
.font
&& a
.font
.match(/\d+(?:\.\d*)?(?=px)/);
4819 a
.font
&& (s
.font
= a
.font
);
4820 a
["font-family"] && (s
.fontFamily
= a
["font-family"]);
4821 a
["font-weight"] && (s
.fontWeight
= a
["font-weight"]);
4822 a
["font-style"] && (s
.fontStyle
= a
["font-style"]);
4823 fontSize
= toFloat(a
["font-size"] || fontSize
&& fontSize
[0]) || 10;
4824 s
.fontSize
= fontSize
* m
+ "px";
4825 res
.textpath
.string
&& (span
.innerHTML
= Str(res
.textpath
.string
).replace(/</g, "<").replace(/&/g, "&").replace(/\n/g
, "<br>"));
4826 var brect
= span
.getBoundingClientRect();
4827 res
.W
= a
.w
= (brect
.right
- brect
.left
) / m
;
4828 res
.H
= a
.h
= (brect
.bottom
- brect
.top
) / m
;
4829 // res.paper.canvas.style.display = "none";
4831 res
.Y
= a
.y
+ res
.H
/ 2;
4833 ("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));
4834 var dirtyattrs
= ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"];
4835 for (var d
= 0, dd
= dirtyattrs
.length
; d
< dd
; d
++) if (dirtyattrs
[d
] in params
) {
4840 // text-anchor emulation
4841 switch (a
["text-anchor"]) {
4843 res
.textpath
.style
["v-text-align"] = "left";
4844 res
.bbx
= res
.W
/ 2;
4847 res
.textpath
.style
["v-text-align"] = "right";
4848 res
.bbx
= -res
.W
/ 2;
4851 res
.textpath
.style
["v-text-align"] = "center";
4855 res
.textpath
.style
["v-text-kern"] = true;
4857 // res.paper.canvas.style.display = E;
4859 addGradientFill = function (o
, gradient
, fill
) {
4860 o
.attrs
= o
.attrs
|| {};
4861 var attrs
= o
.attrs
,
4867 o
.attrs
.gradient
= gradient
;
4868 gradient
= Str(gradient
).replace(R
._radial_gradient
, function (all
, fx
, fy
) {
4873 pow(fx
- .5, 2) + pow(fy
- .5, 2) > .25 && (fy
= math
.sqrt(.25 - pow(fx
- .5, 2)) * ((fy
> .5) * 2 - 1) + .5);
4878 gradient
= gradient
.split(/\s*\-\s*/);
4879 if (type
== "linear") {
4880 var angle
= gradient
.shift();
4881 angle
= -toFloat(angle
);
4886 var dots
= R
._parseDots(gradient
);
4890 o
= o
.shape
|| o
.node
;
4892 o
.removeChild(fill
);
4894 fill
.method
= "none";
4895 fill
.color
= dots
[0].color
;
4896 fill
.color2
= dots
[dots
.length
- 1].color
;
4898 for (var i
= 0, ii
= dots
.length
; i
< ii
; i
++) {
4899 dots
[i
].offset
&& clrs
.push(dots
[i
].offset
+ S
+ dots
[i
].color
);
4901 fill
.colors
= clrs
.length
? clrs
.join() : "0% " + fill
.color
;
4902 if (type
== "radial") {
4903 fill
.type
= "gradientTitle";
4904 fill
.focus
= "100%";
4905 fill
.focussize
= "0 0";
4906 fill
.focusposition
= fxfy
;
4909 // fill.rotate= true;
4910 fill
.type
= "gradient";
4911 fill
.angle
= (270 - angle
) % 360;
4913 o
.appendChild(fill
);
4917 Element = function (node
, vml
) {
4918 this[0] = this.node
= node
;
4919 node
.raphael
= true;
4921 node
.raphaelid
= this.id
;
4926 this.matrix
= R
.matrix();
4937 !vml
.bottom
&& (vml
.bottom
= this);
4938 this.prev
= vml
.top
;
4939 vml
.top
&& (vml
.top
.next
= this);
4945 Element
.prototype = elproto
;
4946 elproto
.constructor = Element
;
4947 elproto
.transform = function (tstr
) {
4949 return this._
.transform
;
4951 var vbs
= this.paper
._viewBoxShift
,
4952 vbt
= vbs
? "s" + [vbs
.scale
, vbs
.scale
] + "-1-1t" + [vbs
.dx
, vbs
.dy
] : E
,
4955 oldt
= tstr
= Str(tstr
).replace(/\.{3}|\u2026/g, this._
.transform
|| E
);
4957 R
._extractTransform(this, vbt
+ tstr
);
4958 var matrix
= this.matrix
.clone(),
4962 isGrad
= ~Str(this.attrs
.fill
).indexOf("-"),
4963 isPatt
= !Str(this.attrs
.fill
).indexOf("url(");
4964 matrix
.translate(-.5, -.5);
4965 if (isPatt
|| isGrad
|| this.type
== "image") {
4966 skew
.matrix
= "1 0 0 1";
4967 skew
.offset
= "0 0";
4968 split
= matrix
.split();
4969 if ((isGrad
&& split
.noRotation
) || !split
.isSimple
) {
4970 o
.style
.filter
= matrix
.toFilter();
4971 var bb
= this.getBBox(),
4972 bbt
= this.getBBox(1),
4975 o
.coordorigin
= (dx
* -zoom
) + S
+ (dy
* -zoom
);
4976 setCoords(this, 1, 1, dx
, dy
, 0);
4979 setCoords(this, split
.scalex
, split
.scaley
, split
.dx
, split
.dy
, split
.rotate
);
4983 skew
.matrix
= Str(matrix
);
4984 skew
.offset
= matrix
.offset();
4986 oldt
&& (this._
.transform
= oldt
);
4989 elproto
.rotate = function (deg
, cx
, cy
) {
4996 deg
= Str(deg
).split(separator
);
4997 if (deg
.length
- 1) {
4998 cx
= toFloat(deg
[1]);
4999 cy
= toFloat(deg
[2]);
5001 deg
= toFloat(deg
[0]);
5002 (cy
== null) && (cx
= cy
);
5003 if (cx
== null || cy
== null) {
5004 var bbox
= this.getBBox(1);
5005 cx
= bbox
.x
+ bbox
.width
/ 2;
5006 cy
= bbox
.y
+ bbox
.height
/ 2;
5009 this.transform(this._
.transform
.concat([["r", deg
, cx
, cy
]]));
5012 elproto
.translate = function (dx
, dy
) {
5016 dx
= Str(dx
).split(separator
);
5017 if (dx
.length
- 1) {
5018 dy
= toFloat(dx
[1]);
5020 dx
= toFloat(dx
[0]) || 0;
5023 this._
.bbox
.x
+= dx
;
5024 this._
.bbox
.y
+= dy
;
5026 this.transform(this._
.transform
.concat([["t", dx
, dy
]]));
5029 elproto
.scale = function (sx
, sy
, cx
, cy
) {
5033 sx
= Str(sx
).split(separator
);
5034 if (sx
.length
- 1) {
5035 sy
= toFloat(sx
[1]);
5036 cx
= toFloat(sx
[2]);
5037 cy
= toFloat(sx
[3]);
5038 isNaN(cx
) && (cx
= null);
5039 isNaN(cy
) && (cy
= null);
5041 sx
= toFloat(sx
[0]);
5042 (sy
== null) && (sy
= sx
);
5043 (cy
== null) && (cx
= cy
);
5044 if (cx
== null || cy
== null) {
5045 var bbox
= this.getBBox(1);
5047 cx
= cx
== null ? bbox
.x
+ bbox
.width
/ 2 : cx
;
5048 cy
= cy
== null ? bbox
.y
+ bbox
.height
/ 2 : cy
;
5050 this.transform(this._
.transform
.concat([["s", sx
, sy
, cx
, cy
]]));
5054 elproto
.hide = function () {
5055 !this.removed
&& (this.node
.style
.display
= "none");
5058 elproto
.show = function () {
5059 !this.removed
&& (this.node
.style
.display
= E
);
5062 elproto
._getBBox = function () {
5067 x
: this.X
+ (this.bbx
|| 0) - this.W
/ 2,
5073 elproto
.remove = function () {
5077 this.paper
.__set__
&& this.paper
.__set__
.exclude(this);
5078 R
.eve
.unbind("*.*." + this.id
);
5079 R
._tear(this, this.paper
);
5080 this.node
.parentNode
.removeChild(this.node
);
5081 this.shape
&& this.shape
.parentNode
.removeChild(this.shape
);
5082 for (var i
in this) {
5083 this[i
] = typeof this[i
] == "function" ? R
._removedFactory(i
) : null;
5085 this.removed
= true;
5087 elproto
.attr = function (name
, value
) {
5093 for (var a
in this.attrs
) if (this.attrs
[has
](a
)) {
5094 res
[a
] = this.attrs
[a
];
5096 res
.gradient
&& res
.fill
== "none" && (res
.fill
= res
.gradient
) && delete res
.gradient
;
5097 res
.transform
= this._
.transform
;
5100 if (value
== null && R
.is(name
, "string")) {
5101 if (name
== fillString
&& this.attrs
.fill
== "none" && this.attrs
.gradient
) {
5102 return this.attrs
.gradient
;
5104 var names
= name
.split(separator
),
5106 for (var i
= 0, ii
= names
.length
; i
< ii
; i
++) {
5108 if (name
in this.attrs
) {
5109 out
[name
] = this.attrs
[name
];
5110 } else if (R
.is(this.paper
.customAttributes
[name
], "function")) {
5111 out
[name
] = this.paper
.customAttributes
[name
].def
;
5113 out
[name
] = R
._availableAttrs
[name
];
5116 return ii
- 1 ? out
: out
[names
[0]];
5118 if (this.attrs
&& value
== null && R
.is(name
, "array")) {
5120 for (i
= 0, ii
= name
.length
; i
< ii
; i
++) {
5121 out
[name
[i
]] = this.attr(name
[i
]);
5126 if (value
!= null) {
5128 params
[name
] = value
;
5130 value
== null && R
.is(name
, "object") && (params
= name
);
5131 for (var key
in params
) {
5132 eve("attr." + key
+ "." + this.id
, this, params
[key
]);
5135 for (key
in this.paper
.customAttributes
) if (this.paper
.customAttributes
[has
](key
) && params
[has
](key
) && R
.is(this.paper
.customAttributes
[key
], "function")) {
5136 var par
= this.paper
.customAttributes
[key
].apply(this, [].concat(params
[key
]));
5137 this.attrs
[key
] = params
[key
];
5138 for (var subkey
in par
) if (par
[has
](subkey
)) {
5139 params
[subkey
] = par
[subkey
];
5142 // this.paper.canvas.style.display = "none";
5143 if (params
.text
&& this.type
== "text") {
5144 this.textpath
.string
= params
.text
;
5146 setFillAndStroke(this, params
);
5147 // this.paper.canvas.style.display = E;
5151 elproto
.toFront = function () {
5152 !this.removed
&& this.node
.parentNode
.appendChild(this.node
);
5153 this.paper
&& this.paper
.top
!= this && R
._tofront(this, this.paper
);
5156 elproto
.toBack = function () {
5160 if (this.node
.parentNode
.firstChild
!= this.node
) {
5161 this.node
.parentNode
.insertBefore(this.node
, this.node
.parentNode
.firstChild
);
5162 R
._toback(this, this.paper
);
5166 elproto
.insertAfter = function (element
) {
5170 if (element
.constructor == R
.st
.constructor) {
5171 element
= element
[element
.length
- 1];
5173 if (element
.node
.nextSibling
) {
5174 element
.node
.parentNode
.insertBefore(this.node
, element
.node
.nextSibling
);
5176 element
.node
.parentNode
.appendChild(this.node
);
5178 R
._insertafter(this, element
, this.paper
);
5181 elproto
.insertBefore = function (element
) {
5185 if (element
.constructor == R
.st
.constructor) {
5186 element
= element
[0];
5188 element
.node
.parentNode
.insertBefore(this.node
, element
.node
);
5189 R
._insertbefore(this, element
, this.paper
);
5192 elproto
.blur = function (size
) {
5193 var s
= this.node
.runtimeStyle
,
5195 f
= f
.replace(blurregexp
, E
);
5197 this.attrs
.blur
= size
;
5198 s
.filter
= f
+ S
+ ms
+ ".Blur(pixelradius=" + (+size
|| 1.5) + ")";
5199 s
.margin
= R
.format("-{0}px 0 0 -{0}px", round(+size
|| 1.5));
5203 delete this.attrs
.blur
;
5207 R
._engine
.path = function (pathString
, vml
) {
5208 var el
= createNode("shape");
5209 el
.style
.cssText
= cssDot
;
5210 el
.coordsize
= zoom
+ S
+ zoom
;
5211 el
.coordorigin
= vml
.coordorigin
;
5212 var p
= new Element(el
, vml
),
5213 attr
= {fill
: "none", stroke
: "#000"};
5214 pathString
&& (attr
.path
= pathString
);
5218 setFillAndStroke(p
, attr
);
5219 vml
.canvas
.appendChild(el
);
5220 var skew
= createNode("skew");
5222 el
.appendChild(skew
);
5227 R
._engine
.rect = function (vml
, x
, y
, w
, h
, r
) {
5228 var path
= R
._rectPath(x
, y
, w
, h
, r
),
5229 res
= vml
.path(path
),
5233 res
.W
= a
.width
= w
;
5234 res
.H
= a
.height
= h
;
5240 R
._engine
.ellipse = function (vml
, x
, y
, rx
, ry
) {
5241 var res
= vml
.path(),
5247 res
.type
= "ellipse";
5248 setFillAndStroke(res
, {
5256 R
._engine
.circle = function (vml
, x
, y
, r
) {
5257 var res
= vml
.path(),
5261 res
.W
= res
.H
= r
* 2;
5262 res
.type
= "circle";
5263 setFillAndStroke(res
, {
5270 R
._engine
.image = function (vml
, src
, x
, y
, w
, h
) {
5271 var path
= R
._rectPath(x
, y
, w
, h
),
5272 res
= vml
.path(path
).attr({stroke
: "none"}),
5275 fill
= node
.getElementsByTagName(fillString
)[0];
5279 res
.W
= a
.width
= w
;
5280 res
.H
= a
.height
= h
;
5283 fill
.parentNode
== node
&& node
.removeChild(fill
);
5287 res
._
.fillpos
= [x
, y
];
5288 res
._
.fillsize
= [w
, h
];
5289 node
.appendChild(fill
);
5290 setCoords(res
, 1, 1, 0, 0, 0);
5293 R
._engine
.text = function (vml
, x
, y
, text
) {
5294 var el
= createNode("shape"),
5295 path
= createNode("path"),
5296 o
= createNode("textpath");
5300 path
.v
= R
.format("m{0},{1}l{2},{1}", round(x
* zoom
), round(y
* zoom
), round(x
* zoom
) + 1);
5301 path
.textpathok
= true;
5302 o
.string
= Str(text
);
5304 el
.style
.cssText
= cssDot
;
5305 el
.coordsize
= zoom
+ S
+ zoom
;
5306 el
.coordorigin
= "0 0";
5307 var p
= new Element(el
, vml
),
5311 font
: R
._availableAttrs
.font
,
5318 p
.attrs
.text
= Str(text
);
5323 setFillAndStroke(p
, attr
);
5325 el
.appendChild(path
);
5326 vml
.canvas
.appendChild(el
);
5327 var skew
= createNode("skew");
5329 el
.appendChild(skew
);
5334 R
._engine
.setSize = function (width
, height
) {
5335 var cs
= this.canvas
.style
;
5337 this.height
= height
;
5338 width
== +width
&& (width
+= "px");
5339 height
== +height
&& (height
+= "px");
5342 cs
.clip
= "rect(0 " + width
+ " " + height
+ " 0)";
5343 if (this._viewBox
) {
5344 R
._engine
.setViewBox
.apply(this, this._viewBox
);
5348 R
._engine
.setViewBox = function (x
, y
, w
, h
, fit
) {
5349 R
.eve("setViewBox", this, this._viewBox
, [x
, y
, w
, h
, fit
]);
5350 var width
= this.width
,
5351 height
= this.height
,
5352 size
= 1 / mmax(w
/ width
, h
/ height
),
5357 if (w
* H
< width
) {
5358 x
-= (width
- w
* H
) / 2 / H
;
5360 if (h
* W
< height
) {
5361 y
-= (height
- h
* W
) / 2 / W
;
5364 this._viewBox
= [x
, y
, w
, h
, !!fit
];
5365 this._viewBoxShift
= {
5370 this.forEach(function (el
) {
5371 el
.transform("...");
5376 R
._engine
.initWin = function (win
) {
5377 var doc
= win
.document
;
5378 doc
.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
5380 !doc
.namespaces
.rvml
&& doc
.namespaces
.add("rvml", "urn:schemas-microsoft-com:vml");
5381 createNode = function (tagName
) {
5382 return doc
.createElement('<rvml:' + tagName
+ ' class="rvml">');
5385 createNode = function (tagName
) {
5386 return doc
.createElement('<' + tagName
+ ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
5390 R
._engine
.initWin(R
._g
.win
);
5391 R
._engine
.create = function () {
5392 var con
= R
._getContainer
.apply(0, arguments
),
5393 container
= con
.container
,
5394 height
= con
.height
,
5400 throw new Error("VML container not found.");
5402 var res
= new R
._Paper
,
5403 c
= res
.canvas
= R
._g
.doc
.createElement("div"),
5407 width
= width
|| 512;
5408 height
= height
|| 342;
5410 res
.height
= height
;
5411 width
== +width
&& (width
+= "px");
5412 height
== +height
&& (height
+= "px");
5413 res
.coordsize
= zoom
* 1e3
+ S
+ zoom
* 1e3
;
5414 res
.coordorigin
= "0 0";
5415 res
.span
= R
._g
.doc
.createElement("span");
5416 res
.span
.style
.cssText
= "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;";
5417 c
.appendChild(res
.span
);
5418 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
);
5419 if (container
== 1) {
5420 R
._g
.doc
.body
.appendChild(c
);
5423 cs
.position
= "absolute";
5425 if (container
.firstChild
) {
5426 container
.insertBefore(c
, container
.firstChild
);
5428 container
.appendChild(c
);
5431 // plugins.call(res, res, R.fn);
5432 res
.renderfix = function () {};
5435 R
.prototype.clear = function () {
5436 R
.eve("clear", this);
5437 this.canvas
.innerHTML
= E
;
5438 this.span
= R
._g
.doc
.createElement("span");
5439 this.span
.style
.cssText
= "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
5440 this.canvas
.appendChild(this.span
);
5441 this.bottom
= this.top
= null;
5443 R
.prototype.remove = function () {
5444 R
.eve("remove", this);
5445 this.canvas
.parentNode
.removeChild(this.canvas
);
5446 for (var i
in this) {
5447 this[i
] = typeof this[i
] == "function" ? R
._removedFactory(i
) : null;
5452 var setproto
= R
.st
;
5453 for (var method
in elproto
) if (elproto
[has
](method
) && !setproto
[has
](method
)) {
5454 setproto
[method
] = (function (methodname
) {
5455 return function () {
5456 var arg
= arguments
;
5457 return this.forEach(function (el
) {
5458 el
[methodname
].apply(el
, arg
);