Skip to content

Commit 8a3f6cd

Browse files
committed
TDD REFACTOR: extract color conversion and add palette caching in usePixelBuffer
1 parent d730c73 commit 8a3f6cd

2 files changed

Lines changed: 44 additions & 7 deletions

File tree

client/src/composables/pixel-canvas/usePixelBuffer.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,31 @@ describe('usePixelBuffer', () => {
9898
updateBuffer();
9999
expect(onBufferUpdate).toHaveBeenCalled();
100100
});
101+
102+
it('updates correctly when palette changes', () => {
103+
const props = ref<PixelBufferProps>({
104+
width: 1,
105+
height: 1,
106+
pixels: new Uint8Array([0]),
107+
palette: ['#ff0000']
108+
});
109+
110+
const { updateBuffer } = usePixelBuffer(props);
111+
updateBuffer();
112+
113+
let imageData = mockContext.putImageData.mock.calls[0][0];
114+
let data32 = new Uint32Array(imageData.data.buffer);
115+
expect(data32[0]).toBe(0xFF0000FF); // #ff0000
116+
117+
// Change palette (new reference)
118+
props.value = {
119+
...props.value,
120+
palette: ['#0000ff']
121+
};
122+
updateBuffer();
123+
124+
imageData = mockContext.putImageData.mock.calls[1][0];
125+
data32 = new Uint32Array(imageData.data.buffer);
126+
expect(data32[0]).toBe(0xFFFF0000); // #0000ff
127+
});
101128
});

client/src/composables/pixel-canvas/usePixelBuffer.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ export interface PixelBufferProps {
77
palette: string[];
88
}
99

10+
function hexToUint32(hex: string): number {
11+
const r = parseInt(hex.slice(1, 3), 16);
12+
const g = parseInt(hex.slice(3, 5), 16);
13+
const b = parseInt(hex.slice(5, 7), 16);
14+
return (255 << 24) | (b << 16) | (g << 8) | r;
15+
}
16+
1017
export function usePixelBuffer(
1118
props: Readonly<Ref<PixelBufferProps>>,
1219
onBufferUpdate?: () => void
@@ -15,6 +22,10 @@ export function usePixelBuffer(
1522
const pixelBuffer = document.createElement('canvas');
1623
const pixelCtx = pixelBuffer.getContext('2d')!;
1724

25+
// Cache for uint32Palette
26+
let cachedPalette: string[] | null = null;
27+
let uint32Palette = new Uint32Array(0);
28+
1829
function updateBuffer() {
1930
const { width, height, pixels, palette } = props.value;
2031
if (width === 0 || height === 0) return;
@@ -25,13 +36,12 @@ export function usePixelBuffer(
2536
const imageData = pixelCtx.createImageData(width, height);
2637
const data32 = new Uint32Array(imageData.data.buffer);
2738

28-
const uint32Palette = new Uint32Array(palette.length);
29-
for (let i = 0; i < palette.length; i++) {
30-
const hex = palette[i];
31-
const r = parseInt(hex.slice(1, 3), 16);
32-
const g = parseInt(hex.slice(3, 5), 16);
33-
const b = parseInt(hex.slice(5, 7), 16);
34-
uint32Palette[i] = (255 << 24) | (b << 16) | (g << 8) | r;
39+
if (palette !== cachedPalette) {
40+
uint32Palette = new Uint32Array(palette.length);
41+
for (let i = 0; i < palette.length; i++) {
42+
uint32Palette[i] = hexToUint32(palette[i]);
43+
}
44+
cachedPalette = palette;
3545
}
3646

3747
for (let i = 0; i < pixels.length; i++) {

0 commit comments

Comments
 (0)