/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkCanvas.h"
#include "include/core/SkM44.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkVertices.h"
#include "include/private/SkTPin.h"
#include "tools/viewer/ClickHandlerSlide.h"

#include <array>
#include <unordered_set>

static SkPaint paint(SkColor color,
                     float strokeWidth = -1.f,
                     SkPaint::Join join = SkPaint::kMiter_Join) {
    SkPaint paint;
    paint.setColor(color);
    paint.setAntiAlias(true);
    if (strokeWidth >= 0.f) {
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(strokeWidth);
        paint.setStrokeJoin(join);
    }
    return paint;
}

// Singular values for [a b][c d] 2x2 matrix, unordered.
static std::pair<float, float> singular_values(float a, float b, float c, float d) {
    float s1 = a*a + b*b + c*c + d*d;

    float e = a*a + b*b - c*c - d*d;
    float f = a*c + b*d;
    float s2 = SkScalarSqrt(e*e + 4*f*f);

    float singular1 = SkScalarSqrt(0.5f * (s1 + s2));
    float singular2 = SkScalarSqrt(0.5f * (s1 - s2));

    return {singular1, singular2};
}

static constexpr float kAARadius = 10.f;

//              [m00 m01 * m03]                                 [f(u,v)]
// Assuming M = [m10 m11 * m13], define the projected p'(u,v) = [g(u,v)] where
//              [ *   *  *  * ]
//              [m30 m31 * m33]
//                                                        [x]     [u]
// f(u,v) = x(u,v) / w(u,v), g(u,v) = y(u,v) / w(u,v) and [y] = M*[v]
//                                                        [*] =   [0]
//                                                        [w]     [1]
//
// x(u,v) = m00*u + m01*v + m03
// y(u,v) = m10*u + m11*v + m13
// w(u,v) = m30*u + m31*v + m33
//
// dx/du = m00, dx/dv = m01,
// dy/du = m10, dy/dv = m11
// dw/du = m30, dw/dv = m31
//
// df/du = (dx/du*w - x*dw/du)/w^2 = (m00*w - m30*x)/w^2
// df/dv = (dx/dv*w - x*dw/dv)/w^2 = (m01*w - m31*x)/w^2
// dg/du = (dy/du*w - y*dw/du)/w^2 = (m10*w - m30*y)/w^2
// dg/dv = (dy/dv*w - y*dw/du)/w^2 = (m11*w - m31*y)/w^2
//
// Singular values of [df/du df/dv] define perspective correct minimum and maximum scale factors
//                    [dg/du dg/dv]
// for M evaluated at  (u,v)
static float local_aa_radius(const SkM44& matrix, const SkV2& p) {
    SkV4 devP = matrix.map(p.x, p.y, 0.f, 1.f);

    const float dxdu = matrix.rc(0,0);
    const float dxdv = matrix.rc(0,1);
    const float dydu = matrix.rc(1,0);
    const float dydv = matrix.rc(1,1);
    const float dwdu = matrix.rc(3,0);
    const float dwdv = matrix.rc(3,1);

    float invW2 = 1.f / (devP.w * devP.w);
    // non-persp has invW2 = 1, devP.w = 1, dwdu = 0, dwdv = 0
    float dfdu = (devP.w*dxdu - devP.x*dwdu) * invW2; // non-persp -> dxdu -> m00
    float dfdv = (devP.w*dxdv - devP.x*dwdv) * invW2; // non-persp -> dxdv -> m01
    float dgdu = (devP.w*dydu - devP.y*dwdu) * invW2; // non-persp -> dydu -> m10
    float dgdv = (devP.w*dydv - devP.y*dwdv) * invW2; // non-persp -> dydv -> m11

    // no-persp, this is the singular values of [m00,m01][m10,m11], which is just the upper 2x2
    // and equivalent to SkMatrix::getMinmaxScales().
    auto [sv1, sv2] = singular_values(dfdu, dfdv, dgdu, dgdv);

    // The minimum and maximum singular values of the above matrix represent the min and maximum
    // scale factors that could be applied by the 'matrix'. So if 'p' is moved 1px locally it will
    // move between [min, max]px after transformation. Thus, moving 1/min px locally will move
    // between [1, max/min]px after transformation, ensuring the device-space offset exceeds the
    // minimum AA offset for analytic AA.
    float minScale = std::min(sv1, sv2);
    return kAARadius / minScale;
}

static constexpr float kMiterScale = 1.f;
static constexpr float kBevelScale = 0.0f;
static constexpr float kRoundScale = SK_FloatSqrt2 - 1.f;

struct LocalCornerVert {
    SkV2 fPosition;     // In unit square that each corner is normalized to
    SkV2 fNormal;       // Direction that AA outset is applied in

    float fStrokeScale; // Signed scale factor applied to external stroke radius, should be [-1,1]
    float fMirrorScale; // Scale fPosition.yx, along with external join-scale, should be [0,1].
    float fCenterWeight; // Added to external center scale, > 0 forces point to center instead.

    // 'cornerMapping' is a row-major 2x2 matrix [[x y], [z w]] to flip and rotate the normalized
    // positions into the local coord space.
    SkV3 transform(const SkM44& m, const SkV4& cornerMapping, const SkV2& cornerPt,
                   const SkV2& cornerRadii, const SkV4& devCenter, float centerWeight,
                   float strokeRadius, float joinScale, float localAARadius) const {
        const bool snapToCenter = centerWeight + fCenterWeight > 0.f;
        if (snapToCenter) {
            return {devCenter.x, devCenter.y, devCenter.w};
        } else {
            // Normalized position before any additional AA offsets
            SkV2 normalizedPos = fPosition + joinScale*fMirrorScale*SkV2{fPosition.y, fPosition.x};
            // scales the normalized unit corner to the actual radii of the corner, before any AA
            // offsets are added.
            SkV2 scale = cornerRadii + SkV2{fStrokeScale*strokeRadius, fStrokeScale*strokeRadius};
            normalizedPos = scale*normalizedPos - cornerRadii;

            if (fStrokeScale < 0.f) {
                // An inset, which means it might cross over or might be forced to the center
                SkV2 maxInset = scale - SkV2{localAARadius, localAARadius};
                if (maxInset.x < 0.f || maxInset.y < 0.f) {
                    normalizedPos =
                            SkV2{std::min(maxInset.x, 0.f), std::min(maxInset.y, 0.f)}
                            - cornerRadii;
                } else {
                    normalizedPos += localAARadius * fNormal;
                }
            } // else no normal offsetting, or device-space offsetting

            SkV2 localPos =
                   {cornerMapping.x*normalizedPos.x + cornerMapping.y*normalizedPos.y + cornerPt.x,
                    cornerMapping.z*normalizedPos.x + cornerMapping.w*normalizedPos.y + cornerPt.y};
            SkV4 devPos = m.map(localPos.x, localPos.y, 0.f, 1.f);

            const bool deviceSpaceNormal =
                    fStrokeScale > 0.f && (fNormal.x > 0.f || fNormal.y > 0.f);
            if (deviceSpaceNormal) {
                SkV2 devNorm;
                {
                    // To calculate a device-space normal, we use the normal matrix (A^-1)^T where
                    // A is CTM * T(cornerPt) * cornerMapping * scale. We inline the calculation
                    // of (T(cornerPt)*cornerMapping*scale)^-1^T * [nx, ny, 0, 0] = N', which means
                    // that CTM^-1^T * N' is equivalent to N'^T*CTM^-1, which can be calculated with
                    // two dot products if the CTM inverse is uploaded to the GPU.

                    // We add epsilon so that rectangular corners are not degenerate, and circular
                    // corners remain unmodified. This only slightly increases inaccuracy for
                    // elliptical corners.
                    float sx = (scale.y + SK_ScalarNearlyZero) / (scale.x + SK_ScalarNearlyZero);
                    // Needed to calculate intermediate W of transformed normal.
                    float px = cornerMapping.y*cornerPt.y - cornerMapping.w*cornerPt.x;
                    float py = cornerMapping.z*cornerPt.x - cornerMapping.x*cornerPt.y;
                    // Inverse CTM, presumably calculated once as a uniform
                    SkM44 inv;
                    SkAssertResult(m.invert(&inv));

                    SkV4 normX4 = { sx*cornerMapping.w*fNormal.x,
                                   -sx*cornerMapping.y*fNormal.x,
                                   0.f,
                                   sx*px*fNormal.x};
                    SkV4 normY4 = {-cornerMapping.z*fNormal.y,
                                    cornerMapping.x*fNormal.y,
                                   0.f,
                                   py*fNormal.y};

                    SkV2 normX = {inv.col(0).dot(normX4), inv.col(1).dot(normX4)};
                    SkV2 normY = {inv.col(0).dot(normY4), inv.col(1).dot(normY4)};

                    if (joinScale == kMiterScale && fNormal.x > 0.f && fNormal.y > 0.f) {
                        // normX and normY represent adjacent edges' normals, so if we normalize
                        // them before adding together, we'll have a vector that bisects the edge
                        // normals instead of a vector matching fNormal, which is what we want when
                        // we're at a miter corner.
                        normX = normX.normalize();
                        normY = normY.normalize();
                        if (normX.dot(normY) < -0.8) {
                            // Nearly opposite directions, so the sum could have cancellation, so
                            // instead bisect orthogonal vectors and flip to keep consistent
                            float sign = normX.cross(normY) >= 0.f ? 1.f : -1.f;
                            normX = sign*SkV2{-normX.y, normX.x};
                            normY = sign*SkV2{normY.y, -normY.x};
                        }
                    }

                    devNorm = (normX + normY).normalize();
                }

                // The local coordinates for a device-space AA outset are clamped to the non-outset
                // point, which means we don't care about remaining in the same pre-homogenous
                // divide plane. This makes it very easy to determine a homogenous coordinate that
                // projects to the correct device-space position.
                devPos.x += devPos.w * kAARadius * devNorm.x;
                devPos.y += devPos.w * kAARadius * devNorm.y;
            }

            return SkV3{devPos.x, devPos.y, devPos.w};
        }
    }
};

static constexpr float kHR2 = SK_ScalarRoot2Over2; // "half root 2"

static constexpr std::array<LocalCornerVert, 19> kCornerTemplate = {{
    // Stroke-scale should be -1, 0, or 1.
    // Mirror-scale should be 0 or 1.
    // Center-weight should be -2 to never snap to center, -1 to snap when stroke coords would
    //     overlap, and 0 to snap for fill-style or overlapping coords.
    // Local-aa-scale should be 0 or 1.

    //  position,       normal,   stroke-scale   mirror-scale   center-weight
    // Device-space AA outsets from outer curve
    { {0.0f, 1.0f}, { 0.0f,  1.0f},  1.0f,          0.0f,           -2.f  },
    { {0.0f, 1.0f}, { 0.0f,  1.0f},  1.0f,          1.0f,           -2.f  },
    { {0.0f, 1.0f}, { kHR2,  kHR2},  1.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { kHR2,  kHR2},  1.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 1.0f,  0.0f},  1.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 1.0f,  0.0f},  1.0f,          0.0f,           -2.f  },

    // Outer anchors (no local or device-space normal outset)
    { {0.0f, 1.0f}, { 0.0f,  0.0f},  1.0f,          0.0f,           -2.f  },
    { {0.0f, 1.0f}, { 0.0f,  0.0f},  1.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 0.0f,  0.0f},  1.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 0.0f,  0.0f},  1.0f,          0.0f,           -2.f  },

    // Center of stroke (equivalent to outer anchors when filling)
    { {0.0f, 1.0f}, { 0.0f,  0.0f},  0.0f,          0.0f,           -2.f  },
    { {0.0f, 1.0f}, { 0.0f,  0.0f},  0.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 0.0f,  0.0f},  0.0f,          1.0f,           -2.f  },
    { {1.0f, 0.0f}, { 0.0f,  0.0f},  0.0f,          0.0f,           -2.f  },

    // Inner AA insets from inner curve
    { {0.0f, 1.0f}, { 0.0f, -1.0f}, -1.0f,          0.0f,           -1.f  },
    { {0.5f, 0.5f}, {-kHR2, -kHR2}, -1.0f,          1.0f,           -1.f  },
    { {1.0f, 0.0f}, {-1.0f,  0.0f}, -1.0f,          0.0f,           -1.f  },

    // Center filling vertices (equal to inner AA insets unless center-weight = 1)
    { {0.5f, 0.5f}, {-kHR2, -kHR2}, -1.0f,          1.0f,            0.f  },
    { {1.0f, 0.0f}, {-1.0f,  0.0f}, -1.0f,          0.0f,            0.f  },
}};

static void compute_corner(SkV3 devPts[19], const SkM44& m, const SkV4& cornerMapping,
                           const SkV2& cornerPt, const SkV2& cornerRadii, const SkV4& center,
                           float centerWeight, float localAARadius, float strokeRadius,
                           SkPaint::Join join) {
    float joinScale;

    // TODO: checking against localAARadius can snap to rect corner unexpectedly under high skew
    // because localAARadius gets so big, but would be nice to be fuzzy here.
    if (cornerRadii.x <= 0.f || cornerRadii.y <= 0.f) {
        // Effectively a rectangular corner
        joinScale = kMiterScale; // default for rect corners
        if (strokeRadius > 0.f) {
            // Non-hairline strokes need to adjust the join scale factor to match style.
            if (join == SkPaint::kBevel_Join) {
                joinScale = kBevelScale;
            } else if (join == SkPaint::kRound_Join) {
                joinScale = kRoundScale;
            }
        }
    } else {
        // Rounded filled corner vertices are always positioned for a round join since the
        // underlying geometry has no real tangent discontinuity.
        joinScale = kRoundScale;
    }

    for (size_t i = 0; i < std::size(kCornerTemplate); ++i) {
        devPts[i] = kCornerTemplate[i].transform(m, cornerMapping, cornerPt, cornerRadii,
                                                 center, centerWeight, strokeRadius, joinScale,
                                                 localAARadius);
    }
}

static const uint16_t kBR = 0*std::size(kCornerTemplate);
static const uint16_t kTR = 1*std::size(kCornerTemplate);
static const uint16_t kTL = 2*std::size(kCornerTemplate);
static const uint16_t kBL = 3*std::size(kCornerTemplate);
static const size_t kVertexCount = 4*std::size(kCornerTemplate);
static void compute_vertices(SkV3 devPts[kVertexCount],
                             const SkM44& m,
                             const SkRRect& rrect,
                             float strokeRadius,
                             SkPaint::Join join) {
    SkV4 devCenter = m.map(rrect.getBounds().centerX(), rrect.getBounds().centerY(), 0.f, 1.f);

    float localAARadius = std::max({
            local_aa_radius(m, {rrect.getBounds().fRight, rrect.getBounds().fBottom}),
            local_aa_radius(m, {rrect.getBounds().fRight, rrect.getBounds().fTop}),
            local_aa_radius(m, {rrect.getBounds().fLeft, rrect.getBounds().fTop}),
            local_aa_radius(m, {rrect.getBounds().fLeft, rrect.getBounds().fBottom})
        });

    float centerWeight = 0.f; // No center snapping
    if (strokeRadius < 0.f) {
        // A fill, so inner vertices need to snap to the center and then adjust the stroke radius
        // to 0 for later math to work out nicely.
        strokeRadius = 0.f;
        centerWeight = 1.f;
    }

    // Check if the inset amount (max stroke-radius + local-aa-radius) would interfere with the
    // opposite edge's inset or interfere with the adjacent corner's curve. When this happens, snap
    // all the interior vertices to the center and let the fragment shader work through it.
    // TODO: Could force centerWeight = 2 for filled rects and quads for simplicity around non
    // orthogonal inset overlap calculations.
    float maxInset = strokeRadius + localAARadius;
    if (maxInset >= rrect.width() - maxInset || // L/R stroke insets would cross over
        maxInset >= rrect.height() - maxInset || // T/B stroke insets would cross over
        maxInset >= rrect.width() - rrect.radii(SkRRect::kLowerLeft_Corner).fX || // X corner cross
        maxInset >= rrect.width() - rrect.radii(SkRRect::kLowerRight_Corner).fX ||
        maxInset >= rrect.width() - rrect.radii(SkRRect::kUpperLeft_Corner).fX ||
        maxInset >= rrect.width() - rrect.radii(SkRRect::kUpperRight_Corner).fX ||
        maxInset >= rrect.height() - rrect.radii(SkRRect::kLowerLeft_Corner).fY || // Y corner cross
        maxInset >= rrect.height() - rrect.radii(SkRRect::kLowerRight_Corner).fY ||
        maxInset >= rrect.height() - rrect.radii(SkRRect::kUpperLeft_Corner).fY ||
        maxInset >= rrect.height() - rrect.radii(SkRRect::kUpperRight_Corner).fY) {
        // All interior vertices need to snap to the center
        centerWeight = 2.f;
    }

    // The normalized corner template is defined relative to the quarter circle with positive X
    // and positive Y, with a counter clockwise winding (if +Y points down). This corresponds to
    // the bottom-right corner.
    static constexpr SkV4 kBRBasis = { 1.f,  0.f,  0.f,  1.f};
    static constexpr SkV4 kTRBasis = { 0.f,  1.f, -1.f,  0.f};
    static constexpr SkV4 kTLBasis = {-1.f,  0.f,  0.f, -1.f};
    static constexpr SkV4 kBLBasis = { 0.f, -1.f,  1.f,  0.f};

    compute_corner(devPts + kBR, m, kBRBasis,
                   {rrect.getBounds().fRight,
                    rrect.getBounds().fBottom},
                   {rrect.radii(SkRRect::kLowerRight_Corner).fX,
                    rrect.radii(SkRRect::kLowerRight_Corner).fY},
                   devCenter, centerWeight, localAARadius, strokeRadius, join);
    compute_corner(devPts + kTR, m, kTRBasis,
                   {rrect.getBounds().fRight,
                    rrect.getBounds().fTop},
                   {rrect.radii(SkRRect::kUpperRight_Corner).fY,
                    rrect.radii(SkRRect::kUpperRight_Corner).fX},
                   devCenter, centerWeight, localAARadius,strokeRadius, join);
    compute_corner(devPts + kTL, m, kTLBasis,
                   {rrect.getBounds().fLeft,
                    rrect.getBounds().fTop},
                   {rrect.radii(SkRRect::kUpperLeft_Corner).fX,
                    rrect.radii(SkRRect::kUpperLeft_Corner).fY},
                   devCenter, centerWeight, localAARadius,strokeRadius, join);
    compute_corner(devPts + kBL, m, kBLBasis,
                   {rrect.getBounds().fLeft,
                    rrect.getBounds().fBottom},
                   {rrect.radii(SkRRect::kLowerLeft_Corner).fY,
                    rrect.radii(SkRRect::kLowerLeft_Corner).fX},
                   devCenter, centerWeight, localAARadius,strokeRadius, join);
}

// All indices
static const uint16_t kIndices[] = {
    // Exterior AA ramp outset
    kBR+0,kBR+6,kBR+1,kBR+7,kBR+2,kBR+8,kBR+3,kBR+8,kBR+4,kBR+9,kBR+5,kBR+9,
    kTR+0,kTR+6,kTR+1,kTR+7,kTR+2,kTR+8,kTR+3,kTR+8,kTR+4,kTR+9,kTR+5,kTR+9,
    kTL+0,kTL+6,kTL+1,kTL+7,kTL+2,kTL+8,kTL+3,kTL+8,kTL+4,kTL+9,kTL+5,kTL+9,
    kBL+0,kBL+6,kBL+1,kBL+7,kBL+2,kBL+8,kBL+3,kBL+8,kBL+4,kBL+9,kBL+5,kBL+9,
    kBR+0,kBR+6,kBR+6, // close and extra vertex to jump to next strip
    // Outer to central curve
    kBR+6,kBR+10,kBR+7,kBR+11,kBR+8,kBR+12,kBR+9,kBR+13,
    kTR+6,kTR+10,kTR+7,kTR+11,kTR+8,kTR+12,kTR+9,kTR+13,
    kTL+6,kTL+10,kTL+7,kTL+11,kTL+8,kTL+12,kTL+9,kTL+13,
    kBL+6,kBL+10,kBL+7,kBL+11,kBL+8,kBL+12,kBL+9,kBL+13,
    kBR+6,kBR+10,kBR+10, // close and extra vertex to jump to next strip
    // Center to inner curve's insets
    kBR+10,kBR+14,kBR+11,kBR+15,kBR+12,kBR+16,kBR+13,kBR+16,
    kTR+10,kTR+14,kTR+11,kTR+15,kTR+12,kTR+16,kTR+13,kTR+16,
    kTL+10,kTL+14,kTL+11,kTL+15,kTL+12,kTL+16,kTL+13,kTL+16,
    kBL+10,kBL+14,kBL+11,kBL+15,kBL+12,kBL+16,kBL+13,kBL+16,
    kBR+10,kBR+14,kBR+14, // close and extra vertex to jump to next strip
    // Inner inset to center of shape
    kBR+14,kBR+17,kBR+15,kBR+17,kBR+16,kBR+16,kBR+18,kTR+14,
    kTR+14,kTR+17,kTR+15,kTR+17,kTR+16,kTR+16,kTR+18,kTL+14,
    kTL+14,kTL+17,kTL+15,kTL+17,kTL+16,kTL+16,kTL+18,kBL+14,
    kBL+14,kBL+17,kBL+15,kBL+17,kBL+16,kBL+16,kBL+18,kBR+14 // close
};

// Separated to draw with different colors (vs. duplicating vertices to change colors).
static const uint16_t kOuterCornerIndices[] = {
    kBR+0,  kBR+0,kBR+6,kBR+1,kBR+7,kBR+2,kBR+8,kBR+3,kBR+8,kBR+4,kBR+9,kBR+5,  kBR+5,
    kTR+0,  kTR+0,kTR+6,kTR+1,kTR+7,kTR+2,kTR+8,kTR+3,kTR+8,kTR+4,kTR+9,kTR+5,  kTR+5,
    kTL+0,  kTL+0,kTL+6,kTL+1,kTL+7,kTL+2,kTL+8,kTL+3,kTL+8,kTL+4,kTL+9,kTL+5,  kTL+5,
    kBL+0,  kBL+0,kBL+6,kBL+1,kBL+7,kBL+2,kBL+8,kBL+3,kBL+8,kBL+4,kBL+9,kBL+5,  kBL+5,

    kBR+6,  kBR+6,kBR+10,kBR+7,kBR+11,kBR+8,kBR+12,kBR+9,kBR+13,  kBR+13,
    kTR+6,  kTR+6,kTR+10,kTR+7,kTR+11,kTR+8,kTR+12,kTR+9,kTR+13,  kTR+13,
    kTL+6,  kTL+6,kTL+10,kTL+7,kTL+11,kTL+8,kTL+12,kTL+9,kTL+13,  kTL+13,
    kBL+6,  kBL+6,kBL+10,kBL+7,kBL+11,kBL+8,kBL+12,kBL+9,kBL+13,  kBL+13
};

static const uint16_t kInnerCornerIndices[] = {
    kBR+10,  kBR+10,kBR+14,kBR+11,kBR+15,kBR+12,kBR+16,kBR+13,  kBR+13,
    kTR+10,  kTR+10,kTR+14,kTR+11,kTR+15,kTR+12,kTR+16,kTR+13,  kTR+13,
    kTL+10,  kTL+10,kTL+14,kTL+11,kTL+15,kTL+12,kTL+16,kTL+13,  kTL+13,
    kBL+10,  kBL+10,kBL+14,kBL+11,kBL+15,kBL+12,kBL+16,kBL+13,  kBL+13,
};

static const uint16_t kInteriorIndices[] = {
    kBR+14,kBR+17,kBR+15,kBR+17,kBR+16,kBR+16,kBR+18,kTR+14,
    kTR+14,kTR+17,kTR+15,kTR+17,kTR+16,kTR+16,kTR+18,kTL+14,
    kTL+14,kTL+17,kTL+15,kTL+17,kTL+16,kTL+16,kTL+18,kBL+14,
    kBL+14,kBL+17,kBL+15,kBL+17,kBL+16,kBL+16,kBL+18,kBR+14 // close
};

// Implicit in the original mesh from the tri-strip connections between corners
static const uint16_t kEdgeIndices[] = {
    kBR+5,   kBR+5,kBR+9,kTR+0,kTR+6,      kTR+6,
    kBR+9,   kBR+9,kBR+13,kTR+6,kTR+10,    kTR+10,
    kBR+13,  kBR+13,kBR+16,kTR+10,kTR+14,  kTR+14,

    kTR+5,   kTR+5,kTR+9,kTL+0,kTL+6,      kTL+6,
    kTR+9,   kTR+9,kTR+13,kTL+6,kTL+10,    kTL+10,
    kTR+13,  kTR+13,kTR+16,kTL+10,kTL+14,  kTL+14,

    kTL+5,   kTL+5,kTL+9,kBL+0,kBL+6,      kBL+6,
    kTL+9,   kTL+9,kTL+13,kBL+6,kBL+10,    kBL+10,
    kTL+13,  kTL+13,kTL+16,kBL+10,kBL+14,  kBL+14,

    kBL+5,   kBL+5,kBL+9,kBR+0,kBR+6,      kBR+6,
    kBL+9,   kBL+9,kBL+13,kBR+6,kBR+10,    kBR+10,
    kBL+13,  kBL+13,kBL+16,kBR+10,kBR+14,  kBR+14,
};

class GraphitePrimitivesSlide : public ClickHandlerSlide {
    static constexpr float kControlPointRadius = 3.f;
    static constexpr float kBaseScale = 50.f;

public:
    GraphitePrimitivesSlide()
        : fOrigin{300.f, 300.f}
        , fXAxisPoint{300.f + kBaseScale, 300.f}
        , fYAxisPoint{300.f, 300.f + kBaseScale}
        , fStrokeWidth{10.f}
        , fJoinMode(SkPaint::kMiter_Join)
        , fMode(PrimitiveMode::kFillRect) {
        fName = "GraphitePrimitives";
    }

    void draw(SkCanvas* canvas) override {
        canvas->save();
        SkM44 viewMatrix = canvas->getLocalToDevice();

        canvas->concat(this->basisMatrix());

        SkM44 totalMatrix = canvas->getLocalToDevice();

            // Base shape + style
            SkRRect rrect = this->primitiveShape();
            canvas->drawRRect(rrect, paint(SK_ColorBLUE, this->strokeWidth(), fJoinMode));
        canvas->restore();

        canvas->save();
        canvas->resetMatrix();
            // Draw the full mesh directly in device space
            this->drawVertices(canvas, totalMatrix);
            // Draw the controls in device space so we get consistent circles for the click points.
            SkV4 origin = viewMatrix.map(fOrigin.x, fOrigin.y, 0.f, 1.f);
            SkV4 xAxis = viewMatrix.map(fXAxisPoint.x, fXAxisPoint.y, 0.f, 1.f);
            SkV4 yAxis = viewMatrix.map(fYAxisPoint.x, fYAxisPoint.y, 0.f, 1.f);

            // Axes
            canvas->drawLine({origin.x/origin.w, origin.y/origin.w},
                             {xAxis.x/xAxis.w, xAxis.y/xAxis.w}, paint(SK_ColorRED, 0.f));
            canvas->drawLine({origin.x/origin.w, origin.y/origin.w},
                             {yAxis.x/yAxis.w, yAxis.y/yAxis.w}, paint(SK_ColorGREEN, 0.f));

            // Control points
            canvas->drawCircle({origin.x/origin.w, origin.y/origin.w},
                               kControlPointRadius, paint(SK_ColorBLACK));
            canvas->drawCircle({xAxis.x/xAxis.w, xAxis.y/xAxis.w},
                               kControlPointRadius, paint(SK_ColorRED));
            canvas->drawCircle({yAxis.x/yAxis.w, yAxis.y/yAxis.w},
                               kControlPointRadius, paint(SK_ColorGREEN));
        canvas->restore();
    }

    bool onChar(SkUnichar) override;

protected:
    Click* onFindClickHandler(SkScalar x, SkScalar y, skui::ModifierKey) override;
    bool onClick(Click*) override;

private:
    class Click;

    enum class PrimitiveMode {
        kFillRect,
        kFillRRect,
        kStrokeRect,
        kStrokeRRect
    };

    // Computed from 3 control points. Concat with CTM to get total matrix.
    SkM44 basisMatrix() const {
        SkV2 xAxis = (fXAxisPoint - fOrigin) / kBaseScale;
        SkV2 yAxis = (fYAxisPoint - fOrigin) / kBaseScale;

        return SkM44::Cols({xAxis.x, xAxis.y, 0.f, 0.f},
                           {yAxis.x, yAxis.y, 0.f, 0.f},
                           {0.f, 0.f, 1.f, 0.f},
                           {fOrigin.x, fOrigin.y, 0.f, 1.f});
    }

    float strokeWidth() const {
        if (fMode == PrimitiveMode::kFillRect || fMode == PrimitiveMode::kFillRRect) {
            return -1.f;
        }
        return fStrokeWidth;
    }

    SkRRect primitiveShape() const {
        static const SkRect kOuterBounds = SkRect::MakeLTRB(-kBaseScale, -kBaseScale,
                                                            kBaseScale, kBaseScale);
        // Filled rounded rects can have arbitrary corners
        static const SkVector kOuterRadii[4] = { { 0.25f * kBaseScale, 0.75f * kBaseScale },
                                                 { 0.f, 0.f},
                                                 { 0.5f * kBaseScale, 0.5f * kBaseScale },
                                                 { 0.75f * kBaseScale, 0.25f * kBaseScale } };
        // // Stroked rounded rects will only have circular corners
        static const SkVector kStrokeRadii[4] = { { 0.25f * kBaseScale, 0.25f * kBaseScale },
                                                  { 0.f, 0.f },
                                                  { 0.5f * kBaseScale, 0.5f * kBaseScale },
                                                  { 0.75f * kBaseScale, 0.75f * kBaseScale } };

        float strokeRadius = 0.5f * fStrokeWidth;
        switch(fMode) {
            case PrimitiveMode::kFillRect:
                return SkRRect::MakeRect(kOuterBounds.makeOutset(strokeRadius, strokeRadius));
            case PrimitiveMode::kFillRRect: {
                SkRRect rrect;
                rrect.setRectRadii(kOuterBounds, kOuterRadii);
                rrect.outset(strokeRadius, strokeRadius);
                return rrect; }
            case PrimitiveMode::kStrokeRect:
                return SkRRect::MakeRect(kOuterBounds);
            case PrimitiveMode::kStrokeRRect: {
                SkRRect rrect;
                rrect.setRectRadii(kOuterBounds, kStrokeRadii);
                return rrect;
            }
        }

        SkUNREACHABLE;
    }

    void drawVertices(SkCanvas* canvas, const SkM44& ctm) {
        SkRRect rrect = this->primitiveShape();
        float strokeRadius = 0.5f * this->strokeWidth();

        std::array<SkV3, kVertexCount> points;
        SkPoint vertices[kVertexCount];
        compute_vertices(points.data(), ctm, rrect, strokeRadius, fJoinMode);
        // SkCanvas::drawVertices() wants SkPoint, but normally we'd let the GPU handle the
        // perspective division and clipping.
        for (size_t i = 0; i < kVertexCount; ++i) {
            vertices[i] = SkPoint{points[i].x/points[i].z, points[i].y/points[i].z};
        }

        auto drawMeshSubset = [vertices, canvas](SkColor color,
                                                 const uint16_t* indices,
                                                 size_t indexCount) {
            sk_sp<SkVertices> mesh = SkVertices::MakeCopy(
                    SkVertices::kTriangleStrip_VertexMode, kVertexCount, vertices,
                    nullptr, nullptr, (int) indexCount, indices);
            SkPaint meshPaint;
            meshPaint.setColor(color);
            meshPaint.setAlphaf(0.5f);
            canvas->drawVertices(mesh, SkBlendMode::kSrc, meshPaint);
        };
        if (fColorize) {
            drawMeshSubset(SK_ColorGRAY,
                           kEdgeIndices,
                           std::size(kEdgeIndices));
            drawMeshSubset(SK_ColorDKGRAY,
                           kInteriorIndices,
                           std::size(kInteriorIndices));
            drawMeshSubset(SK_ColorMAGENTA,
                           kInnerCornerIndices,
                           std::size(kInnerCornerIndices));
            drawMeshSubset(SK_ColorCYAN,
                           kOuterCornerIndices,
                           std::size(kOuterCornerIndices));
        } else {
            drawMeshSubset(SK_ColorGRAY, kIndices, std::size(kIndices));
        }

        // Draw the edges over the triangle strip mesh, but keep track of edges already drawn so
        // that we don't oversaturate AA on edges shared by multiple triangles.
        std::unordered_set<uint32_t> edges;
        auto drawEdge = [&edges, vertices, canvas](uint16_t e0, uint16_t e1) {
            uint32_t edgeID = (std::max(e0, e1) << 16) | std::min(e0, e1);
            if (edges.find(edgeID) == edges.end()) {
                edges.insert(edgeID);
                if (SkScalarNearlyEqual(vertices[e0].fX, vertices[e1].fX) &&
                    SkScalarNearlyEqual(vertices[e0].fY, vertices[e1].fY)) {
                    return;
                }
                canvas->drawLine(vertices[e0], vertices[e1], paint(SK_ColorBLACK, 0.f));
            }
        };
        for (size_t i = 2; i < std::size(kIndices); ++i) {
            drawEdge(kIndices[i-1], kIndices[i]);
            drawEdge(kIndices[i-2], kIndices[i]);
        }
    }

    // This Sample is responsive to the entire transform of the viewer slide, including the
    // transform (rotation, scale, and perspective) selected from the widget. The 3 points below
    // define the location and basis of the local coordinate space, relative to the viewer's
    // coordinate space. This is used instead of the root canvas coordinate space because it aligns
    // with the coordinate space that the click handler operates in.
    SkV2 fOrigin;
    SkV2 fXAxisPoint;
    SkV2 fYAxisPoint;

    float fStrokeWidth;
    SkPaint::Join fJoinMode;
    PrimitiveMode fMode;
    bool fColorize = true;
};

class GraphitePrimitivesSlide::Click : public ClickHandlerSlide::Click {
public:
    Click(SkV2* point) : fPoint(point) {}

    void drag() {
        SkVector delta = fCurr - fPrev;
        *fPoint += {delta.fX, delta.fY};
    }

private:
    SkV2* fPoint;
};

ClickHandlerSlide::Click* GraphitePrimitivesSlide::onFindClickHandler(SkScalar x, SkScalar y,
                                                                      skui::ModifierKey) {
    auto selected = [x,y](const SkV2& p) {
        return ((p - SkV2{x,y}).length() < kControlPointRadius);
    };

    if (selected(fOrigin)) {
        return new Click(&fOrigin);
    } else if (selected(fXAxisPoint)) {
        return new Click(&fXAxisPoint);
    } else if (selected(fYAxisPoint)) {
        return new Click(&fYAxisPoint);
    } else {
        return nullptr;
    }
}

bool GraphitePrimitivesSlide::onClick(ClickHandlerSlide::Click* click) {
    Click* myClick = (Click*) click;
    myClick->drag();
    return true;
}

bool GraphitePrimitivesSlide::onChar(SkUnichar code) {
        switch(code) {
            case '1':
                fMode = PrimitiveMode::kFillRect;
                return true;
            case '2':
                fMode = PrimitiveMode::kFillRRect;
                return true;
            case '3':
                fMode = PrimitiveMode::kStrokeRect;
                return true;
            case '4':
                fMode = PrimitiveMode::kStrokeRRect;
                return true;
            case '-':
                fStrokeWidth = std::max(0.f, fStrokeWidth - 0.4f);
                return true;
            case '=':
                fStrokeWidth = std::min(5 * kBaseScale, fStrokeWidth + 0.4f);
                return true;
            case 'q':
                fJoinMode = SkPaint::kRound_Join;
                return true;
            case 'w':
                fJoinMode = SkPaint::kBevel_Join;
                return true;
            case 'e':
                fJoinMode = SkPaint::kMiter_Join;
                return true;
            case 'r':
                fStrokeWidth = 10.f;
                fOrigin = {300.f, 300.f};
                fXAxisPoint = {300.f + kBaseScale, 300.f};
                fYAxisPoint = {300.f, 300.f + kBaseScale};
                return true;
            case 'c':
                fColorize = !fColorize;
                return true;
        }
        return false;
}

DEF_SLIDE(return new GraphitePrimitivesSlide();)
