<!DOCTYPE html>
<title>CanvasKit Extra features (Skia via Web Assembly)</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<style>
  canvas {
    border: 1px dashed #AAA;
  }

</style>

<h2> Skottie </h2>
<canvas id=sk_legos width=300 height=300></canvas>
<canvas id=sk_drinks width=500 height=500></canvas>
<canvas id=sk_party width=500 height=500></canvas>
<canvas id=sk_onboarding width=500 height=500></canvas>
<canvas id=sk_animated_gif width=500 height=500
        title='This is an animated gif being animated in Skottie'></canvas>

<h2> RT Shader </h2>
<canvas id=rtshader width=300 height=300></canvas>
<canvas id=rtshader2 width=300 height=300></canvas>

<h2> Particles </h2>
<canvas id=particles width=500 height=500></canvas>

<h2> Paragraph </h2>
<canvas id=para1 width=600 height=600></canvas>

<h2> CanvasKit can serialize/deserialize .skp files</h2>
<canvas id=skp width=500 height=500></canvas>

<h2> 3D perspective transformations </h2>
<canvas id=camera3d width=500 height=500></canvas>
<canvas id=glyphgame width=500 height=500></canvas>

<h2> Support for extended color spaces </h2>
<a href="chrome://flags/#force-color-profile">Force P3 profile</a>
<canvas id=colorsupport width=300 height=300></canvas>

<script type="text/javascript" src="/node_modules/canvaskit/bin/canvaskit.js"></script>

<script type="text/javascript" charset="utf-8">

  var CanvasKit = null;
  var cdn = 'https://storage.googleapis.com/skia-cdn/misc/';

  const ckLoaded = CanvasKitInit({locateFile: (file) => '/node_modules/canvaskit/bin/'+file});

  const loadLegoJSON = fetch(cdn + 'lego_loader.json').then((response) => response.text());
  const loadDrinksJSON = fetch(cdn + 'drinks.json').then((response) => response.text());
  const loadConfettiJSON = fetch(cdn + 'confetti.json').then((response) => response.text());
  const loadOnboardingJSON = fetch(cdn + 'onboarding.json').then((response) => response.text());
  const loadMultiframeJSON = fetch(cdn + 'skottie_sample_multiframe.json').then((response) => response.text());

  const loadFlightGif = fetch(cdn + 'flightAnim.gif').then((response) => response.arrayBuffer());
  const loadSkp = fetch(cdn + 'picture2.skp').then((response) => response.arrayBuffer());
  const loadFont = fetch(cdn + 'Roboto-Regular.ttf').then((response) => response.arrayBuffer());
  const loadDog = fetch(cdn + 'dog.jpg').then((response) => response.arrayBuffer());
  const loadMandrill = fetch(cdn + 'mandrill_256.png').then((response) => response.arrayBuffer());
  const loadBrickTex = fetch(cdn + 'brickwork-texture.jpg').then((response) => response.arrayBuffer());
  const loadBrickBump = fetch(cdn + 'brickwork_normal-map.jpg').then((response) => response.arrayBuffer());

  const curves = {
    "MaxCount": 1000,
    "Drawable": {
      "Type": "SkCircleDrawable",
      "Radius": 2
    },
    "EffectCode": [`
      void effectSpawn(inout Effect effect) {
        effect.rate = 200;
        effect.color = float4(1, 0, 0, 1);
      }
      `
    ],
    "Code": [`
      void spawn(inout Particle p) {
        p.lifetime = 3 + rand(p.seed);
        p.vel.y = -50;
      }
      
      void update(inout Particle p) {
        float w = mix(15, 3, p.age);
        p.pos.x = sin(radians(p.age * 320)) * mix(25, 10, p.age) + mix(-w, w, rand(p.seed));
        if (rand(p.seed) < 0.5) { p.pos.x = -p.pos.x; }
      
        p.color.g = (mix(75, 220, p.age) + mix(-30, 30, rand(p.seed))) / 255;
      }
      `
    ],
    "Bindings": []
  };

  const spiralSkSL = `
  uniform float rad_scale;
  uniform float2 in_center;
  uniform float4 in_colors0;
  uniform float4 in_colors1;

  void main(float2 p, inout half4 color) {
      float2 pp = p - in_center;
      float radius = sqrt(dot(pp, pp));
      radius = sqrt(radius);
      float angle = atan(pp.y / pp.x);
      float t = (angle + 3.1415926/2) / (3.1415926);
      t += radius * rad_scale;
      t = fract(t);
      color = half4(mix(in_colors0, in_colors1, t));
  }`;

  // Examples which only require canvaskit
  ckLoaded.then((CK) => {
    CanvasKit = CK;
    ParticlesAPI1(CanvasKit);
    RTShaderAPI1(CanvasKit);
    ColorSupport(CanvasKit);
  });

  // Examples requiring external resources.
  // Set bounds to fix the 4:3 resolution of the legos
  Promise.all([ckLoaded, loadLegoJSON]).then(([ck, jsonstr]) => {
    SkottieExample(ck, 'sk_legos', jsonstr, {fLeft: -50, fTop: 0, fRight: 350, fBottom: 300});
  });
  // Re-size to fit
  let fullBounds = {fLeft: 0, fTop: 0, fRight: 500, fBottom: 500};
  Promise.all([ckLoaded, loadDrinksJSON]).then(([ck, jsonstr]) => {
    SkottieExample(ck, 'sk_drinks', jsonstr, fullBounds);
  });
  Promise.all([ckLoaded, loadConfettiJSON]).then(([ck, jsonstr]) => {
    SkottieExample(ck, 'sk_party', jsonstr, fullBounds);
  });
  Promise.all([ckLoaded, loadOnboardingJSON]).then(([ck, jsonstr]) => {
    SkottieExample(ck, 'sk_onboarding', jsonstr, fullBounds);
  });
  Promise.all([ckLoaded, loadMultiframeJSON, loadFlightGif]).then(([ck, jsonstr, gif]) => {
    SkottieExample(ck, 'sk_animated_gif', jsonstr, fullBounds, {'image_0.png': gif});
  });

  Promise.all([ckLoaded, loadFont]).then((results) => {
    ParagraphAPI1(...results);
    GlyphGame(...results)
  });
  Promise.all([ckLoaded, loadSkp]).then((results) => {SkpExample(...results)});
  Promise.all([ckLoaded, loadBrickTex, loadBrickBump, loadFont]).then((results) => {Camera3D(...results)});

  function SkottieExample(CanvasKit, id, jsonStr, bounds, assets) {
    if (!CanvasKit || !jsonStr) {
      return;
    }
    const animation = CanvasKit.MakeManagedAnimation(jsonStr, assets);
    const duration = animation.duration() * 1000;
    const size = animation.size();
    let c = document.getElementById(id);
    bounds = bounds || {fLeft: 0, fTop: 0, fRight: size.w, fBottom: size.h};

    // Basic managed animation test.
    if (id === 'sk_drinks') {
      animation.setColor('BACKGROUND_FILL', CanvasKit.Color(0, 163, 199, 1.0));
    }

    const surface = CanvasKit.MakeCanvasSurface(id);
    if (!surface) {
      console.error('Could not make surface');
      return;
    }

    let firstFrame = Date.now();

    function drawFrame(canvas) {
      let seek = ((Date.now() - firstFrame) / duration) % 1.0;
      let damage = animation.seek(seek);
      // TODO: SkRect.isEmpty()?
      if (damage.fRight > damage.fLeft && damage.fBottom > damage.fTop) {
        canvas.clear(CanvasKit.WHITE);
        animation.render(canvas, bounds);
      }
      surface.requestAnimationFrame(drawFrame);
    }
    surface.requestAnimationFrame(drawFrame);

    //animation.delete();
    return surface;
  }

  function ParticlesAPI1(CanvasKit) {
    const surface = CanvasKit.MakeCanvasSurface('particles');
    if (!surface) {
      console.error('Could not make surface');
      return;
    }
    const context = CanvasKit.currentContext();
    const canvas = surface.getCanvas();
    canvas.translate(250, 450);

    const particles = CanvasKit.MakeParticles(JSON.stringify(curves));
    particles.start(Date.now() / 1000.0, true);

    function drawFrame(canvas) {
      canvas.clear(CanvasKit.BLACK);

      particles.update(Date.now() / 1000.0);
      particles.draw(canvas);
      surface.requestAnimationFrame(drawFrame);
    }
    surface.requestAnimationFrame(drawFrame);
  }

  function ParagraphAPI1(CanvasKit, fontData) {
    if (!CanvasKit || !fontData) {
      return;
    }

    const surface = CanvasKit.MakeCanvasSurface('para1');
    if (!surface) {
      console.error('Could not make surface');
      return;
    }

    const canvas = surface.getCanvas();
    const fontMgr = CanvasKit.SkFontMgr.FromData([fontData]);

    const paraStyle = new CanvasKit.ParagraphStyle({
        textStyle: {
            color: CanvasKit.BLACK,
            fontFamilies: ['Roboto'],
            fontSize: 50,
        },
        textAlign: CanvasKit.TextAlign.Left,
        maxLines: 5,
    });

    const builder = CanvasKit.ParagraphBuilder.Make(paraStyle, fontMgr);
    builder.addText('The quick brown fox ate a hamburgerfons and got sick.');
    const paragraph = builder.build();

    let wrapTo = 0;

    let X = 100;
    let Y = 100;

    const font = new CanvasKit.SkFont(null, 18);
    const fontPaint = new CanvasKit.SkPaint();
    fontPaint.setStyle(CanvasKit.PaintStyle.Fill);
    fontPaint.setAntiAlias(true);

    function drawFrame(canvas) {
      canvas.clear(CanvasKit.WHITE);
      wrapTo = 350 + 150 * Math.sin(Date.now() / 2000);
      paragraph.layout(wrapTo);
      canvas.drawParagraph(paragraph, 0, 0);

      canvas.drawLine(wrapTo, 0, wrapTo, 400, fontPaint);

      let posA = paragraph.getGlyphPositionAtCoordinate(X, Y);
      canvas.drawText(`At (${X.toFixed(2)}, ${Y.toFixed(2)}) glyph is ${posA.pos}`, 5, 450, fontPaint, font);

      surface.requestAnimationFrame(drawFrame);
    }
    surface.requestAnimationFrame(drawFrame);

    let interact = (e) => {
      X = e.offsetX*2; // multiply by 2 because the canvas is 300 css pixels wide,
      Y = e.offsetY*2; // but the canvas itself is 600px wide
    };

    document.getElementById('para1').addEventListener('pointermove', interact);
    return surface;
  }

  function RTShaderAPI1(CanvasKit) {
    if (!CanvasKit) {
      return;
    }

    const surface = CanvasKit.MakeCanvasSurface('rtshader');
    if (!surface) {
      console.error('Could not make surface');
      return;
    }

    const canvas = surface.getCanvas();

    const effect = CanvasKit.SkRuntimeEffect.Make(spiralSkSL);
    const shader = effect.makeShader([
      0.5,
      150, 150,
      0, 1, 0, 1,
      1, 0, 0, 1], true);
    const paint = new CanvasKit.SkPaint();
    paint.setShader(shader);
    canvas.drawRect(CanvasKit.LTRBRect(0, 0, 300, 300), paint);

    surface.flush();
    shader.delete();
    paint.delete();
    effect.delete();
  }

  // RTShader2 demo
  Promise.all([ckLoaded, loadDog, loadMandrill]).then((values) => {
    const [CanvasKit, dogData, mandrillData] = values;
    const dogImg = CanvasKit.MakeImageFromEncoded(dogData);
    if (!dogImg) {
      console.error('could not decode dog');
      return;
    }
    const mandrillImg = CanvasKit.MakeImageFromEncoded(mandrillData);
    if (!mandrillImg) {
      console.error('could not decode mandrill');
      return;
    }
    const quadrantSize = 150;

    const dogShader = dogImg.makeShader(CanvasKit.TileMode.Clamp, CanvasKit.TileMode.Clamp,
                                        CanvasKit.SkMatrix.scaled(quadrantSize/dogImg.width(),
                                                                  quadrantSize/dogImg.height()));
    const mandrillShader = mandrillImg.makeShader(CanvasKit.TileMode.Clamp, CanvasKit.TileMode.Clamp,
                                                  CanvasKit.SkMatrix.scaled(
                                                    quadrantSize/mandrillImg.width(),
                                                    quadrantSize/mandrillImg.height()));

    const surface = CanvasKit.MakeCanvasSurface('rtshader2');
    if (!surface) {
      console.error('Could not make surface');
      return;
    }

    const prog = `
      in shader before_map;
      in shader after_map;
      in shader threshold_map;

      uniform float cutoff;
      uniform float slope;

      float smooth_cutoff(float x) {
          x = x * slope + (0.5 - slope * cutoff);
          return clamp(x, 0, 1);
      }

      void main(float2 xy, inout half4 color) {
          half4 before = sample(before_map, xy);
          half4 after = sample(after_map, xy);

          float m = smooth_cutoff(sample(threshold_map, xy).r);
          color = mix(before, after, half(m));
      }`;

    const canvas = surface.getCanvas();

    const thresholdEffect = CanvasKit.SkRuntimeEffect.Make(prog);
    const spiralEffect = CanvasKit.SkRuntimeEffect.Make(spiralSkSL);

    const draw = (x, y, shader) => {
      const paint = new CanvasKit.SkPaint();
      paint.setShader(shader);
      canvas.save();
      canvas.translate(x, y);
      canvas.drawRect(CanvasKit.LTRBRect(0, 0, quadrantSize, quadrantSize), paint);
      canvas.restore();
      paint.delete();
    };

    const offscreenSurface = CanvasKit.MakeSurface(quadrantSize, quadrantSize);
    const getBlurrySpiralShader = (rad_scale) => {
      const oCanvas = offscreenSurface.getCanvas();

      const spiralShader = spiralEffect.makeShader([
      rad_scale,
      quadrantSize/2, quadrantSize/2,
      1, 1, 1, 1,
      0, 0, 0, 1], true);

      return spiralShader;
      // TODO(kjlubick): The raster backend does not like atan or fract, so we can't
      // draw the shader into the offscreen canvas and mess with it. When we can, that
      // would be cool to show off.

      const blur = CanvasKit.SkImageFilter.MakeBlur(0.1, 0.1, CanvasKit.TileMode.Clamp, null);

      const paint = new CanvasKit.SkPaint();
      paint.setShader(spiralShader);
      paint.setImageFilter(blur);
      oCanvas.drawRect(CanvasKit.LTRBRect(0, 0, quadrantSize, quadrantSize), paint);

      paint.delete();
      blur.delete();
      spiralShader.delete();
      return offscreenSurface.makeImageSnapshot()
                             .makeShader(CanvasKit.TileMode.Clamp, CanvasKit.TileMode.Clamp);

    };

    const drawFrame = () => {
      surface.requestAnimationFrame(drawFrame);
      const thresholdShader = getBlurrySpiralShader(Math.sin(Date.now() / 5000) / 2);

      const blendShader = thresholdEffect.makeShaderWithChildren(
        [0.5, 10],
        true, [dogShader, mandrillShader, thresholdShader]);
      draw(0, 0, blendShader);
      draw(quadrantSize, 0, thresholdShader);
      draw(0, quadrantSize, dogShader);
      draw(quadrantSize, quadrantSize, mandrillShader);

      blendShader.delete();
    };

    surface.requestAnimationFrame(drawFrame);
  });

  function SkpExample(CanvasKit, skpData) {
    if (!skpData || !CanvasKit) {
      return;
    }

    const surface = CanvasKit.MakeSWCanvasSurface('skp');
    if (!surface) {
      console.error('Could not make surface');
      return;
    }

    const pic = CanvasKit.MakeSkPicture(skpData);

    function drawFrame(canvas) {
      canvas.clear(CanvasKit.TRANSPARENT);
      // this particular file has a path drawing at (68,582) that's 1300x1300 pixels
      // scale it down to 500x500 and translate it to fit.
      const scale = 500.0/1300;
      canvas.scale(scale, scale);
      canvas.translate(-68, -582);
      canvas.drawPicture(pic);
    }
    // Intentionally just draw frame once
    surface.drawOnce(drawFrame);
  }

  // Return the inverse of an SkM44. throw an error if it's not invertible
  function mustInvert(m) {
    const m2 = CanvasKit.SkM44.invert(m);
    if (m2 === null) {
      throw "Matrix not invertible";
    }
    return m2;
  }

  // TODO(nifong): This function is in desperate need of some explanation of what it does
  // cam is a object having eye, coa, up, near, far, angle
  function saveCamera(canvas, /* rect */ area, /* scalar */ zscale, cam) {
    const camera = CanvasKit.SkM44.lookat(cam.eye, cam.coa, cam.up);
    const perspective = CanvasKit.SkM44.perspective(cam.near, cam.far, cam.angle);
    // Calculate viewport scale. Even through we know these values are all constants in this
    // example it might be handy to change the size later.
    const center = [(area.fLeft + area.fRight)/2, (area.fTop + area.fBottom)/2, 0];
    const viewScale = [(area.fRight - area.fLeft)/2, (area.fBottom - area.fTop)/2, zscale];
    const viewport = CanvasKit.SkM44.multiply(
      CanvasKit.SkM44.translated(center),
      CanvasKit.SkM44.scaled(viewScale));

    // want "world" to be in our big coordinates (e.g. area), so apply this inverse
    // as part of our "camera".
    canvas.concat(CanvasKit.SkM44.multiply(viewport, perspective));
    canvas.concat(CanvasKit.SkM44.multiply(camera, mustInvert(viewport)));
    // Mark the matrix to make it available to the shader by this name.
    canvas.markCTM('local_to_world');
  }

  function Camera3D(canvas, textureImgData, normalImgData, robotoData) {
    const surface = CanvasKit.MakeCanvasSurface('camera3d');
    if (!surface) {
      console.error('Could not make surface');
      return;
    }

    const sizeX = document.getElementById('camera3d').width;
    const sizeY = document.getElementById('camera3d').height;

    let clickToWorld = CanvasKit.SkM44.identity();
    let worldToClick = CanvasKit.SkM44.identity();
    // rotation of the cube shown in the demo
    let rotation = CanvasKit.SkM44.identity();
    // temporary during a click and drag
    let clickRotation = CanvasKit.SkM44.identity();

    // A virtual sphere used for tumbling the object on screen.
    const vSphereCenter = [sizeX/2, sizeY/2];
    const vSphereRadius = Math.min(...vSphereCenter);

    // The rounded rect used for each face
    const margin = vSphereRadius / 20;
    const rr = CanvasKit.RRectXY(CanvasKit.LTRBRect(margin, margin,
      vSphereRadius - margin, vSphereRadius - margin), margin*2.5, margin*2.5);

    const camAngle = Math.PI / 12;
    const cam = {
      'eye'  : [0, 0, 1 / Math.tan(camAngle/2) - 1],
      'coa'  : [0, 0, 0],
      'up'   : [0, 1, 0],
      'near' : 0.05,
      'far'  : 4,
      'angle': camAngle,
    };

    let mouseDown = false;
    let clickDown = [0, 0]; // location of click down
    let lastMouse = [0, 0]; // last mouse location

    // keep spinning after mouse up. Also start spinning on load
    let axis = [0.4, 1, 1];
    let totalSpin = 0;
    let spinRate = 0.1;
    let lastRadians = 0;
    let spinning = setInterval(keepSpinning, 30);

    const textPaint = new CanvasKit.SkPaint();
    textPaint.setColor(CanvasKit.BLACK);
    textPaint.setAntiAlias(true);
    const roboto = CanvasKit.SkFontMgr.RefDefault().MakeTypefaceFromData(robotoData);
    const textFont = new CanvasKit.SkFont(roboto, 30);

    const imgscale = CanvasKit.SkMatrix.scaled(2, 2);
    const textureShader = CanvasKit.MakeImageFromEncoded(textureImgData).makeShader(
      CanvasKit.TileMode.Clamp, CanvasKit.TileMode.Clamp, imgscale);
    const normalShader = CanvasKit.MakeImageFromEncoded(normalImgData).makeShader(
      CanvasKit.TileMode.Clamp, CanvasKit.TileMode.Clamp, imgscale);
    const children = [textureShader, normalShader];

    const prog = `
      in shader color_map;
      in shader normal_map;

      uniform float3   lightPos;
      layout (marker=local_to_world)          uniform float4x4 localToWorld;
      layout (marker=normals(local_to_world)) uniform float4x4 localToWorldAdjInv;

      float3 convert_normal_sample(half4 c) {
        float3 n = 2 * c.rgb - 1;
        n.y = -n.y;
        return n;
      }

      void main(float2 p, inout half4 color) {
        float3 norm = convert_normal_sample(sample(normal_map, p));
        float3 plane_norm = normalize(localToWorldAdjInv * float4(norm, 0)).xyz;

        float3 plane_pos = (localToWorld * float4(p, 0, 1)).xyz;
        float3 light_dir = normalize(lightPos - plane_pos);

        float ambient = 0.2;
        float dp = dot(plane_norm, light_dir);
        float scale = min(ambient + max(dp, 0), 1);

        color = sample(color_map, p) * half4(float4(scale, scale, scale, 1)); 
      }
`;

    const fact = CanvasKit.SkRuntimeEffect.Make(prog);

    // properties of light
    let lightLocation = [...vSphereCenter];
    let lightDistance = vSphereRadius;
    let lightIconRadius = 12;
    let draggingLight = false;

    function computeLightWorldPos() {
      return CanvasKit.SkVector.add(CanvasKit.SkVector.mulScalar([...vSphereCenter, 0], 0.5),
        CanvasKit.SkVector.mulScalar(vSphereUnitV3(lightLocation), lightDistance));
    }

    let lightWorldPos = computeLightWorldPos();

    function drawLight(canvas) {
      const paint = new CanvasKit.SkPaint();
      paint.setAntiAlias(true);
      paint.setColor(CanvasKit.WHITE);
      canvas.drawCircle(...lightLocation, lightIconRadius + 2, paint);
      paint.setColor(CanvasKit.BLACK);
      canvas.drawCircle(...lightLocation, lightIconRadius, paint);
    }

    // Takes an x and y rotation in radians and a scale and returns a 4x4 matrix used to draw a
    // face of the cube in that orientation.
    function faceM44(rx, ry, scale) {
      return CanvasKit.SkM44.multiply(
        CanvasKit.SkM44.rotated([0,1,0], ry),
        CanvasKit.SkM44.rotated([1,0,0], rx),
        CanvasKit.SkM44.translated([0, 0, scale]));
    }

    const faceScale = vSphereRadius/2
    const faces = [
      {matrix: faceM44(         0,         0, faceScale ), color:CanvasKit.RED}, // front
      {matrix: faceM44(         0,   Math.PI, faceScale ), color:CanvasKit.GREEN}, // back

      {matrix: faceM44( Math.PI/2,         0, faceScale ), color:CanvasKit.BLUE}, // top
      {matrix: faceM44(-Math.PI/2,         0, faceScale ), color:CanvasKit.CYAN}, // bottom

      {matrix: faceM44(         0, Math.PI/2, faceScale ), color:CanvasKit.MAGENTA}, // left
      {matrix: faceM44(         0,-Math.PI/2, faceScale ), color:CanvasKit.YELLOW}, // right
    ];

    // Returns a component of the matrix m indicating whether it faces the camera.
    // If it's positive for one of the matrices representing the face of the cube,
    // that face is currently in front.
    function front(m) {
      // Is this invertible?
      var m2 = CanvasKit.SkM44.invert(m);
      if (m2 === null) {
        m2 = CanvasKit.SkM44.identity();
      }
      // look at the sign of the z-scale of the inverse of m.
      // that's the number in row 2, col 2.
      return m2[10]
    }

    function setClickToWorld(canvas, matrix) {
      const l2d = canvas.getLocalToDevice();
      worldToClick = CanvasKit.SkM44.multiply(mustInvert(matrix), l2d);
      clickToWorld = mustInvert(worldToClick);
    }

    function drawCubeFace(canvas, m, color) {
      const trans = new CanvasKit.SkM44.translated([vSphereRadius/2, vSphereRadius/2, 0]);
      canvas.concat(CanvasKit.SkM44.multiply(trans, m, mustInvert(trans)));
      const znormal = front(canvas.getLocalToDevice());
      if (znormal < 0) {
        return; // skip faces facing backwards
      }
      // Pad with space for two 4x4 matrices. Even though the shader uses a layout()
      // statement to populate them, we still have to reserve space for them.
      const uniforms = [...lightWorldPos, ...Array(32).fill(0)];
      const paint = new CanvasKit.SkPaint();
      paint.setAntiAlias(true);
      const shader = fact.makeShaderWithChildren(uniforms, true /*=opaque*/, children);
      paint.setShader(shader);
      canvas.drawRRect(rr, paint);
      canvas.drawText(znormal.toFixed(2), faceScale*0.25, faceScale*0.4, textPaint, textFont);
    }

    function drawFrame(canvas) {
      const clickM = canvas.getLocalToDevice();
      canvas.save();
      canvas.translate(vSphereCenter[0] - vSphereRadius/2, vSphereCenter[1] - vSphereRadius/2);
      // pass surface dimensions as viewport size.
      saveCamera(canvas, CanvasKit.LTRBRect(0, 0, vSphereRadius, vSphereRadius), vSphereRadius/2, cam);
      setClickToWorld(canvas, clickM);
      for (let f of faces) {
        const saveCount = canvas.getSaveCount();
        canvas.save();
        drawCubeFace(canvas, CanvasKit.SkM44.multiply(clickRotation, rotation, f.matrix), f.color);
        canvas.restoreToCount(saveCount);
      }
      canvas.restore();  // camera
      canvas.restore();  // center the following content in the window

      // draw virtual sphere outline.
      const paint = new CanvasKit.SkPaint();
      paint.setAntiAlias(true);
      paint.setStyle(CanvasKit.PaintStyle.Stroke);
      paint.setColor(CanvasKit.Color(64, 255, 0, 1.0));
      canvas.drawCircle(vSphereCenter[0], vSphereCenter[1], vSphereRadius, paint);
      canvas.drawLine(vSphereCenter[0], vSphereCenter[1] - vSphereRadius,
                       vSphereCenter[0], vSphereCenter[1] + vSphereRadius, paint);
      canvas.drawLine(vSphereCenter[0] - vSphereRadius, vSphereCenter[1],
                       vSphereCenter[0] + vSphereRadius, vSphereCenter[1], paint);

      drawLight(canvas);
    }

    // convert a 2D point in the circle displayed on screen to a 3D unit vector.
    // the virtual sphere is a technique selecting a 3D direction by clicking on a the projection
    // of a hemisphere.
    function vSphereUnitV3(p) {
      // v = (v - fCenter) * (1 / fRadius);
      let v = CanvasKit.SkVector.mulScalar(CanvasKit.SkVector.sub(p, vSphereCenter), 1/vSphereRadius);

      // constrain the clicked point within the circle.
      let len2 = CanvasKit.SkVector.lengthSquared(v);
      if (len2 > 1) {
          v = CanvasKit.SkVector.normalize(v);
          len2 = 1;
      }
      // the closer to the edge of the circle you are, the closer z is to zero.
      const z = Math.sqrt(1 - len2);
      v.push(z);
      return v;
    }

    function computeVSphereRotation(start, end) {
      const u = vSphereUnitV3(start);
      const v = vSphereUnitV3(end);
      // Axis is in the scope of the Camera3D function so it can be used in keepSpinning.
      axis = CanvasKit.SkVector.cross(u, v);
      const sinValue = CanvasKit.SkVector.length(axis);
      const cosValue = CanvasKit.SkVector.dot(u, v);

      let m = new CanvasKit.SkM44.identity();
      if (Math.abs(sinValue) > 0.000000001) {
          m = CanvasKit.SkM44.rotatedUnitSinCos(
            CanvasKit.SkVector.mulScalar(axis, 1/sinValue), sinValue, cosValue);
          const radians = Math.atan(cosValue / sinValue);
          spinRate = lastRadians - radians;
          lastRadians = radians;
      }
      return m;
    }

    function keepSpinning() {
      totalSpin += spinRate;
      clickRotation = CanvasKit.SkM44.rotated(axis, totalSpin);
      spinRate *= .998;
      if (spinRate < 0.01) {
        stopSpinning();
      }
      surface.requestAnimationFrame(drawFrame);
    }

    function stopSpinning() {
        clearInterval(spinning);
        rotation = CanvasKit.SkM44.multiply(clickRotation, rotation);
        clickRotation = CanvasKit.SkM44.identity();
    }

    function interact(e) {
      const type = e.type;
      let eventPos = [e.offsetX, e.offsetY];
      if (type === 'lostpointercapture' || type === 'pointerup' || type == 'pointerleave') {
        if (draggingLight) {
          draggingLight = false;
        } else if (mouseDown) {
          mouseDown = false;
          if (spinRate > 0.02) {
            stopSpinning();
            spinning = setInterval(keepSpinning, 30);
          }
        } else {
          return;
        }
        return;
      } else if (type === 'pointermove') {
        if (draggingLight) {
          lightLocation = eventPos;
          lightWorldPos = computeLightWorldPos();
        } else if (mouseDown) {
          lastMouse = eventPos;
          clickRotation = computeVSphereRotation(clickDown, lastMouse);
        } else {
          return;
        }
      } else if (type === 'pointerdown') {
        // Are we repositioning the light?
        if (CanvasKit.SkVector.dist(eventPos, lightLocation) < lightIconRadius) {
          draggingLight = true;
          return;
        }
        stopSpinning();
        mouseDown = true;
        clickDown = eventPos;
        lastMouse = eventPos;
      }
      surface.requestAnimationFrame(drawFrame);
    };

    document.getElementById('camera3d').addEventListener('pointermove', interact);
    document.getElementById('camera3d').addEventListener('pointerdown', interact);
    document.getElementById('camera3d').addEventListener('lostpointercapture', interact);
    document.getElementById('camera3d').addEventListener('pointerleave', interact);
    document.getElementById('camera3d').addEventListener('pointerup', interact);

    surface.requestAnimationFrame(drawFrame);
  }

  // Shows a hidden message by rotating all the characters in a kind of way that makes you
  // search with your mouse.
  function GlyphGame(canvas, robotoData) {
    const surface = CanvasKit.MakeCanvasSurface('glyphgame');
    if (!surface) {
      console.error('Could not make surface');
      return;
    }
    const sizeX = document.getElementById('glyphgame').width;
    const sizeY = document.getElementById('glyphgame').height;
    const halfDim = Math.min(sizeX, sizeY) / 2;
    const margin = 50;
    const marginTop = 25;
    let rotX = 0; //  expected to be updated in interact()
    let rotY = 0;
    let pointer = [500, 450];
    const radPerPixel = 0.005; // radians of subject rotation per pixel distance moved by mouse.

    const camAngle = Math.PI / 12;
    const cam = {
      'eye'  : [0, 0, 1 / Math.tan(camAngle/2) - 1],
      'coa'  : [0, 0, 0],
      'up'   : [0, 1, 0],
      'near' : 0.02,
      'far'  : 4,
      'angle': camAngle,
    };

    let lastImage = null;

    const fontMgr = CanvasKit.SkFontMgr.FromData([robotoData]);

    const paraStyle = new CanvasKit.ParagraphStyle({
        textStyle: {
            color: CanvasKit.Color(105, 56, 16), // brown
            fontFamilies: ['Roboto'],
            fontSize: 28,
        },
        textAlign: CanvasKit.TextAlign.Left,
    });
    const hStyle = CanvasKit.RectHeightStyle.Max;
    const wStyle = CanvasKit.RectWidthStyle.Tight;

    const quotes = [
      'Some activities superficially familiar to you are merely stupid and should be avoided for your safety, although they are not illegal as such. These include: giving your bank account details to the son of the Nigerian Minister of Finance; buying title to bridges, skyscrapers, spacecraft, planets, or other real assets; murder; selling your identity; and entering into financial contracts with entities running Economics 2.0 or higher.',
      // Charles Stross - Accelerando
      'If only there were evil people somewhere insidiously committing evil deeds, and it were necessary only to separate them from the rest of us and destroy them. But the line dividing good and evil cuts through the heart of every human being. And who is willing to destroy a piece of his own heart?',
      // Aleksandr Solzhenitsyn - The Gulag Archipelago
      'There is one metaphor of which the moderns are very fond; they are always saying, “You can’t put the clock back.” The simple and obvious answer is “You can.” A clock, being a piece of human construction, can be restored by the human finger to any figure or hour. In the same way society, being a piece of human construction, can be reconstructed upon any plan that has ever existed.',
      // G. K. Chesterton - What's Wrong With The World?
    ];

    // pick one at random
    const text = quotes[Math.floor(Math.random()*3)];
    const builder = CanvasKit.ParagraphBuilder.Make(paraStyle, fontMgr);
    builder.addText(text);
    const paragraph = builder.build();
    const font = new CanvasKit.SkFont(null, 18);
    // wrap the text to a given width.
    paragraph.layout(sizeX - margin*2);

    // to rotate every glyph individually, calculate the bounding rect of each one,
    // construct an array of rects and paragraphs that would draw each glyph individually.
    const letters = Array(text.length);
    for (let i = 0; i < text.length; i++) {
      const r = paragraph.getRectsForRange(i, i+1, hStyle, wStyle)[0];
      // The character is drawn with drawParagraph so we can pass the paraStyle,
      // and have our character be the exact size and shape the paragraph expected
      // when it wrapped the text. canvas.drawText wouldn't cut it.
      const tmpbuilder = CanvasKit.ParagraphBuilder.Make(paraStyle, fontMgr);
      tmpbuilder.addText(text[i]);
      const para = tmpbuilder.build();
      para.layout(100);
      letters[i] = {
        'r': r,
        'para': para,
      };
    }

    function drawFrame(canvas) {
      // persistence of vision effect is done by drawing the past frame as an image,
      // then covering with semitransparent background color.
      if (lastImage) {
        canvas.drawImage(lastImage, 0, 0, null);
        canvas.drawColor(CanvasKit.Color(171, 244, 255, 0.1)); // sky blue, almost transparent 
      } else {
        canvas.clear(CanvasKit.Color(171, 244, 255)); // sky blue, opaque
      }
      canvas.save();
      // Set up 3D view enviroment
      saveCamera(canvas, CanvasKit.LTRBRect(0, 0, sizeX, sizeY), halfDim, cam);

      // Rotate the whole paragraph as a unit.
      const paraRotPoint = [halfDim, halfDim, 1];
      canvas.concat(CanvasKit.SkM44.multiply(
        CanvasKit.SkM44.translated(paraRotPoint),
        CanvasKit.SkM44.rotated([0,1,0], rotX),
        CanvasKit.SkM44.rotated([1,0,0], rotY * 0.2),
        CanvasKit.SkM44.translated(CanvasKit.SkVector.mulScalar(paraRotPoint, -1)),
      ));

      // Rotate every glyph in the paragraph individually.
      let i = 0;
      for (const letter of letters) {
        canvas.save();
        let r = letter['r'];
        // rotate about the center of the glyph's rect.
        rotationPoint = [
          margin + r.fLeft + (r.fRight - r.fLeft) / 2,
          marginTop + r.fTop + (r.fBottom - r.fTop) / 2,
          0
        ];
        distanceFromPointer = CanvasKit.SkVector.dist(pointer, rotationPoint.slice(0, 2));
        // Rotate more around the Y-axis depending on the glyph's distance from the pointer.
        canvas.concat(CanvasKit.SkM44.multiply(
          CanvasKit.SkM44.translated(rotationPoint),
          // note that I'm rotating around the x axis first, undoing some of the rotation done to the whole
          // paragraph above, where x came second. If I rotated y first, a lot of letters would end up
          // upside down, which is a bit too hard to unscramble.
          CanvasKit.SkM44.rotated([1,0,0], rotY * -0.6),
          CanvasKit.SkM44.rotated([0,1,0], distanceFromPointer * -0.035),
          CanvasKit.SkM44.translated(CanvasKit.SkVector.mulScalar(rotationPoint, -1)),
        ));
        canvas.drawParagraph(letter['para'], margin + r.fLeft, marginTop + r.fTop);
        i++;
        canvas.restore();
      }
      canvas.restore();
      lastImage = surface.makeImageSnapshot();
    }

    function interact(e) {
      pointer = [e.offsetX, e.offsetY]
      rotX = (pointer[0] - halfDim) * radPerPixel;
      rotY = (pointer[1] - halfDim) * radPerPixel * -1;
      surface.requestAnimationFrame(drawFrame);
    };

    document.getElementById('glyphgame').addEventListener('pointermove', interact);
    surface.requestAnimationFrame(drawFrame);
  }

  function ColorSupport(CanvasKit) {
    const surface = CanvasKit.MakeCanvasSurface('colorsupport', CanvasKit.SkColorSpace.ADOBE_RGB);
    if (!surface) {
      console.error('Could not make surface');
      return;
    }
    const canvas = surface.getCanvas();

    // If the surface is correctly initialized with a higher bit depth color type,
    // And chrome is compositing it into a buffer with the P3 color space,
    // then the inner round rect should be distinct and less saturated than the full red background.
    // Even if the monitor it is viewed on cannot accurately represent that color space.

    let red = CanvasKit.Color4f(1, 0, 0, 1);
    let paint = new CanvasKit.SkPaint();
    paint.setColor(red, CanvasKit.SkColorSpace.ADOBE_RGB);
    canvas.drawPaint(paint);
    paint.setColor(red, CanvasKit.SkColorSpace.DISPLAY_P3);
    canvas.drawRoundRect(CanvasKit.LTRBRect(50, 50, 250, 250), 30, 30, paint);
    paint.setColor(red, CanvasKit.SkColorSpace.SRGB);
    canvas.drawRoundRect(CanvasKit.LTRBRect(100, 100, 200, 200), 30, 30, paint);

    surface.flush();
    surface.delete();
  }
</script>
