Skip to content

Commit

Permalink
feat(geom): add opt attribs for pathFromSvg()
Browse files Browse the repository at this point in the history
- update docs
- add/update tests
  • Loading branch information
postspectacular committed May 8, 2024
1 parent e68d0bc commit 2da31f6
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 22 deletions.
21 changes: 16 additions & 5 deletions packages/geom/src/path-from-svg.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { IObjectOf } from "@thi.ng/api";
import { illegalState } from "@thi.ng/errors/illegal-state";
import type { Attribs } from "@thi.ng/geom-api";
import { rad } from "@thi.ng/math/angle";
import { WS } from "@thi.ng/strings/groups";
import type { Vec } from "@thi.ng/vectors";
Expand All @@ -8,8 +9,19 @@ import { PathBuilder } from "./path-builder.js";
const CMD_RE = /[achlmqstvz]/i;
const WSC: IObjectOf<boolean> = { ...WS, ",": true };

export const pathFromSvg = (svg: string) => {
const b = new PathBuilder();
/**
* Takes a SVG path string and parses it into a {@link Path} shape, optionally
* with given attributes.
*
* @remarks
* If the path contains multiple sub-paths (e.g. holes or multiple curves), they
* will be added as sub-paths to the returned main path.
*
* @param svg
* @param attribs
*/
export const pathFromSvg = (svg: string, attribs?: Attribs) => {
const b = new PathBuilder(attribs);
try {
let cmd = "";
for (let n = svg.length, i = 0; i < n; ) {
Expand Down Expand Up @@ -75,9 +87,8 @@ export const pathFromSvg = (svg: string) => {
);
}
}
return b.paths[0].addSubPaths(
...b.paths.slice(1).map((p) => p.segments)
);
const [main, ...subPaths] = b.paths;
return main.addSubPaths(...subPaths.map((p) => p.segments));
} catch (e) {
throw e instanceof Error
? e
Expand Down
46 changes: 29 additions & 17 deletions packages/geom/test/path.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
asPolyline,
asSvg,
line,
pathBuilder,
pathFromCubics,
pathFromSvg,
polyline,
Expand All @@ -14,9 +15,13 @@ import {
vertices,
} from "../src/index.js";

const A = pathFromSvg("M0,0h100v100h-100zM10,10v80h80v-80z");
const A = pathFromSvg("M0,0h100v100h-100zM10,10v80h80v-80z", { fill: "red" });

describe("path", () => {
test("pathbuilder", () => {
expect(pathBuilder().current()).toEqual(new Path());
});

test("fromSvg", () => {
expect(A).toEqual(
new Path(
Expand All @@ -37,35 +42,42 @@ describe("path", () => {
{ type: "l", geo: line([90, 10], [10, 10]) },
{ type: "z" },
],
]
],
{ fill: "red" }
)
);
});

test("asSvg", () => {
expect(asSvg(A)).toBe(
'<path d="M0,0H100V100H0V0zM10,10V90H90V10H10z"/>'
'<path d="M0,0H100V100H0V0zM10,10V90H90V10H10z" fill="red"/>'
);
});

test("asPolyline", () => {
expect(
asPolyline(A, { dist: 20 }).map((x) => simplify(x, 1e-3))
).toEqual([
polyline([
[0, 0],
[100, 0],
[100, 100],
[0, 100],
[0, 0],
]),
polyline([
[10, 10],
[10, 90],
[90, 90],
[90, 10],
[10, 10],
]),
polyline(
[
[0, 0],
[100, 0],
[100, 100],
[0, 100],
[0, 0],
],
{ fill: "red" }
),
polyline(
[
[10, 10],
[10, 90],
[90, 90],
[90, 10],
[10, 10],
],
{ fill: "red" }
),
]);
});

Expand Down

0 comments on commit 2da31f6

Please sign in to comment.