提交 a04b27a1 编写于 作者: B Bogdan Chadkin

Refactor convertToRelative

Slight code simplification. Each command is processed exclusively
without assumtions. Removed moveto and closepath common coords
reference, handle in applyTransform instead. Rely on new path data
naming.
上级 d2796174
......@@ -124,7 +124,6 @@ exports.applyTransforms = function (elem, path, params) {
stroke = elem.computedAttr('stroke'),
id = elem.computedAttr('id'),
transformPrecision = params.transformPrecision,
newPoint,
scale;
if (stroke && stroke != 'none') {
......@@ -200,74 +199,92 @@ exports.applyTransforms = function (elem, path, params) {
return path;
}
let lastMovetoCoords = [0, 0];
path.forEach(function (pathItem) {
if (pathItem.data) {
// h -> l
if (pathItem.instruction === 'h') {
pathItem.instruction = 'l';
pathItem.data[1] = 0;
// v -> l
} else if (pathItem.instruction === 'v') {
pathItem.instruction = 'l';
pathItem.data[1] = pathItem.data[0];
pathItem.data[0] = 0;
}
// h -> l
if (pathItem.instruction === 'h') {
pathItem.instruction = 'l';
pathItem.data[1] = 0;
// v -> l
} else if (pathItem.instruction === 'v') {
pathItem.instruction = 'l';
pathItem.data[1] = pathItem.data[0];
pathItem.data[0] = 0;
}
// if there is a translate() transform
if (
pathItem.instruction === 'M' &&
(matrix.data[4] !== 0 || matrix.data[5] !== 0)
) {
// then apply it only to the first absoluted M
newPoint = transformPoint(
// if there is a translate() transform
if (
pathItem.instruction === 'M' &&
(matrix.data[4] !== 0 || matrix.data[5] !== 0)
) {
// then apply it only to the first absoluted M
const newPoint = transformPoint(
matrix.data,
pathItem.data[0],
pathItem.data[1]
);
pathItem.data[0] = newPoint[0];
pathItem.data[1] = newPoint[1];
pathItem.coords[0] = newPoint[0];
pathItem.coords[1] = newPoint[1];
lastMovetoCoords[0] = pathItem.coords[0];
lastMovetoCoords[1] = pathItem.coords[1];
// clear translate() data from transform matrix
matrix.data[4] = 0;
matrix.data[5] = 0;
} else if (pathItem.instruction === 'm') {
const newPoint = transformPoint(
matrix.data,
pathItem.data[0],
pathItem.data[1]
);
pathItem.data[0] = newPoint[0];
pathItem.data[1] = newPoint[1];
pathItem.coords[0] = pathItem.base[0] + newPoint[0];
pathItem.coords[1] = pathItem.base[1] + newPoint[1];
lastMovetoCoords[0] = pathItem.coords[0];
lastMovetoCoords[1] = pathItem.coords[1];
} else if (pathItem.instruction === 'Z' || pathItem.instruction === 'z') {
pathItem.coords[0] = lastMovetoCoords[0];
pathItem.coords[1] = lastMovetoCoords[1];
} else {
if (pathItem.instruction == 'a') {
transformArc(pathItem.data, matrix.data);
// reduce number of digits in rotation angle
if (Math.abs(pathItem.data[2]) > 80) {
var a = pathItem.data[0],
rotation = pathItem.data[2];
pathItem.data[0] = pathItem.data[1];
pathItem.data[1] = a;
pathItem.data[2] = rotation + (rotation > 0 ? -90 : 90);
}
const newPoint = transformPoint(
matrix.data,
pathItem.data[0],
pathItem.data[1]
pathItem.data[5],
pathItem.data[6]
);
set(pathItem.data, newPoint);
set(pathItem.coords, newPoint);
// clear translate() data from transform matrix
matrix.data[4] = 0;
matrix.data[5] = 0;
pathItem.data[5] = newPoint[0];
pathItem.data[6] = newPoint[1];
} else {
if (pathItem.instruction == 'a') {
transformArc(pathItem.data, matrix.data);
// reduce number of digits in rotation angle
if (Math.abs(pathItem.data[2]) > 80) {
var a = pathItem.data[0],
rotation = pathItem.data[2];
pathItem.data[0] = pathItem.data[1];
pathItem.data[1] = a;
pathItem.data[2] = rotation + (rotation > 0 ? -90 : 90);
}
newPoint = transformPoint(
for (var i = 0; i < pathItem.data.length; i += 2) {
const newPoint = transformPoint(
matrix.data,
pathItem.data[5],
pathItem.data[6]
pathItem.data[i],
pathItem.data[i + 1]
);
pathItem.data[5] = newPoint[0];
pathItem.data[6] = newPoint[1];
} else {
for (var i = 0; i < pathItem.data.length; i += 2) {
newPoint = transformPoint(
matrix.data,
pathItem.data[i],
pathItem.data[i + 1]
);
pathItem.data[i] = newPoint[0];
pathItem.data[i + 1] = newPoint[1];
}
pathItem.data[i] = newPoint[0];
pathItem.data[i + 1] = newPoint[1];
}
pathItem.coords[0] =
pathItem.base[0] + pathItem.data[pathItem.data.length - 2];
pathItem.coords[1] =
pathItem.base[1] + pathItem.data[pathItem.data.length - 1];
}
pathItem.coords[0] =
pathItem.base[0] + pathItem.data[pathItem.data.length - 2];
pathItem.coords[1] =
pathItem.base[1] + pathItem.data[pathItem.data.length - 1];
}
});
......
......@@ -109,143 +109,170 @@ exports.fn = function (item, params) {
* @param {Object} params plugin params
* @return {Array} output path data
*/
function convertToRelative(path) {
var point = [0, 0],
subpathPoint = [0, 0],
baseItem;
path.forEach(function (item, index) {
var instruction = item.instruction,
data = item.data;
// data !== !z
if (data) {
// already relative
// recalculate current point
if ('mcslqta'.indexOf(instruction) > -1) {
point[0] += data[data.length - 2];
point[1] += data[data.length - 1];
if (instruction === 'm') {
subpathPoint[0] = point[0];
subpathPoint[1] = point[1];
baseItem = item;
}
} else if (instruction === 'h') {
point[0] += data[0];
} else if (instruction === 'v') {
point[1] += data[0];
}
// convert absolute path data coordinates to relative
// if "M" was not transformed from "m"
const convertToRelative = (pathData) => {
let start = [0, 0];
let cursor = [0, 0];
let prevCoords = [0, 0];
for (let i = 0; i < pathData.length; i += 1) {
const pathItem = pathData[i];
let { instruction: command, data: args } = pathItem;
// moveto (x y)
if (command === 'm') {
// update start and cursor
cursor[0] += args[0];
cursor[1] += args[1];
start[0] = cursor[0];
start[1] = cursor[1];
}
if (command === 'M') {
// M → m
if (instruction === 'M') {
if (index > 0) instruction = 'm';
data[0] -= point[0];
data[1] -= point[1];
subpathPoint[0] = point[0] += data[0];
subpathPoint[1] = point[1] += data[1];
baseItem = item;
// skip first moveto
if (i !== 0) {
command = 'm';
}
args[0] -= cursor[0];
args[1] -= cursor[1];
// update start and cursor
cursor[0] += args[0];
cursor[1] += args[1];
start[0] = cursor[0];
start[1] = cursor[1];
}
// lineto (x y)
if (command === 'l') {
cursor[0] += args[0];
cursor[1] += args[1];
}
if (command === 'L') {
// L → l
// T → t
else if ('LT'.indexOf(instruction) > -1) {
instruction = instruction.toLowerCase();
// x y
// 0 1
data[0] -= point[0];
data[1] -= point[1];
point[0] += data[0];
point[1] += data[1];
// C → c
} else if (instruction === 'C') {
instruction = 'c';
// x1 y1 x2 y2 x y
// 0 1 2 3 4 5
data[0] -= point[0];
data[1] -= point[1];
data[2] -= point[0];
data[3] -= point[1];
data[4] -= point[0];
data[5] -= point[1];
point[0] += data[4];
point[1] += data[5];
// S → s
// Q → q
} else if ('SQ'.indexOf(instruction) > -1) {
instruction = instruction.toLowerCase();
// x1 y1 x y
// 0 1 2 3
data[0] -= point[0];
data[1] -= point[1];
data[2] -= point[0];
data[3] -= point[1];
point[0] += data[2];
point[1] += data[3];
// A → a
} else if (instruction === 'A') {
instruction = 'a';
// rx ry x-axis-rotation large-arc-flag sweep-flag x y
// 0 1 2 3 4 5 6
data[5] -= point[0];
data[6] -= point[1];
point[0] += data[5];
point[1] += data[6];
// H → h
} else if (instruction === 'H') {
instruction = 'h';
command = 'l';
args[0] -= cursor[0];
args[1] -= cursor[1];
cursor[0] += args[0];
cursor[1] += args[1];
}
data[0] -= point[0];
// horizontal lineto (x)
if (command === 'h') {
cursor[0] += args[0];
}
if (command === 'H') {
// H → h
command = 'h';
args[0] -= cursor[0];
cursor[0] += args[0];
}
point[0] += data[0];
// vertical lineto (y)
if (command === 'v') {
cursor[1] += args[0];
}
if (command === 'V') {
// V → v
command = 'v';
args[0] -= cursor[1];
cursor[1] += args[0];
}
// V → v
} else if (instruction === 'V') {
instruction = 'v';
// curveto (x1 y1 x2 y2 x y)
if (command === 'c') {
cursor[0] += args[4];
cursor[1] += args[5];
}
if (command === 'C') {
// C → c
command = 'c';
args[0] -= cursor[0];
args[1] -= cursor[1];
args[2] -= cursor[0];
args[3] -= cursor[1];
args[4] -= cursor[0];
args[5] -= cursor[1];
cursor[0] += args[4];
cursor[1] += args[5];
}
data[0] -= point[1];
// smooth curveto (x2 y2 x y)
if (command === 's') {
cursor[0] += args[2];
cursor[1] += args[3];
}
if (command === 'S') {
// S → s
command = 's';
args[0] -= cursor[0];
args[1] -= cursor[1];
args[2] -= cursor[0];
args[3] -= cursor[1];
cursor[0] += args[2];
cursor[1] += args[3];
}
point[1] += data[0];
}
// quadratic Bézier curveto (x1 y1 x y)
if (command === 'q') {
cursor[0] += args[2];
cursor[1] += args[3];
}
if (command === 'Q') {
// Q → q
command = 'q';
args[0] -= cursor[0];
args[1] -= cursor[1];
args[2] -= cursor[0];
args[3] -= cursor[1];
cursor[0] += args[2];
cursor[1] += args[3];
}
item.instruction = instruction;
item.data = data;
// smooth quadratic Bézier curveto (x y)
if (command === 't') {
cursor[0] += args[0];
cursor[1] += args[1];
}
if (command === 'T') {
// T → t
command = 't';
args[0] -= cursor[0];
args[1] -= cursor[1];
cursor[0] += args[0];
cursor[1] += args[1];
}
// store absolute coordinates for later use
item.coords = point.slice(-2);
// elliptical arc (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
if (command === 'a') {
cursor[0] += args[5];
cursor[1] += args[6];
}
if (command === 'A') {
// A → a
command = 'a';
args[5] -= cursor[0];
args[6] -= cursor[1];
cursor[0] += args[5];
cursor[1] += args[6];
}
// !data === z, reset current point
else if (instruction == 'z') {
if (baseItem) {
item.coords = baseItem.coords;
}
point[0] = subpathPoint[0];
point[1] = subpathPoint[1];
// closepath
if (command === 'Z' || command === 'z') {
// reset current cursor
cursor[0] = start[0];
cursor[1] = start[1];
}
item.base = index > 0 ? path[index - 1].coords : [0, 0];
});
pathItem.instruction = command;
pathItem.data = args;
// store absolute coordinates for later use
// base should preserve reference from other element
pathItem.base = prevCoords;
pathItem.coords = [cursor[0], cursor[1]];
prevCoords = pathItem.coords;
}
return path;
}
return pathData;
};
/**
* Main filters loop.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册