diff options
author | wout <wout@impinc.co.uk> | 2014-02-14 22:25:12 +0100 |
---|---|---|
committer | wout <wout@impinc.co.uk> | 2014-02-14 22:25:12 +0100 |
commit | 8f9ccb16300142307b8ed6aed46c2a4984545600 (patch) | |
tree | 77040e5aa3802c7890d67aa0a62cdff432c2359f /src/patharray.js | |
parent | a7d61df3e8e065599c42752d60bb2f0190395080 (diff) | |
download | svg.js-8f9ccb16300142307b8ed6aed46c2a4984545600.tar.gz svg.js-8f9ccb16300142307b8ed6aed46c2a4984545600.zip |
Completely reworked `SVG.Text`, `SVG.TSpan` and `SVG.PathArray` and bumped to 1.0.0-rc.5
Diffstat (limited to 'src/patharray.js')
-rwxr-xr-x[-rw-r--r--] | src/patharray.js | 337 |
1 files changed, 142 insertions, 195 deletions
diff --git a/src/patharray.js b/src/patharray.js index 314f53e..2ccb7d5 100644..100755 --- a/src/patharray.js +++ b/src/patharray.js @@ -9,48 +9,7 @@ SVG.PathArray.prototype = new SVG.Array SVG.extend(SVG.PathArray, { // Convert array to string toString: function() { - for (var s, i = 0, il = this.value.length, array = []; i < il; i++) { - s = [this.value[i].type] - - switch(this.value[i].type) { - case 'H': - s.push(this.value[i].x) - break - case 'V': - s.push(this.value[i].y) - break - case 'M': - case 'L': - case 'T': - case 'S': - case 'Q': - case 'C': - if (/[QC]/.test(this.value[i].type)) - s.push(this.value[i].x1, this.value[i].y1) - if (/[CS]/.test(this.value[i].type)) - s.push(this.value[i].x2, this.value[i].y2) - - s.push(this.value[i].x, this.value[i].y) - - break - case 'A': - s.push( - this.value[i].r1 - , this.value[i].r2 - , this.value[i].a - , this.value[i].l - , this.value[i].s - , this.value[i].x - , this.value[i].y - ) - break - } - - /* add to array */ - array.push(s.join(' ')) - } - - return array.join(' ') + return arrayToString(this.value) } // Move path string , move: function(x, y) { @@ -63,45 +22,35 @@ SVG.extend(SVG.PathArray, { if (!isNaN(x) && !isNaN(y)) { /* move every point */ - for (var i = this.value.length - 1; i >= 0; i--) { - switch (this.value[i].type) { - case 'H': - /* move along x axis only */ - this.value[i].x += x - break - case 'V': - /* move along y axis only */ - this.value[i].y += y - break - case 'M': - case 'L': - case 'T': - case 'S': - case 'Q': - case 'C': - /* move first point along x and y axes */ - this.value[i].x += x - this.value[i].y += y - - /* move third points along x and y axes */ - if (/[CQ]/.test(this.value[i].type)) { - this.value[i].x1 += x - this.value[i].y1 += y - } + for (var l, i = this.value.length - 1; i >= 0; i--) { + l = this.value[i][0] - /* move second points along x and y axes */ - if (/[CS]/.test(this.value[i].type)) { - this.value[i].x2 += x - this.value[i].y2 += y - } + if (l == 'M' || l == 'L' || l == 'T') { + this.value[i][1] += x + this.value[i][2] += y + + } else if (l == 'H') { + this.value[i][1] += x + + } else if (l == 'V') { + this.value[i][1] += y + + } else if (l == 'C' || l == 'S' || l == 'Q') { + this.value[i][1] += x + this.value[i][2] += y + this.value[i][3] += x + this.value[i][4] += y + + if (l == 'C') { + this.value[i][5] += x + this.value[i][6] += y + } - break - case 'A': - /* only move position values */ - this.value[i].x += x - this.value[i].y += y - break + } else if (l == 'A') { + this.value[i][6] += x + this.value[i][7] += y } + } } @@ -110,61 +59,51 @@ SVG.extend(SVG.PathArray, { // Resize path string , size: function(width, height) { /* get bounding box of current situation */ - var box = this.bbox() + var i, l, box = this.bbox() /* recalculate position of all points according to new size */ - for (var i = this.value.length - 1; i >= 0; i--) { - switch (this.value[i].type) { - case 'H': - /* move along x axis only */ - this.value[i].x = ((this.value[i].x - box.x) * width) / box.width + box.x - break - case 'V': - /* move along y axis only */ - this.value[i].y = ((this.value[i].y - box.y) * height) / box.height + box.y - break - case 'M': - case 'L': - case 'T': - case 'S': - case 'Q': - case 'C': - this.value[i].x = ((this.value[i].x - box.x) * width) / box.width + box.x - this.value[i].y = ((this.value[i].y - box.y) * height) / box.height + box.y - - /* move third points along x and y axes */ - if (/[CQ]/.test(this.value[i].type)) { - this.value[i].x1 = ((this.value[i].x1 - box.x) * width) / box.width + box.x - this.value[i].y1 = ((this.value[i].y1 - box.y) * height) / box.height + box.y - } + for (i = this.value.length - 1; i >= 0; i--) { + l = this.value[i][0] - /* move second points along x and y axes */ - if (/[CS]/.test(this.value[i].type)) { - this.value[i].x2 = ((this.value[i].x2 - box.x) * width) / box.width + box.x - this.value[i].y2 = ((this.value[i].y2 - box.y) * height) / box.height + box.y - } + if (l == 'M' || l == 'L' || l == 'T') { + this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x + this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y + + } else if (l == 'H') { + this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x + + } else if (l == 'V') { + this.value[i][1] = ((this.value[i][1] - box.y) * height) / box.height + box.y - break - case 'A': - /* resize radii */ - this.value[i].values.r1 = (this.value[i].values.r1 * width) / box.width - this.value[i].values.r2 = (this.value[i].values.r2 * height) / box.height + } else if (l == 'C' || l == 'S' || l == 'Q') { + this.value[i][1] = ((this.value[i][1] - box.x) * width) / box.width + box.x + this.value[i][2] = ((this.value[i][2] - box.y) * height) / box.height + box.y + this.value[i][3] = ((this.value[i][3] - box.x) * width) / box.width + box.x + this.value[i][4] = ((this.value[i][4] - box.y) * height) / box.height + box.y - /* move position values */ - this.value[i].values.x = ((this.value[i].values.x - box.x) * width) / box.width + box.x - this.value[i].values.y = ((this.value[i].values.y - box.y) * height) / box.height + box.y - break + if (l == 'C') { + this.value[i][5] = ((this.value[i][5] - box.x) * width) / box.width + box.x + this.value[i][6] = ((this.value[i][6] - box.y) * height) / box.height + box.y + } + + } else if (l == 'A') { + /* resize radii */ + this.value[i][1] = (this.value[i][1] * width) / box.width + this.value[i][2] = (this.value[i][2] * height) / box.height + + /* move position values */ + this.value[i][6] = ((this.value[i][6] - box.x) * width) / box.width + box.x + this.value[i][7] = ((this.value[i][7] - box.y) * height) / box.height + box.y } + } return this } // Absolutize and parse path to array , parse: function(array) { - array = array.valueOf() - - /* if already is an array, no need to parse it */ - if (Array.isArray(array)) return array + /* if it's already is a patharray, no need to parse it */ + if (array instanceof SVG.PathArray) return array.valueOf() /* prepare for parsing */ var i, il, x0, y0, x1, y1, x2, y2, s, seg, segs @@ -172,7 +111,7 @@ SVG.extend(SVG.PathArray, { , y = 0 /* populate working path */ - SVG.parser.path.setAttribute('d', array) + SVG.parser.path.setAttribute('d', typeof array === 'string' ? array : arrayToString(array)) /* get segments */ segs = SVG.parser.path.pathSegList @@ -181,7 +120,8 @@ SVG.extend(SVG.PathArray, { seg = segs.getItem(i) s = seg.pathSegTypeAsLetter - if (/[MLHVCSQTA]/.test(s)) { + /* yes, this IS quite verbose but also about 30 times faster than .test() with a precompiled regex */ + if (s == 'M' || s == 'L' || s == 'H' || s == 'V' || s == 'C' || s == 'S' || s == 'Q' || s == 'T' || s == 'A') { if ('x' in seg) x = seg.x if ('y' in seg) y = seg.y @@ -193,44 +133,32 @@ SVG.extend(SVG.PathArray, { if ('x' in seg) x += seg.x if ('y' in seg) y += seg.y - switch(s){ - case 'm': - segs.replaceItem(SVG.parser.path.createSVGPathSegMovetoAbs(x, y), i) - break - case 'l': - segs.replaceItem(SVG.parser.path.createSVGPathSegLinetoAbs(x, y), i) - break - case 'h': - segs.replaceItem(SVG.parser.path.createSVGPathSegLinetoHorizontalAbs(x), i) - break - case 'v': - segs.replaceItem(SVG.parser.path.createSVGPathSegLinetoVerticalAbs(y), i) - break - case 'c': - segs.replaceItem(SVG.parser.path.createSVGPathSegCurvetoCubicAbs(x, y, x1, y1, x2, y2), i) - break - case 's': - segs.replaceItem(SVG.parser.path.createSVGPathSegCurvetoCubicSmoothAbs(x, y, x2, y2), i) - break - case 'q': - segs.replaceItem(SVG.parser.path.createSVGPathSegCurvetoQuadraticAbs(x, y, x1, y1), i) - break - case 't': - segs.replaceItem(SVG.parser.path.createSVGPathSegCurvetoQuadraticSmoothAbs(x, y), i) - break - case 'a': - segs.replaceItem(SVG.parser.path.createSVGPathSegArcAbs(x, y, seg.r1, seg.r2, seg.angle, seg.largeArcFlag, seg.sweepFlag), i) - break - case 'z': - case 'Z': - x = x0 - y = y0 - break + if (s == 'm') + segs.replaceItem(SVG.parser.path.createSVGPathSegMovetoAbs(x, y), i) + else if (s == 'l') + segs.replaceItem(SVG.parser.path.createSVGPathSegLinetoAbs(x, y), i) + else if (s == 'h') + segs.replaceItem(SVG.parser.path.createSVGPathSegLinetoHorizontalAbs(x), i) + else if (s == 'v') + segs.replaceItem(SVG.parser.path.createSVGPathSegLinetoVerticalAbs(y), i) + else if (s == 'c') + segs.replaceItem(SVG.parser.path.createSVGPathSegCurvetoCubicAbs(x, y, x1, y1, x2, y2), i) + else if (s == 's') + segs.replaceItem(SVG.parser.path.createSVGPathSegCurvetoCubicSmoothAbs(x, y, x2, y2), i) + else if (s == 'q') + segs.replaceItem(SVG.parser.path.createSVGPathSegCurvetoQuadraticAbs(x, y, x1, y1), i) + else if (s == 't') + segs.replaceItem(SVG.parser.path.createSVGPathSegCurvetoQuadraticSmoothAbs(x, y), i) + else if (s == 'a') + segs.replaceItem(SVG.parser.path.createSVGPathSegArcAbs(x, y, seg.r1, seg.r2, seg.angle, seg.largeArcFlag, seg.sweepFlag), i) + else if (s == 'z' || s == 'Z') { + x = x0 + y = y0 } } /* record the start of a subpath */ - if (/[Mm]/.test(s)) { + if (s == 'M' || s == 'm') { x0 = x y0 = y } @@ -238,48 +166,30 @@ SVG.extend(SVG.PathArray, { /* build internal representation */ array = [] - segs = SVG.parser.path.pathSegList + segs = SVG.parser.path.pathSegList for (i = 0, il = segs.numberOfItems; i < il; ++i) { seg = segs.getItem(i) - s = {} - - switch (seg.pathSegTypeAsLetter) { - case 'M': - case 'L': - case 'T': - case 'S': - case 'Q': - case 'C': - if (/[QC]/.test(seg.pathSegTypeAsLetter)) { - s.x1 = seg.x1 - s.y1 = seg.y1 - } - - if (/[SC]/.test(seg.pathSegTypeAsLetter)) { - s.x2 = seg.x2 - s.y2 = seg.y2 - } - - break - case 'A': - s = { - r1: seg.r1 - , r2: seg.r2 - , a: seg.angle - , l: seg.largeArcFlag|0 - , s: seg.sweepFlag|0 - } - break - } - - /* make the letter, x and y values accessible as key/values */ - s.type = seg.pathSegTypeAsLetter - s.x = seg.x - s.y = seg.y + s = seg.pathSegTypeAsLetter + x = [s] + + if (s == 'M' || s == 'L' || s == 'T') + x.push(seg.x, seg.y) + else if (s == 'H') + x.push(seg.x) + else if (s == 'V') + x.push(seg.y) + else if (s == 'C') + x.push(seg.x1, seg.y1, seg.x2, seg.y2, seg.x, seg.y) + else if (s == 'S') + x.push(seg.x2, seg.y2, seg.x, seg.y) + else if (s == 'Q') + x.push(seg.x1, seg.y1, seg.x, seg.y) + else if (s == 'A') + x.push(seg.r1, seg.r2, seg.angle, seg.largeArcFlag|0, seg.sweepFlag|0, seg.x, seg.y) /* store segment */ - array.push(s) + array.push(x) } return array @@ -291,4 +201,41 @@ SVG.extend(SVG.PathArray, { return SVG.parser.path.getBBox() } -})
\ No newline at end of file +}) + +// PathArray Helpers +function arrayToString(a) { + for (var i = 0, il = a.length, s = ''; i < il; i++) { + s += a[i][0] + + if (a[i][1] != null) { + s += a[i][1] + + if (a[i][2] != null) { + s += ' ' + s += a[i][2] + + if (a[i][3] != null) { + s += ' ' + s += a[i][3] + s += ' ' + s += a[i][4] + + if (a[i][5] != null) { + s += ' ' + s += a[i][5] + s += ' ' + s += a[i][6] + + if (a[i][7] != null) { + s += ' ' + s += a[i][7] + } + } + } + } + } + } + + return s + ' ' +}
\ No newline at end of file |