Mercurial > laserkard
view js-lib/raphael.js @ 83:e0dadfad3dc4 laserkard
going to try a pure raphael solution
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sun, 25 Jul 2010 21:46:00 -0400 |
parents | |
children |
line wrap: on
line source
1 /*!2 * Raphael 1.4.7 - JavaScript Vector Library3 *4 * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com)5 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.6 */8 Raphael = (function () {9 function R() {10 if (R.is(arguments[0], array)) {11 var a = arguments[0],12 cnv = create[apply](R, a.splice(0, 3 + R.is(a[0], nu))),13 res = cnv.set();14 for (var i = 0, ii = a[length]; i < ii; i++) {15 var j = a[i] || {};16 elements.test(j.type) && res[push](cnv[j.type]().attr(j));17 }18 return res;19 }20 return create[apply](R, arguments);21 }22 R.version = "1.4.7";23 var separator = /[, ]+/,24 elements = /^(circle|rect|path|ellipse|text|image)$/,25 proto = "prototype",26 has = "hasOwnProperty",27 doc = document,28 win = window,29 oldRaphael = {30 was: Object[proto][has].call(win, "Raphael"),31 is: win.Raphael32 },33 Paper = function () {},34 appendChild = "appendChild",35 apply = "apply",36 concat = "concat",37 supportsTouch = "createTouch" in doc,38 E = "",39 S = " ",40 Str = String,41 split = "split",42 events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend orientationchange touchcancel gesturestart gesturechange gestureend"[split](S),43 touchMap = {44 mousedown: "touchstart",45 mousemove: "touchmove",46 mouseup: "touchend"47 },48 join = "join",49 length = "length",50 lowerCase = String[proto].toLowerCase,51 math = Math,52 mmax = math.max,53 mmin = math.min,54 nu = "number",55 string = "string",56 array = "array",57 toString = "toString",58 fillString = "fill",59 objectToString = Object[proto][toString],60 paper = {},61 pow = math.pow,62 push = "push",63 rg = /^(?=[\da-f]$)/,64 ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i,65 colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+(?:\s*,\s*[\d\.]+)?)\s*\)|rgba?\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%(?:\s*,\s*[\d\.]+%)?)\s*\)|hsb\(\s*([\d\.]+(?:deg|\xb0)?\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|hsb\(\s*([\d\.]+(?:deg|\xb0|%)\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\)|hsl\(\s*([\d\.]+(?:deg|\xb0)?\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|hsl\(\s*([\d\.]+(?:deg|\xb0|%)\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\))\s*$/i,66 round = math.round,67 setAttribute = "setAttribute",68 toFloat = parseFloat,69 toInt = parseInt,70 ms = " progid:DXImageTransform.Microsoft",71 upperCase = String[proto].toUpperCase,72 availableAttrs = {blur: 0, "clip-rect": "0 0 1e9 1e9", cursor: "default", cx: 0, cy: 0, fill: "#fff", "fill-opacity": 1, font: '10px "Arial"', "font-family": '"Arial"', "font-size": "10", "font-style": "normal", "font-weight": 400, gradient: 0, height: 0, href: "http://raphaeljs.com/", opacity: 1, path: "M0,0", r: 0, rotation: 0, rx: 0, ry: 0, scale: "1 1", src: "", stroke: "#000", "stroke-dasharray": "", "stroke-linecap": "butt", "stroke-linejoin": "butt", "stroke-miterlimit": 0, "stroke-opacity": 1, "stroke-width": 1, target: "_blank", "text-anchor": "middle", title: "Raphael", translation: "0 0", width: 0, x: 0, y: 0},73 availableAnimAttrs = {along: "along", blur: nu, "clip-rect": "csv", cx: nu, cy: nu, fill: "colour", "fill-opacity": nu, "font-size": nu, height: nu, opacity: nu, path: "path", r: nu, rotation: "csv", rx: nu, ry: nu, scale: "csv", stroke: "colour", "stroke-opacity": nu, "stroke-width": nu, translation: "csv", width: nu, x: nu, y: nu},74 rp = "replace";75 R.type = (win.SVGAngle || doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML");76 if (R.type == "VML") {77 var d = doc.createElement("div"),78 b;79 d.innerHTML = '<v:shape adj="1"/>';80 b = d.firstChild;81 b.style.behavior = "url(#default#VML)";82 if (!(b && typeof b.adj == "object")) {83 return R.type = null;84 }85 d = null;86 }87 R.svg = !(R.vml = R.type == "VML");88 Paper[proto] = R[proto];89 R._id = 0;90 R._oid = 0;91 R.fn = {};92 R.is = function (o, type) {93 type = lowerCase.call(type);94 return (type == "object" && o === Object(o)) ||95 (type == "undefined" && typeof o == type) ||96 (type == "null" && o == null) ||97 (type == "array" && Array.isArray && Array.isArray(o)) ||98 lowerCase.call(objectToString.call(o).slice(8, -1)) == type;99 };101 R.setWindow = function (newwin) {102 win = newwin;103 doc = win.document;104 };105 // colour utilities106 var toHex = function (color) {107 if (R.vml) {108 // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/109 var trim = /^\s+|\s+$/g;110 toHex = cacher(function (color) {111 var bod;112 color = Str(color)[rp](trim, E);113 try {114 var docum = new win.ActiveXObject("htmlfile");115 docum.write("<body>");116 docum.close();117 bod = docum.body;118 } catch(e) {119 bod = win.createPopup().document.body;120 }121 var range = bod.createTextRange();122 try {123 bod.style.color = color;124 var value = range.queryCommandValue("ForeColor");125 value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);126 return "#" + ("000000" + value[toString](16)).slice(-6);127 } catch(e) {128 return "none";129 }130 });131 } else {132 var i = doc.createElement("i");133 i.title = "Rapha\xebl Colour Picker";134 i.style.display = "none";135 doc.body[appendChild](i);136 toHex = cacher(function (color) {137 i.style.color = color;138 return doc.defaultView.getComputedStyle(i, E).getPropertyValue("color");139 });140 }141 return toHex(color);142 },143 hsbtoString = function () {144 return "hsb(" + [this.h, this.s, this.b] + ")";145 },146 hsltoString = function () {147 return "hsl(" + [this.h, this.s, this.l] + ")";148 },149 rgbtoString = function () {150 return this.hex;151 };152 R.hsb2rgb = function (h, s, b) {153 if (R.is(h, "object") && "h" in h && "s" in h && "b" in h) {154 b = h.b;155 s = h.s;156 h = h.h;157 }158 return R.hsl2rgb(h, s, b / 2);159 };160 R.hsl2rgb = function (h, s, l) {161 if (R.is(h, "object") && "h" in h && "s" in h && "l" in h) {162 l = h.l;163 s = h.s;164 h = h.h;165 }166 if (h > 1 || s > 1 || l > 1) {167 h /= 255;168 s /= 255;169 l /= 255;170 }171 var rgb = {},172 channels = ["r", "g", "b"],173 t2, t1, t3, r, g, b;174 if (!s) {175 rgb = {176 r: l,177 g: l,178 b: l179 };180 } else {181 if (l < .5) {182 t2 = l * (1 + s);183 } else {184 t2 = l + s - l * s;185 }186 t1 = 2 * l - t2;187 for (var i = 0, ii = channels.length; i < ii; i++) {188 t3 = h + 1 / 3 * -(i - 1);189 t3 < 0 && t3++;190 t3 > 1 && t3--;191 if (t3 * 6 < 1) {192 rgb[channels[i]] = t1 + (t2 - t1) * 6 * t3;193 } else if (t3 * 2 < 1) {194 rgb[channels[i]] = t2;195 } else if (t3 * 3 < 2) {196 rgb[channels[i]] = t1 + (t2 - t1) * (2 / 3 - t3) * 6;197 } else {198 rgb[channels[i]] = t1;199 }200 }201 }202 rgb.r *= 255;203 rgb.g *= 255;204 rgb.b *= 255;205 r = (~~rgb.r)[toString](16);206 g = (~~rgb.g)[toString](16);207 b = (~~rgb.b)[toString](16);208 r = r[rp](rg, "0");209 g = g[rp](rg, "0");210 b = b[rp](rg, "0");211 rgb.hex = "#" + r + g + b;212 rgb.toString = rgbtoString;213 return rgb;214 };215 R.rgb2hsb = function (red, green, blue) {216 if (green == null && R.is(red, "object") && "r" in red && "g" in red && "b" in red) {217 blue = red.b;218 green = red.g;219 red = red.r;220 }221 if (green == null && R.is(red, string)) {222 var clr = R.getRGB(red);223 red = clr.r;224 green = clr.g;225 blue = clr.b;226 }227 if (red > 1 || green > 1 || blue > 1) {228 red /= 255;229 green /= 255;230 blue /= 255;231 }232 var max = mmax(red, green, blue),233 min = mmin(red, green, blue),234 hue,235 saturation,236 brightness = max;237 if (min == max) {238 return {h: 0, s: 0, b: max, toString: hsbtoString};239 } else {240 var delta = (max - min);241 saturation = delta / max;242 if (red == max) {243 hue = (green - blue) / delta;244 } else if (green == max) {245 hue = 2 + ((blue - red) / delta);246 } else {247 hue = 4 + ((red - green) / delta);248 }249 hue /= 6;250 hue < 0 && hue++;251 hue > 1 && hue--;252 }253 return {h: hue, s: saturation, b: brightness, toString: hsbtoString};254 };255 R.rgb2hsl = function (red, green, blue) {256 if (green == null && R.is(red, "object") && "r" in red && "g" in red && "b" in red) {257 blue = red.b;258 green = red.g;259 red = red.r;260 }261 if (green == null && R.is(red, string)) {262 var clr = R.getRGB(red);263 red = clr.r;264 green = clr.g;265 blue = clr.b;266 }267 if (red > 1 || green > 1 || blue > 1) {268 red /= 255;269 green /= 255;270 blue /= 255;271 }272 var max = mmax(red, green, blue),273 min = mmin(red, green, blue),274 h,275 s,276 l = (max + min) / 2,277 hsl;278 if (min == max) {279 hsl = {h: 0, s: 0, l: l};280 } else {281 var delta = max - min;282 s = l < .5 ? delta / (max + min) : delta / (2 - max - min);283 if (red == max) {284 h = (green - blue) / delta;285 } else if (green == max) {286 h = 2 + (blue - red) / delta;287 } else {288 h = 4 + (red - green) / delta;289 }290 h /= 6;291 h < 0 && h++;292 h > 1 && h--;293 hsl = {h: h, s: s, l: l};294 }295 hsl.toString = hsltoString;296 return hsl;297 };298 var p2s = /,?([achlmqrstvxz]),?/gi,299 commaSpaces = /\s*,\s*/,300 hsrg = {hs: 1, rg: 1};301 R._path2string = function () {302 return this.join(",")[rp](p2s, "$1");303 };304 function cacher(f, scope, postprocessor) {305 function newf() {306 var arg = Array[proto].slice.call(arguments, 0),307 args = arg[join]("\u25ba"),308 cache = newf.cache = newf.cache || {},309 count = newf.count = newf.count || [];310 if (cache[has](args)) {311 return postprocessor ? postprocessor(cache[args]) : cache[args];312 }313 count[length] >= 1e3 && delete cache[count.shift()];314 count[push](args);315 cache[args] = f[apply](scope, arg);316 return postprocessor ? postprocessor(cache[args]) : cache[args];317 }318 return newf;319 }321 R.getRGB = cacher(function (colour) {322 if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) {323 return {r: -1, g: -1, b: -1, hex: "none", error: 1};324 }325 if (colour == "none") {326 return {r: -1, g: -1, b: -1, hex: "none"};327 }328 !(hsrg[has](colour.substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour));329 var res,330 red,331 green,332 blue,333 opacity,334 t,335 rgb = colour.match(colourRegExp);336 if (rgb) {337 if (rgb[2]) {338 blue = toInt(rgb[2].substring(5), 16);339 green = toInt(rgb[2].substring(3, 5), 16);340 red = toInt(rgb[2].substring(1, 3), 16);341 }342 if (rgb[3]) {343 blue = toInt((t = rgb[3].charAt(3)) + t, 16);344 green = toInt((t = rgb[3].charAt(2)) + t, 16);345 red = toInt((t = rgb[3].charAt(1)) + t, 16);346 }347 if (rgb[4]) {348 rgb = rgb[4][split](commaSpaces);349 red = toFloat(rgb[0]);350 green = toFloat(rgb[1]);351 blue = toFloat(rgb[2]);352 opacity = toFloat(rgb[3]);353 }354 if (rgb[5]) {355 rgb = rgb[5][split](commaSpaces);356 red = toFloat(rgb[0]) * 2.55;357 green = toFloat(rgb[1]) * 2.55;358 blue = toFloat(rgb[2]) * 2.55;359 opacity = toFloat(rgb[3]);360 }361 if (rgb[6]) {362 rgb = rgb[6][split](commaSpaces);363 red = toFloat(rgb[0]);364 green = toFloat(rgb[1]);365 blue = toFloat(rgb[2]);366 (rgb[0].slice(-3) == "deg" || rgb[0].slice(-1) == "\xb0") && (red /= 360);367 return R.hsb2rgb(red, green, blue);368 }369 if (rgb[7]) {370 rgb = rgb[7][split](commaSpaces);371 red = toFloat(rgb[0]) * 2.55;372 green = toFloat(rgb[1]) * 2.55;373 blue = toFloat(rgb[2]) * 2.55;374 (rgb[0].slice(-3) == "deg" || rgb[0].slice(-1) == "\xb0") && (red /= 360 * 2.55);375 return R.hsb2rgb(red, green, blue);376 }377 if (rgb[8]) {378 rgb = rgb[8][split](commaSpaces);379 red = toFloat(rgb[0]);380 green = toFloat(rgb[1]);381 blue = toFloat(rgb[2]);382 (rgb[0].slice(-3) == "deg" || rgb[0].slice(-1) == "\xb0") && (red /= 360);383 return R.hsl2rgb(red, green, blue);384 }385 if (rgb[9]) {386 rgb = rgb[9][split](commaSpaces);387 red = toFloat(rgb[0]) * 2.55;388 green = toFloat(rgb[1]) * 2.55;389 blue = toFloat(rgb[2]) * 2.55;390 (rgb[0].slice(-3) == "deg" || rgb[0].slice(-1) == "\xb0") && (red /= 360 * 2.55);391 return R.hsl2rgb(red, green, blue);392 }393 rgb = {r: red, g: green, b: blue};394 var r = (~~red)[toString](16),395 g = (~~green)[toString](16),396 b = (~~blue)[toString](16);397 r = r[rp](rg, "0");398 g = g[rp](rg, "0");399 b = b[rp](rg, "0");400 rgb.hex = "#" + r + g + b;401 isFinite(toFloat(opacity)) && (rgb.o = opacity);402 return rgb;403 }404 return {r: -1, g: -1, b: -1, hex: "none", error: 1};405 }, R);406 R.getColor = function (value) {407 var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},408 rgb = this.hsb2rgb(start.h, start.s, start.b);409 start.h += .075;410 if (start.h > 1) {411 start.h = 0;412 start.s -= .2;413 start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});414 }415 return rgb.hex;416 };417 R.getColor.reset = function () {418 delete this.start;419 };420 // path utilities421 var pathCommand = /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,422 pathValues = /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig;423 R.parsePathString = cacher(function (pathString) {424 if (!pathString) {425 return null;426 }427 var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0},428 data = [];429 if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption430 data = pathClone(pathString);431 }432 if (!data[length]) {433 Str(pathString)[rp](pathCommand, function (a, b, c) {434 var params = [],435 name = lowerCase.call(b);436 c[rp](pathValues, function (a, b) {437 b && params[push](+b);438 });439 if (name == "m" && params[length] > 2) {440 data[push]([b][concat](params.splice(0, 2)));441 name = "l";442 b = b == "m" ? "l" : "L";443 }444 while (params[length] >= paramCounts[name]) {445 data[push]([b][concat](params.splice(0, paramCounts[name])));446 if (!paramCounts[name]) {447 break;448 }449 }450 });451 }452 data[toString] = R._path2string;453 return data;454 });455 R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {456 var t1 = 1 - t,457 x = pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,458 y = pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y,459 mx = p1x + 2 * t * (c1x - p1x) + t * t * (c2x - 2 * c1x + p1x),460 my = p1y + 2 * t * (c1y - p1y) + t * t * (c2y - 2 * c1y + p1y),461 nx = c1x + 2 * t * (c2x - c1x) + t * t * (p2x - 2 * c2x + c1x),462 ny = c1y + 2 * t * (c2y - c1y) + t * t * (p2y - 2 * c2y + c1y),463 ax = (1 - t) * p1x + t * c1x,464 ay = (1 - t) * p1y + t * c1y,465 cx = (1 - t) * c2x + t * p2x,466 cy = (1 - t) * c2y + t * p2y,467 alpha = (90 - math.atan((mx - nx) / (my - ny)) * 180 / math.PI);468 (mx > nx || my < ny) && (alpha += 180);469 return {x: x, y: y, m: {x: mx, y: my}, n: {x: nx, y: ny}, start: {x: ax, y: ay}, end: {x: cx, y: cy}, alpha: alpha};470 };471 var pathDimensions = cacher(function (path) {472 if (!path) {473 return {x: 0, y: 0, width: 0, height: 0};474 }475 path = path2curve(path);476 var x = 0,477 y = 0,478 X = [],479 Y = [],480 p;481 for (var i = 0, ii = path[length]; i < ii; i++) {482 p = path[i];483 if (p[0] == "M") {484 x = p[1];485 y = p[2];486 X[push](x);487 Y[push](y);488 } else {489 var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);490 X = X[concat](dim.min.x, dim.max.x);491 Y = Y[concat](dim.min.y, dim.max.y);492 x = p[5];493 y = p[6];494 }495 }496 var xmin = mmin[apply](0, X),497 ymin = mmin[apply](0, Y);498 return {499 x: xmin,500 y: ymin,501 width: mmax[apply](0, X) - xmin,502 height: mmax[apply](0, Y) - ymin503 };504 }),505 pathClone = function (pathArray) {506 var res = [];507 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption508 pathArray = R.parsePathString(pathArray);509 }510 for (var i = 0, ii = pathArray[length]; i < ii; i++) {511 res[i] = [];512 for (var j = 0, jj = pathArray[i][length]; j < jj; j++) {513 res[i][j] = pathArray[i][j];514 }515 }516 res[toString] = R._path2string;517 return res;518 },519 pathToRelative = cacher(function (pathArray) {520 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption521 pathArray = R.parsePathString(pathArray);522 }523 var res = [],524 x = 0,525 y = 0,526 mx = 0,527 my = 0,528 start = 0;529 if (pathArray[0][0] == "M") {530 x = pathArray[0][1];531 y = pathArray[0][2];532 mx = x;533 my = y;534 start++;535 res[push](["M", x, y]);536 }537 for (var i = start, ii = pathArray[length]; i < ii; i++) {538 var r = res[i] = [],539 pa = pathArray[i];540 if (pa[0] != lowerCase.call(pa[0])) {541 r[0] = lowerCase.call(pa[0]);542 switch (r[0]) {543 case "a":544 r[1] = pa[1];545 r[2] = pa[2];546 r[3] = pa[3];547 r[4] = pa[4];548 r[5] = pa[5];549 r[6] = +(pa[6] - x).toFixed(3);550 r[7] = +(pa[7] - y).toFixed(3);551 break;552 case "v":553 r[1] = +(pa[1] - y).toFixed(3);554 break;555 case "m":556 mx = pa[1];557 my = pa[2];558 default:559 for (var j = 1, jj = pa[length]; j < jj; j++) {560 r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);561 }562 }563 } else {564 r = res[i] = [];565 if (pa[0] == "m") {566 mx = pa[1] + x;567 my = pa[2] + y;568 }569 for (var k = 0, kk = pa[length]; k < kk; k++) {570 res[i][k] = pa[k];571 }572 }573 var len = res[i][length];574 switch (res[i][0]) {575 case "z":576 x = mx;577 y = my;578 break;579 case "h":580 x += +res[i][len - 1];581 break;582 case "v":583 y += +res[i][len - 1];584 break;585 default:586 x += +res[i][len - 2];587 y += +res[i][len - 1];588 }589 }590 res[toString] = R._path2string;591 return res;592 }, 0, pathClone),593 pathToAbsolute = cacher(function (pathArray) {594 if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption595 pathArray = R.parsePathString(pathArray);596 }597 var res = [],598 x = 0,599 y = 0,600 mx = 0,601 my = 0,602 start = 0;603 if (pathArray[0][0] == "M") {604 x = +pathArray[0][1];605 y = +pathArray[0][2];606 mx = x;607 my = y;608 start++;609 res[0] = ["M", x, y];610 }611 for (var i = start, ii = pathArray[length]; i < ii; i++) {612 var r = res[i] = [],613 pa = pathArray[i];614 if (pa[0] != upperCase.call(pa[0])) {615 r[0] = upperCase.call(pa[0]);616 switch (r[0]) {617 case "A":618 r[1] = pa[1];619 r[2] = pa[2];620 r[3] = pa[3];621 r[4] = pa[4];622 r[5] = pa[5];623 r[6] = +(pa[6] + x);624 r[7] = +(pa[7] + y);625 break;626 case "V":627 r[1] = +pa[1] + y;628 break;629 case "H":630 r[1] = +pa[1] + x;631 break;632 case "M":633 mx = +pa[1] + x;634 my = +pa[2] + y;635 default:636 for (var j = 1, jj = pa[length]; j < jj; j++) {637 r[j] = +pa[j] + ((j % 2) ? x : y);638 }639 }640 } else {641 for (var k = 0, kk = pa[length]; k < kk; k++) {642 res[i][k] = pa[k];643 }644 }645 switch (r[0]) {646 case "Z":647 x = mx;648 y = my;649 break;650 case "H":651 x = r[1];652 break;653 case "V":654 y = r[1];655 break;656 case "M":657 mx = res[i][res[i][length] - 2];658 my = res[i][res[i][length] - 1];659 default:660 x = res[i][res[i][length] - 2];661 y = res[i][res[i][length] - 1];662 }663 }664 res[toString] = R._path2string;665 return res;666 }, null, pathClone),667 l2c = function (x1, y1, x2, y2) {668 return [x1, y1, x2, y2, x2, y2];669 },670 q2c = function (x1, y1, ax, ay, x2, y2) {671 var _13 = 1 / 3,672 _23 = 2 / 3;673 return [674 _13 * x1 + _23 * ax,675 _13 * y1 + _23 * ay,676 _13 * x2 + _23 * ax,677 _13 * y2 + _23 * ay,678 x2,679 y2680 ];681 },682 a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {683 // for more information of where this math came from visit:684 // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes685 var PI = math.PI,686 _120 = PI * 120 / 180,687 rad = PI / 180 * (+angle || 0),688 res = [],689 xy,690 rotate = cacher(function (x, y, rad) {691 var X = x * math.cos(rad) - y * math.sin(rad),692 Y = x * math.sin(rad) + y * math.cos(rad);693 return {x: X, y: Y};694 });695 if (!recursive) {696 xy = rotate(x1, y1, -rad);697 x1 = xy.x;698 y1 = xy.y;699 xy = rotate(x2, y2, -rad);700 x2 = xy.x;701 y2 = xy.y;702 var cos = math.cos(PI / 180 * angle),703 sin = math.sin(PI / 180 * angle),704 x = (x1 - x2) / 2,705 y = (y1 - y2) / 2;706 var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);707 if (h > 1) {708 h = math.sqrt(h);709 rx = h * rx;710 ry = h * ry;711 }712 var rx2 = rx * rx,713 ry2 = ry * ry,714 k = (large_arc_flag == sweep_flag ? -1 : 1) *715 math.sqrt(math.abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),716 cx = k * rx * y / ry + (x1 + x2) / 2,717 cy = k * -ry * x / rx + (y1 + y2) / 2,718 f1 = math.asin(((y1 - cy) / ry).toFixed(7)),719 f2 = math.asin(((y2 - cy) / ry).toFixed(7));721 f1 = x1 < cx ? PI - f1 : f1;722 f2 = x2 < cx ? PI - f2 : f2;723 f1 < 0 && (f1 = PI * 2 + f1);724 f2 < 0 && (f2 = PI * 2 + f2);725 if (sweep_flag && f1 > f2) {726 f1 = f1 - PI * 2;727 }728 if (!sweep_flag && f2 > f1) {729 f2 = f2 - PI * 2;730 }731 } else {732 f1 = recursive[0];733 f2 = recursive[1];734 cx = recursive[2];735 cy = recursive[3];736 }737 var df = f2 - f1;738 if (math.abs(df) > _120) {739 var f2old = f2,740 x2old = x2,741 y2old = y2;742 f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);743 x2 = cx + rx * math.cos(f2);744 y2 = cy + ry * math.sin(f2);745 res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);746 }747 df = f2 - f1;748 var c1 = math.cos(f1),749 s1 = math.sin(f1),750 c2 = math.cos(f2),751 s2 = math.sin(f2),752 t = math.tan(df / 4),753 hx = 4 / 3 * rx * t,754 hy = 4 / 3 * ry * t,755 m1 = [x1, y1],756 m2 = [x1 + hx * s1, y1 - hy * c1],757 m3 = [x2 + hx * s2, y2 - hy * c2],758 m4 = [x2, y2];759 m2[0] = 2 * m1[0] - m2[0];760 m2[1] = 2 * m1[1] - m2[1];761 if (recursive) {762 return [m2, m3, m4][concat](res);763 } else {764 res = [m2, m3, m4][concat](res)[join]()[split](",");765 var newres = [];766 for (var i = 0, ii = res[length]; i < ii; i++) {767 newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;768 }769 return newres;770 }771 },772 findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {773 var t1 = 1 - t;774 return {775 x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,776 y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y777 };778 },779 curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {780 var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),781 b = 2 * (c1x - p1x) - 2 * (c2x - c1x),782 c = p1x - c1x,783 t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,784 t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,785 y = [p1y, p2y],786 x = [p1x, p2x],787 dot;788 math.abs(t1) > 1e12 && (t1 = .5);789 math.abs(t2) > 1e12 && (t2 = .5);790 if (t1 > 0 && t1 < 1) {791 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);792 x[push](dot.x);793 y[push](dot.y);794 }795 if (t2 > 0 && t2 < 1) {796 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);797 x[push](dot.x);798 y[push](dot.y);799 }800 a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);801 b = 2 * (c1y - p1y) - 2 * (c2y - c1y);802 c = p1y - c1y;803 t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;804 t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;805 math.abs(t1) > 1e12 && (t1 = .5);806 math.abs(t2) > 1e12 && (t2 = .5);807 if (t1 > 0 && t1 < 1) {808 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);809 x[push](dot.x);810 y[push](dot.y);811 }812 if (t2 > 0 && t2 < 1) {813 dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);814 x[push](dot.x);815 y[push](dot.y);816 }817 return {818 min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},819 max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}820 };821 }),822 path2curve = cacher(function (path, path2) {823 var p = pathToAbsolute(path),824 p2 = path2 && pathToAbsolute(path2),825 attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},826 attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},827 processPath = function (path, d) {828 var nx, ny;829 if (!path) {830 return ["C", d.x, d.y, d.x, d.y, d.x, d.y];831 }832 !(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null);833 switch (path[0]) {834 case "M":835 d.X = path[1];836 d.Y = path[2];837 break;838 case "A":839 path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));840 break;841 case "S":842 nx = d.x + (d.x - (d.bx || d.x));843 ny = d.y + (d.y - (d.by || d.y));844 path = ["C", nx, ny][concat](path.slice(1));845 break;846 case "T":847 d.qx = d.x + (d.x - (d.qx || d.x));848 d.qy = d.y + (d.y - (d.qy || d.y));849 path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));850 break;851 case "Q":852 d.qx = path[1];853 d.qy = path[2];854 path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));855 break;856 case "L":857 path = ["C"][concat](l2c(d.x, d.y, path[1], path[2]));858 break;859 case "H":860 path = ["C"][concat](l2c(d.x, d.y, path[1], d.y));861 break;862 case "V":863 path = ["C"][concat](l2c(d.x, d.y, d.x, path[1]));864 break;865 case "Z":866 path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y));867 break;868 }869 return path;870 },871 fixArc = function (pp, i) {872 if (pp[i][length] > 7) {873 pp[i].shift();874 var pi = pp[i];875 while (pi[length]) {876 pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6)));877 }878 pp.splice(i, 1);879 ii = mmax(p[length], p2 && p2[length] || 0);880 }881 },882 fixM = function (path1, path2, a1, a2, i) {883 if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {884 path2.splice(i, 0, ["M", a2.x, a2.y]);885 a1.bx = 0;886 a1.by = 0;887 a1.x = path1[i][1];888 a1.y = path1[i][2];889 ii = mmax(p[length], p2 && p2[length] || 0);890 }891 };892 for (var i = 0, ii = mmax(p[length], p2 && p2[length] || 0); i < ii; i++) {893 p[i] = processPath(p[i], attrs);894 fixArc(p, i);895 p2 && (p2[i] = processPath(p2[i], attrs2));896 p2 && fixArc(p2, i);897 fixM(p, p2, attrs, attrs2, i);898 fixM(p2, p, attrs2, attrs, i);899 var seg = p[i],900 seg2 = p2 && p2[i],901 seglen = seg[length],902 seg2len = p2 && seg2[length];903 attrs.x = seg[seglen - 2];904 attrs.y = seg[seglen - 1];905 attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;906 attrs.by = toFloat(seg[seglen - 3]) || attrs.y;907 attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);908 attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);909 attrs2.x = p2 && seg2[seg2len - 2];910 attrs2.y = p2 && seg2[seg2len - 1];911 }912 return p2 ? [p, p2] : p;913 }, null, pathClone),914 parseDots = cacher(function (gradient) {915 var dots = [];916 for (var i = 0, ii = gradient[length]; i < ii; i++) {917 var dot = {},918 par = gradient[i].match(/^([^:]*):?([\d\.]*)/);919 dot.color = R.getRGB(par[1]);920 if (dot.color.error) {921 return null;922 }923 dot.color = dot.color.hex;924 par[2] && (dot.offset = par[2] + "%");925 dots[push](dot);926 }927 for (i = 1, ii = dots[length] - 1; i < ii; i++) {928 if (!dots[i].offset) {929 var start = toFloat(dots[i - 1].offset || 0),930 end = 0;931 for (var j = i + 1; j < ii; j++) {932 if (dots[j].offset) {933 end = dots[j].offset;934 break;935 }936 }937 if (!end) {938 end = 100;939 j = ii;940 }941 end = toFloat(end);942 var d = (end - start) / (j - i + 1);943 for (; i < j; i++) {944 start += d;945 dots[i].offset = start + "%";946 }947 }948 }949 return dots;950 }),951 getContainer = function (x, y, w, h) {952 var container;953 if (R.is(x, string) || R.is(x, "object")) {954 container = R.is(x, string) ? doc.getElementById(x) : x;955 if (container.tagName) {956 if (y == null) {957 return {958 container: container,959 width: container.style.pixelWidth || container.offsetWidth,960 height: container.style.pixelHeight || container.offsetHeight961 };962 } else {963 return {container: container, width: y, height: w};964 }965 }966 } else {967 return {container: 1, x: x, y: y, width: w, height: h};968 }969 },970 plugins = function (con, add) {971 var that = this;972 for (var prop in add) {973 if (add[has](prop) && !(prop in con)) {974 switch (typeof add[prop]) {975 case "function":976 (function (f) {977 con[prop] = con === that ? f : function () { return f[apply](that, arguments); };978 })(add[prop]);979 break;980 case "object":981 con[prop] = con[prop] || {};982 plugins.call(this, con[prop], add[prop]);983 break;984 default:985 con[prop] = add[prop];986 break;987 }988 }989 }990 },991 tear = function (el, paper) {992 el == paper.top && (paper.top = el.prev);993 el == paper.bottom && (paper.bottom = el.next);994 el.next && (el.next.prev = el.prev);995 el.prev && (el.prev.next = el.next);996 },997 tofront = function (el, paper) {998 if (paper.top === el) {999 return;1000 }1001 tear(el, paper);1002 el.next = null;1003 el.prev = paper.top;1004 paper.top.next = el;1005 paper.top = el;1006 },1007 toback = function (el, paper) {1008 if (paper.bottom === el) {1009 return;1010 }1011 tear(el, paper);1012 el.next = paper.bottom;1013 el.prev = null;1014 paper.bottom.prev = el;1015 paper.bottom = el;1016 },1017 insertafter = function (el, el2, paper) {1018 tear(el, paper);1019 el2 == paper.top && (paper.top = el);1020 el2.next && (el2.next.prev = el);1021 el.next = el2.next;1022 el.prev = el2;1023 el2.next = el;1024 },1025 insertbefore = function (el, el2, paper) {1026 tear(el, paper);1027 el2 == paper.bottom && (paper.bottom = el);1028 el2.prev && (el2.prev.next = el);1029 el.prev = el2.prev;1030 el2.prev = el;1031 el.next = el2;1032 },1033 removed = function (methodname) {1034 return function () {1035 throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object");1036 };1037 },1038 radial_gradient = /^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/;1039 R.pathToRelative = pathToRelative;1040 // SVG1041 if (R.svg) {1042 Paper[proto].svgns = "http://www.w3.org/2000/svg";1043 Paper[proto].xlink = "http://www.w3.org/1999/xlink";1044 round = function (num) {1045 return +num + (~~num === num) * .5;1046 };1047 var $ = function (el, attr) {1048 if (attr) {1049 for (var key in attr) {1050 if (attr[has](key)) {1051 el[setAttribute](key, Str(attr[key]));1052 }1053 }1054 } else {1055 el = doc.createElementNS(Paper[proto].svgns, el);1056 el.style.webkitTapHighlightColor = "rgba(0,0,0,0)";1057 return el;1058 }1059 };1060 R[toString] = function () {1061 return "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version;1062 };1063 var thePath = function (pathString, SVG) {1064 var el = $("path");1065 SVG.canvas && SVG.canvas[appendChild](el);1066 var p = new Element(el, SVG);1067 p.type = "path";1068 setFillAndStroke(p, {fill: "none", stroke: "#000", path: pathString});1069 return p;1070 };1071 var addGradientFill = function (o, gradient, SVG) {1072 var type = "linear",1073 fx = .5, fy = .5,1074 s = o.style;1075 gradient = Str(gradient)[rp](radial_gradient, function (all, _fx, _fy) {1076 type = "radial";1077 if (_fx && _fy) {1078 fx = toFloat(_fx);1079 fy = toFloat(_fy);1080 var dir = ((fy > .5) * 2 - 1);1081 pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&1082 (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&1083 fy != .5 &&1084 (fy = fy.toFixed(5) - 1e-5 * dir);1085 }1086 return E;1087 });1088 gradient = gradient[split](/\s*\-\s*/);1089 if (type == "linear") {1090 var angle = gradient.shift();1091 angle = -toFloat(angle);1092 if (isNaN(angle)) {1093 return null;1094 }1095 var vector = [0, 0, math.cos(angle * math.PI / 180), math.sin(angle * math.PI / 180)],1096 max = 1 / (mmax(math.abs(vector[2]), math.abs(vector[3])) || 1);1097 vector[2] *= max;1098 vector[3] *= max;1099 if (vector[2] < 0) {1100 vector[0] = -vector[2];1101 vector[2] = 0;1102 }1103 if (vector[3] < 0) {1104 vector[1] = -vector[3];1105 vector[3] = 0;1106 }1107 }1108 var dots = parseDots(gradient);1109 if (!dots) {1110 return null;1111 }1112 var id = o.getAttribute(fillString);1113 id = id.match(/^url\(#(.*)\)$/);1114 id && SVG.defs.removeChild(doc.getElementById(id[1]));1116 var el = $(type + "Gradient");1117 el.id = "r" + (R._id++)[toString](36);1118 $(el, type == "radial" ? {fx: fx, fy: fy} : {x1: vector[0], y1: vector[1], x2: vector[2], y2: vector[3]});1119 SVG.defs[appendChild](el);1120 for (var i = 0, ii = dots[length]; i < ii; i++) {1121 var stop = $("stop");1122 $(stop, {1123 offset: dots[i].offset ? dots[i].offset : !i ? "0%" : "100%",1124 "stop-color": dots[i].color || "#fff"1125 });1126 el[appendChild](stop);1127 }1128 $(o, {1129 fill: "url(#" + el.id + ")",1130 opacity: 1,1131 "fill-opacity": 11132 });1133 s.fill = E;1134 s.opacity = 1;1135 s.fillOpacity = 1;1136 return 1;1137 };1138 var updatePosition = function (o) {1139 var bbox = o.getBBox();1140 $(o.pattern, {patternTransform: R.format("translate({0},{1})", bbox.x, bbox.y)});1141 };1142 var setFillAndStroke = function (o, params) {1143 var dasharray = {1144 "": [0],1145 "none": [0],1146 "-": [3, 1],1147 ".": [1, 1],1148 "-.": [3, 1, 1, 1],1149 "-..": [3, 1, 1, 1, 1, 1],1150 ". ": [1, 3],1151 "- ": [4, 3],1152 "--": [8, 3],1153 "- .": [4, 3, 1, 3],1154 "--.": [8, 3, 1, 3],1155 "--..": [8, 3, 1, 3, 1, 3]1156 },1157 node = o.node,1158 attrs = o.attrs,1159 rot = o.rotate(),1160 addDashes = function (o, value) {1161 value = dasharray[lowerCase.call(value)];1162 if (value) {1163 var width = o.attrs["stroke-width"] || "1",1164 butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0,1165 dashes = [];1166 var i = value[length];1167 while (i--) {1168 dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;1169 }1170 $(node, {"stroke-dasharray": dashes[join](",")});1171 }1172 };1173 params[has]("rotation") && (rot = params.rotation);1174 var rotxy = Str(rot)[split](separator);1175 if (!(rotxy.length - 1)) {1176 rotxy = null;1177 } else {1178 rotxy[1] = +rotxy[1];1179 rotxy[2] = +rotxy[2];1180 }1181 toFloat(rot) && o.rotate(0, true);1182 for (var att in params) {1183 if (params[has](att)) {1184 if (!availableAttrs[has](att)) {1185 continue;1186 }1187 var value = params[att];1188 attrs[att] = value;1189 switch (att) {1190 case "blur":1191 o.blur(value);1192 break;1193 case "rotation":1194 o.rotate(value, true);1195 break;1196 case "href":1197 case "title":1198 case "target":1199 var pn = node.parentNode;1200 if (lowerCase.call(pn.tagName) != "a") {1201 var hl = $("a");1202 pn.insertBefore(hl, node);1203 hl[appendChild](node);1204 pn = hl;1205 }1206 pn.setAttributeNS(o.paper.xlink, att, value);1207 break;1208 case "cursor":1209 node.style.cursor = value;1210 break;1211 case "clip-rect":1212 var rect = Str(value)[split](separator);1213 if (rect[length] == 4) {1214 o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);1215 var el = $("clipPath"),1216 rc = $("rect");1217 el.id = "r" + (R._id++)[toString](36);1218 $(rc, {1219 x: rect[0],1220 y: rect[1],1221 width: rect[2],1222 height: rect[3]1223 });1224 el[appendChild](rc);1225 o.paper.defs[appendChild](el);1226 $(node, {"clip-path": "url(#" + el.id + ")"});1227 o.clip = rc;1228 }1229 if (!value) {1230 var clip = doc.getElementById(node.getAttribute("clip-path")[rp](/(^url\(#|\)$)/g, E));1231 clip && clip.parentNode.removeChild(clip);1232 $(node, {"clip-path": E});1233 delete o.clip;1234 }1235 break;1236 case "path":1237 if (o.type == "path") {1238 $(node, {d: value ? attrs.path = pathToAbsolute(value) : "M0,0"});1239 }1240 break;1241 case "width":1242 node[setAttribute](att, value);1243 if (attrs.fx) {1244 att = "x";1245 value = attrs.x;1246 } else {1247 break;1248 }1249 case "x":1250 if (attrs.fx) {1251 value = -attrs.x - (attrs.width || 0);1252 }1253 case "rx":1254 if (att == "rx" && o.type == "rect") {1255 break;1256 }1257 case "cx":1258 rotxy && (att == "x" || att == "cx") && (rotxy[1] += value - attrs[att]);1259 node[setAttribute](att, value);1260 o.pattern && updatePosition(o);1261 break;1262 case "height":1263 node[setAttribute](att, value);1264 if (attrs.fy) {1265 att = "y";1266 value = attrs.y;1267 } else {1268 break;1269 }1270 case "y":1271 if (attrs.fy) {1272 value = -attrs.y - (attrs.height || 0);1273 }1274 case "ry":1275 if (att == "ry" && o.type == "rect") {1276 break;1277 }1278 case "cy":1279 rotxy && (att == "y" || att == "cy") && (rotxy[2] += value - attrs[att]);1280 node[setAttribute](att, value);1281 o.pattern && updatePosition(o);1282 break;1283 case "r":1284 if (o.type == "rect") {1285 $(node, {rx: value, ry: value});1286 } else {1287 node[setAttribute](att, value);1288 }1289 break;1290 case "src":1291 if (o.type == "image") {1292 node.setAttributeNS(o.paper.xlink, "href", value);1293 }1294 break;1295 case "stroke-width":1296 node.style.strokeWidth = value;1297 // Need following line for Firefox1298 node[setAttribute](att, value);1299 if (attrs["stroke-dasharray"]) {1300 addDashes(o, attrs["stroke-dasharray"]);1301 }1302 break;1303 case "stroke-dasharray":1304 addDashes(o, value);1305 break;1306 case "translation":1307 var xy = Str(value)[split](separator);1308 xy[0] = +xy[0] || 0;1309 xy[1] = +xy[1] || 0;1310 if (rotxy) {1311 rotxy[1] += xy[0];1312 rotxy[2] += xy[1];1313 }1314 translate.call(o, xy[0], xy[1]);1315 break;1316 case "scale":1317 xy = Str(value)[split](separator);1318 o.scale(+xy[0] || 1, +xy[1] || +xy[0] || 1, isNaN(toFloat(xy[2])) ? null : +xy[2], isNaN(toFloat(xy[3])) ? null : +xy[3]);1319 break;1320 case fillString:1321 var isURL = Str(value).match(ISURL);1322 if (isURL) {1323 el = $("pattern");1324 var ig = $("image");1325 el.id = "r" + (R._id++)[toString](36);1326 $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1});1327 $(ig, {x: 0, y: 0});1328 ig.setAttributeNS(o.paper.xlink, "href", isURL[1]);1329 el[appendChild](ig);1331 var img = doc.createElement("img");1332 img.style.cssText = "position:absolute;left:-9999em;top-9999em";1333 img.onload = function () {1334 $(el, {width: this.offsetWidth, height: this.offsetHeight});1335 $(ig, {width: this.offsetWidth, height: this.offsetHeight});1336 doc.body.removeChild(this);1337 o.paper.safari();1338 };1339 doc.body[appendChild](img);1340 img.src = isURL[1];1341 o.paper.defs[appendChild](el);1342 node.style.fill = "url(#" + el.id + ")";1343 $(node, {fill: "url(#" + el.id + ")"});1344 o.pattern = el;1345 o.pattern && updatePosition(o);1346 break;1347 }1348 var clr = R.getRGB(value);1349 if (!clr.error) {1350 delete params.gradient;1351 delete attrs.gradient;1352 !R.is(attrs.opacity, "undefined") &&1353 R.is(params.opacity, "undefined") &&1354 $(node, {opacity: attrs.opacity});1355 !R.is(attrs["fill-opacity"], "undefined") &&1356 R.is(params["fill-opacity"], "undefined") &&1357 $(node, {"fill-opacity": attrs["fill-opacity"]});1358 } else if ((({circle: 1, ellipse: 1})[has](o.type) || Str(value).charAt() != "r") && addGradientFill(node, value, o.paper)) {1359 attrs.gradient = value;1360 attrs.fill = "none";1361 break;1362 }1363 clr[has]("o") && $(node, {"fill-opacity": clr.o > 1 ? clr.o / 100 : clr.o});1364 case "stroke":1365 clr = R.getRGB(value);1366 node[setAttribute](att, clr.hex);1367 att == "stroke" && clr[has]("o") && $(node, {"stroke-opacity": clr.o > 1 ? clr.o / 100 : clr.o});1368 break;1369 case "gradient":1370 (({circle: 1, ellipse: 1})[has](o.type) || Str(value).charAt() != "r") && addGradientFill(node, value, o.paper);1371 break;1372 case "opacity":1373 case "fill-opacity":1374 if (attrs.gradient) {1375 var gradient = doc.getElementById(node.getAttribute(fillString)[rp](/^url\(#|\)$/g, E));1376 if (gradient) {1377 var stops = gradient.getElementsByTagName("stop");1378 stops[stops[length] - 1][setAttribute]("stop-opacity", value);1379 }1380 break;1381 }1382 default:1383 att == "font-size" && (value = toInt(value, 10) + "px");1384 var cssrule = att[rp](/(\-.)/g, function (w) {1385 return upperCase.call(w.substring(1));1386 });1387 node.style[cssrule] = value;1388 // Need following line for Firefox1389 node[setAttribute](att, value);1390 break;1391 }1392 }1393 }1395 tuneText(o, params);1396 if (rotxy) {1397 o.rotate(rotxy.join(S));1398 } else {1399 toFloat(rot) && o.rotate(rot, true);1400 }1401 };1402 var leading = 1.2,1403 tuneText = function (el, params) {1404 if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) {1405 return;1406 }1407 var a = el.attrs,1408 node = el.node,1409 fontSize = node.firstChild ? toInt(doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10;1411 if (params[has]("text")) {1412 a.text = params.text;1413 while (node.firstChild) {1414 node.removeChild(node.firstChild);1415 }1416 var texts = Str(params.text)[split]("\n");1417 for (var i = 0, ii = texts[length]; i < ii; i++) if (texts[i]) {1418 var tspan = $("tspan");1419 i && $(tspan, {dy: fontSize * leading, x: a.x});1420 tspan[appendChild](doc.createTextNode(texts[i]));1421 node[appendChild](tspan);1422 }1423 } else {1424 texts = node.getElementsByTagName("tspan");1425 for (i = 0, ii = texts[length]; i < ii; i++) {1426 i && $(texts[i], {dy: fontSize * leading, x: a.x});1427 }1428 }1429 $(node, {y: a.y});1430 var bb = el.getBBox(),1431 dif = a.y - (bb.y + bb.height / 2);1432 dif && isFinite(dif) && $(node, {y: a.y + dif});1433 },1434 Element = function (node, svg) {1435 var X = 0,1436 Y = 0;1437 this[0] = node;1438 this.id = R._oid++;1439 this.node = node;1440 node.raphael = this;1441 this.paper = svg;1442 this.attrs = this.attrs || {};1443 this.transformations = []; // rotate, translate, scale1444 this._ = {1445 tx: 0,1446 ty: 0,1447 rt: {deg: 0, cx: 0, cy: 0},1448 sx: 1,1449 sy: 11450 };1451 !svg.bottom && (svg.bottom = this);1452 this.prev = svg.top;1453 svg.top && (svg.top.next = this);1454 svg.top = this;1455 this.next = null;1456 };1457 Element[proto].rotate = function (deg, cx, cy) {1458 if (this.removed) {1459 return this;1460 }1461 if (deg == null) {1462 if (this._.rt.cx) {1463 return [this._.rt.deg, this._.rt.cx, this._.rt.cy][join](S);1464 }1465 return this._.rt.deg;1466 }1467 var bbox = this.getBBox();1468 deg = Str(deg)[split](separator);1469 if (deg[length] - 1) {1470 cx = toFloat(deg[1]);1471 cy = toFloat(deg[2]);1472 }1473 deg = toFloat(deg[0]);1474 if (cx != null) {1475 this._.rt.deg = deg;1476 } else {1477 this._.rt.deg += deg;1478 }1479 (cy == null) && (cx = null);1480 this._.rt.cx = cx;1481 this._.rt.cy = cy;1482 cx = cx == null ? bbox.x + bbox.width / 2 : cx;1483 cy = cy == null ? bbox.y + bbox.height / 2 : cy;1484 if (this._.rt.deg) {1485 this.transformations[0] = R.format("rotate({0} {1} {2})", this._.rt.deg, cx, cy);1486 this.clip && $(this.clip, {transform: R.format("rotate({0} {1} {2})", -this._.rt.deg, cx, cy)});1487 } else {1488 this.transformations[0] = E;1489 this.clip && $(this.clip, {transform: E});1490 }1491 $(this.node, {transform: this.transformations[join](S)});1492 return this;1493 };1494 Element[proto].hide = function () {1495 !this.removed && (this.node.style.display = "none");1496 return this;1497 };1498 Element[proto].show = function () {1499 !this.removed && (this.node.style.display = "");1500 return this;1501 };1502 Element[proto].remove = function () {1503 if (this.removed) {1504 return;1505 }1506 tear(this, this.paper);1507 this.node.parentNode.removeChild(this.node);1508 for (var i in this) {1509 delete this[i];1510 }1511 this.removed = true;1512 };1513 Element[proto].getBBox = function () {1514 if (this.removed) {1515 return this;1516 }1517 if (this.type == "path") {1518 return pathDimensions(this.attrs.path);1519 }1520 if (this.node.style.display == "none") {1521 this.show();1522 var hide = true;1523 }1524 var bbox = {};1525 try {1526 bbox = this.node.getBBox();1527 } catch(e) {1528 // Firefox 3.0.x plays badly here1529 } finally {1530 bbox = bbox || {};1531 }1532 if (this.type == "text") {1533 bbox = {x: bbox.x, y: Infinity, width: 0, height: 0};1534 for (var i = 0, ii = this.node.getNumberOfChars(); i < ii; i++) {1535 var bb = this.node.getExtentOfChar(i);1536 (bb.y < bbox.y) && (bbox.y = bb.y);1537 (bb.y + bb.height - bbox.y > bbox.height) && (bbox.height = bb.y + bb.height - bbox.y);1538 (bb.x + bb.width - bbox.x > bbox.width) && (bbox.width = bb.x + bb.width - bbox.x);1539 }1540 }1541 hide && this.hide();1542 return bbox;1543 };1544 Element[proto].attr = function (name, value) {1545 if (this.removed) {1546 return this;1547 }1548 if (name == null) {1549 var res = {};1550 for (var i in this.attrs) if (this.attrs[has](i)) {1551 res[i] = this.attrs[i];1552 }1553 this._.rt.deg && (res.rotation = this.rotate());1554 (this._.sx != 1 || this._.sy != 1) && (res.scale = this.scale());1555 res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;1556 return res;1557 }1558 if (value == null && R.is(name, string)) {1559 if (name == "translation") {1560 return translate.call(this);1561 }1562 if (name == "rotation") {1563 return this.rotate();1564 }1565 if (name == "scale") {1566 return this.scale();1567 }1568 if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {1569 return this.attrs.gradient;1570 }1571 return this.attrs[name];1572 }1573 if (value == null && R.is(name, array)) {1574 var values = {};1575 for (var j = 0, jj = name.length; j < jj; j++) {1576 values[name[j]] = this.attr(name[j]);1577 }1578 return values;1579 }1580 if (value != null) {1581 var params = {};1582 params[name] = value;1583 setFillAndStroke(this, params);1584 } else if (name != null && R.is(name, "object")) {1585 setFillAndStroke(this, name);1586 }1587 return this;1588 };1589 Element[proto].toFront = function () {1590 if (this.removed) {1591 return this;1592 }1593 this.node.parentNode[appendChild](this.node);1594 var svg = this.paper;1595 svg.top != this && tofront(this, svg);1596 return this;1597 };1598 Element[proto].toBack = function () {1599 if (this.removed) {1600 return this;1601 }1602 if (this.node.parentNode.firstChild != this.node) {1603 this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);1604 toback(this, this.paper);1605 var svg = this.paper;1606 }1607 return this;1608 };1609 Element[proto].insertAfter = function (element) {1610 if (this.removed) {1611 return this;1612 }1613 var node = element.node || element[element.length].node;1614 if (node.nextSibling) {1615 node.parentNode.insertBefore(this.node, node.nextSibling);1616 } else {1617 node.parentNode[appendChild](this.node);1618 }1619 insertafter(this, element, this.paper);1620 return this;1621 };1622 Element[proto].insertBefore = function (element) {1623 if (this.removed) {1624 return this;1625 }1626 var node = element.node || element[0].node;1627 node.parentNode.insertBefore(this.node, node);1628 insertbefore(this, element, this.paper);1629 return this;1630 };1631 Element[proto].blur = function (size) {1632 // Experimental. No Safari support. Use it on your own risk.1633 var t = this;1634 if (+size !== 0) {1635 var fltr = $("filter"),1636 blur = $("feGaussianBlur");1637 t.attrs.blur = size;1638 fltr.id = "r" + (R._id++)[toString](36);1639 $(blur, {stdDeviation: +size || 1.5});1640 fltr.appendChild(blur);1641 t.paper.defs.appendChild(fltr);1642 t._blur = fltr;1643 $(t.node, {filter: "url(#" + fltr.id + ")"});1644 } else {1645 if (t._blur) {1646 t._blur.parentNode.removeChild(t._blur);1647 delete t._blur;1648 delete t.attrs.blur;1649 }1650 t.node.removeAttribute("filter");1651 }1652 };1653 var theCircle = function (svg, x, y, r) {1654 var el = $("circle");1655 svg.canvas && svg.canvas[appendChild](el);1656 var res = new Element(el, svg);1657 res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"};1658 res.type = "circle";1659 $(el, res.attrs);1660 return res;1661 };1662 var theRect = function (svg, x, y, w, h, r) {1663 var el = $("rect");1664 svg.canvas && svg.canvas[appendChild](el);1665 var res = new Element(el, svg);1666 res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"};1667 res.type = "rect";1668 $(el, res.attrs);1669 return res;1670 };1671 var theEllipse = function (svg, x, y, rx, ry) {1672 var el = $("ellipse");1673 svg.canvas && svg.canvas[appendChild](el);1674 var res = new Element(el, svg);1675 res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"};1676 res.type = "ellipse";1677 $(el, res.attrs);1678 return res;1679 };1680 var theImage = function (svg, src, x, y, w, h) {1681 var el = $("image");1682 $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"});1683 el.setAttributeNS(svg.xlink, "href", src);1684 svg.canvas && svg.canvas[appendChild](el);1685 var res = new Element(el, svg);1686 res.attrs = {x: x, y: y, width: w, height: h, src: src};1687 res.type = "image";1688 return res;1689 };1690 var theText = function (svg, x, y, text) {1691 var el = $("text");1692 $(el, {x: x, y: y, "text-anchor": "middle"});1693 svg.canvas && svg.canvas[appendChild](el);1694 var res = new Element(el, svg);1695 res.attrs = {x: x, y: y, "text-anchor": "middle", text: text, font: availableAttrs.font, stroke: "none", fill: "#000"};1696 res.type = "text";1697 setFillAndStroke(res, res.attrs);1698 return res;1699 };1700 var setSize = function (width, height) {1701 this.width = width || this.width;1702 this.height = height || this.height;1703 this.canvas[setAttribute]("width", this.width);1704 this.canvas[setAttribute]("height", this.height);1705 return this;1706 };1707 var create = function () {1708 var con = getContainer[apply](0, arguments),1709 container = con && con.container,1710 x = con.x,1711 y = con.y,1712 width = con.width,1713 height = con.height;1714 if (!container) {1715 throw new Error("SVG container not found.");1716 }1717 var cnvs = $("svg");1718 x = x || 0;1719 y = y || 0;1720 width = width || 512;1721 height = height || 342;1722 $(cnvs, {1723 xmlns: "http://www.w3.org/2000/svg",1724 version: 1.1,1725 width: width,1726 height: height1727 });1728 if (container == 1) {1729 cnvs.style.cssText = "position:absolute;left:" + x + "px;top:" + y + "px";1730 doc.body[appendChild](cnvs);1731 } else {1732 if (container.firstChild) {1733 container.insertBefore(cnvs, container.firstChild);1734 } else {1735 container[appendChild](cnvs);1736 }1737 }1738 container = new Paper;1739 container.width = width;1740 container.height = height;1741 container.canvas = cnvs;1742 plugins.call(container, container, R.fn);1743 container.clear();1744 return container;1745 };1746 Paper[proto].clear = function () {1747 var c = this.canvas;1748 while (c.firstChild) {1749 c.removeChild(c.firstChild);1750 }1751 this.bottom = this.top = null;1752 (this.desc = $("desc"))[appendChild](doc.createTextNode("Created with Rapha\xebl"));1753 c[appendChild](this.desc);1754 c[appendChild](this.defs = $("defs"));1755 };1756 Paper[proto].remove = function () {1757 this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);1758 for (var i in this) {1759 this[i] = removed(i);1760 }1761 };1762 }1764 // VML1765 if (R.vml) {1766 var map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},1767 bites = /([clmz]),?([^clmz]*)/gi,1768 val = /-?[^,\s-]+/g,1769 coordsize = 1e3 + S + 1e3,1770 zoom = 10,1771 pathlike = {path: 1, rect: 1},1772 path2vml = function (path) {1773 var total = /[ahqstv]/ig,1774 command = pathToAbsolute;1775 Str(path).match(total) && (command = path2curve);1776 total = /[clmz]/g;1777 if (command == pathToAbsolute && !Str(path).match(total)) {1778 var res = Str(path)[rp](bites, function (all, command, args) {1779 var vals = [],1780 isMove = lowerCase.call(command) == "m",1781 res = map[command];1782 args[rp](val, function (value) {1783 if (isMove && vals[length] == 2) {1784 res += vals + map[command == "m" ? "l" : "L"];1785 vals = [];1786 }1787 vals[push](round(value * zoom));1788 });1789 return res + vals;1790 });1791 return res;1792 }1793 var pa = command(path), p, r;1794 res = [];1795 for (var i = 0, ii = pa[length]; i < ii; i++) {1796 p = pa[i];1797 r = lowerCase.call(pa[i][0]);1798 r == "z" && (r = "x");1799 for (var j = 1, jj = p[length]; j < jj; j++) {1800 r += round(p[j] * zoom) + (j != jj - 1 ? "," : E);1801 }1802 res[push](r);1803 }1804 return res[join](S);1805 };1807 R[toString] = function () {1808 return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version;1809 };1810 thePath = function (pathString, vml) {1811 var g = createNode("group");1812 g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";1813 g.coordsize = vml.coordsize;1814 g.coordorigin = vml.coordorigin;1815 var el = createNode("shape"), ol = el.style;1816 ol.width = vml.width + "px";1817 ol.height = vml.height + "px";1818 el.coordsize = coordsize;1819 el.coordorigin = vml.coordorigin;1820 g[appendChild](el);1821 var p = new Element(el, g, vml),1822 attr = {fill: "none", stroke: "#000"};1823 pathString && (attr.path = pathString);1824 p.isAbsolute = true;1825 p.type = "path";1826 p.path = [];1827 p.Path = E;1828 setFillAndStroke(p, attr);1829 vml.canvas[appendChild](g);1830 return p;1831 };1832 setFillAndStroke = function (o, params) {1833 o.attrs = o.attrs || {};1834 var node = o.node,1835 a = o.attrs,1836 s = node.style,1837 xy,1838 newpath = (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.r != a.r) && o.type == "rect",1839 res = o;1841 for (var par in params) if (params[has](par)) {1842 a[par] = params[par];1843 }1844 if (newpath) {1845 a.path = rectPath(a.x, a.y, a.width, a.height, a.r);1846 o.X = a.x;1847 o.Y = a.y;1848 o.W = a.width;1849 o.H = a.height;1850 }1851 params.href && (node.href = params.href);1852 params.title && (node.title = params.title);1853 params.target && (node.target = params.target);1854 params.cursor && (s.cursor = params.cursor);1855 "blur" in params && o.blur(params.blur);1856 if (params.path && o.type == "path" || newpath) {1857 node.path = path2vml(a.path);1858 }1859 if (params.rotation != null) {1860 o.rotate(params.rotation, true);1861 }1862 if (params.translation) {1863 xy = Str(params.translation)[split](separator);1864 translate.call(o, xy[0], xy[1]);1865 if (o._.rt.cx != null) {1866 o._.rt.cx +=+ xy[0];1867 o._.rt.cy +=+ xy[1];1868 o.setBox(o.attrs, xy[0], xy[1]);1869 }1870 }1871 if (params.scale) {1872 xy = Str(params.scale)[split](separator);1873 o.scale(+xy[0] || 1, +xy[1] || +xy[0] || 1, +xy[2] || null, +xy[3] || null);1874 }1875 if ("clip-rect" in params) {1876 var rect = Str(params["clip-rect"])[split](separator);1877 if (rect[length] == 4) {1878 rect[2] = +rect[2] + (+rect[0]);1879 rect[3] = +rect[3] + (+rect[1]);1880 var div = node.clipRect || doc.createElement("div"),1881 dstyle = div.style,1882 group = node.parentNode;1883 dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect);1884 if (!node.clipRect) {1885 dstyle.position = "absolute";1886 dstyle.top = 0;1887 dstyle.left = 0;1888 dstyle.width = o.paper.width + "px";1889 dstyle.height = o.paper.height + "px";1890 group.parentNode.insertBefore(div, group);1891 div[appendChild](group);1892 node.clipRect = div;1893 }1894 }1895 if (!params["clip-rect"]) {1896 node.clipRect && (node.clipRect.style.clip = E);1897 }1898 }1899 if (o.type == "image" && params.src) {1900 node.src = params.src;1901 }1902 if (o.type == "image" && params.opacity) {1903 node.filterOpacity = ms + ".Alpha(opacity=" + (params.opacity * 100) + ")";1904 s.filter = (node.filterMatrix || E) + (node.filterOpacity || E);1905 }1906 params.font && (s.font = params.font);1907 params["font-family"] && (s.fontFamily = '"' + params["font-family"][split](",")[0][rp](/^['"]+|['"]+$/g, E) + '"');1908 params["font-size"] && (s.fontSize = params["font-size"]);1909 params["font-weight"] && (s.fontWeight = params["font-weight"]);1910 params["font-style"] && (s.fontStyle = params["font-style"]);1911 if (params.opacity != null ||1912 params["stroke-width"] != null ||1913 params.fill != null ||1914 params.stroke != null ||1915 params["stroke-width"] != null ||1916 params["stroke-opacity"] != null ||1917 params["fill-opacity"] != null ||1918 params["stroke-dasharray"] != null ||1919 params["stroke-miterlimit"] != null ||1920 params["stroke-linejoin"] != null ||1921 params["stroke-linecap"] != null) {1922 node = o.shape || node;1923 var fill = (node.getElementsByTagName(fillString) && node.getElementsByTagName(fillString)[0]),1924 newfill = false;1925 !fill && (newfill = fill = createNode(fillString));1926 if ("fill-opacity" in params || "opacity" in params) {1927 var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);1928 opacity < 0 && (opacity = 0);1929 opacity > 1 && (opacity = 1);1930 fill.opacity = opacity;1931 }1932 params.fill && (fill.on = true);1933 if (fill.on == null || params.fill == "none") {1934 fill.on = false;1935 }1936 if (fill.on && params.fill) {1937 var isURL = params.fill.match(ISURL);1938 if (isURL) {1939 fill.src = isURL[1];1940 fill.type = "tile";1941 } else {1942 fill.color = R.getRGB(params.fill).hex;1943 fill.src = E;1944 fill.type = "solid";1945 if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill)) {1946 a.fill = "none";1947 a.gradient = params.fill;1948 }1949 }1950 }1951 newfill && node[appendChild](fill);1952 var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]),1953 newstroke = false;1954 !stroke && (newstroke = stroke = createNode("stroke"));1955 if ((params.stroke && params.stroke != "none") ||1956 params["stroke-width"] ||1957 params["stroke-opacity"] != null ||1958 params["stroke-dasharray"] ||1959 params["stroke-miterlimit"] ||1960 params["stroke-linejoin"] ||1961 params["stroke-linecap"]) {1962 stroke.on = true;1963 }1964 (params.stroke == "none" || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false);1965 var strokeColor = R.getRGB(params.stroke);1966 stroke.on && params.stroke && (stroke.color = strokeColor.hex);1967 opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);1968 var width = (toFloat(params["stroke-width"]) || 1) * .75;1969 opacity < 0 && (opacity = 0);1970 opacity > 1 && (opacity = 1);1971 params["stroke-width"] == null && (width = a["stroke-width"]);1972 params["stroke-width"] && (stroke.weight = width);1973 width && width < 1 && (opacity *= width) && (stroke.weight = 1);1974 stroke.opacity = opacity;1976 params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter");1977 stroke.miterlimit = params["stroke-miterlimit"] || 8;1978 params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round");1979 if (params["stroke-dasharray"]) {1980 var dasharray = {1981 "-": "shortdash",1982 ".": "shortdot",1983 "-.": "shortdashdot",1984 "-..": "shortdashdotdot",1985 ". ": "dot",1986 "- ": "dash",1987 "--": "longdash",1988 "- .": "dashdot",1989 "--.": "longdashdot",1990 "--..": "longdashdotdot"1991 };1992 stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E;1993 }1994 newstroke && node[appendChild](stroke);1995 }1996 if (res.type == "text") {1997 s = res.paper.span.style;1998 a.font && (s.font = a.font);1999 a["font-family"] && (s.fontFamily = a["font-family"]);2000 a["font-size"] && (s.fontSize = a["font-size"]);2001 a["font-weight"] && (s.fontWeight = a["font-weight"]);2002 a["font-style"] && (s.fontStyle = a["font-style"]);2003 res.node.string && (res.paper.span.innerHTML = Str(res.node.string)[rp](/</g, "<")[rp](/&/g, "&")[rp](/\n/g, "<br>"));2004 res.W = a.w = res.paper.span.offsetWidth;2005 res.H = a.h = res.paper.span.offsetHeight;2006 res.X = a.x;2007 res.Y = a.y + round(res.H / 2);2009 // text-anchor emulationm2010 switch (a["text-anchor"]) {2011 case "start":2012 res.node.style["v-text-align"] = "left";2013 res.bbx = round(res.W / 2);2014 break;2015 case "end":2016 res.node.style["v-text-align"] = "right";2017 res.bbx = -round(res.W / 2);2018 break;2019 default:2020 res.node.style["v-text-align"] = "center";2021 break;2022 }2023 }2024 };2025 addGradientFill = function (o, gradient) {2026 o.attrs = o.attrs || {};2027 var attrs = o.attrs,2028 fill,2029 type = "linear",2030 fxfy = ".5 .5";2031 o.attrs.gradient = gradient;2032 gradient = Str(gradient)[rp](radial_gradient, function (all, fx, fy) {2033 type = "radial";2034 if (fx && fy) {2035 fx = toFloat(fx);2036 fy = toFloat(fy);2037 pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);2038 fxfy = fx + S + fy;2039 }2040 return E;2041 });2042 gradient = gradient[split](/\s*\-\s*/);2043 if (type == "linear") {2044 var angle = gradient.shift();2045 angle = -toFloat(angle);2046 if (isNaN(angle)) {2047 return null;2048 }2049 }2050 var dots = parseDots(gradient);2051 if (!dots) {2052 return null;2053 }2054 o = o.shape || o.node;2055 fill = o.getElementsByTagName(fillString)[0] || createNode(fillString);2056 !fill.parentNode && o.appendChild(fill);2057 if (dots[length]) {2058 fill.on = true;2059 fill.method = "none";2060 fill.color = dots[0].color;2061 fill.color2 = dots[dots[length] - 1].color;2062 var clrs = [];2063 for (var i = 0, ii = dots[length]; i < ii; i++) {2064 dots[i].offset && clrs[push](dots[i].offset + S + dots[i].color);2065 }2066 fill.colors && (fill.colors.value = clrs[length] ? clrs[join]() : "0% " + fill.color);2067 if (type == "radial") {2068 fill.type = "gradientradial";2069 fill.focus = "100%";2070 fill.focussize = fxfy;2071 fill.focusposition = fxfy;2072 } else {2073 fill.type = "gradient";2074 fill.angle = (270 - angle) % 360;2075 }2076 }2077 return 1;2078 };2079 Element = function (node, group, vml) {2080 var Rotation = 0,2081 RotX = 0,2082 RotY = 0,2083 Scale = 1;2084 this[0] = node;2085 this.id = R._oid++;2086 this.node = node;2087 node.raphael = this;2088 this.X = 0;2089 this.Y = 0;2090 this.attrs = {};2091 this.Group = group;2092 this.paper = vml;2093 this._ = {2094 tx: 0,2095 ty: 0,2096 rt: {deg:0},2097 sx: 1,2098 sy: 12099 };2100 !vml.bottom && (vml.bottom = this);2101 this.prev = vml.top;2102 vml.top && (vml.top.next = this);2103 vml.top = this;2104 this.next = null;2105 };2106 Element[proto].rotate = function (deg, cx, cy) {2107 if (this.removed) {2108 return this;2109 }2110 if (deg == null) {2111 if (this._.rt.cx) {2112 return [this._.rt.deg, this._.rt.cx, this._.rt.cy][join](S);2113 }2114 return this._.rt.deg;2115 }2116 deg = Str(deg)[split](separator);2117 if (deg[length] - 1) {2118 cx = toFloat(deg[1]);2119 cy = toFloat(deg[2]);2120 }2121 deg = toFloat(deg[0]);2122 if (cx != null) {2123 this._.rt.deg = deg;2124 } else {2125 this._.rt.deg += deg;2126 }2127 cy == null && (cx = null);2128 this._.rt.cx = cx;2129 this._.rt.cy = cy;2130 this.setBox(this.attrs, cx, cy);2131 this.Group.style.rotation = this._.rt.deg;2132 // gradient fix for rotation. TODO2133 // var fill = (this.shape || this.node).getElementsByTagName(fillString);2134 // fill = fill[0] || {};2135 // var b = ((360 - this._.rt.deg) - 270) % 360;2136 // !R.is(fill.angle, "undefined") && (fill.angle = b);2137 return this;2138 };2139 Element[proto].setBox = function (params, cx, cy) {2140 if (this.removed) {2141 return this;2142 }2143 var gs = this.Group.style,2144 os = (this.shape && this.shape.style) || this.node.style;2145 params = params || {};2146 for (var i in params) if (params[has](i)) {2147 this.attrs[i] = params[i];2148 }2149 cx = cx || this._.rt.cx;2150 cy = cy || this._.rt.cy;2151 var attr = this.attrs,2152 x,2153 y,2154 w,2155 h;2156 switch (this.type) {2157 case "circle":2158 x = attr.cx - attr.r;2159 y = attr.cy - attr.r;2160 w = h = attr.r * 2;2161 break;2162 case "ellipse":2163 x = attr.cx - attr.rx;2164 y = attr.cy - attr.ry;2165 w = attr.rx * 2;2166 h = attr.ry * 2;2167 break;2168 case "image":2169 x = +attr.x;2170 y = +attr.y;2171 w = attr.width || 0;2172 h = attr.height || 0;2173 break;2174 case "text":2175 this.textpath.v = ["m", round(attr.x), ", ", round(attr.y - 2), "l", round(attr.x) + 1, ", ", round(attr.y - 2)][join](E);2176 x = attr.x - round(this.W / 2);2177 y = attr.y - this.H / 2;2178 w = this.W;2179 h = this.H;2180 break;2181 case "rect":2182 case "path":2183 if (!this.attrs.path) {2184 x = 0;2185 y = 0;2186 w = this.paper.width;2187 h = this.paper.height;2188 } else {2189 var dim = pathDimensions(this.attrs.path);2190 x = dim.x;2191 y = dim.y;2192 w = dim.width;2193 h = dim.height;2194 }2195 break;2196 default:2197 x = 0;2198 y = 0;2199 w = this.paper.width;2200 h = this.paper.height;2201 break;2202 }2203 cx = (cx == null) ? x + w / 2 : cx;2204 cy = (cy == null) ? y + h / 2 : cy;2205 var left = cx - this.paper.width / 2,2206 top = cy - this.paper.height / 2, t;2207 gs.left != (t = left + "px") && (gs.left = t);2208 gs.top != (t = top + "px") && (gs.top = t);2209 this.X = pathlike[has](this.type) ? -left : x;2210 this.Y = pathlike[has](this.type) ? -top : y;2211 this.W = w;2212 this.H = h;2213 if (pathlike[has](this.type)) {2214 os.left != (t = -left * zoom + "px") && (os.left = t);2215 os.top != (t = -top * zoom + "px") && (os.top = t);2216 } else if (this.type == "text") {2217 os.left != (t = -left + "px") && (os.left = t);2218 os.top != (t = -top + "px") && (os.top = t);2219 } else {2220 gs.width != (t = this.paper.width + "px") && (gs.width = t);2221 gs.height != (t = this.paper.height + "px") && (gs.height = t);2222 os.left != (t = x - left + "px") && (os.left = t);2223 os.top != (t = y - top + "px") && (os.top = t);2224 os.width != (t = w + "px") && (os.width = t);2225 os.height != (t = h + "px") && (os.height = t);2226 }2227 };2228 Element[proto].hide = function () {2229 !this.removed && (this.Group.style.display = "none");2230 return this;2231 };2232 Element[proto].show = function () {2233 !this.removed && (this.Group.style.display = "block");2234 return this;2235 };2236 Element[proto].getBBox = function () {2237 if (this.removed) {2238 return this;2239 }2240 if (pathlike[has](this.type)) {2241 return pathDimensions(this.attrs.path);2242 }2243 return {2244 x: this.X + (this.bbx || 0),2245 y: this.Y,2246 width: this.W,2247 height: this.H2248 };2249 };2250 Element[proto].remove = function () {2251 if (this.removed) {2252 return;2253 }2254 tear(this, this.paper);2255 this.node.parentNode.removeChild(this.node);2256 this.Group.parentNode.removeChild(this.Group);2257 this.shape && this.shape.parentNode.removeChild(this.shape);2258 for (var i in this) {2259 delete this[i];2260 }2261 this.removed = true;2262 };2263 Element[proto].attr = function (name, value) {2264 if (this.removed) {2265 return this;2266 }2267 if (name == null) {2268 var res = {};2269 for (var i in this.attrs) if (this.attrs[has](i)) {2270 res[i] = this.attrs[i];2271 }2272 this._.rt.deg && (res.rotation = this.rotate());2273 (this._.sx != 1 || this._.sy != 1) && (res.scale = this.scale());2274 res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;2275 return res;2276 }2277 if (value == null && R.is(name, string)) {2278 if (name == "translation") {2279 return translate.call(this);2280 }2281 if (name == "rotation") {2282 return this.rotate();2283 }2284 if (name == "scale") {2285 return this.scale();2286 }2287 if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {2288 return this.attrs.gradient;2289 }2290 return this.attrs[name];2291 }2292 if (this.attrs && value == null && R.is(name, array)) {2293 var ii, values = {};2294 for (i = 0, ii = name[length]; i < ii; i++) {2295 values[name[i]] = this.attr(name[i]);2296 }2297 return values;2298 }2299 var params;2300 if (value != null) {2301 params = {};2302 params[name] = value;2303 }2304 value == null && R.is(name, "object") && (params = name);2305 if (params) {2306 if (params.text && this.type == "text") {2307 this.node.string = params.text;2308 }2309 setFillAndStroke(this, params);2310 if (params.gradient && (({circle: 1, ellipse: 1})[has](this.type) || Str(params.gradient).charAt() != "r")) {2311 addGradientFill(this, params.gradient);2312 }2313 (!pathlike[has](this.type) || this._.rt.deg) && this.setBox(this.attrs);2314 }2315 return this;2316 };2317 Element[proto].toFront = function () {2318 !this.removed && this.Group.parentNode[appendChild](this.Group);2319 this.paper.top != this && tofront(this, this.paper);2320 return this;2321 };2322 Element[proto].toBack = function () {2323 if (this.removed) {2324 return this;2325 }2326 if (this.Group.parentNode.firstChild != this.Group) {2327 this.Group.parentNode.insertBefore(this.Group, this.Group.parentNode.firstChild);2328 toback(this, this.paper);2329 }2330 return this;2331 };2332 Element[proto].insertAfter = function (element) {2333 if (this.removed) {2334 return this;2335 }2336 if (element.constructor == Set) {2337 element = element[element.length];2338 }2339 if (element.Group.nextSibling) {2340 element.Group.parentNode.insertBefore(this.Group, element.Group.nextSibling);2341 } else {2342 element.Group.parentNode[appendChild](this.Group);2343 }2344 insertafter(this, element, this.paper);2345 return this;2346 };2347 Element[proto].insertBefore = function (element) {2348 if (this.removed) {2349 return this;2350 }2351 if (element.constructor == Set) {2352 element = element[0];2353 }2354 element.Group.parentNode.insertBefore(this.Group, element.Group);2355 insertbefore(this, element, this.paper);2356 return this;2357 };2358 var blurregexp = / progid:\S+Blur\([^\)]+\)/g;2359 Element[proto].blur = function (size) {2360 var s = this.node.runtimeStyle,2361 f = s.filter;2362 f = f.replace(blurregexp, E);2363 if (+size !== 0) {2364 this.attrs.blur = size;2365 s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")";2366 s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5));2367 } else {2368 s.filter = f;2369 s.margin = 0;2370 delete this.attrs.blur;2371 }2372 };2374 theCircle = function (vml, x, y, r) {2375 var g = createNode("group"),2376 o = createNode("oval"),2377 ol = o.style;2378 g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";2379 g.coordsize = coordsize;2380 g.coordorigin = vml.coordorigin;2381 g[appendChild](o);2382 var res = new Element(o, g, vml);2383 res.type = "circle";2384 setFillAndStroke(res, {stroke: "#000", fill: "none"});2385 res.attrs.cx = x;2386 res.attrs.cy = y;2387 res.attrs.r = r;2388 res.setBox({x: x - r, y: y - r, width: r * 2, height: r * 2});2389 vml.canvas[appendChild](g);2390 return res;2391 };2392 function rectPath(x, y, w, h, r) {2393 if (r) {2394 return R.format("M{0},{1}l{2},0a{3},{3},0,0,1,{3},{3}l0,{5}a{3},{3},0,0,1,{4},{3}l{6},0a{3},{3},0,0,1,{4},{4}l0,{7}a{3},{3},0,0,1,{3},{4}z", x + r, y, w - r * 2, r, -r, h - r * 2, r * 2 - w, r * 2 - h);2395 } else {2396 return R.format("M{0},{1}l{2},0,0,{3},{4},0z", x, y, w, h, -w);2397 }2398 }2399 theRect = function (vml, x, y, w, h, r) {2400 var path = rectPath(x, y, w, h, r),2401 res = vml.path(path),2402 a = res.attrs;2403 res.X = a.x = x;2404 res.Y = a.y = y;2405 res.W = a.width = w;2406 res.H = a.height = h;2407 a.r = r;2408 a.path = path;2409 res.type = "rect";2410 return res;2411 };2412 theEllipse = function (vml, x, y, rx, ry) {2413 var g = createNode("group"),2414 o = createNode("oval"),2415 ol = o.style;2416 g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";2417 g.coordsize = coordsize;2418 g.coordorigin = vml.coordorigin;2419 g[appendChild](o);2420 var res = new Element(o, g, vml);2421 res.type = "ellipse";2422 setFillAndStroke(res, {stroke: "#000"});2423 res.attrs.cx = x;2424 res.attrs.cy = y;2425 res.attrs.rx = rx;2426 res.attrs.ry = ry;2427 res.setBox({x: x - rx, y: y - ry, width: rx * 2, height: ry * 2});2428 vml.canvas[appendChild](g);2429 return res;2430 };2431 theImage = function (vml, src, x, y, w, h) {2432 var g = createNode("group"),2433 o = createNode("image"),2434 ol = o.style;2435 g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";2436 g.coordsize = coordsize;2437 g.coordorigin = vml.coordorigin;2438 o.src = src;2439 g[appendChild](o);2440 var res = new Element(o, g, vml);2441 res.type = "image";2442 res.attrs.src = src;2443 res.attrs.x = x;2444 res.attrs.y = y;2445 res.attrs.w = w;2446 res.attrs.h = h;2447 res.setBox({x: x, y: y, width: w, height: h});2448 vml.canvas[appendChild](g);2449 return res;2450 };2451 theText = function (vml, x, y, text) {2452 var g = createNode("group"),2453 el = createNode("shape"),2454 ol = el.style,2455 path = createNode("path"),2456 ps = path.style,2457 o = createNode("textpath");2458 g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";2459 g.coordsize = coordsize;2460 g.coordorigin = vml.coordorigin;2461 path.v = R.format("m{0},{1}l{2},{1}", round(x * 10), round(y * 10), round(x * 10) + 1);2462 path.textpathok = true;2463 ol.width = vml.width;2464 ol.height = vml.height;2465 o.string = Str(text);2466 o.on = true;2467 el[appendChild](o);2468 el[appendChild](path);2469 g[appendChild](el);2470 var res = new Element(o, g, vml);2471 res.shape = el;2472 res.textpath = path;2473 res.type = "text";2474 res.attrs.text = text;2475 res.attrs.x = x;2476 res.attrs.y = y;2477 res.attrs.w = 1;2478 res.attrs.h = 1;2479 setFillAndStroke(res, {font: availableAttrs.font, stroke: "none", fill: "#000"});2480 res.setBox();2481 vml.canvas[appendChild](g);2482 return res;2483 };2484 setSize = function (width, height) {2485 var cs = this.canvas.style;2486 width == +width && (width += "px");2487 height == +height && (height += "px");2488 cs.width = width;2489 cs.height = height;2490 cs.clip = "rect(0 " + width + " " + height + " 0)";2491 return this;2492 };2493 var createNode;2494 doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");2495 try {2496 !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");2497 createNode = function (tagName) {2498 return doc.createElement('<rvml:' + tagName + ' class="rvml">');2499 };2500 } catch (e) {2501 createNode = function (tagName) {2502 return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');2503 };2504 }2505 create = function () {2506 var con = getContainer[apply](0, arguments),2507 container = con.container,2508 height = con.height,2509 s,2510 width = con.width,2511 x = con.x,2512 y = con.y;2513 if (!container) {2514 throw new Error("VML container not found.");2515 }2516 var res = new Paper,2517 c = res.canvas = doc.createElement("div"),2518 cs = c.style;2519 x = x || 0;2520 y = y || 0;2521 width = width || 512;2522 height = height || 342;2523 width == +width && (width += "px");2524 height == +height && (height += "px");2525 res.width = 1e3;2526 res.height = 1e3;2527 res.coordsize = zoom * 1e3 + S + zoom * 1e3;2528 res.coordorigin = "0 0";2529 res.span = doc.createElement("span");2530 res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";2531 c[appendChild](res.span);2532 cs.cssText = R.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height);2533 if (container == 1) {2534 doc.body[appendChild](c);2535 cs.left = x + "px";2536 cs.top = y + "px";2537 cs.position = "absolute";2538 } else {2539 if (container.firstChild) {2540 container.insertBefore(c, container.firstChild);2541 } else {2542 container[appendChild](c);2543 }2544 }2545 plugins.call(res, res, R.fn);2546 return res;2547 };2548 Paper[proto].clear = function () {2549 this.canvas.innerHTML = E;2550 this.span = doc.createElement("span");2551 this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";2552 this.canvas[appendChild](this.span);2553 this.bottom = this.top = null;2554 };2555 Paper[proto].remove = function () {2556 this.canvas.parentNode.removeChild(this.canvas);2557 for (var i in this) {2558 this[i] = removed(i);2559 }2560 return true;2561 };2562 }2564 // rest2565 // WebKit rendering bug workaround method2566 if ((navigator.vendor == "Apple Computer, Inc.") && (navigator.userAgent.match(/Version\/(.*?)\s/)[1] < 4 || win.navigator.platform.slice(0, 2) == "iP")) {2567 Paper[proto].safari = function () {2568 var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"});2569 win.setTimeout(function () {rect.remove();});2570 };2571 } else {2572 Paper[proto].safari = function () {};2573 }2575 // Events2576 var preventDefault = function () {2577 this.returnValue = false;2578 },2579 preventTouch = function () {2580 return this.originalEvent.preventDefault();2581 },2582 stopPropagation = function () {2583 this.cancelBubble = true;2584 },2585 stopTouch = function () {2586 return this.originalEvent.stopPropagation();2587 },2588 addEvent = (function () {2589 if (doc.addEventListener) {2590 return function (obj, type, fn, element) {2591 var realName = supportsTouch && touchMap[type] ? touchMap[type] : type;2592 var f = function (e) {2593 if (supportsTouch && touchMap[has](type)) {2594 for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {2595 if (e.targetTouches[i].target == obj) {2596 var olde = e;2597 e = e.targetTouches[i];2598 e.originalEvent = olde;2599 e.preventDefault = preventTouch;2600 e.stopPropagation = stopTouch;2601 break;2602 }2603 }2604 }2605 return fn.call(element, e);2606 };2607 obj.addEventListener(realName, f, false);2608 return function () {2609 obj.removeEventListener(realName, f, false);2610 return true;2611 };2612 };2613 } else if (doc.attachEvent) {2614 return function (obj, type, fn, element) {2615 var f = function (e) {2616 e = e || win.event;2617 e.preventDefault = e.preventDefault || preventDefault;2618 e.stopPropagation = e.stopPropagation || stopPropagation;2619 return fn.call(element, e);2620 };2621 obj.attachEvent("on" + type, f);2622 var detacher = function () {2623 obj.detachEvent("on" + type, f);2624 return true;2625 };2626 return detacher;2627 };2628 }2629 })(),2630 drag = [],2631 dragMove = function (e) {2632 var x = e.clientX,2633 y = e.clientY,2634 dragi,2635 j = drag.length;2636 while (j--) {2637 dragi = drag[j];2638 if (supportsTouch) {2639 var i = e.touches.length,2640 touch;2641 while (i--) {2642 touch = e.touches[i];2643 if (touch.identifier == dragi.el._drag.id) {2644 x = touch.clientX;2645 y = touch.clientY;2646 (e.originalEvent ? e.originalEvent : e).preventDefault();2647 break;2648 }2649 }2650 } else {2651 e.preventDefault();2652 }2653 dragi.move && dragi.move.call(dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y);2654 }2655 },2656 dragUp = function () {2657 R.unmousemove(dragMove).unmouseup(dragUp);2658 var i = drag.length,2659 dragi;2660 while (i--) {2661 dragi = drag[i];2662 dragi.el._drag = {};2663 dragi.end && dragi.end.call(dragi.el);2664 }2665 drag = [];2666 };2667 for (var i = events[length]; i--;) {2668 (function (eventName) {2669 R[eventName] = Element[proto][eventName] = function (fn) {2670 if (R.is(fn, "function")) {2671 this.events = this.events || [];2672 this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || doc, eventName, fn, this)});2673 }2674 return this;2675 };2676 R["un" + eventName] = Element[proto]["un" + eventName] = function (fn) {2677 var events = this.events,2678 l = events[length];2679 while (l--) if (events[l].name == eventName && events[l].f == fn) {2680 events[l].unbind();2681 events.splice(l, 1);2682 !events.length && delete this.events;2683 return this;2684 }2685 return this;2686 };2687 })(events[i]);2688 }2689 Element[proto].hover = function (f_in, f_out) {2690 return this.mouseover(f_in).mouseout(f_out);2691 };2692 Element[proto].unhover = function (f_in, f_out) {2693 return this.unmouseover(f_in).unmouseout(f_out);2694 };2695 Element[proto].drag = function (onmove, onstart, onend) {2696 this._drag = {};2697 this.mousedown(function (e) {2698 (e.originalEvent || e).preventDefault();2699 this._drag.x = e.clientX;2700 this._drag.y = e.clientY;2701 this._drag.id = e.identifier;2702 onstart && onstart.call(this, e.clientX, e.clientY);2703 !drag.length && R.mousemove(dragMove).mouseup(dragUp);2704 drag.push({el: this, move: onmove, end: onend});2705 });2706 return this;2707 };2708 Element[proto].undrag = function (onmove, onstart, onend) {2709 var i = drag.length;2710 while (i--) {2711 drag[i].el == this && (drag[i].move == onmove && drag[i].end == onend) && drag.splice(i, 1);2712 !drag.length && R.unmousemove(dragMove).unmouseup(dragUp);2713 }2714 };2715 Paper[proto].circle = function (x, y, r) {2716 return theCircle(this, x || 0, y || 0, r || 0);2717 };2718 Paper[proto].rect = function (x, y, w, h, r) {2719 return theRect(this, x || 0, y || 0, w || 0, h || 0, r || 0);2720 };2721 Paper[proto].ellipse = function (x, y, rx, ry) {2722 return theEllipse(this, x || 0, y || 0, rx || 0, ry || 0);2723 };2724 Paper[proto].path = function (pathString) {2725 pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);2726 return thePath(R.format[apply](R, arguments), this);2727 };2728 Paper[proto].image = function (src, x, y, w, h) {2729 return theImage(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0);2730 };2731 Paper[proto].text = function (x, y, text) {2732 return theText(this, x || 0, y || 0, text || E);2733 };2734 Paper[proto].set = function (itemsArray) {2735 arguments[length] > 1 && (itemsArray = Array[proto].splice.call(arguments, 0, arguments[length]));2736 return new Set(itemsArray);2737 };2738 Paper[proto].setSize = setSize;2739 Paper[proto].top = Paper[proto].bottom = null;2740 Paper[proto].raphael = R;2741 function x_y() {2742 return this.x + S + this.y;2743 }2744 Element[proto].resetScale = function () {2745 if (this.removed) {2746 return this;2747 }2748 this._.sx = 1;2749 this._.sy = 1;2750 this.attrs.scale = "1 1";2751 };2752 Element[proto].scale = function (x, y, cx, cy) {2753 if (this.removed) {2754 return this;2755 }2756 if (x == null && y == null) {2757 return {2758 x: this._.sx,2759 y: this._.sy,2760 toString: x_y2761 };2762 }2763 y = y || x;2764 !+y && (y = x);2765 var dx,2766 dy,2767 dcx,2768 dcy,2769 a = this.attrs;2770 if (x != 0) {2771 var bb = this.getBBox(),2772 rcx = bb.x + bb.width / 2,2773 rcy = bb.y + bb.height / 2,2774 kx = x / this._.sx,2775 ky = y / this._.sy;2776 cx = (+cx || cx == 0) ? cx : rcx;2777 cy = (+cy || cy == 0) ? cy : rcy;2778 var dirx = ~~(x / math.abs(x)),2779 diry = ~~(y / math.abs(y)),2780 s = this.node.style,2781 ncx = cx + (rcx - cx) * kx,2782 ncy = cy + (rcy - cy) * ky;2783 switch (this.type) {2784 case "rect":2785 case "image":2786 var neww = a.width * dirx * kx,2787 newh = a.height * diry * ky;2788 this.attr({2789 height: newh,2790 r: a.r * mmin(dirx * kx, diry * ky),2791 width: neww,2792 x: ncx - neww / 2,2793 y: ncy - newh / 22794 });2795 break;2796 case "circle":2797 case "ellipse":2798 this.attr({2799 rx: a.rx * dirx * kx,2800 ry: a.ry * diry * ky,2801 r: a.r * mmin(dirx * kx, diry * ky),2802 cx: ncx,2803 cy: ncy2804 });2805 break;2806 case "text":2807 this.attr({2808 x: ncx,2809 y: ncy2810 });2811 break;2812 case "path":2813 var path = pathToRelative(a.path),2814 skip = true;2815 for (var i = 0, ii = path[length]; i < ii; i++) {2816 var p = path[i],2817 P0 = upperCase.call(p[0]);2818 if (P0 == "M" && skip) {2819 continue;2820 } else {2821 skip = false;2822 }2823 if (P0 == "A") {2824 p[path[i][length] - 2] *= kx;2825 p[path[i][length] - 1] *= ky;2826 p[1] *= dirx * kx;2827 p[2] *= diry * ky;2828 p[5] = +!(dirx + diry ? !+p[5] : +p[5]);2829 } else if (P0 == "H") {2830 for (var j = 1, jj = p[length]; j < jj; j++) {2831 p[j] *= kx;2832 }2833 } else if (P0 == "V") {2834 for (j = 1, jj = p[length]; j < jj; j++) {2835 p[j] *= ky;2836 }2837 } else {2838 for (j = 1, jj = p[length]; j < jj; j++) {2839 p[j] *= (j % 2) ? kx : ky;2840 }2841 }2842 }2843 var dim2 = pathDimensions(path);2844 dx = ncx - dim2.x - dim2.width / 2;2845 dy = ncy - dim2.y - dim2.height / 2;2846 path[0][1] += dx;2847 path[0][2] += dy;2848 this.attr({path: path});2849 break;2850 }2851 if (this.type in {text: 1, image:1} && (dirx != 1 || diry != 1)) {2852 if (this.transformations) {2853 this.transformations[2] = "scale("[concat](dirx, ",", diry, ")");2854 this.node[setAttribute]("transform", this.transformations[join](S));2855 dx = (dirx == -1) ? -a.x - (neww || 0) : a.x;2856 dy = (diry == -1) ? -a.y - (newh || 0) : a.y;2857 this.attr({x: dx, y: dy});2858 a.fx = dirx - 1;2859 a.fy = diry - 1;2860 } else {2861 this.node.filterMatrix = ms + ".Matrix(M11="[concat](dirx,2862 ", M12=0, M21=0, M22=", diry,2863 ", Dx=0, Dy=0, sizingmethod='auto expand', filtertype='bilinear')");2864 s.filter = (this.node.filterMatrix || E) + (this.node.filterOpacity || E);2865 }2866 } else {2867 if (this.transformations) {2868 this.transformations[2] = E;2869 this.node[setAttribute]("transform", this.transformations[join](S));2870 a.fx = 0;2871 a.fy = 0;2872 } else {2873 this.node.filterMatrix = E;2874 s.filter = (this.node.filterMatrix || E) + (this.node.filterOpacity || E);2875 }2876 }2877 a.scale = [x, y, cx, cy][join](S);2878 this._.sx = x;2879 this._.sy = y;2880 }2881 return this;2882 };2883 Element[proto].clone = function () {2884 if (this.removed) {2885 return null;2886 }2887 var attr = this.attr();2888 delete attr.scale;2889 delete attr.translation;2890 return this.paper[this.type]().attr(attr);2891 };2892 var getPointAtSegmentLength = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {2893 var len = 0,2894 old;2895 for (var i = 0; i < 1.01; i+=.01) {2896 var dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i);2897 i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5));2898 if (len >= length) {2899 return dot;2900 }2901 old = dot;2902 }2903 }),2904 getLengthFactory = function (istotal, subpath) {2905 return function (path, length, onlystart) {2906 path = path2curve(path);2907 var x, y, p, l, sp = "", subpaths = {}, point,2908 len = 0;2909 for (var i = 0, ii = path.length; i < ii; i++) {2910 p = path[i];2911 if (p[0] == "M") {2912 x = +p[1];2913 y = +p[2];2914 } else {2915 l = segmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);2916 if (len + l > length) {2917 if (subpath && !subpaths.start) {2918 point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);2919 sp += ["C", point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];2920 if (onlystart) {return sp;}2921 subpaths.start = sp;2922 sp = ["M", point.x, point.y + "C", point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]][join]();2923 len += l;2924 x = +p[5];2925 y = +p[6];2926 continue;2927 }2928 if (!istotal && !subpath) {2929 point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);2930 return {x: point.x, y: point.y, alpha: point.alpha};2931 }2932 }2933 len += l;2934 x = +p[5];2935 y = +p[6];2936 }2937 sp += p;2938 }2939 subpaths.end = sp;2940 point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[1], p[2], p[3], p[4], p[5], p[6], 1);2941 point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});2942 return point;2943 };2944 },2945 segmentLength = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {2946 var old = {x: 0, y: 0},2947 len = 0;2948 for (var i = 0; i < 1.01; i+=.01) {2949 var dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i);2950 i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5));2951 old = dot;2952 }2953 return len;2954 });2955 var getTotalLength = getLengthFactory(1),2956 getPointAtLength = getLengthFactory(),2957 getSubpathsAtLength = getLengthFactory(0, 1);2958 Element[proto].getTotalLength = function () {2959 if (this.type != "path") {return;}2960 if (this.node.getTotalLength) {2961 return this.node.getTotalLength();2962 }2963 return getTotalLength(this.attrs.path);2964 };2965 Element[proto].getPointAtLength = function (length) {2966 if (this.type != "path") {return;}2967 if (this.node.getPointAtLength) {2968 return this.node.getPointAtLength(length);2969 }2970 return getPointAtLength(this.attrs.path, length);2971 };2972 Element[proto].getSubpath = function (from, to) {2973 if (this.type != "path") {return;}2974 if (math.abs(this.getTotalLength() - to) < 1e-6) {2975 return getSubpathsAtLength(this.attrs.path, from).end;2976 }2977 var a = getSubpathsAtLength(this.attrs.path, to, 1);2978 return from ? getSubpathsAtLength(a, from).end : a;2979 };2981 // animation easing formulas2982 R.easing_formulas = {2983 linear: function (n) {2984 return n;2985 },2986 "<": function (n) {2987 return pow(n, 3);2988 },2989 ">": function (n) {2990 return pow(n - 1, 3) + 1;2991 },2992 "<>": function (n) {2993 n = n * 2;2994 if (n < 1) {2995 return pow(n, 3) / 2;2996 }2997 n -= 2;2998 return (pow(n, 3) + 2) / 2;2999 },3000 backIn: function (n) {3001 var s = 1.70158;3002 return n * n * ((s + 1) * n - s);3003 },3004 backOut: function (n) {3005 n = n - 1;3006 var s = 1.70158;3007 return n * n * ((s + 1) * n + s) + 1;3008 },3009 elastic: function (n) {3010 if (n == 0 || n == 1) {3011 return n;3012 }3013 var p = .3,3014 s = p / 4;3015 return pow(2, -10 * n) * math.sin((n - s) * (2 * math.PI) / p) + 1;3016 },3017 bounce: function (n) {3018 var s = 7.5625,3019 p = 2.75,3020 l;3021 if (n < (1 / p)) {3022 l = s * n * n;3023 } else {3024 if (n < (2 / p)) {3025 n -= (1.5 / p);3026 l = s * n * n + .75;3027 } else {3028 if (n < (2.5 / p)) {3029 n -= (2.25 / p);3030 l = s * n * n + .9375;3031 } else {3032 n -= (2.625 / p);3033 l = s * n * n + .984375;3034 }3035 }3036 }3037 return l;3038 }3039 };3041 var animationElements = {length : 0},3042 animation = function () {3043 var Now = +new Date;3044 for (var l in animationElements) if (l != "length" && animationElements[has](l)) {3045 var e = animationElements[l];3046 if (e.stop || e.el.removed) {3047 delete animationElements[l];3048 animationElements[length]--;3049 continue;3050 }3051 var time = Now - e.start,3052 ms = e.ms,3053 easing = e.easing,3054 from = e.from,3055 diff = e.diff,3056 to = e.to,3057 t = e.t,3058 prev = e.prev || 0,3059 that = e.el,3060 callback = e.callback,3061 set = {},3062 now;3063 if (time < ms) {3064 var pos = R.easing_formulas[easing] ? R.easing_formulas[easing](time / ms) : time / ms;3065 for (var attr in from) if (from[has](attr)) {3066 switch (availableAnimAttrs[attr]) {3067 case "along":3068 now = pos * ms * diff[attr];3069 to.back && (now = to.len - now);3070 var point = getPointAtLength(to[attr], now);3071 that.translate(diff.sx - diff.x || 0, diff.sy - diff.y || 0);3072 diff.x = point.x;3073 diff.y = point.y;3074 that.translate(point.x - diff.sx, point.y - diff.sy);3075 to.rot && that.rotate(diff.r + point.alpha, point.x, point.y);3076 break;3077 case nu:3078 now = +from[attr] + pos * ms * diff[attr];3079 break;3080 case "colour":3081 now = "rgb(" + [3082 upto255(round(from[attr].r + pos * ms * diff[attr].r)),3083 upto255(round(from[attr].g + pos * ms * diff[attr].g)),3084 upto255(round(from[attr].b + pos * ms * diff[attr].b))3085 ][join](",") + ")";3086 break;3087 case "path":3088 now = [];3089 for (var i = 0, ii = from[attr][length]; i < ii; i++) {3090 now[i] = [from[attr][i][0]];3091 for (var j = 1, jj = from[attr][i][length]; j < jj; j++) {3092 now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];3093 }3094 now[i] = now[i][join](S);3095 }3096 now = now[join](S);3097 break;3098 case "csv":3099 switch (attr) {3100 case "translation":3101 var x = diff[attr][0] * (time - prev),3102 y = diff[attr][1] * (time - prev);3103 t.x += x;3104 t.y += y;3105 now = x + S + y;3106 break;3107 case "rotation":3108 now = +from[attr][0] + pos * ms * diff[attr][0];3109 from[attr][1] && (now += "," + from[attr][1] + "," + from[attr][2]);3110 break;3111 case "scale":3112 now = [+from[attr][0] + pos * ms * diff[attr][0], +from[attr][1] + pos * ms * diff[attr][1], (2 in to[attr] ? to[attr][2] : E), (3 in to[attr] ? to[attr][3] : E)][join](S);3113 break;3114 case "clip-rect":3115 now = [];3116 i = 4;3117 while (i--) {3118 now[i] = +from[attr][i] + pos * ms * diff[attr][i];3119 }3120 break;3121 }3122 break;3123 }3124 set[attr] = now;3125 }3126 that.attr(set);3127 that._run && that._run.call(that);3128 } else {3129 if (to.along) {3130 point = getPointAtLength(to.along, to.len * !to.back);3131 that.translate(diff.sx - (diff.x || 0) + point.x - diff.sx, diff.sy - (diff.y || 0) + point.y - diff.sy);3132 to.rot && that.rotate(diff.r + point.alpha, point.x, point.y);3133 }3134 (t.x || t.y) && that.translate(-t.x, -t.y);3135 to.scale && (to.scale += E);3136 that.attr(to);3137 delete animationElements[l];3138 animationElements[length]--;3139 that.in_animation = null;3140 R.is(callback, "function") && callback.call(that);3141 }3142 e.prev = time;3143 }3144 R.svg && that && that.paper && that.paper.safari();3145 animationElements[length] && win.setTimeout(animation);3146 },3147 upto255 = function (color) {3148 return mmax(mmin(color, 255), 0);3149 },3150 translate = function (x, y) {3151 if (x == null) {3152 return {x: this._.tx, y: this._.ty, toString: x_y};3153 }3154 this._.tx += +x;3155 this._.ty += +y;3156 switch (this.type) {3157 case "circle":3158 case "ellipse":3159 this.attr({cx: +x + this.attrs.cx, cy: +y + this.attrs.cy});3160 break;3161 case "rect":3162 case "image":3163 case "text":3164 this.attr({x: +x + this.attrs.x, y: +y + this.attrs.y});3165 break;3166 case "path":3167 var path = pathToRelative(this.attrs.path);3168 path[0][1] += +x;3169 path[0][2] += +y;3170 this.attr({path: path});3171 break;3172 }3173 return this;3174 };3175 Element[proto].animateWith = function (element, params, ms, easing, callback) {3176 animationElements[element.id] && (params.start = animationElements[element.id].start);3177 return this.animate(params, ms, easing, callback);3178 };3179 Element[proto].animateAlong = along();3180 Element[proto].animateAlongBack = along(1);3181 function along(isBack) {3182 return function (path, ms, rotate, callback) {3183 var params = {back: isBack};3184 R.is(rotate, "function") ? (callback = rotate) : (params.rot = rotate);3185 path && path.constructor == Element && (path = path.attrs.path);3186 path && (params.along = path);3187 return this.animate(params, ms, callback);3188 };3189 }3190 Element[proto].onAnimation = function (f) {3191 this._run = f || 0;3192 return this;3193 };3194 Element[proto].animate = function (params, ms, easing, callback) {3195 if (R.is(easing, "function") || !easing) {3196 callback = easing || null;3197 }3198 var from = {},3199 to = {},3200 diff = {};3201 for (var attr in params) if (params[has](attr)) {3202 if (availableAnimAttrs[has](attr)) {3203 from[attr] = this.attr(attr);3204 (from[attr] == null) && (from[attr] = availableAttrs[attr]);3205 to[attr] = params[attr];3206 switch (availableAnimAttrs[attr]) {3207 case "along":3208 var len = getTotalLength(params[attr]);3209 var point = getPointAtLength(params[attr], len * !!params.back);3210 var bb = this.getBBox();3211 diff[attr] = len / ms;3212 diff.tx = bb.x;3213 diff.ty = bb.y;3214 diff.sx = point.x;3215 diff.sy = point.y;3216 to.rot = params.rot;3217 to.back = params.back;3218 to.len = len;3219 params.rot && (diff.r = toFloat(this.rotate()) || 0);3220 break;3221 case nu:3222 diff[attr] = (to[attr] - from[attr]) / ms;3223 break;3224 case "colour":3225 from[attr] = R.getRGB(from[attr]);3226 var toColour = R.getRGB(to[attr]);3227 diff[attr] = {3228 r: (toColour.r - from[attr].r) / ms,3229 g: (toColour.g - from[attr].g) / ms,3230 b: (toColour.b - from[attr].b) / ms3231 };3232 break;3233 case "path":3234 var pathes = path2curve(from[attr], to[attr]);3235 from[attr] = pathes[0];3236 var toPath = pathes[1];3237 diff[attr] = [];3238 for (var i = 0, ii = from[attr][length]; i < ii; i++) {3239 diff[attr][i] = [0];3240 for (var j = 1, jj = from[attr][i][length]; j < jj; j++) {3241 diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;3242 }3243 }3244 break;3245 case "csv":3246 var values = Str(params[attr])[split](separator),3247 from2 = Str(from[attr])[split](separator);3248 switch (attr) {3249 case "translation":3250 from[attr] = [0, 0];3251 diff[attr] = [values[0] / ms, values[1] / ms];3252 break;3253 case "rotation":3254 from[attr] = (from2[1] == values[1] && from2[2] == values[2]) ? from2 : [0, values[1], values[2]];3255 diff[attr] = [(values[0] - from[attr][0]) / ms, 0, 0];3256 break;3257 case "scale":3258 params[attr] = values;3259 from[attr] = Str(from[attr])[split](separator);3260 diff[attr] = [(values[0] - from[attr][0]) / ms, (values[1] - from[attr][1]) / ms, 0, 0];3261 break;3262 case "clip-rect":3263 from[attr] = Str(from[attr])[split](separator);3264 diff[attr] = [];3265 i = 4;3266 while (i--) {3267 diff[attr][i] = (values[i] - from[attr][i]) / ms;3268 }3269 break;3270 }3271 to[attr] = values;3272 }3273 }3274 }3275 this.stop();3276 this.in_animation = 1;3277 animationElements[this.id] = {3278 start: params.start || +new Date,3279 ms: ms,3280 easing: easing,3281 from: from,3282 diff: diff,3283 to: to,3284 el: this,3285 callback: callback,3286 t: {x: 0, y: 0}3287 };3288 ++animationElements[length] == 1 && animation();3289 return this;3290 };3291 Element[proto].stop = function () {3292 animationElements[this.id] && animationElements[length]--;3293 delete animationElements[this.id];3294 return this;3295 };3296 Element[proto].translate = function (x, y) {3297 return this.attr({translation: x + " " + y});3298 };3299 Element[proto][toString] = function () {3300 return "Rapha\xebl\u2019s object";3301 };3302 R.ae = animationElements;3304 // Set3305 var Set = function (items) {3306 this.items = [];3307 this[length] = 0;3308 this.type = "set";3309 if (items) {3310 for (var i = 0, ii = items[length]; i < ii; i++) {3311 if (items[i] && (items[i].constructor == Element || items[i].constructor == Set)) {3312 this[this.items[length]] = this.items[this.items[length]] = items[i];3313 this[length]++;3314 }3315 }3316 }3317 };3318 Set[proto][push] = function () {3319 var item,3320 len;3321 for (var i = 0, ii = arguments[length]; i < ii; i++) {3322 item = arguments[i];3323 if (item && (item.constructor == Element || item.constructor == Set)) {3324 len = this.items[length];3325 this[len] = this.items[len] = item;3326 this[length]++;3327 }3328 }3329 return this;3330 };3331 Set[proto].pop = function () {3332 delete this[this[length]--];3333 return this.items.pop();3334 };3335 for (var method in Element[proto]) if (Element[proto][has](method)) {3336 Set[proto][method] = (function (methodname) {3337 return function () {3338 for (var i = 0, ii = this.items[length]; i < ii; i++) {3339 this.items[i][methodname][apply](this.items[i], arguments);3340 }3341 return this;3342 };3343 })(method);3344 }3345 Set[proto].attr = function (name, value) {3346 if (name && R.is(name, array) && R.is(name[0], "object")) {3347 for (var j = 0, jj = name[length]; j < jj; j++) {3348 this.items[j].attr(name[j]);3349 }3350 } else {3351 for (var i = 0, ii = this.items[length]; i < ii; i++) {3352 this.items[i].attr(name, value);3353 }3354 }3355 return this;3356 };3357 Set[proto].animate = function (params, ms, easing, callback) {3358 (R.is(easing, "function") || !easing) && (callback = easing || null);3359 var len = this.items[length],3360 i = len,3361 item,3362 set = this,3363 collector;3364 callback && (collector = function () {3365 !--len && callback.call(set);3366 });3367 easing = R.is(easing, string) ? easing : collector;3368 item = this.items[--i].animate(params, ms, easing, collector);3369 while (i--) {3370 this.items[i].animateWith(item, params, ms, easing, collector);3371 }3372 return this;3373 };3374 Set[proto].insertAfter = function (el) {3375 var i = this.items[length];3376 while (i--) {3377 this.items[i].insertAfter(el);3378 }3379 return this;3380 };3381 Set[proto].getBBox = function () {3382 var x = [],3383 y = [],3384 w = [],3385 h = [];3386 for (var i = this.items[length]; i--;) {3387 var box = this.items[i].getBBox();3388 x[push](box.x);3389 y[push](box.y);3390 w[push](box.x + box.width);3391 h[push](box.y + box.height);3392 }3393 x = mmin[apply](0, x);3394 y = mmin[apply](0, y);3395 return {3396 x: x,3397 y: y,3398 width: mmax[apply](0, w) - x,3399 height: mmax[apply](0, h) - y3400 };3401 };3402 Set[proto].clone = function (s) {3403 s = new Set;3404 for (var i = 0, ii = this.items[length]; i < ii; i++) {3405 s[push](this.items[i].clone());3406 }3407 return s;3408 };3410 R.registerFont = function (font) {3411 if (!font.face) {3412 return font;3413 }3414 this.fonts = this.fonts || {};3415 var fontcopy = {3416 w: font.w,3417 face: {},3418 glyphs: {}3419 },3420 family = font.face["font-family"];3421 for (var prop in font.face) if (font.face[has](prop)) {3422 fontcopy.face[prop] = font.face[prop];3423 }3424 if (this.fonts[family]) {3425 this.fonts[family][push](fontcopy);3426 } else {3427 this.fonts[family] = [fontcopy];3428 }3429 if (!font.svg) {3430 fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10);3431 for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {3432 var path = font.glyphs[glyph];3433 fontcopy.glyphs[glyph] = {3434 w: path.w,3435 k: {},3436 d: path.d && "M" + path.d[rp](/[mlcxtrv]/g, function (command) {3437 return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M";3438 }) + "z"3439 };3440 if (path.k) {3441 for (var k in path.k) if (path[has](k)) {3442 fontcopy.glyphs[glyph].k[k] = path.k[k];3443 }3444 }3445 }3446 }3447 return font;3448 };3449 Paper[proto].getFont = function (family, weight, style, stretch) {3450 stretch = stretch || "normal";3451 style = style || "normal";3452 weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;3453 if (!R.fonts) {3454 return;3455 }3456 var font = R.fonts[family];3457 if (!font) {3458 var name = new RegExp("(^|\\s)" + family[rp](/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i");3459 for (var fontName in R.fonts) if (R.fonts[has](fontName)) {3460 if (name.test(fontName)) {3461 font = R.fonts[fontName];3462 break;3463 }3464 }3465 }3466 var thefont;3467 if (font) {3468 for (var i = 0, ii = font[length]; i < ii; i++) {3469 thefont = font[i];3470 if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) {3471 break;3472 }3473 }3474 }3475 return thefont;3476 };3477 Paper[proto].print = function (x, y, string, font, size, origin) {3478 origin = origin || "middle"; // baseline|middle3479 var out = this.set(),3480 letters = Str(string)[split](E),3481 shift = 0,3482 path = E,3483 scale;3484 R.is(font, string) && (font = this.getFont(font));3485 if (font) {3486 scale = (size || 16) / font.face["units-per-em"];3487 var bb = font.face.bbox.split(separator),3488 top = +bb[0],3489 height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2);3490 for (var i = 0, ii = letters[length]; i < ii; i++) {3491 var prev = i && font.glyphs[letters[i - 1]] || {},3492 curr = font.glyphs[letters[i]];3493 shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) : 0;3494 curr && curr.d && out[push](this.path(curr.d).attr({fill: "#000", stroke: "none", translation: [shift, 0]}));3495 }3496 out.scale(scale, scale, top, height).translate(x - top, y - height);3497 }3498 return out;3499 };3501 var formatrg = /\{(\d+)\}/g;3502 R.format = function (token, params) {3503 var args = R.is(params, array) ? [0][concat](params) : arguments;3504 token && R.is(token, string) && args[length] - 1 && (token = token[rp](formatrg, function (str, i) {3505 return args[++i] == null ? E : args[i];3506 }));3507 return token || E;3508 };3509 R.ninja = function () {3510 oldRaphael.was ? (Raphael = oldRaphael.is) : delete Raphael;3511 return R;3512 };3513 R.el = Element[proto];3514 return R;3515 })();