// Standalone tests for reasampler::ui::stroke_aa — no REAPER, no LICE, no framework.
// Same fast assert loop as the sibling pure tests.
//
// The three properties here are the ones the shipped LICE draws failed, so each is asserted as a
// NUMBER rather than eyeballed: an opaque core (LICE_Arc's AA circle splits one unit of ink across
// two pixels by the radius's fraction, so no pixel ever reached 255); perpendicular weight that
// does not vary with angle (LICE_ThickFLine lays its width along the minor axis, rippling 42%
// around a knob sweep); and MAX-into-scratch accumulation (per-segment blending re-lays ink over
// the previous segment's fringe, which is what made a stroke read as a glow).

#include "../src/core/ui/stroke_aa.h"

#include <cmath>
#include <cstdio>
#include <vector>

using namespace reasampler;
using namespace reasampler::ui;

static int g_fail = 0;
#define CHECK(cond) do { if(!(cond)) { \
    std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)

static const Rect kBig{0, 0, 240, 240};
static constexpr float kPi = 3.14159265358979323846f;

// --- helpers -----------------------------------------------------------------

static float peakCoverage(const StrokeCanvas& c) {
    float peak = 0.0f;
    const Rect& b = c.bounds();
    for (int y = b.y; y < b.bottom(); ++y)
        for (int x = b.x; x < b.right(); ++x)
            if (c.coverageAt(x, y) > peak) peak = c.coverageAt(x, y);
    return peak;
}

static float totalInk(const StrokeCanvas& c) {
    float sum = 0.0f;
    const Rect& b = c.bounds();
    for (int y = b.y; y < b.bottom(); ++y)
        for (int x = b.x; x < b.right(); ++x) sum += c.coverageAt(x, y);
    return sum;
}

// Ink per unit length across a window in the MIDDLE of a straight stroke, binned by each pixel's
// projection onto the stroke direction. This is literally "perpendicular weight": for a stroke of
// half-width hw the answer is 2*hw at every angle, and it is the measurement that fails against a
// minor-axis-width primitive.
static float perpendicularWeight(float angleDeg, float halfWidth) {
    const float a = angleDeg * kPi / 180.0f;
    const float dx = std::cos(a), dy = std::sin(a);
    const float cx = 120.0f, cy = 120.0f;
    const float half = 90.0f;   // stroke reaches well past the window on both sides
    const float win = 40.0f;    // window half-length, clear of both round caps
    const StrokePoint pts[2] = {{cx - dx * half, cy - dy * half},
                                {cx + dx * half, cy + dy * half}};
    StrokeCanvas c;
    strokePolyline(c, pts, 2, halfWidth, kBig);
    float sum = 0.0f;
    const Rect& b = c.bounds();
    for (int y = b.y; y < b.bottom(); ++y) {
        for (int x = b.x; x < b.right(); ++x) {
            const float s = (static_cast<float>(x) + 0.5f - cx) * dx +
                            (static_cast<float>(y) + 0.5f - cy) * dy;
            if (s >= -win && s < win) sum += c.coverageAt(x, y);
        }
    }
    return sum / (2.0f * win);
}

// --- coverage / distance math ------------------------------------------------

static void testStraightStrokeHasAnOpaqueCore() {
    // The shipped defect stated numerically: peak alpha must reach full, not 137-192/255.
    // 2 and 3 px only: below the >= 2 px opaque-core threshold (core/ui/CLAUDE.md), a stroke
    // does NOT reliably reach full alpha — see testSubOpaqueCoreAtOnePixelWidth below.
    for (float w : {2.0f, 3.0f}) {
        for (float deg : {0.0f, 17.0f, 45.0f, 63.0f, 90.0f}) {
            const float a = deg * kPi / 180.0f;
            const StrokePoint pts[2] = {{120.0f - 80.0f * std::cos(a), 120.0f - 80.0f * std::sin(a)},
                                        {120.0f + 80.0f * std::cos(a), 120.0f + 80.0f * std::sin(a)}};
            StrokeCanvas c;
            strokePolyline(c, pts, 2, w * 0.5f, kBig);
            CHECK(peakCoverage(c) >= 0.999f);
        }
    }
}

static void testSubOpaqueCoreAtOnePixelWidth() {
    // Below the >= 2 px opaque-core threshold: a 1 px stroke (halfWidth = 0.5) has zero slack
    // against the 0.5 px worst-case pixel-centre distance (core/ui/CLAUDE.md), so peak alpha
    // tracks the stroke's alignment to the pixel grid instead of reaching 255 everywhere. Pin
    // both ends of that modulation — no shipping surface draws at 1 px anymore (Daniel's
    // ruling, 2026-08-01), but this stays a real property of the stroker worth guarding
    // against reintroducing.
    const StrokePoint onRowCentre[2] = {{20.0f, 100.5f}, {220.0f, 100.5f}};  // centred on row 100
    StrokeCanvas aligned;
    strokePolyline(aligned, onRowCentre, 2, 0.5f, kBig);
    CHECK(aligned.coverageAt(120, 100) >= 0.999f);   // aligned to the grid: reaches opaque

    const StrokePoint onRowBoundary[2] = {{20.0f, 100.0f}, {220.0f, 100.0f}};  // on the boundary
    StrokeCanvas misaligned;
    strokePolyline(misaligned, onRowBoundary, 2, 0.5f, kBig);
    CHECK(std::fabs(misaligned.coverageAt(120, 99) - 0.5f) < 1e-4f);   // split evenly...
    CHECK(std::fabs(misaligned.coverageAt(120, 100) - 0.5f) < 1e-4f);  // ...across both rows
    CHECK(peakCoverage(misaligned) < 0.999f);        // and never reaches the opaque core here
}

static void testPerpendicularWeightIsAngleIndependent() {
    // The criterion that killed the ThickFLine option: it dips to wid*cos(theta) at every 45
    // degrees. An axis-aligned-only sample would pass against it, so sample the diagonals.
    for (float w : {2.0f, 3.0f}) {
        float lo = 1e9f, hi = -1e9f;
        for (float deg = 0.0f; deg <= 90.0f; deg += 7.5f) {
            const float m = perpendicularWeight(deg, w * 0.5f);
            if (m < lo) lo = m;
            if (m > hi) hi = m;
            CHECK(std::fabs(m - w) < 0.06f * w);   // within 6% of nominal at every angle
        }
        CHECK((hi - lo) / w < 0.08f);              // and the spread across angles is under 8%
    }
}

static void testWeightHoldsAtTheExactDiagonal() {
    // Pinned separately because 45 degrees is where the rejected primitive was worst (0.707x).
    const float m = perpendicularWeight(45.0f, 1.0f);
    CHECK(m > 1.88f && m < 2.12f);
}

static void testZeroLengthSegmentIsARoundDot() {
    StrokeCanvas c;
    c.reset(kBig);
    c.addSegment(60.0f, 60.0f, 60.0f, 60.0f, 1.5f);   // degenerate: start == end
    CHECK(peakCoverage(c) >= 0.999f);
    // Radially symmetric about the point, and zero well outside the reach.
    CHECK(std::fabs(c.coverageAt(58, 60) - c.coverageAt(61, 60)) < 1e-5f);
    CHECK(std::fabs(c.coverageAt(60, 58) - c.coverageAt(60, 61)) < 1e-5f);
    CHECK(c.coverageAt(65, 60) == 0.0f);
    CHECK(c.coverageAt(60, 65) == 0.0f);
}

static void testZeroLengthPolylineOfOnePointDraws() {
    const StrokePoint one[1] = {{40.0f, 40.0f}};
    StrokeCanvas c;
    strokePolyline(c, one, 1, 1.5f, kBig);
    CHECK(!c.bounds().empty());
    CHECK(peakCoverage(c) >= 0.999f);
}

static void testVerticalSegmentIsContinuousAndFullWeight() {
    // Infinite slope: dx == 0 exactly, the case an x-stepping rasterizer cannot express.
    const StrokePoint pts[2] = {{100.0f, 20.0f}, {100.0f, 200.0f}};
    StrokeCanvas c;
    strokePolyline(c, pts, 2, 1.0f, kBig);
    for (int y = 25; y < 195; ++y) {
        float rowPeak = 0.0f, rowInk = 0.0f;
        for (int x = 90; x < 110; ++x) {
            rowPeak = c.coverageAt(x, y) > rowPeak ? c.coverageAt(x, y) : rowPeak;
            rowInk += c.coverageAt(x, y);
        }
        CHECK(rowPeak >= 0.999f);                     // no gap, no weak row
        CHECK(std::fabs(rowInk - 2.0f) < 0.02f);      // and uniform weight down the whole run
    }
}

static void testNearVerticalSegmentIsContinuous() {
    // The slope that broke into dots on screen: steep but not exactly vertical, so the old
    // integer-y loop quantized it into alternating 1/2-px steps.
    const StrokePoint pts[2] = {{100.0f, 20.0f}, {103.0f, 200.0f}};
    StrokeCanvas c;
    strokePolyline(c, pts, 2, 1.0f, kBig);
    for (int y = 25; y < 195; ++y) {
        float rowPeak = 0.0f;
        for (int x = 90; x < 115; ++x)
            rowPeak = c.coverageAt(x, y) > rowPeak ? c.coverageAt(x, y) : rowPeak;
        CHECK(rowPeak >= 0.999f);
    }
}

static void testCoverageFallsOffOverExactlyOnePixel() {
    // The AA fringe is one pixel wide by construction: cov = clamp(hw + 0.5 - d, 0, 1). With the
    // centreline on an integer y, pixel centres sit at d = 0.5, 1.5, 2.5 — one saturated row, one
    // exactly-half fringe row, then nothing.
    const StrokePoint pts[2] = {{20.0f, 100.0f}, {220.0f, 100.0f}};
    StrokeCanvas c;
    strokePolyline(c, pts, 2, 1.5f, kBig);
    CHECK(std::fabs(c.coverageAt(120, 99) - 1.0f) < 1e-4f);    // d = 0.5 -> saturated
    CHECK(std::fabs(c.coverageAt(120, 98) - 0.5f) < 1e-4f);    // d = 1.5 -> half
    CHECK(c.coverageAt(120, 97) == 0.0f);                      // d = 2.5 -> past the reach
}

// --- accumulation semantics --------------------------------------------------

static void testOverlappingSegmentsTakeTheMaxNotTheSum() {
    // The whole point of the scratch mask: an overlap must not read brighter than one stroke, or
    // the joints of a 500-segment contour build up into a glow.
    StrokeCanvas one;
    one.reset(kBig);
    one.addSegment(40.0f, 100.3f, 160.0f, 100.3f, 1.0f);

    // Locate a genuinely partial fringe pixel rather than assuming which row it lands on — the
    // assertion below is only meaningful on a pixel that is neither empty nor already saturated.
    int fy = -1;
    for (int y = 95; y < 106; ++y) {
        const float v = one.coverageAt(100, y);
        if (v > 0.05f && v < 0.95f) { fy = y; break; }
    }
    CHECK(fy != -1);
    if (fy == -1) return;
    const float soloEdge = one.coverageAt(100, fy);

    StrokeCanvas both;
    both.reset(kBig);
    both.addSegment(40.0f, 100.3f, 160.0f, 100.3f, 1.0f);
    both.addSegment(40.0f, 100.3f, 160.0f, 100.3f, 1.0f);   // exactly on top of the first
    CHECK(std::fabs(both.coverageAt(100, fy) - soloEdge) < 1e-6f);
    CHECK(totalInk(both) <= totalInk(one) + 1e-3f);
}

static void testNoPixelEverExceedsFullCoverage() {
    // Many mutually overlapping segments through one point — the pile-up case.
    StrokeCanvas c;
    c.reset(kBig);
    for (int i = 0; i < 12; ++i) {
        const float a = static_cast<float>(i) * kPi / 12.0f;
        c.addSegment(120.0f - 60.0f * std::cos(a), 120.0f - 60.0f * std::sin(a),
                     120.0f + 60.0f * std::cos(a), 120.0f + 60.0f * std::sin(a), 1.5f);
    }
    const Rect& b = c.bounds();
    for (int y = b.y; y < b.bottom(); ++y)
        for (int x = b.x; x < b.right(); ++x) CHECK(c.coverageAt(x, y) <= 1.0f);
}

static void testRevisitedRowGapReadsZeroNotGarbage() {
    // A circle touches most rows on BOTH sides, leaving an untouched gap between the two spans.
    // The row's valid extent grows over that gap, so the gap must be zero-filled, not left at
    // whatever the reused scratch buffer held.
    //
    // The dirtying pass must land at the SAME bounds/stride the arc pass will reuse, or the two
    // writes address disjoint buffer offsets and the "old" value the gap reads back is just the
    // scratch buffer's original zero-init — the guard would then have nothing to prove itself
    // against (verified: deleting extendRow's fill at stroke_aa.cpp:48-51 left this test passing
    // when the dirtying pass used `kBig` while the arc pass reset to its own tighter bounds).
    std::vector<StrokePoint> ring;
    appendArc(ring, 120.0f, 120.0f, 60.0f, 0.0f, 2.0f * kPi);
    const Rect arcBounds = strokeBounds(ring.data(), ring.size(), 1.5f, kBig);

    StrokeCanvas c;
    c.reset(arcBounds);
    // A horizontal segment straight across the row/columns the assertion below checks, so the
    // buffer genuinely holds nonzero ink there before the arc's own pass reuses the canvas.
    c.addSegment(100.0f, 120.0f, 140.0f, 120.0f, 1.5f);
    CHECK(c.coverageAt(120, 120) > 0.9f);   // sanity: the dirtying pass actually landed here

    strokePolyline(c, ring.data(), ring.size(), 1.5f, kBig);
    for (int x = 100; x < 140; ++x) CHECK(c.coverageAt(x, 120) == 0.0f);  // hollow middle
}

// --- bounds / clipping -------------------------------------------------------

static void testBoundsClipToTheClipRectAndCoverTheReach() {
    const StrokePoint pts[2] = {{10.0f, 10.0f}, {50.0f, 50.0f}};
    const Rect b = strokeBounds(pts, 2, 1.5f, kBig);
    CHECK(b.x <= 8 && b.y <= 8);
    CHECK(b.right() >= 52 && b.bottom() >= 52);

    const Rect clipped = strokeBounds(pts, 2, 1.5f, Rect{20, 20, 10, 10});
    CHECK(clipped.x == 20 && clipped.y == 20);
    CHECK(clipped.right() == 30 && clipped.bottom() == 30);

    const StrokePoint away[2] = {{500.0f, 500.0f}, {600.0f, 600.0f}};
    CHECK(strokeBounds(away, 2, 1.5f, kBig).empty());   // wholly outside -> nothing to draw
}

static void testStrokeEntirelyOutsideTheClipDrawsNothing() {
    const StrokePoint away[2] = {{500.0f, 500.0f}, {600.0f, 600.0f}};
    StrokeCanvas c;
    strokePolyline(c, away, 2, 1.5f, kBig);
    CHECK(c.bounds().empty());
}

static void testCoverageOutsideTheValidSpanReadsZero() {
    StrokeCanvas c;
    c.reset(kBig);
    c.addSegment(100.0f, 100.0f, 140.0f, 100.0f, 1.0f);
    CHECK(c.coverageAt(10, 100) == 0.0f);    // same row, outside the touched span
    CHECK(c.coverageAt(120, 10) == 0.0f);    // an untouched row entirely
    CHECK(c.coverageAt(-5, 100) == 0.0f);    // outside the canvas
    CHECK(c.coverageAt(1000, 1000) == 0.0f);
}

// --- non-finite input rejection ------------------------------------------------

static void testInteriorNonFiniteCoordinateRejectsTheWholeStroke() {
    // Only pts[0] going non-finite used to propagate through strokeBounds's min/max reduction:
    // std::min/max against NaN silently returns the OTHER, finite, operand, so a NaN anywhere
    // else in the polyline vanished from the reduction instead of rejecting it. pts[1] here is
    // the case that check missed.
    const StrokePoint pts[3] = {{10.0f, 10.0f}, {NAN, 50.0f}, {90.0f, 10.0f}};
    CHECK(strokeBounds(pts, 3, 1.5f, kBig).empty());

    StrokeCanvas c;
    strokePolyline(c, pts, 3, 1.5f, kBig);
    CHECK(c.bounds().empty());
}

static void testAddSegmentRejectsNonFiniteInputsDirectly() {
    // addSegment casts a pieces-count derived from len2 to int; a NaN/Inf endpoint must be
    // caught before that cast, not one call layer down in addPiece where it's already too late.
    StrokeCanvas c;
    c.reset(kBig);
    c.addSegment(10.0f, 10.0f, NAN, 50.0f, 1.5f);
    c.addSegment(10.0f, 10.0f, INFINITY, 50.0f, 1.5f);
    CHECK(peakCoverage(c) == 0.0f);
}

// --- raster row addressing ----------------------------------------------------

static void testRasterRowOffsetMatchesUnflippedAndFlippedLayouts() {
    // Unflipped: row y is just y*rowSpan (LICE's top-down layout).
    CHECK(rasterRowOffset(0, 100, 240, false) == 0u);
    CHECK(rasterRowOffset(5, 100, 240, false) == 5u * 240u);
    CHECK(rasterRowOffset(99, 100, 240, false) == 99u * 240u);
    // Flipped (bottom-up DIBs): row y is (height-1-y)*rowSpan — matches the free function
    // LICE_GetPixel's own row math, `(h-1-y)*rowspan + x` (lice.cpp:2262).
    CHECK(rasterRowOffset(0, 100, 240, true) == 99u * 240u);
    CHECK(rasterRowOffset(99, 100, 240, true) == 0u);
    CHECK(rasterRowOffset(40, 100, 240, true) == 59u * 240u);
}

// --- long-segment subdivision ------------------------------------------------

static void testSubdivisionDoesNotChangeTheRenderedStroke() {
    // Pieces exist to keep each bounding box tight; min-distance to a partition IS min-distance
    // to the whole, so the output must be identical to the same span drawn in short hops.
    const StrokePoint whole[2] = {{20.0f, 20.0f}, {200.0f, 140.0f}};
    StrokeCanvas a;
    strokePolyline(a, whole, 2, 1.0f, kBig);

    std::vector<StrokePoint> hops;
    for (int i = 0; i <= 180; ++i) {
        const float t = static_cast<float>(i) / 180.0f;
        hops.push_back(StrokePoint{20.0f + 180.0f * t, 20.0f + 120.0f * t});
    }
    StrokeCanvas b;
    strokePolyline(b, hops.data(), hops.size(), 1.0f, kBig);

    CHECK(a.bounds() == b.bounds());
    float worst = 0.0f;
    for (int y = kBig.y; y < kBig.bottom(); ++y)
        for (int x = kBig.x; x < kBig.right(); ++x) {
            const float d = std::fabs(a.coverageAt(x, y) - b.coverageAt(x, y));
            if (d > worst) worst = d;
        }
    // Not exactly zero: the two paths split the line at different parameter values, so the
    // projections differ in the last float bits. Measured worst case 1.6e-5 — a rounding
    // difference, not a coverage one, and the identical bounds above rule out a clipping gap.
    CHECK(worst < 1e-4f);
}

// --- arc flattening ----------------------------------------------------------

static void testArcPointsLieOnTheCircleAndRespectTheFlatness() {
    std::vector<StrokePoint> pts;
    appendArc(pts, 100.0f, 100.0f, 17.5f, -2.618f, 2.618f);   // the knob's 300-degree sweep
    CHECK(pts.size() >= 3);
    for (const StrokePoint& p : pts) {
        const float r = std::sqrt((p.x - 100.0f) * (p.x - 100.0f) +
                                  (p.y - 100.0f) * (p.y - 100.0f));
        CHECK(std::fabs(r - 17.5f) < 1e-2f);
    }
    // Chord sagitta stays inside the requested flatness, with a little numeric slack.
    for (std::size_t i = 1; i < pts.size(); ++i) {
        const float mx = 0.5f * (pts[i - 1].x + pts[i].x);
        const float my = 0.5f * (pts[i - 1].y + pts[i].y);
        const float rm = std::sqrt((mx - 100.0f) * (mx - 100.0f) + (my - 100.0f) * (my - 100.0f));
        CHECK(17.5f - rm < kArcFlatnessPx * 1.5f);
    }
}

static void testArcDensityGrowsWithRadius() {
    std::vector<StrokePoint> small, large;
    appendArc(small, 0.0f, 0.0f, 10.0f, 0.0f, kPi);
    appendArc(large, 0.0f, 0.0f, 200.0f, 0.0f, kPi);
    CHECK(large.size() > small.size());
}

static void testArcFlatteningTerminatesOnDegenerateInputs() {
    std::vector<StrokePoint> pts;
    appendArc(pts, 10.0f, 10.0f, 0.0f, 0.0f, kPi);              // zero radius
    CHECK(pts.size() == 1);

    pts.clear();
    appendArc(pts, 0.0f, 0.0f, 20.0f, 1.0f, 1.0f);              // zero sweep
    CHECK(pts.size() == 2 && std::fabs(pts[0].x - pts[1].x) < 1e-5f);

    pts.clear();
    appendArc(pts, 0.0f, 0.0f, 20.0f, 0.0f, kPi, 0.0f);         // flatness 0 falls back
    CHECK(!pts.empty() &&
          pts.size() <= static_cast<std::size_t>(kMaxArcSegments) + 1);

    pts.clear();
    appendArc(pts, 0.0f, 0.0f, 20.0f, 0.0f, kPi, -3.0f);        // negative flatness falls back
    CHECK(!pts.empty() &&
          pts.size() <= static_cast<std::size_t>(kMaxArcSegments) + 1);

    pts.clear();
    appendArc(pts, 0.0f, 0.0f, 1.0e9f, 0.0f, 2.0f * kPi, 1e-6f);  // the cap is the guarantee
    CHECK(pts.size() <= static_cast<std::size_t>(kMaxArcSegments) + 1);

    pts.clear();
    appendArc(pts, 0.0f, 0.0f, 4.0f, 0.0f, kPi, 50.0f);         // flatness past the diameter
    CHECK(pts.size() >= 2 && pts.size() <= 8);
}

// --- an arc as a rendered stroke ---------------------------------------------

static void testKnobArcIsOpaqueAndEvenAllTheWayRound() {
    // The shipped defect, measured: 27 of 33 columns never reached full opacity and column ink
    // ran 1.60-3.13 px against a nominal 3. Sweep radially instead of by column so the check is
    // a true perpendicular cut at every angle, including the cardinals the old code was worst at.
    const float cx = 120.0f, cy = 120.0f, radius = 16.0f, width = 3.0f;
    std::vector<StrokePoint> pts;
    appendArc(pts, cx, cy, radius, -2.618f, 2.618f);
    StrokeCanvas c;
    strokePolyline(c, pts.data(), pts.size(), width * 0.5f, kBig);

    float lo = 1e9f, hi = -1e9f;
    for (int i = 0; i < 72; ++i) {
        const float a = -2.5f + (5.0f * static_cast<float>(i)) / 71.0f;   // inside the sweep
        const float ux = std::sin(a), uy = -std::cos(a);
        float ink = 0.0f, peak = 0.0f;
        // Integrate along the radial ray in fine steps, converting to a per-pixel weight.
        constexpr int kSteps = 400;
        constexpr float kSpan = 8.0f;   // radial window centred on the arc
        for (int s = 0; s < kSteps; ++s) {
            const float r = radius - kSpan * 0.5f + kSpan * static_cast<float>(s) / kSteps;
            const int px = static_cast<int>(std::floor(cx + ux * r));
            const int py = static_cast<int>(std::floor(cy + uy * r));
            const float v = c.coverageAt(px, py);
            ink += v * (kSpan / kSteps);
            if (v > peak) peak = v;
        }
        CHECK(peak >= 0.999f);          // an opaque core at EVERY angle
        if (ink < lo) lo = ink;
        if (ink > hi) hi = ink;
    }
    CHECK(lo > width * 0.90f);
    CHECK(hi < width * 1.10f);
    CHECK((hi - lo) / width < 0.15f);
}

int main() {
    testStraightStrokeHasAnOpaqueCore();
    testSubOpaqueCoreAtOnePixelWidth();
    testPerpendicularWeightIsAngleIndependent();
    testWeightHoldsAtTheExactDiagonal();
    testZeroLengthSegmentIsARoundDot();
    testZeroLengthPolylineOfOnePointDraws();
    testVerticalSegmentIsContinuousAndFullWeight();
    testNearVerticalSegmentIsContinuous();
    testCoverageFallsOffOverExactlyOnePixel();
    testOverlappingSegmentsTakeTheMaxNotTheSum();
    testNoPixelEverExceedsFullCoverage();
    testRevisitedRowGapReadsZeroNotGarbage();
    testBoundsClipToTheClipRectAndCoverTheReach();
    testStrokeEntirelyOutsideTheClipDrawsNothing();
    testCoverageOutsideTheValidSpanReadsZero();
    testInteriorNonFiniteCoordinateRejectsTheWholeStroke();
    testAddSegmentRejectsNonFiniteInputsDirectly();
    testRasterRowOffsetMatchesUnflippedAndFlippedLayouts();
    testSubdivisionDoesNotChangeTheRenderedStroke();
    testArcPointsLieOnTheCircleAndRespectTheFlatness();
    testArcDensityGrowsWithRadius();
    testArcFlatteningTerminatesOnDegenerateInputs();
    testKnobArcIsOpaqueAndEvenAllTheWayRound();
    if (g_fail == 0) std::printf("test_stroke_aa: all tests passed\n");
    return g_fail == 0 ? 0 : 1;
}
