Skip to content

Commit 58c7e57

Browse files
committed
Fix clamping for different fit than cover and don't clamp SVGs by default
1 parent 3679ee6 commit 58c7e57

3 files changed

Lines changed: 58 additions & 14 deletions

File tree

src/handlers/handlers.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ export const resize: Handler = {
9494
height = width;
9595
}
9696
// sharp's `withoutEnlargement` doesn't respect the requested aspect ratio, so we need to do it ourselves
97-
if (!context.enlarge) {
98-
const clamped = clampDimensionsPreservingAspectRatio(context.meta, {
97+
// By default don't clamp svgs unless explicitly desired with enlarge=false
98+
if (context.meta.type === 'svg' ? context.enlarge === false : !context.enlarge) {
99+
const clamped = clampDimensionsPreservingAspectRatio(context.fit, context.meta, {
99100
width,
100101
height,
101102
});

src/handlers/utils.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,28 @@ export function applyHandler(
3535
}
3636

3737
export function clampDimensionsPreservingAspectRatio(
38+
fit: HandlerContext['fit'],
3839
sourceDimensions: ImageMeta,
3940
desiredDimensions: { width: number; height: number },
4041
) {
4142
const desiredAspectRatio = desiredDimensions.width / desiredDimensions.height;
43+
const sourceAspectRatio = sourceDimensions.width / sourceDimensions.height;
4244
let { width, height } = desiredDimensions;
4345
if (sourceDimensions.width && width > sourceDimensions.width) {
44-
width = sourceDimensions.width;
45-
height = Math.round(sourceDimensions.width / desiredAspectRatio);
46+
if (['contain', 'fill', 'inside'].includes(fit) && sourceAspectRatio < desiredAspectRatio) {
47+
width = Math.round(height * desiredAspectRatio)
48+
} else {
49+
width = sourceDimensions.width;
50+
height = Math.round(sourceDimensions.width / desiredAspectRatio);
51+
}
4652
}
4753
if (sourceDimensions.height && height > sourceDimensions.height) {
48-
height = sourceDimensions.height;
49-
width = Math.round(sourceDimensions.height * desiredAspectRatio);
54+
if (['contain', 'fill', 'inside'].includes(fit) && sourceAspectRatio > desiredAspectRatio) {
55+
height = Math.round(width / desiredAspectRatio);
56+
} else {
57+
height = sourceDimensions.height;
58+
width = Math.round(sourceDimensions.height * desiredAspectRatio);
59+
}
5060
}
51-
5261
return { width, height };
5362
}

test/handlers/utils.test.ts

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,46 @@ describe("utils", () => {
2222
});
2323

2424
it("clampDimensionsPreservingAspectRatio", () => {
25-
const sourceDimensions = { width: 200, height: 100 };
26-
const desiredDimensions = { width: 300, height: 150 };
27-
const result = clampDimensionsPreservingAspectRatio(
28-
sourceDimensions,
29-
desiredDimensions,
30-
);
31-
expect(result).toEqual({ width: 200, height: 100 });
25+
const dimensions = [
26+
{
27+
source: [200, 100],
28+
desired: [300, 150],
29+
expected: [200, 100],
30+
},
31+
{
32+
source: [200, 150],
33+
desired: [150, 200],
34+
expected: [113, 150],
35+
},
36+
{
37+
source: [150, 200],
38+
desired: [200, 150],
39+
expected: [150, 113],
40+
},
41+
{
42+
source: [211, 40],
43+
desired: [170, 170, "contain"],
44+
expected: [170, 170],
45+
},
46+
{
47+
source: [211, 40],
48+
desired: [220, 110, "contain"],
49+
expected: [211, 106],
50+
},
51+
{
52+
source: [40, 211],
53+
desired: [110, 220, "contain"],
54+
expected: [106, 211],
55+
},
56+
];
57+
58+
for (const d of dimensions) {
59+
const result = clampDimensionsPreservingAspectRatio(
60+
d.desired[2] ?? null,
61+
{ width: d.source[0], height: d.source[1] },
62+
{ width: d.desired[0], height: d.desired[1] },
63+
);
64+
expect(result).toEqual({ width: d.expected[0], height: d.expected[1] });
65+
}
3266
});
3367
});

0 commit comments

Comments
 (0)