1
0
mirror of https://github.com/svg/svgo.git synced 2025-07-31 07:44:22 +03:00

Fix applying transform to arc with zero radius

Ref https://github.com/svg/svgo/issues/1500
This commit is contained in:
Bogdan Chadkin
2021-08-27 01:03:11 +03:00
parent 1b02799e18
commit ac8edbaf41
2 changed files with 40 additions and 25 deletions

View File

@ -309,40 +309,42 @@ const transformToMatrix = (transform) => {
exports.transformArc = (cursor, arc, transform) => { exports.transformArc = (cursor, arc, transform) => {
const x = arc[5] - cursor[0]; const x = arc[5] - cursor[0];
const y = arc[6] - cursor[1]; const y = arc[6] - cursor[1];
var a = arc[0], let a = arc[0];
b = arc[1], let b = arc[1];
rot = (arc[2] * Math.PI) / 180, const rot = (arc[2] * Math.PI) / 180;
cos = Math.cos(rot), const cos = Math.cos(rot);
sin = Math.sin(rot), const sin = Math.sin(rot);
h = // skip if radius is 0
if (a > 0 && b > 0) {
let h =
Math.pow(x * cos + y * sin, 2) / (4 * a * a) + Math.pow(x * cos + y * sin, 2) / (4 * a * a) +
Math.pow(y * cos - x * sin, 2) / (4 * b * b); Math.pow(y * cos - x * sin, 2) / (4 * b * b);
if (h > 1) { if (h > 1) {
h = Math.sqrt(h); h = Math.sqrt(h);
a *= h; a *= h;
b *= h; b *= h;
}
} }
var ellipse = [a * cos, a * sin, -b * sin, b * cos, 0, 0], const ellipse = [a * cos, a * sin, -b * sin, b * cos, 0, 0];
m = multiplyTransformMatrices(transform, ellipse), const m = multiplyTransformMatrices(transform, ellipse);
// Decompose the new ellipse matrix // Decompose the new ellipse matrix
lastCol = m[2] * m[2] + m[3] * m[3], const lastCol = m[2] * m[2] + m[3] * m[3];
squareSum = m[0] * m[0] + m[1] * m[1] + lastCol, const squareSum = m[0] * m[0] + m[1] * m[1] + lastCol;
root = const root =
Math.hypot(m[0] - m[3], m[1] + m[2]) * Math.hypot(m[0] - m[3], m[1] + m[2]) * Math.hypot(m[0] + m[3], m[1] - m[2]);
Math.hypot(m[0] + m[3], m[1] - m[2]);
if (!root) { if (!root) {
// circle // circle
arc[0] = arc[1] = Math.sqrt(squareSum / 2); arc[0] = arc[1] = Math.sqrt(squareSum / 2);
arc[2] = 0; arc[2] = 0;
} else { } else {
var majorAxisSqr = (squareSum + root) / 2, const majorAxisSqr = (squareSum + root) / 2;
minorAxisSqr = (squareSum - root) / 2, const minorAxisSqr = (squareSum - root) / 2;
major = Math.abs(majorAxisSqr - lastCol) > 1e-6, const major = Math.abs(majorAxisSqr - lastCol) > 1e-6;
sub = (major ? majorAxisSqr : minorAxisSqr) - lastCol, const sub = (major ? majorAxisSqr : minorAxisSqr) - lastCol;
rowsSum = m[0] * m[2] + m[1] * m[3], const rowsSum = m[0] * m[2] + m[1] * m[3];
term1 = m[0] * sub + m[2] * rowsSum, const term1 = m[0] * sub + m[2] * rowsSum;
term2 = m[1] * sub + m[3] * rowsSum; const term2 = m[1] * sub + m[3] * rowsSum;
arc[0] = Math.sqrt(majorAxisSqr); arc[0] = Math.sqrt(majorAxisSqr);
arc[1] = Math.sqrt(minorAxisSqr); arc[1] = Math.sqrt(minorAxisSqr);
arc[2] = arc[2] =

View File

@ -0,0 +1,13 @@
Applying transform to arc with zero radius should not produce NaNs
===
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31.6 31.6">
<path d="m5.25,2.2H25.13a0,0,0,0,1-.05-.05V14.18Z" transform="translate(0 0)"/>
</svg>
@@@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31.6 31.6">
<path d="M5.25 2.2h19.88l-.05-.05v12.03Z"/>
</svg>