diff --git a/packages/stage-ui/src/composables/canvas-alpha-use-pixel.test.ts b/packages/stage-ui/src/composables/canvas-alpha-use-pixel.test.ts new file mode 100644 index 000000000..d3e321772 --- /dev/null +++ b/packages/stage-ui/src/composables/canvas-alpha-use-pixel.test.ts @@ -0,0 +1,42 @@ +import { describe, expect, it, vi } from 'vitest' +import { ref } from 'vue' + +import { useCanvasPixelAtPoint } from './canvas-alpha' + +vi.mock('@vueuse/core', async () => { + const vue = await import('vue') + + return { + toRef: (value: unknown) => vue.isRef(value) ? value : vue.ref(value), + unrefElement: (value: unknown) => vue.unref(value), + useElementBounding: () => ({ + left: vue.ref(10), + top: vue.ref(20), + width: vue.ref(100), + height: vue.ref(100), + }), + } +}) + +describe('useCanvasPixelAtPoint', () => { + it('flips the Y coordinate before reading the WebGL pixel', () => { + const readPixels = vi.fn((_x, _y, _width, _height, _format, _type, data: Uint8Array) => { + data[3] = 255 + }) + const gl = { + drawingBufferWidth: 200, + drawingBufferHeight: 100, + RGBA: 0x1908, + UNSIGNED_BYTE: 0x1401, + readPixels, + } + const canvas = { + getContext: vi.fn(() => gl), + } as unknown as HTMLCanvasElement + + const { pixel } = useCanvasPixelAtPoint(ref(canvas), ref(60), ref(30)) + + expect(Array.from(pixel.value)).toEqual([0, 0, 0, 255]) + expect(readPixels).toHaveBeenCalledWith(100, 89, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, expect.any(Uint8Array)) + }) +}) diff --git a/packages/stage-ui/src/composables/canvas-alpha.ts b/packages/stage-ui/src/composables/canvas-alpha.ts index 5c57179dd..e92413344 100644 --- a/packages/stage-ui/src/composables/canvas-alpha.ts +++ b/packages/stage-ui/src/composables/canvas-alpha.ts @@ -132,7 +132,7 @@ export function useCanvasPixelAtPoint( const scaleY = gl.drawingBufferHeight / height.value const pixelX = Math.floor(xIn * scaleX) // Flip Y; subtract 1 to avoid top-edge off-by-one - const pixelY = Math.floor(gl.drawingBufferHeight + yIn * scaleY) + const pixelY = Math.floor(gl.drawingBufferHeight - 1 - yIn * scaleY) const data = new Uint8Array(4) try {