summaryrefslogtreecommitdiffstats
path: root/src/patharray.js
diff options
context:
space:
mode:
authorwout <wout@impinc.co.uk>2014-02-14 22:25:12 +0100
committerwout <wout@impinc.co.uk>2014-02-14 22:25:12 +0100
commit8f9ccb16300142307b8ed6aed46c2a4984545600 (patch)
tree77040e5aa3802c7890d67aa0a62cdff432c2359f /src/patharray.js
parenta7d61df3e8e065599c42752d60bb2f0190395080 (diff)
downloadsvg.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.js337
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