Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/components/canvas/players/html5-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const BAKE_SCALES = [0.25, 0.5, 0.75, 1];
// A remembered frame holds its body markup, so a window bounds the memory. 300 frames covers a 10 s loop at 30 fps.
const REPEAT_WINDOW_FRAMES = 300;
// Part of every bake's cache key, so raising it redraws every cached bake.
const FRAME_DRAWING_VERSION = 1;
const FRAME_DRAWING_VERSION = 2;
const ANIMATION_OVERRIDE = `<style>*,*::before,*::after{animation:none!important;transition:none!important}</style>`;

// A base64 bitmap in a frame's markup: a CSS url(), an <img> source, or a canvas painted as a background.
Expand Down Expand Up @@ -109,7 +109,8 @@ async function foreignObjectSvgToWebp(svg: string, width: number, height: number
const canvas = document.createElement("canvas");
canvas.width = width * scale;
canvas.height = height * scale;
const ctx = canvas.getContext("2d");
// Firefox's GPU canvas draws some of a frame's gradients as a solid fill. A canvas set for reading back draws in software.
const ctx = canvas.getContext("2d", { willReadFrequently: true });
if (!ctx) throw new Error("2D context unavailable for foreignObject rasterise");
ctx.drawImage(img, 0, 0, width * scale, height * scale);
const blob = await new Promise<Blob | null>(resolve => {
Expand Down
9 changes: 9 additions & 0 deletions tests/html5-player.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,15 @@ it("draws frames at the bake scale and sizes their texture back to the clip", as
expect((harness.contentContainer.children.at(-1) as PlaybackSprite).texture.resolution).toBe(0.5);
});

it("draws frames on a software canvas, since Firefox's GPU canvas fills some gradients solid", async () => {
const { harness } = createStillPlayer();
const getContext = jest.spyOn(HTMLCanvasElement.prototype, "getContext").mockReturnValue({ drawImage: jest.fn() } as never);

await harness.runCapture();

expect(getContext).toHaveBeenCalledWith("2d", { willReadFrequently: true });
});

it("draws a full-size frame of a fractional clip size as an unscaled draw does", async () => {
const { harness } = createStillPlayer();
Object.assign(harness, { renderedWidth: 1080.6, renderedHeight: 1920.4 });
Expand Down
Loading