mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-03 19:45:44 -05:00
Improve SVG path data parser.
This commit is contained in:
parent
c99d13178b
commit
97a29e6ada
1 changed files with 13 additions and 31 deletions
|
@ -85,25 +85,16 @@ var PathItem = Item.extend(/** @lends PathItem# */{
|
|||
// This is a very compact SVG Path Data parser that works both for Path
|
||||
// and CompoundPath.
|
||||
|
||||
var parts = data.match(/[a-z][^a-z]*/ig),
|
||||
// First split the path data into parts of command-coordinates pairs
|
||||
// Commands are any of these characters: mzlhvcsqta
|
||||
var parts = data.match(/[mzlhvcsqta][^mzlhvcsqta]*/ig),
|
||||
coords,
|
||||
coordsLength,
|
||||
relative = false,
|
||||
control,
|
||||
current = new Point(); // the current position
|
||||
|
||||
function getCoord(index, coord, update) {
|
||||
var val = coords[index];
|
||||
// Before parsing the value, we might actually have to further split
|
||||
// it, in case it contains two '.':
|
||||
var match = val.match(/^([+-]?\d*\.\d+)(\.\d*)$/);
|
||||
if (match) {
|
||||
// Insert the 2nd half as the next value.
|
||||
coords.splice(index + 1, 0, match[2]);
|
||||
coordsLength++;
|
||||
val = match[1];
|
||||
}
|
||||
val = parseFloat(val);
|
||||
var val = parseFloat(coords[index]);
|
||||
if (relative)
|
||||
val += current[coord];
|
||||
if (update)
|
||||
|
@ -125,36 +116,27 @@ var PathItem = Item.extend(/** @lends PathItem# */{
|
|||
var part = parts[i],
|
||||
cmd = part[0],
|
||||
lower = cmd.toLowerCase();
|
||||
// Split at white-space, commas but also before signs.
|
||||
// Use positive lookahead to include signs.
|
||||
// Note that we should also check for coordinate values that contain
|
||||
// two decimal periods, as these should be plit into two separate
|
||||
// values. With positive lookbehind, this would look like this:
|
||||
// |(?<=\d*\.\d+)(?=\.\d+)
|
||||
// Unfortunately, JavaScript does not have lookbehind in RegExps, so
|
||||
// instead we leave these values that way and parse them further in
|
||||
// getCoord() above. Note that coordsLength may increase as we're
|
||||
// reading values.
|
||||
coords = part.slice(1).trim().split(/[\s,]+|(?=[+-])/);
|
||||
coordsLength = coords.length;
|
||||
// Match all coordinate values
|
||||
coords = part.match(/([+-]?(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)/g);
|
||||
var length = coords && coords.length;
|
||||
relative = cmd === lower;
|
||||
switch (lower) {
|
||||
case 'm':
|
||||
case 'l':
|
||||
for (var j = 0; j < coordsLength; j += 2)
|
||||
for (var j = 0; j < length; j += 2)
|
||||
this[j === 0 && lower === 'm' ? 'moveTo' : 'lineTo'](
|
||||
getPoint(j, true));
|
||||
break;
|
||||
case 'h':
|
||||
case 'v':
|
||||
var coord = lower == 'h' ? 'x' : 'y';
|
||||
for (var j = 0; j < coordsLength; j++) {
|
||||
for (var j = 0; j < length; j++) {
|
||||
getCoord(j, coord, true);
|
||||
this.lineTo(current);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
for (var j = 0; j < coordsLength; j += 6) {
|
||||
for (var j = 0; j < length; j += 6) {
|
||||
this.cubicCurveTo(
|
||||
getPoint(j),
|
||||
control = getPoint(j + 2),
|
||||
|
@ -163,7 +145,7 @@ var PathItem = Item.extend(/** @lends PathItem# */{
|
|||
break;
|
||||
case 's':
|
||||
// Shorthand cubic bezierCurveTo, absolute
|
||||
for (var j = 0; j < coordsLength; j += 4) {
|
||||
for (var j = 0; j < length; j += 4) {
|
||||
this.cubicCurveTo(
|
||||
// Calculate reflection of previous control points
|
||||
current.multiply(2).subtract(control),
|
||||
|
@ -172,14 +154,14 @@ var PathItem = Item.extend(/** @lends PathItem# */{
|
|||
}
|
||||
break;
|
||||
case 'q':
|
||||
for (var j = 0; j < coordsLength; j += 4) {
|
||||
for (var j = 0; j < length; j += 4) {
|
||||
this.quadraticCurveTo(
|
||||
control = getPoint(j),
|
||||
getPoint(j + 2, true));
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
for (var j = 0; j < coordsLength; j += 2) {
|
||||
for (var j = 0; j < length; j += 2) {
|
||||
this.quadraticCurveTo(
|
||||
// Calculate reflection of previous control points
|
||||
control = current.multiply(2).subtract(control),
|
||||
|
|
Loading…
Reference in a new issue