123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119 |
-
- // @info
- // Polyfill for SVG getPathData() and setPathData() methods. Based on:
- // - SVGPathSeg polyfill by Philip Rogers (MIT License)
- // https://github.com/progers/pathseg
- // - SVGPathNormalizer by Tadahisa Motooka (MIT License)
- // https://github.com/motooka/SVGPathNormalizer/tree/master/src
- // - arcToCubicCurves() by Dmitry Baranovskiy (MIT License)
- // https://github.com/DmitryBaranovskiy/raphael/blob/v2.1.1/raphael.core.js#L1837
- // @author
- // Jarosław Foksa
- // @license
- // MIT License
- if (!SVGPathElement.prototype.getPathData || !SVGPathElement.prototype.setPathData) {
- (function () {
- var commandsMap = {
- "Z": "Z", "M": "M", "L": "L", "C": "C", "Q": "Q", "A": "A", "H": "H", "V": "V", "S": "S", "T": "T",
- "z": "Z", "m": "m", "l": "l", "c": "c", "q": "q", "a": "a", "h": "h", "v": "v", "s": "s", "t": "t"
- };
-
- var Source = function (string) {
- this._string = string;
- this._currentIndex = 0;
- this._endIndex = this._string.length;
- this._prevCommand = null;
- this._skipOptionalSpaces();
- };
-
- var isIE = window.navigator.userAgent.indexOf("MSIE ") !== -1;
-
- Source.prototype = {
- parseSegment: function () {
- var char = this._string[this._currentIndex];
- var command = commandsMap[char] ? commandsMap[char] : null;
-
- if (command === null) {
- // Possibly an implicit command. Not allowed if this is the first command.
- if (this._prevCommand === null) {
- return null;
- }
-
- // Check for remaining coordinates in the current command.
- if (
- (char === "+" || char === "-" || char === "." || (char >= "0" && char <= "9")) && this._prevCommand !== "Z"
- ) {
- if (this._prevCommand === "M") {
- command = "L";
- }
- else if (this._prevCommand === "m") {
- command = "l";
- }
- else {
- command = this._prevCommand;
- }
- }
- else {
- command = null;
- }
-
- if (command === null) {
- return null;
- }
- }
- else {
- this._currentIndex += 1;
- }
-
- this._prevCommand = command;
-
- var values = null;
- var cmd = command.toUpperCase();
-
- if (cmd === "H" || cmd === "V") {
- values = [this._parseNumber()];
- }
- else if (cmd === "M" || cmd === "L" || cmd === "T") {
- values = [this._parseNumber(), this._parseNumber()];
- }
- else if (cmd === "S" || cmd === "Q") {
- values = [this._parseNumber(), this._parseNumber(), this._parseNumber(), this._parseNumber()];
- }
- else if (cmd === "C") {
- values = [
- this._parseNumber(),
- this._parseNumber(),
- this._parseNumber(),
- this._parseNumber(),
- this._parseNumber(),
- this._parseNumber()
- ];
- }
- else if (cmd === "A") {
- values = [
- this._parseNumber(),
- this._parseNumber(),
- this._parseNumber(),
- this._parseArcFlag(),
- this._parseArcFlag(),
- this._parseNumber(),
- this._parseNumber()
- ];
- }
- else if (cmd === "Z") {
- this._skipOptionalSpaces();
- values = [];
- }
-
- if (values === null || values.indexOf(null) >= 0) {
- // Unknown command or known command with invalid values
- return null;
- }
- else {
- return { type: command, values: values };
- }
- },
-
- hasMoreData: function () {
- return this._currentIndex < this._endIndex;
- },
-
- peekSegmentType: function () {
- var char = this._string[this._currentIndex];
- return commandsMap[char] ? commandsMap[char] : null;
- },
-
- initialCommandIsMoveTo: function () {
- // If the path is empty it is still valid, so return true.
- if (!this.hasMoreData()) {
- return true;
- }
-
- var command = this.peekSegmentType();
- // Path must start with moveTo.
- return command === "M" || command === "m";
- },
-
- _isCurrentSpace: function () {
- var char = this._string[this._currentIndex];
- return char <= " " && (char === " " || char === "\n" || char === "\t" || char === "\r" || char === "\f");
- },
-
- _skipOptionalSpaces: function () {
- while (this._currentIndex < this._endIndex && this._isCurrentSpace()) {
- this._currentIndex += 1;
- }
-
- return this._currentIndex < this._endIndex;
- },
-
- _skipOptionalSpacesOrDelimiter: function () {
- if (
- this._currentIndex < this._endIndex &&
- !this._isCurrentSpace() &&
- this._string[this._currentIndex] !== ","
- ) {
- return false;
- }
-
- if (this._skipOptionalSpaces()) {
- if (this._currentIndex < this._endIndex && this._string[this._currentIndex] === ",") {
- this._currentIndex += 1;
- this._skipOptionalSpaces();
- }
- }
- return this._currentIndex < this._endIndex;
- },
-
- // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from
- // Source/core/svg/SVGParserUtilities.cpp.
- // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
- _parseNumber: function () {
- var exponent = 0;
- var integer = 0;
- var frac = 1;
- var decimal = 0;
- var sign = 1;
- var expsign = 1;
- var startIndex = this._currentIndex;
-
- this._skipOptionalSpaces();
-
- // Read the sign.
- if (this._currentIndex < this._endIndex && this._string[this._currentIndex] === "+") {
- this._currentIndex += 1;
- }
- else if (this._currentIndex < this._endIndex && this._string[this._currentIndex] === "-") {
- this._currentIndex += 1;
- sign = -1;
- }
-
- if (
- this._currentIndex === this._endIndex ||
- (
- (this._string[this._currentIndex] < "0" || this._string[this._currentIndex] > "9") &&
- this._string[this._currentIndex] !== "."
- )
- ) {
- // The first character of a number must be one of [0-9+-.].
- return null;
- }
-
- // Read the integer part, build right-to-left.
- var startIntPartIndex = this._currentIndex;
-
- while (
- this._currentIndex < this._endIndex &&
- this._string[this._currentIndex] >= "0" &&
- this._string[this._currentIndex] <= "9"
- ) {
- this._currentIndex += 1; // Advance to first non-digit.
- }
-
- if (this._currentIndex !== startIntPartIndex) {
- var scanIntPartIndex = this._currentIndex - 1;
- var multiplier = 1;
-
- while (scanIntPartIndex >= startIntPartIndex) {
- integer += multiplier * (this._string[scanIntPartIndex] - "0");
- scanIntPartIndex -= 1;
- multiplier *= 10;
- }
- }
-
- // Read the decimals.
- if (this._currentIndex < this._endIndex && this._string[this._currentIndex] === ".") {
- this._currentIndex += 1;
-
- // There must be a least one digit following the .
- if (
- this._currentIndex >= this._endIndex ||
- this._string[this._currentIndex] < "0" ||
- this._string[this._currentIndex] > "9"
- ) {
- return null;
- }
-
- while (
- this._currentIndex < this._endIndex &&
- this._string[this._currentIndex] >= "0" &&
- this._string[this._currentIndex] <= "9"
- ) {
- frac *= 10;
- decimal += (this._string.charAt(this._currentIndex) - "0") / frac;
- this._currentIndex += 1;
- }
- }
-
- // Read the exponent part.
- if (
- this._currentIndex !== startIndex &&
- this._currentIndex + 1 < this._endIndex &&
- (this._string[this._currentIndex] === "e" || this._string[this._currentIndex] === "E") &&
- (this._string[this._currentIndex + 1] !== "x" && this._string[this._currentIndex + 1] !== "m")
- ) {
- this._currentIndex += 1;
-
- // Read the sign of the exponent.
- if (this._string[this._currentIndex] === "+") {
- this._currentIndex += 1;
- }
- else if (this._string[this._currentIndex] === "-") {
- this._currentIndex += 1;
- expsign = -1;
- }
-
- // There must be an exponent.
- if (
- this._currentIndex >= this._endIndex ||
- this._string[this._currentIndex] < "0" ||
- this._string[this._currentIndex] > "9"
- ) {
- return null;
- }
-
- while (
- this._currentIndex < this._endIndex &&
- this._string[this._currentIndex] >= "0" &&
- this._string[this._currentIndex] <= "9"
- ) {
- exponent *= 10;
- exponent += (this._string[this._currentIndex] - "0");
- this._currentIndex += 1;
- }
- }
-
- var number = integer + decimal;
- number *= sign;
-
- if (exponent) {
- number *= Math.pow(10, expsign * exponent);
- }
-
- if (startIndex === this._currentIndex) {
- return null;
- }
-
- this._skipOptionalSpacesOrDelimiter();
-
- return number;
- },
-
- _parseArcFlag: function () {
- if (this._currentIndex >= this._endIndex) {
- return null;
- }
-
- var flag = null;
- var flagChar = this._string[this._currentIndex];
-
- this._currentIndex += 1;
-
- if (flagChar === "0") {
- flag = 0;
- }
- else if (flagChar === "1") {
- flag = 1;
- }
- else {
- return null;
- }
-
- this._skipOptionalSpacesOrDelimiter();
- return flag;
- }
- };
-
- var parsePathDataString = function (string) {
- if (!string || string.length === 0) return [];
-
- var source = new Source(string);
- var pathData = [];
-
- if (source.initialCommandIsMoveTo()) {
- while (source.hasMoreData()) {
- var pathSeg = source.parseSegment();
-
- if (pathSeg === null) {
- break;
- }
- else {
- pathData.push(pathSeg);
- }
- }
- }
-
- return pathData;
- }
-
- var setAttribute = SVGPathElement.prototype.setAttribute;
- var removeAttribute = SVGPathElement.prototype.removeAttribute;
-
- var $cachedPathData = window.Symbol ? Symbol() : "__cachedPathData";
- var $cachedNormalizedPathData = window.Symbol ? Symbol() : "__cachedNormalizedPathData";
-
- // @info
- // Get an array of corresponding cubic bezier curve parameters for given arc curve paramters.
- var arcToCubicCurves = function (x1, y1, x2, y2, r1, r2, angle, largeArcFlag, sweepFlag, _recursive) {
- var degToRad = function (degrees) {
- return (Math.PI * degrees) / 180;
- };
-
- var rotate = function (x, y, angleRad) {
- var X = x * Math.cos(angleRad) - y * Math.sin(angleRad);
- var Y = x * Math.sin(angleRad) + y * Math.cos(angleRad);
- return { x: X, y: Y };
- };
-
- var angleRad = degToRad(angle);
- var params = [];
- var f1, f2, cx, cy;
-
- if (_recursive) {
- f1 = _recursive[0];
- f2 = _recursive[1];
- cx = _recursive[2];
- cy = _recursive[3];
- }
- else {
- var p1 = rotate(x1, y1, -angleRad);
- x1 = p1.x;
- y1 = p1.y;
-
- var p2 = rotate(x2, y2, -angleRad);
- x2 = p2.x;
- y2 = p2.y;
-
- var x = (x1 - x2) / 2;
- var y = (y1 - y2) / 2;
- var h = (x * x) / (r1 * r1) + (y * y) / (r2 * r2);
-
- if (h > 1) {
- h = Math.sqrt(h);
- r1 = h * r1;
- r2 = h * r2;
- }
-
- var sign;
-
- if (largeArcFlag === sweepFlag) {
- sign = -1;
- }
- else {
- sign = 1;
- }
-
- var r1Pow = r1 * r1;
- var r2Pow = r2 * r2;
-
- var left = r1Pow * r2Pow - r1Pow * y * y - r2Pow * x * x;
- var right = r1Pow * y * y + r2Pow * x * x;
-
- var k = sign * Math.sqrt(Math.abs(left / right));
-
- cx = k * r1 * y / r2 + (x1 + x2) / 2;
- cy = k * -r2 * x / r1 + (y1 + y2) / 2;
-
- f1 = Math.asin(parseFloat(((y1 - cy) / r2).toFixed(9)));
- f2 = Math.asin(parseFloat(((y2 - cy) / r2).toFixed(9)));
-
- if (x1 < cx) {
- f1 = Math.PI - f1;
- }
- if (x2 < cx) {
- f2 = Math.PI - f2;
- }
-
- if (f1 < 0) {
- f1 = Math.PI * 2 + f1;
- }
- if (f2 < 0) {
- f2 = Math.PI * 2 + f2;
- }
-
- if (sweepFlag && f1 > f2) {
- f1 = f1 - Math.PI * 2;
- }
- if (!sweepFlag && f2 > f1) {
- f2 = f2 - Math.PI * 2;
- }
- }
-
- var df = f2 - f1;
-
- if (Math.abs(df) > (Math.PI * 120 / 180)) {
- var f2old = f2;
- var x2old = x2;
- var y2old = y2;
-
- if (sweepFlag && f2 > f1) {
- f2 = f1 + (Math.PI * 120 / 180) * (1);
- }
- else {
- f2 = f1 + (Math.PI * 120 / 180) * (-1);
- }
-
- x2 = cx + r1 * Math.cos(f2);
- y2 = cy + r2 * Math.sin(f2);
- params = arcToCubicCurves(x2, y2, x2old, y2old, r1, r2, angle, 0, sweepFlag, [f2, f2old, cx, cy]);
- }
-
- df = f2 - f1;
-
- var c1 = Math.cos(f1);
- var s1 = Math.sin(f1);
- var c2 = Math.cos(f2);
- var s2 = Math.sin(f2);
- var t = Math.tan(df / 4);
- var hx = 4 / 3 * r1 * t;
- var hy = 4 / 3 * r2 * t;
-
- var m1 = [x1, y1];
- var m2 = [x1 + hx * s1, y1 - hy * c1];
- var m3 = [x2 + hx * s2, y2 - hy * c2];
- var m4 = [x2, y2];
-
- m2[0] = 2 * m1[0] - m2[0];
- m2[1] = 2 * m1[1] - m2[1];
-
- if (_recursive) {
- return [m2, m3, m4].concat(params);
- }
- else {
- params = [m2, m3, m4].concat(params);
-
- var curves = [];
-
- for (var i = 0; i < params.length; i += 3) {
- var r1 = rotate(params[i][0], params[i][1], angleRad);
- var r2 = rotate(params[i + 1][0], params[i + 1][1], angleRad);
- var r3 = rotate(params[i + 2][0], params[i + 2][1], angleRad);
- curves.push([r1.x, r1.y, r2.x, r2.y, r3.x, r3.y]);
- }
-
- return curves;
- }
- };
-
- var clonePathData = function (pathData) {
- return pathData.map(function (seg) {
- return { type: seg.type, values: Array.prototype.slice.call(seg.values) }
- });
- };
-
- // @info
- // Takes any path data, returns path data that consists only from absolute commands.
- var absolutizePathData = function (pathData) {
- var absolutizedPathData = [];
-
- var currentX = null;
- var currentY = null;
-
- var subpathX = null;
- var subpathY = null;
-
- pathData.forEach(function (seg) {
- var type = seg.type;
-
- if (type === "M") {
- var x = seg.values[0];
- var y = seg.values[1];
-
- absolutizedPathData.push({ type: "M", values: [x, y] });
-
- subpathX = x;
- subpathY = y;
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "m") {
- var x = currentX + seg.values[0];
- var y = currentY + seg.values[1];
-
- absolutizedPathData.push({ type: "M", values: [x, y] });
-
- subpathX = x;
- subpathY = y;
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "L") {
- var x = seg.values[0];
- var y = seg.values[1];
-
- absolutizedPathData.push({ type: "L", values: [x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "l") {
- var x = currentX + seg.values[0];
- var y = currentY + seg.values[1];
-
- absolutizedPathData.push({ type: "L", values: [x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "C") {
- var x1 = seg.values[0];
- var y1 = seg.values[1];
- var x2 = seg.values[2];
- var y2 = seg.values[3];
- var x = seg.values[4];
- var y = seg.values[5];
-
- absolutizedPathData.push({ type: "C", values: [x1, y1, x2, y2, x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "c") {
- var x1 = currentX + seg.values[0];
- var y1 = currentY + seg.values[1];
- var x2 = currentX + seg.values[2];
- var y2 = currentY + seg.values[3];
- var x = currentX + seg.values[4];
- var y = currentY + seg.values[5];
-
- absolutizedPathData.push({ type: "C", values: [x1, y1, x2, y2, x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "Q") {
- var x1 = seg.values[0];
- var y1 = seg.values[1];
- var x = seg.values[2];
- var y = seg.values[3];
-
- absolutizedPathData.push({ type: "Q", values: [x1, y1, x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "q") {
- var x1 = currentX + seg.values[0];
- var y1 = currentY + seg.values[1];
- var x = currentX + seg.values[2];
- var y = currentY + seg.values[3];
-
- absolutizedPathData.push({ type: "Q", values: [x1, y1, x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "A") {
- var x = seg.values[5];
- var y = seg.values[6];
-
- absolutizedPathData.push({
- type: "A",
- values: [seg.values[0], seg.values[1], seg.values[2], seg.values[3], seg.values[4], x, y]
- });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "a") {
- var x = currentX + seg.values[5];
- var y = currentY + seg.values[6];
-
- absolutizedPathData.push({
- type: "A",
- values: [seg.values[0], seg.values[1], seg.values[2], seg.values[3], seg.values[4], x, y]
- });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "H") {
- var x = seg.values[0];
- absolutizedPathData.push({ type: "H", values: [x] });
- currentX = x;
- }
-
- else if (type === "h") {
- var x = currentX + seg.values[0];
- absolutizedPathData.push({ type: "H", values: [x] });
- currentX = x;
- }
-
- else if (type === "V") {
- var y = seg.values[0];
- absolutizedPathData.push({ type: "V", values: [y] });
- currentY = y;
- }
-
- else if (type === "v") {
- var y = currentY + seg.values[0];
- absolutizedPathData.push({ type: "V", values: [y] });
- currentY = y;
- }
-
- else if (type === "S") {
- var x2 = seg.values[0];
- var y2 = seg.values[1];
- var x = seg.values[2];
- var y = seg.values[3];
-
- absolutizedPathData.push({ type: "S", values: [x2, y2, x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "s") {
- var x2 = currentX + seg.values[0];
- var y2 = currentY + seg.values[1];
- var x = currentX + seg.values[2];
- var y = currentY + seg.values[3];
-
- absolutizedPathData.push({ type: "S", values: [x2, y2, x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "T") {
- var x = seg.values[0];
- var y = seg.values[1]
-
- absolutizedPathData.push({ type: "T", values: [x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "t") {
- var x = currentX + seg.values[0];
- var y = currentY + seg.values[1]
-
- absolutizedPathData.push({ type: "T", values: [x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (type === "Z" || type === "z") {
- absolutizedPathData.push({ type: "Z", values: [] });
-
- currentX = subpathX;
- currentY = subpathY;
- }
- });
-
- return absolutizedPathData;
- };
-
- // @info
- // Takes path data that consists only from absolute commands, returns path data that consists only from
- // "M", "L", "C" and "Z" commands.
- var reducePathData = function (pathData) {
- var reducedPathData = [];
- var lastType = null;
-
- var lastControlX = null;
- var lastControlY = null;
-
- var currentX = null;
- var currentY = null;
-
- var subpathX = null;
- var subpathY = null;
-
- pathData.forEach(function (seg) {
- if (seg.type === "M") {
- var x = seg.values[0];
- var y = seg.values[1];
-
- reducedPathData.push({ type: "M", values: [x, y] });
-
- subpathX = x;
- subpathY = y;
-
- currentX = x;
- currentY = y;
- }
-
- else if (seg.type === "C") {
- var x1 = seg.values[0];
- var y1 = seg.values[1];
- var x2 = seg.values[2];
- var y2 = seg.values[3];
- var x = seg.values[4];
- var y = seg.values[5];
-
- reducedPathData.push({ type: "C", values: [x1, y1, x2, y2, x, y] });
-
- lastControlX = x2;
- lastControlY = y2;
-
- currentX = x;
- currentY = y;
- }
-
- else if (seg.type === "L") {
- var x = seg.values[0];
- var y = seg.values[1];
-
- reducedPathData.push({ type: "L", values: [x, y] });
-
- currentX = x;
- currentY = y;
- }
-
- else if (seg.type === "H") {
- var x = seg.values[0];
-
- reducedPathData.push({ type: "L", values: [x, currentY] });
-
- currentX = x;
- }
-
- else if (seg.type === "V") {
- var y = seg.values[0];
-
- reducedPathData.push({ type: "L", values: [currentX, y] });
-
- currentY = y;
- }
-
- else if (seg.type === "S") {
- var x2 = seg.values[0];
- var y2 = seg.values[1];
- var x = seg.values[2];
- var y = seg.values[3];
-
- var cx1, cy1;
-
- if (lastType === "C" || lastType === "S") {
- cx1 = currentX + (currentX - lastControlX);
- cy1 = currentY + (currentY - lastControlY);
- }
- else {
- cx1 = currentX;
- cy1 = currentY;
- }
-
- reducedPathData.push({ type: "C", values: [cx1, cy1, x2, y2, x, y] });
-
- lastControlX = x2;
- lastControlY = y2;
-
- currentX = x;
- currentY = y;
- }
-
- else if (seg.type === "T") {
- var x = seg.values[0];
- var y = seg.values[1];
-
- var x1, y1;
-
- if (lastType === "Q" || lastType === "T") {
- x1 = currentX + (currentX - lastControlX);
- y1 = currentY + (currentY - lastControlY);
- }
- else {
- x1 = currentX;
- y1 = currentY;
- }
-
- var cx1 = currentX + 2 * (x1 - currentX) / 3;
- var cy1 = currentY + 2 * (y1 - currentY) / 3;
- var cx2 = x + 2 * (x1 - x) / 3;
- var cy2 = y + 2 * (y1 - y) / 3;
-
- reducedPathData.push({ type: "C", values: [cx1, cy1, cx2, cy2, x, y] });
-
- lastControlX = x1;
- lastControlY = y1;
-
- currentX = x;
- currentY = y;
- }
-
- else if (seg.type === "Q") {
- var x1 = seg.values[0];
- var y1 = seg.values[1];
- var x = seg.values[2];
- var y = seg.values[3];
-
- var cx1 = currentX + 2 * (x1 - currentX) / 3;
- var cy1 = currentY + 2 * (y1 - currentY) / 3;
- var cx2 = x + 2 * (x1 - x) / 3;
- var cy2 = y + 2 * (y1 - y) / 3;
-
- reducedPathData.push({ type: "C", values: [cx1, cy1, cx2, cy2, x, y] });
-
- lastControlX = x1;
- lastControlY = y1;
-
- currentX = x;
- currentY = y;
- }
-
- else if (seg.type === "A") {
- var r1 = Math.abs(seg.values[0]);
- var r2 = Math.abs(seg.values[1]);
- var angle = seg.values[2];
- var largeArcFlag = seg.values[3];
- var sweepFlag = seg.values[4];
- var x = seg.values[5];
- var y = seg.values[6];
-
- if (r1 === 0 || r2 === 0) {
- reducedPathData.push({ type: "C", values: [currentX, currentY, x, y, x, y] });
-
- currentX = x;
- currentY = y;
- }
- else {
- if (currentX !== x || currentY !== y) {
- var curves = arcToCubicCurves(currentX, currentY, x, y, r1, r2, angle, largeArcFlag, sweepFlag);
-
- curves.forEach(function (curve) {
- reducedPathData.push({ type: "C", values: curve });
- });
-
- currentX = x;
- currentY = y;
- }
- }
- }
-
- else if (seg.type === "Z") {
- reducedPathData.push(seg);
-
- currentX = subpathX;
- currentY = subpathY;
- }
-
- lastType = seg.type;
- });
-
- return reducedPathData;
- };
-
- SVGPathElement.prototype.setAttribute = function (name, value) {
- if (name === "d") {
- this[$cachedPathData] = null;
- this[$cachedNormalizedPathData] = null;
- }
-
- setAttribute.call(this, name, value);
- };
-
- SVGPathElement.prototype.removeAttribute = function (name, value) {
- if (name === "d") {
- this[$cachedPathData] = null;
- this[$cachedNormalizedPathData] = null;
- }
-
- removeAttribute.call(this, name);
- };
-
- SVGPathElement.prototype.getPathData = function (options) {
- if (options && options.normalize) {
- if (this[$cachedNormalizedPathData]) {
- return clonePathData(this[$cachedNormalizedPathData]);
- }
- else {
- var pathData;
-
- if (this[$cachedPathData]) {
- pathData = clonePathData(this[$cachedPathData]);
- }
- else {
- pathData = parsePathDataString(this.getAttribute("d") || "");
- this[$cachedPathData] = clonePathData(pathData);
- }
-
- var normalizedPathData = reducePathData(absolutizePathData(pathData));
- this[$cachedNormalizedPathData] = clonePathData(normalizedPathData);
- return normalizedPathData;
- }
- }
- else {
- if (this[$cachedPathData]) {
- return clonePathData(this[$cachedPathData]);
- }
- else {
- var pathData = parsePathDataString(this.getAttribute("d") || "");
- this[$cachedPathData] = clonePathData(pathData);
- return pathData;
- }
- }
- };
-
- SVGPathElement.prototype.setPathData = function (pathData) {
- if (pathData.length === 0) {
- if (isIE) {
- // @bugfix https://github.com/mbostock/d3/issues/1737
- this.setAttribute("d", "");
- }
- else {
- this.removeAttribute("d");
- }
- }
- else {
- var d = "";
-
- for (var i = 0, l = pathData.length; i < l; i += 1) {
- var seg = pathData[i];
-
- if (i > 0) {
- d += " ";
- }
-
- d += seg.type;
-
- if (seg.values && seg.values.length > 0) {
- d += " " + seg.values.join(" ");
- }
- }
-
- this.setAttribute("d", d);
- }
- };
-
- SVGRectElement.prototype.getPathData = function (options) {
- var x = this.x.baseVal.value;
- var y = this.y.baseVal.value;
- var width = this.width.baseVal.value;
- var height = this.height.baseVal.value;
- var rx = this.hasAttribute("rx") ? this.rx.baseVal.value : this.ry.baseVal.value;
- var ry = this.hasAttribute("ry") ? this.ry.baseVal.value : this.rx.baseVal.value;
-
- if (rx > width / 2) {
- rx = width / 2;
- }
-
- if (ry > height / 2) {
- ry = height / 2;
- }
-
- var pathData = [
- { type: "M", values: [x + rx, y] },
- { type: "H", values: [x + width - rx] },
- { type: "A", values: [rx, ry, 0, 0, 1, x + width, y + ry] },
- { type: "V", values: [y + height - ry] },
- { type: "A", values: [rx, ry, 0, 0, 1, x + width - rx, y + height] },
- { type: "H", values: [x + rx] },
- { type: "A", values: [rx, ry, 0, 0, 1, x, y + height - ry] },
- { type: "V", values: [y + ry] },
- { type: "A", values: [rx, ry, 0, 0, 1, x + rx, y] },
- { type: "Z", values: [] }
- ];
-
- // Get rid of redundant "A" segs when either rx or ry is 0
- pathData = pathData.filter(function (s) {
- return s.type === "A" && (s.values[0] === 0 || s.values[1] === 0) ? false : true;
- });
-
- if (options && options.normalize === true) {
- pathData = reducePathData(pathData);
- }
-
- return pathData;
- };
-
- SVGCircleElement.prototype.getPathData = function (options) {
- var cx = this.cx.baseVal.value;
- var cy = this.cy.baseVal.value;
- var r = this.r.baseVal.value;
-
- var pathData = [
- { type: "M", values: [cx + r, cy] },
- { type: "A", values: [r, r, 0, 0, 1, cx, cy + r] },
- { type: "A", values: [r, r, 0, 0, 1, cx - r, cy] },
- { type: "A", values: [r, r, 0, 0, 1, cx, cy - r] },
- { type: "A", values: [r, r, 0, 0, 1, cx + r, cy] },
- { type: "Z", values: [] }
- ];
-
- if (options && options.normalize === true) {
- pathData = reducePathData(pathData);
- }
-
- return pathData;
- };
-
- SVGEllipseElement.prototype.getPathData = function (options) {
- var cx = this.cx.baseVal.value;
- var cy = this.cy.baseVal.value;
- var rx = this.rx.baseVal.value;
- var ry = this.ry.baseVal.value;
-
- var pathData = [
- { type: "M", values: [cx + rx, cy] },
- { type: "A", values: [rx, ry, 0, 0, 1, cx, cy + ry] },
- { type: "A", values: [rx, ry, 0, 0, 1, cx - rx, cy] },
- { type: "A", values: [rx, ry, 0, 0, 1, cx, cy - ry] },
- { type: "A", values: [rx, ry, 0, 0, 1, cx + rx, cy] },
- { type: "Z", values: [] }
- ];
-
- if (options && options.normalize === true) {
- pathData = reducePathData(pathData);
- }
-
- return pathData;
- };
-
- SVGLineElement.prototype.getPathData = function () {
- return [
- { type: "M", values: [this.x1.baseVal.value, this.y1.baseVal.value] },
- { type: "L", values: [this.x2.baseVal.value, this.y2.baseVal.value] }
- ];
- };
-
- SVGPolylineElement.prototype.getPathData = function () {
- var pathData = [];
-
- for (var i = 0; i < this.points.numberOfItems; i += 1) {
- var point = this.points.getItem(i);
-
- pathData.push({
- type: (i === 0 ? "M" : "L"),
- values: [point.x, point.y]
- });
- }
-
- return pathData;
- };
-
- SVGPolygonElement.prototype.getPathData = function () {
- var pathData = [];
-
- for (var i = 0; i < this.points.numberOfItems; i += 1) {
- var point = this.points.getItem(i);
-
- pathData.push({
- type: (i === 0 ? "M" : "L"),
- values: [point.x, point.y]
- });
- }
-
- pathData.push({
- type: "Z",
- values: []
- });
-
- return pathData;
- };
- })();
- }
|