<!-- This benchmark aims to measure performance degredation related to
moving a complex path. May be related to caching an alpha mask of the path at
subpixel coordinates i.e. (25.234, 43.119) instead of (25, 43).
As a consequence the cache may get full very quickly. Effect of paint opacity
and rotation transformations on performance can also be tested using the query param options.

Available query param options:
 - snap: Round all path translations to the nearest integer. This means subpixel coordinate.
    translations will not be used. Only has an effect when the translating option is used.
 - opacity: Use a transparent color to fill the path. If this option is
    not included then opaque black is used.
 - translate: The path will be randomly translated every frame.
 - rotate: The path will be randomly rotated every frame.
-->
<!DOCTYPE html>
<html>
<head>
  <title>Complex Path translation Perf</title>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="/static/canvaskit.js" type="text/javascript" charset="utf-8"></script>
  <style type="text/css" media="screen">
    body {
      margin: 0;
      padding: 0;
    }
    #test-svg {
      height: 0;
      width: 0;
    }
    #complex-path {
      height: 1000px;
      width: 1000px;
    }
  </style>
</head>
<body>
  <!-- Arbitrary svg for testing. Source: https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/gallardo.svg-->
  <object type="image/svg+xml" data="/static/assets/car.svg" id="test-svg">
    Car image
  </object>

  <main>
    <button id="start_bench">Start Benchmark</button>
    <br>
    <canvas id=complex-path width=1000 height=1000></canvas>
  </main>
  <script type="text/javascript" charset="utf-8">
  const urlSearchParams = new URLSearchParams(window.location.search);

  // We sample MAX_FRAMES or until MAX_SAMPLE_SECONDS has elapsed.
  const MAX_FRAMES = 60 * 30; // ~30s at 60fps
  const MAX_SAMPLE_MS = 30 * 1000; // in case something takes a while, stop after 30 seconds.
  const TRANSPARENT_PINK = new Float32Array([1,0,1,0.1]);

  const svgObjectElement = document.getElementById('test-svg');
  svgObjectElement.addEventListener('load', () => {
    CanvasKitInit({
      locateFile: (file) => '/static/' + file,
    }).then(run);
  });

  function run(CanvasKit) {

    const surface = getSurface(CanvasKit);
    if (!surface) {
      console.error('Could not make surface', window._error);
      return;
    }
    const skcanvas = surface.getCanvas();
    const grContext = surface.grContext;

    document.getElementById('start_bench').addEventListener('click', () => {
      // Initialize drawing related objects
      const svgElement = svgObjectElement.contentDocument;
      const svgPathAndFillColorPairs = svgToPathAndFillColorPairs(svgElement, CanvasKit);

      const paint = new CanvasKit.SkPaint();
      paint.setAntiAlias(true);
      paint.setStyle(CanvasKit.PaintStyle.Fill);
      let paintColor = CanvasKit.BLACK;

      // Path is large, scale canvas so entire path is visible
      skcanvas.scale(0.5, 0.5);

      // Initialize perf data
      let currentFrameNumber = 0;
      const frameTimesMs = new Float32Array(MAX_FRAMES);
      let startTimeMs = performance.now();
      let previousFrameTimeMs = performance.now();

      const resourceCacheUsageBytes = new Float32Array(MAX_FRAMES);
      const usedJSHeapSizesBytes = new Float32Array(MAX_FRAMES);

      function drawFrame() {
        // Draw complex path with random translations and rotations.
        let randomHorizontalTranslation = 0;
        let randomVerticalTranslation = 0;
        let randomRotation = 0;

        if (urlSearchParams.has('translate')) {
          randomHorizontalTranslation = Math.random() * 50 - 25;
          randomVerticalTranslation = Math.random() * 50 - 25;
        }
        if (urlSearchParams.has('snap')) {
          randomHorizontalTranslation = Math.round(randomHorizontalTranslation);
          randomVerticalTranslation = Math.round(randomVerticalTranslation);
        }
        if (urlSearchParams.has('opacity')) {
          paintColor = TRANSPARENT_PINK;
        }
        if (urlSearchParams.has('rotate')) {
          randomRotation = (Math.random() - 0.5) / 20;
        }

        skcanvas.clear(CanvasKit.WHITE);
        for (const [path, color] of svgPathAndFillColorPairs) {
          path.transform([Math.cos(randomRotation), -Math.sin(randomRotation), randomHorizontalTranslation,
                          Math.sin(randomRotation), Math.cos(randomRotation), randomVerticalTranslation,
                          0, 0, 1 ]);
          paint.setColor(paintColor);
          skcanvas.drawPath(path, paint);
        }
        surface.flush();

        // Record perf data: measure frame times, memory usage
        const currentFrameTimeMs = performance.now();
        frameTimesMs[currentFrameNumber] = currentFrameTimeMs - previousFrameTimeMs;
        previousFrameTimeMs = currentFrameTimeMs;

        resourceCacheUsageBytes[currentFrameNumber] = grContext.getResourceCacheUsageBytes();
        usedJSHeapSizesBytes[currentFrameNumber] = window.performance.memory.totalJSHeapSize;
        currentFrameNumber++;

        const timeSinceStart = performance.now() - startTimeMs;
        if (currentFrameNumber >= MAX_FRAMES || timeSinceStart >= MAX_SAMPLE_MS) {
          window._perfData = {
            frames_ms: Array.from(frameTimesMs).slice(0, currentFrameNumber),
            resourceCacheUsage_bytes: Array.from(resourceCacheUsageBytes).slice(0, currentFrameNumber),
            usedJSHeapSizes_bytes: Array.from(usedJSHeapSizesBytes).slice(0, currentFrameNumber),
          };
          window._perfDone = true;
          return;
        }
        window.requestAnimationFrame(drawFrame);
      }
      window.requestAnimationFrame(drawFrame);
    });

    console.log('Perf is ready');
    window._perfReady = true;
  }

  function svgToPathAndFillColorPairs(svgElement, CanvasKit) {
    const pathElements = Array.from(svgElement.getElementsByTagName('path'));
    return pathElements.map((path) => [
      CanvasKit.MakePathFromSVGString(path.getAttribute("d")),
      CanvasKit.parseColorString(path.getAttribute("fill")??'#000000')
    ]);
  }

  function getSurface(CanvasKit) {
    let surface;
    if (window.location.hash.indexOf('gpu') !== -1) {
      surface = CanvasKit.MakeWebGLCanvasSurface('complex-path');
      if (!surface) {
        window._error = 'Could not make GPU surface';
        return null;
      }
      let c = document.getElementById('complex-path');
      // If CanvasKit was unable to instantiate a WebGL context, it will fallback
      // to CPU and add a ck-replaced class to the canvas element.
      if (c.classList.contains('ck-replaced')) {
        window._error = 'fell back to CPU';
        return null;
      }
    } else {
      surface = CanvasKit.MakeSWCanvasSurface('complex-path');
      if (!surface) {
        window._error = 'Could not make CPU surface';
        return null;
      }
    }
    return surface;
  }
  </script>
</body>
</html>