Split up paths w/ multiple shapes into multiple shapes.
rodzic
b441b10493
commit
81a1e32b0f
|
@ -95,12 +95,23 @@ function float(value: string | number | undefined): number {
|
||||||
return float;
|
return float;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pathToBeziers(path: string): Bezier[] {
|
function flatten<T>(arr: T[][]): T[] {
|
||||||
|
const result: T[] = [];
|
||||||
|
|
||||||
|
for (let subarr of arr) {
|
||||||
|
result.push(...subarr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pathToBeziers(path: string): Bezier[][] {
|
||||||
const parts = path.trim().split(" ");
|
const parts = path.trim().split(" ");
|
||||||
let x = 0;
|
let x = 0;
|
||||||
let y = 0;
|
let y = 0;
|
||||||
let i = 0;
|
let i = 0;
|
||||||
const beziers: Bezier[] = [];
|
const shapes: Bezier[][] = [];
|
||||||
|
let currShape: Bezier[] = [];
|
||||||
|
|
||||||
const chomp = () => {
|
const chomp = () => {
|
||||||
if (i >= parts.length) {
|
if (i >= parts.length) {
|
||||||
|
@ -111,10 +122,18 @@ function pathToBeziers(path: string): Bezier[] {
|
||||||
return val;
|
return val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const finishCurrShape = () => {
|
||||||
|
if (currShape.length) {
|
||||||
|
shapes.push(currShape);
|
||||||
|
currShape = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while (i < parts.length) {
|
while (i < parts.length) {
|
||||||
const command = chomp();
|
const command = chomp();
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case "M":
|
case "M":
|
||||||
|
finishCurrShape();
|
||||||
x = float(chomp());
|
x = float(chomp());
|
||||||
y = float(chomp());
|
y = float(chomp());
|
||||||
break;
|
break;
|
||||||
|
@ -125,18 +144,21 @@ function pathToBeziers(path: string): Bezier[] {
|
||||||
const y2 = float(chomp());
|
const y2 = float(chomp());
|
||||||
const endX = float(chomp());
|
const endX = float(chomp());
|
||||||
const endY = float(chomp());
|
const endY = float(chomp());
|
||||||
beziers.push(new Bezier(x, y, x1, y1, x2, y2, endX, endY));
|
currShape.push(new Bezier(x, y, x1, y1, x2, y2, endX, endY));
|
||||||
x = endX;
|
x = endX;
|
||||||
y = endY;
|
y = endY;
|
||||||
break;
|
break;
|
||||||
case "Z":
|
case "Z":
|
||||||
|
finishCurrShape();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown SVG path command: '${command}'`);
|
throw new Error(`Unknown SVG path command: '${command}'`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return beziers;
|
finishCurrShape();
|
||||||
|
|
||||||
|
return shapes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBezierBoundingBox(bezier: Bezier): Bbox {
|
function getBezierBoundingBox(bezier: Bezier): Bbox {
|
||||||
|
@ -151,7 +173,7 @@ function getPathBoundingBox(props: SVGProps<SVGPathElement>): Bbox {
|
||||||
if (!props.d) {
|
if (!props.d) {
|
||||||
throw new Error(`SVG path has no 'd' attribute value!`);
|
throw new Error(`SVG path has no 'd' attribute value!`);
|
||||||
}
|
}
|
||||||
const beziers = pathToBeziers(props.d);
|
const beziers = flatten(pathToBeziers(props.d));
|
||||||
const bezierBboxes = beziers.map(getBezierBoundingBox);
|
const bezierBboxes = beziers.map(getBezierBoundingBox);
|
||||||
const bbox = coalesceBoundingBoxes(bezierBboxes);
|
const bbox = coalesceBoundingBoxes(bezierBboxes);
|
||||||
return props.strokeWidth
|
return props.strokeWidth
|
||||||
|
|
Ładowanie…
Reference in New Issue