feat(proxy): add offset param to inset or outset traced shapes
Trace results can now be inset (negative) or outset (positive) by a pixel amount. Offset the outline and holes in opposite directions with clipper-lib's miter joins, then recombine with a boolean difference so holes grow on inset and shrink on outset. Collapsed shapes return an empty outline; a split outline keeps the largest ring. Document the parameter and the new dependency.
This commit is contained in:
@@ -100,4 +100,48 @@ describe('trace route', () => {
|
||||
expect(result.mode).toBe('bw');
|
||||
expect(result.shape.outline.length).toBeGreaterThan(3);
|
||||
});
|
||||
|
||||
it('applies an inset offset to the shape', async () => {
|
||||
stubFetch(await makePng());
|
||||
const res = await trace.request(
|
||||
'/?url=https%3A%2F%2Fexample.com%2Fa.png&offset=-2',
|
||||
);
|
||||
expect(res.status).toBe(200);
|
||||
const result = deserialize(new Uint8Array(await res.arrayBuffer()));
|
||||
expect(result.offset).toBe(-2);
|
||||
expect(result.shape.outline.length).toBeGreaterThan(3);
|
||||
// An inset of 2px on a 20px circle must be visibly smaller.
|
||||
const extent = (pts: number[][]) => [
|
||||
Math.min(...pts.map((p) => p[0]!)),
|
||||
Math.max(...pts.map((p) => p[0]!)),
|
||||
];
|
||||
const [minX, maxX] = extent(result.shape.outline);
|
||||
expect((maxX ?? 0) - (minX ?? 0)).toBeLessThan(20);
|
||||
});
|
||||
|
||||
it('applies an outset offset to the shape', async () => {
|
||||
stubFetch(await makePng());
|
||||
const res = await trace.request(
|
||||
'/?url=https%3A%2F%2Fexample.com%2Fa.png&offset=2',
|
||||
);
|
||||
expect(res.status).toBe(200);
|
||||
const result = deserialize(new Uint8Array(await res.arrayBuffer()));
|
||||
expect(result.offset).toBe(2);
|
||||
expect(result.shape.outline.length).toBeGreaterThan(3);
|
||||
});
|
||||
|
||||
it('rejects a non-numeric offset', async () => {
|
||||
stubFetch(await makePng());
|
||||
const res = await trace.request(
|
||||
'/?url=https%3A%2F%2Fexample.com%2Fa.png&offset=abc',
|
||||
);
|
||||
expect(res.status).toBe(400);
|
||||
});
|
||||
|
||||
it('omits offset when not requested', async () => {
|
||||
stubFetch(await makePng());
|
||||
const res = await trace.request('/?url=https%3A%2F%2Fexample.com%2Fa.png');
|
||||
const result = deserialize(new Uint8Array(await res.arrayBuffer()));
|
||||
expect(result.offset).toBeUndefined();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user