aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/test/canvas/detect-canvas-block.ts
blob: 4557213020db191dc11303171a5610a965d33b6e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
export const detect2dCanvasBlockOnCanvas = (canvas: HTMLCanvasElement, resetDimensions = true, canvasOpts: CanvasRenderingContext2D | CanvasRenderingContext2DSettings = {
  desynchronized: true,
  alpha: true,
  willReadFrequently: false,
  // @ts-ignore type is incomplete
  colorType: 'float16' as const,
  colorSpace: 'display-p3' as const,
}): null | Error => {
  const dimensions = resetDimensions ? [canvas.width, canvas.height] as const : [0, 0] as const;
  const [w, h] = [255, 255];
  const checks = 32;
  const ctx = canvasOpts instanceof CanvasRenderingContext2D && canvasOpts && canvasOpts.canvas.width >= 256 && canvasOpts.canvas.height >= 256 ? canvasOpts : (() => {
    [canvas.width, canvas.height] = [w, h];
    return canvas.getContext('2d', canvasOpts) as CanvasRenderingContext2D | null
  })();
  if (ctx) {
    try {
      // make sure we have canvas support
      ctx.fillStyle = '#0099ff';
      ctx.fillRect(0, 0, w, h);
      for (let i = 0; i < checks; i++) {
        const data = ctx.getImageData(i % w, i % h, 1, 1).data;
        if (
          data[0] !== 0 ||
          data[1] !== 153 ||
          data[2] !== 255 ||
          data[3] !== 255
        ) {
          if (resetDimensions) [canvas.width, canvas.height] = dimensions;
          return new Error("Canvas Data doesn't match written data.");
        }
      }
      ctx.clearRect(0, 0, w, h);
    } catch (error) {
      if (resetDimensions) [canvas.width, canvas.height] = dimensions;
      return new Error('No canvas support', {
        cause: error
      });
    }
  } else {
    if (resetDimensions) [canvas.width, canvas.height] = dimensions;
    return new Error('No canvas support: ctx is undefined.');
  }
  return null;
}
export const checkFor2dCanvasSupport = () => detect2dCanvasBlockOnCanvas(document.createElement('canvas'), false)