<!-- 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.Paint();
      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>
