/*
 * Copyright 2025 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "src/core/SkPathRawShapes.h"

#include "include/core/SkPathTypes.h"
#include "include/core/SkRRect.h"
#include "include/private/base/SkAssert.h"
#include "src/core/SkPathMakers.h"

const SkPathFillType kDefFillType = SkPathFillType::kWinding;

const SkPathVerb gRectVerbs[] = {
    SkPathVerb::kMove,
    SkPathVerb::kLine,
    SkPathVerb::kLine,
    SkPathVerb::kLine,
    SkPathVerb::kClose
};

const uint8_t gRectSegMask = kLine_SkPathSegmentMask;

static void set_as_rect(SkPathRaw* raw, SkSpan<SkPoint> storage,
                        const SkRect& r, SkPathDirection dir, unsigned index) {
    SkASSERT(storage.size() >= 4);

    raw->fPoints = { storage.data(), 4 };
    raw->fVerbs = gRectVerbs;
    raw->fConics = {};
    raw->fBounds = r;
    raw->fFillType = kDefFillType;
    raw->fConvexity = SkPathDirection_ToConvexity(dir);
    raw->fSegmentMask = gRectSegMask;

    SkPath_RectPointIterator iter(r, dir, index);

    storage[0] = iter.current();
    storage[1] = iter.next();
    storage[2] = iter.next();
    storage[3] = iter.next();
}

//////////////////

const SkPathVerb gOvalVerbs[] = {
    SkPathVerb::kMove,
    SkPathVerb::kConic,
    SkPathVerb::kConic,
    SkPathVerb::kConic,
    SkPathVerb::kConic,
    SkPathVerb::kClose
};

const uint8_t gOvalSegMask = kConic_SkPathSegmentMask;

const float gFourQuarterCircleConics[] = {
    SK_ScalarRoot2Over2,
    SK_ScalarRoot2Over2,
    SK_ScalarRoot2Over2,
    SK_ScalarRoot2Over2,
};

static void set_as_oval(SkPathRaw* raw, SkSpan<SkPoint> storage,
                        const SkRect& r, SkPathDirection dir, unsigned index) {
    SkASSERT(storage.size() >= 9);

    raw->fPoints = { storage.data(), 9 };
    raw->fVerbs = gOvalVerbs;
    raw->fConics = gFourQuarterCircleConics;
    raw->fBounds = r;
    raw->fFillType = kDefFillType;
    raw->fConvexity = SkPathDirection_ToConvexity(dir);
    raw->fSegmentMask = gOvalSegMask;

    SkPath_OvalPointIterator ovalIter(r, dir, index);
    SkPath_RectPointIterator rectIter(r, dir, index + (dir == SkPathDirection::kCW ? 0 : 1));

    storage[0] = ovalIter.current();
    for (unsigned i = 0; i < 4; ++i) {
        storage[i*2 + 1] = rectIter.next();
        storage[i*2 + 2] = ovalIter.next();
    }
}

/////////////////////////////

const SkPathVerb gRRectVerbs_LineStart[] = {
    SkPathVerb::kMove,
    SkPathVerb::kLine, SkPathVerb::kConic,
    SkPathVerb::kLine, SkPathVerb::kConic,
    SkPathVerb::kLine, SkPathVerb::kConic,
    SkPathVerb::kLine, SkPathVerb::kConic,
    SkPathVerb::kClose
};

const SkPathVerb gRRectVerbs_ConicStart[] = {
    SkPathVerb::kMove,
    SkPathVerb::kConic, SkPathVerb::kLine,
    SkPathVerb::kConic, SkPathVerb::kLine,
    SkPathVerb::kConic, SkPathVerb::kLine,
    SkPathVerb::kConic, // we can skip the last line
    SkPathVerb::kClose
};

const uint8_t gRRectSegMask = kLine_SkPathSegmentMask | kConic_SkPathSegmentMask;

static void set_as_rrect(SkPathRaw* raw, SkSpan<SkPoint> storage,
                         const SkRRect& rrect, SkPathDirection dir, unsigned index) {
    // we start with a conic on odd indices when moving CW vs. even indices when moving CCW
    const bool startsWithConic = ((index & 1) == (dir == SkPathDirection::kCW));
    // if we start with a conic, we end with a line, which we can skip (relying on close())
    const size_t npoints = 13 - startsWithConic;
    const SkRect& bounds = rrect.getBounds();

    SkASSERT(storage.size() >= npoints);

    raw->fPoints = { storage.data(), npoints };
    if (startsWithConic) {
        raw->fVerbs = gRRectVerbs_ConicStart;
    } else {
        raw->fVerbs = gRRectVerbs_LineStart;
    }
    raw->fConics = gFourQuarterCircleConics;
    raw->fBounds = bounds;
    raw->fFillType = kDefFillType;
    raw->fConvexity = SkPathDirection_ToConvexity(dir);
    raw->fSegmentMask = gRRectSegMask;

    SkPath_RRectPointIterator rrectIter(rrect, dir, index);
    // Corner iterator indices follow the collapsed radii model,
    // adjusted such that the start pt is "behind" the radii start pt.
    const unsigned rectStartIndex = index / 2 + (dir == SkPathDirection::kCW ? 0 : 1);
    SkPath_RectPointIterator rectIter(bounds, dir, rectStartIndex);

    storage[0] = rrectIter.current();
    if (startsWithConic) {
        for (unsigned i = 0; i < 3; ++i) {
            // conic points
            storage[i*3 + 1] = rectIter.next();
            storage[i*3 + 2] = rrectIter.next();
            // line point
            storage[i*3 + 3] = rrectIter.next();
        }
        // last conic points
        storage[10] = rectIter.next();
        storage[11] = rrectIter.next();
        // the final line is accomplished by close()
    } else {
        for (unsigned i = 0; i < 4; ++i) {
            // line point
            storage[i*3 + 1] = rrectIter.next();
            // conic points
            storage[i*3 + 2] = rectIter.next();
            storage[i*3 + 3] = rrectIter.next();
        }
    }
    // close
}

/////////////////////////////

SkPathRawShapes::Rect::Rect(const SkRect& r, SkPathDirection dir, unsigned index) {
    set_as_rect(this, fStorage, r, dir, index);
}

SkPathRawShapes::Oval::Oval(const SkRect& r, SkPathDirection dir, unsigned index) {
    set_as_oval(this, fStorage, r, dir, index);
}

SkPathRawShapes::RRect::RRect(const SkRRect& rrect, SkPathDirection dir, unsigned index) {
    const SkRect& bounds = rrect.getBounds();

    if (rrect.isRect() || rrect.isEmpty()) {
        // degenerate(rect) => radii points are collapsing
        set_as_rect(this, fStorage, bounds, dir, (index + 1) / 2);
    } else if (rrect.isOval()) {
        // degenerate(oval) => line points are collapsing
        set_as_oval(this, fStorage, bounds, dir, index / 2);
    } else {
        set_as_rrect(this, fStorage, rrect, dir, index);
    }
}

/////////////////////////////

const SkPathVerb gTriangle_Verbs[] = {
    SkPathVerb::kMove,
    SkPathVerb::kLine,
    SkPathVerb::kLine,
    SkPathVerb::kClose
};

static SkPathConvexity tri_to_convexity(SkSpan<const SkPoint> pts) {
    SkVector u = pts[1] - pts[0],
             v = pts[2] - pts[1];
    float cross = u.fX * v.fY - u.fY * v.fX;

    return cross > 0 ? SkPathConvexity::kConvex_CW
                     : (cross < 0) ? SkPathConvexity::kConvex_CCW
                                   : SkPathConvexity::kConvex_Degenerate;
}

SkPathRawShapes::Triangle::Triangle(SkSpan<const SkPoint> threePoints, const SkRect& bounds)
    : SkPathRaw{threePoints, gTriangle_Verbs, {}, bounds,
                SkPathFillType::kDefault, tri_to_convexity(threePoints), kLine_SkPathSegmentMask}
{
    SkASSERT(threePoints.size() == 3);
    SkASSERT(SkRect::Bounds(threePoints).value() == bounds);
}
