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

#include "src/gpu/geometry/GrShape.h"

#include "src/core/SkPathPriv.h"

GrShape& GrShape::operator=(const GrShape& shape) {
    switch(shape.type()) {
        case Type::kEmpty:
            this->reset();
            break;
        case Type::kPoint:
            this->setPoint(shape.fPoint);
            break;
        case Type::kRect:
            this->setRect(shape.fRect);
            break;
        case Type::kRRect:
            this->setRRect(shape.fRRect);
            break;
        case Type::kPath:
            this->setPath(shape.fPath);
            break;
        case Type::kArc:
            this->setArc(shape.fArc);
            break;
        case Type::kLine:
            this->setLine(shape.fLine);
            break;
        default:
            SkUNREACHABLE;
    }

    fStart = shape.fStart;
    fCW = shape.fCW;
    fInverted = shape.fInverted;

    return *this;
}

uint32_t GrShape::stateKey() const {
    // Use the path's full fill type instead of just whether or not it's inverted.
    uint32_t key = this->isPath() ? static_cast<uint32_t>(fPath.getFillType())
                                  : (fInverted ? 1 : 0);
    key |= ((uint32_t) fType) << 2; // fill type was 2 bits
    key |= fStart             << 5; // type was 3 bits, total 5 bits so far
    key |= (fCW ? 1 : 0)      << 8; // start was 3 bits, total 8 bits so far
    return key;
}

bool GrShape::simplifyPath(unsigned flags) {
    SkASSERT(this->isPath());

    SkRect rect;
    SkRRect rrect;
    SkPoint pts[2];

    SkPathDirection dir;
    unsigned start;

    if (fPath.isEmpty()) {
        this->setType(Type::kEmpty);
        return false;
    } else if (fPath.isLine(pts)) {
        this->simplifyLine(pts[0], pts[1], flags);
        return false;
    } else if (SkPathPriv::IsRRect(fPath, &rrect, &dir, &start)) {
        this->simplifyRRect(rrect, dir, start, flags);
        return true;
    } else if (SkPathPriv::IsOval(fPath, &rect, &dir, &start)) {
        // Convert to rrect indexing since oval is not represented explicitly
        this->simplifyRRect(SkRRect::MakeOval(rect), dir, start * 2, flags);
        return true;
    } else if (SkPathPriv::IsSimpleClosedRect(fPath, &rect, &dir, &start)) {
        // When there is a path effect we restrict rect detection to the narrower API that
        // gives us the starting position. Otherwise, we will retry with the more aggressive
        // isRect().
        this->simplifyRect(rect, dir, start, flags);
        return true;
    } else if (flags & kIgnoreWinding_Flag) {
        // Attempt isRect() since we don't have to preserve any winding info
        bool closed;
        if (fPath.isRect(&rect, &closed) && (closed || (flags & kSimpleFill_Flag))) {
            this->simplifyRect(rect, kDefaultDir, kDefaultStart, flags);
            return true;
        }
    }
    // No further simplification for a path. For performance reasons, we don't query the path to
    // determine it was closed, as whether or not it was closed when it remains a path type is not
    // important for styling.
    return false;
}

bool GrShape::simplifyArc(unsigned flags) {
    SkASSERT(this->isArc());

    // Arcs can simplify to rrects, lines, points, or empty; regardless of what it simplifies to
    // it was closed if went through the center point.
    bool wasClosed = fArc.fUseCenter;
    if (fArc.fOval.isEmpty() || !fArc.fSweepAngle) {
        if (flags & kSimpleFill_Flag) {
            // Go straight to empty, since the other degenerate shapes all have 0 area anyway.
            this->setType(Type::kEmpty);
        } else if (!fArc.fSweepAngle) {
            SkPoint center = {fArc.fOval.centerX(), fArc.fOval.centerY()};
            SkScalar startRad = SkDegreesToRadians(fArc.fStartAngle);
            SkPoint start = {center.fX + 0.5f * fArc.fOval.width() * SkScalarCos(startRad),
                                center.fY + 0.5f * fArc.fOval.height() * SkScalarSin(startRad)};
            // Either just the starting point, or a line from the center to the start
            if (fArc.fUseCenter) {
                this->simplifyLine(center, start, flags);
             } else {
                this->simplifyPoint(start, flags);
             }
        } else {
            // TODO: Theoretically, we could analyze the arc projected into the empty bounds to
            // determine a line, but that is somewhat complex for little value (since the arc
            // can backtrack on itself if the sweep angle is large enough).
            this->setType(Type::kEmpty);
        }
    } else {
        if ((flags & kSimpleFill_Flag) || ((flags & kIgnoreWinding_Flag) && !fArc.fUseCenter)) {
             // Eligible to turn into an oval if it sweeps a full circle
            if (fArc.fSweepAngle <= -360.f || fArc.fSweepAngle >= 360.f) {
                this->simplifyRRect(SkRRect::MakeOval(fArc.fOval),
                                    kDefaultDir, kDefaultStart, flags);
                return true;
            }
        }

        if (flags & kMakeCanonical_Flag) {
            // Map start to 0 to 360, sweep is always positive
            if (fArc.fSweepAngle < 0) {
                fArc.fStartAngle = fArc.fStartAngle + fArc.fSweepAngle;
                fArc.fSweepAngle = -fArc.fSweepAngle;
            }

            if (fArc.fStartAngle < 0 || fArc.fStartAngle >= 360.f) {
                fArc.fStartAngle = SkScalarMod(fArc.fStartAngle, 360.f);
            }
        }
    }

    return wasClosed;
}

void GrShape::simplifyRRect(const SkRRect& rrect, SkPathDirection dir, unsigned start,
                            unsigned flags) {
    if (rrect.isEmpty() || rrect.isRect()) {
        // Change index from rrect to rect
        start = ((start + 1) / 2) % 4;
        this->simplifyRect(rrect.rect(), dir, start, flags);
    } else if (!this->isRRect()) {
        this->setType(Type::kRRect);
        fRRect = rrect;
        this->setPathWindingParams(dir, start);
        // A round rect is already canonical, so there's nothing more to do
    } else {
        // If starting as a round rect, the provided rrect/winding params should be already set
        SkASSERT(fRRect == rrect && this->dir() == dir && this->startIndex() == start);
    }
}

void GrShape::simplifyRect(const SkRect& rect, SkPathDirection dir, unsigned start,
                           unsigned flags) {
    if (!rect.width() || !rect.height()) {
        if (flags & kSimpleFill_Flag) {
            // A zero area, filled shape so go straight to empty
            this->setType(Type::kEmpty);
        } else if (!rect.width() ^ !rect.height()) {
            // A line, choose the first point that best matches the starting index
            SkPoint p1 = {rect.fLeft, rect.fTop};
            SkPoint p2 = {rect.fRight, rect.fBottom};
            if (start >= 2 && !(flags & kIgnoreWinding_Flag)) {
                using std::swap;
                swap(p1, p2);
            }
            this->simplifyLine(p1, p2, flags);
        } else {
            // A point (all edges are equal, so start+dir doesn't affect choice)
            this->simplifyPoint({rect.fLeft, rect.fTop}, flags);
        }
    } else {
        if (!this->isRect()) {
            this->setType(Type::kRect);
            fRect = rect;
            this->setPathWindingParams(dir, start);
        } else {
            // If starting as a rect, the provided rect/winding params should already be set
            SkASSERT(fRect == rect && this->dir() == dir && this->startIndex() == start);
        }
        if (flags & kMakeCanonical_Flag) {
            fRect.sort();
        }
    }
}

void GrShape::simplifyLine(const SkPoint& p1, const SkPoint& p2, unsigned flags) {
    if (flags & kSimpleFill_Flag) {
        this->setType(Type::kEmpty);
    } else if (p1 == p2) {
        this->simplifyPoint(p1, false);
    } else {
        if (!this->isLine()) {
            this->setType(Type::kLine);
            fLine.fP1 = p1;
            fLine.fP2 = p2;
        } else {
            // If starting as a line, the provided points should already be set
            SkASSERT(fLine.fP1 == p1 && fLine.fP2 == p2);
        }
        if (flags & kMakeCanonical_Flag) {
             // Sort the end points
             if (fLine.fP2.fY < fLine.fP1.fY ||
                 (fLine.fP2.fY == fLine.fP1.fY && fLine.fP2.fX < fLine.fP1.fX)) {
                using std::swap;
                swap(fLine.fP1, fLine.fP2);
            }
        }
    }
}

void GrShape::simplifyPoint(const SkPoint& point, unsigned flags) {
    if (flags & kSimpleFill_Flag) {
        this->setType(Type::kEmpty);
    } else if (!this->isPoint()) {
        this->setType(Type::kPoint);
        fPoint = point;
    } else {
        // If starting as a point, the provided position should already be set
        SkASSERT(point == fPoint);
    }
}

bool GrShape::simplify(unsigned flags) {
    // Verify that winding parameters are valid for the current type.
    SkASSERT((fType == Type::kRect || fType == Type::kRRect) ||
             (this->dir() == kDefaultDir && this->startIndex() == kDefaultStart));

    // The type specific functions automatically fall through to the simpler shapes, so
    // we only need to start in the right place.
    bool wasClosed = false;
    switch(fType) {
        case Type::kEmpty:
            // do nothing
            break;
        case Type::kPoint:
            this->simplifyPoint(fPoint, flags);
            break;
        case Type::kLine:
            this->simplifyLine(fLine.fP1, fLine.fP2, flags);
            break;
        case Type::kRect:
            this->simplifyRect(fRect, this->dir(), this->startIndex(), flags);
            wasClosed = true;
            break;
        case Type::kRRect:
            this->simplifyRRect(fRRect, this->dir(), this->startIndex(), flags);
            wasClosed = true;
            break;
        case Type::kPath:
            wasClosed = this->simplifyPath(flags);
            break;
        case Type::kArc:
            wasClosed = this->simplifyArc(flags);
            break;

        default:
            SkUNREACHABLE;
    }

    if (((flags & kIgnoreWinding_Flag) || (fType != Type::kRect && fType != Type::kRRect))) {
        // Reset winding parameters if we don't need them anymore
        this->setPathWindingParams(kDefaultDir, kDefaultStart);
    }

    return wasClosed;
}

bool GrShape::contains(const SkRect& rect) const {
    switch(this->type()) {
        case Type::kEmpty:
        case Type::kPoint: // fall through since a point has 0 area
        case Type::kLine:  // fall through, "" (currently choosing not to test if 'rect' == line)
            return false;
        case Type::kRect:
            return fRect.contains(rect);
        case Type::kRRect:
            return fRRect.contains(rect);
        case Type::kPath:
            return fPath.conservativelyContainsRect(rect);
        case Type::kArc:
            if (fArc.fUseCenter) {
                SkPath arc;
                this->asPath(&arc);
                return arc.conservativelyContainsRect(rect);
            } else {
                return false;
            }
        default:
            SkUNREACHABLE;
    }
}

bool GrShape::closed() const {
    switch(this->type()) {
        case Type::kEmpty: // fall through
        case Type::kRect:  // fall through
        case Type::kRRect:
            return true;
        case Type::kPath:
            // SkPath doesn't keep track of the closed status of each contour.
            return SkPathPriv::IsClosedSingleContour(fPath);
        case Type::kArc:
            return fArc.fUseCenter;
        case Type::kPoint: // fall through
        case Type::kLine:
            return false;
        default:
            SkUNREACHABLE;
    }
}

bool GrShape::convex(bool simpleFill) const {
    switch(this->type()) {
        case Type::kEmpty: // fall through
        case Type::kRect:  // fall through
        case Type::kRRect:
            return true;
        case Type::kPath:
            // SkPath.isConvex() really means "is this path convex were it to be closed".
            // Convex paths may only have one contour hence isLastContourClosed() is sufficient.
            return (simpleFill || fPath.isLastContourClosed()) && fPath.isConvex();
        case Type::kArc:
            return SkPathPriv::DrawArcIsConvex(fArc.fSweepAngle, fArc.fUseCenter, simpleFill);
        case Type::kPoint: // fall through
        case Type::kLine:
            return false;
        default:
            SkUNREACHABLE;
    }
}

SkRect GrShape::bounds() const {
    // Bounds where left == bottom or top == right can indicate a line or point shape. We return
    // inverted bounds for a truly empty shape.
    static constexpr SkRect kInverted = SkRect::MakeLTRB(1, 1, -1, -1);
    switch(this->type()) {
        case Type::kEmpty:
            return kInverted;
        case Type::kPoint:
            return {fPoint.fX, fPoint.fY, fPoint.fX, fPoint.fY};
        case Type::kRect:
            return fRect.makeSorted();
        case Type::kRRect:
            return fRRect.getBounds();
        case Type::kPath:
            return fPath.getBounds();
        case Type::kArc:
            return fArc.fOval;
        case Type::kLine: {
            SkRect b = SkRect::MakeLTRB(fLine.fP1.fX, fLine.fP1.fY,
                                        fLine.fP2.fX, fLine.fP2.fY);
            b.sort();
            return b; }
        default:
            SkUNREACHABLE;
    }
}

uint32_t GrShape::segmentMask() const {
    // In order to match what a path would report, this has to inspect the shapes slightly
    // to reflect what they might simplify to.
    switch(this->type()) {
        case Type::kEmpty:
            return 0;
        case Type::kRRect:
            if (fRRect.isEmpty() || fRRect.isRect()) {
                return SkPath::kLine_SegmentMask;
            } else if (fRRect.isOval()) {
                return SkPath::kConic_SegmentMask;
            } else {
                return SkPath::kConic_SegmentMask | SkPath::kLine_SegmentMask;
            }
        case Type::kPath:
            return fPath.getSegmentMasks();
        case Type::kArc:
            if (fArc.fUseCenter) {
                return SkPath::kConic_SegmentMask | SkPath::kLine_SegmentMask;
            } else {
                return SkPath::kConic_SegmentMask;
            }
        case Type::kPoint: // fall through
        case Type::kLine:  // ""
        case Type::kRect:
            return SkPath::kLine_SegmentMask;
        default:
            SkUNREACHABLE;
    }
}

void GrShape::asPath(SkPath* out, bool simpleFill) const {
    if (!this->isPath() && !this->isArc()) {
        // When not a path, we need to set fill type on the path to match invertedness.
        // All the non-path geometries produce equivalent shapes with either even-odd or winding
        // so we can use the default fill type.
        out->reset();
        out->setFillType(kDefaultFillType);
        if (fInverted) {
            out->toggleInverseFillType();
        }
    } // Else when we're already a path, that will assign the fill type directly to 'out'.

    switch(this->type()) {
        case Type::kEmpty:
            return;
        case Type::kPoint:
            // A plain moveTo() or moveTo+close() does not match the expected path for a
            // point that is being dashed (see SkDashPath's handling of zero-length segments).
            out->moveTo(fPoint);
            out->lineTo(fPoint);
            return;
        case Type::kRect:
            out->addRect(fRect, this->dir(), this->startIndex());
            return;
        case Type::kRRect:
            out->addRRect(fRRect, this->dir(), this->startIndex());
            return;
        case Type::kPath:
            *out = fPath;
            return;
        case Type::kArc:
            SkPathPriv::CreateDrawArcPath(out, fArc.fOval, fArc.fStartAngle, fArc.fSweepAngle,
                                          fArc.fUseCenter, simpleFill);
            // CreateDrawArcPath resets the output path and configures its fill type, so we just
            // have to ensure invertedness is correct.
            if (fInverted) {
                out->toggleInverseFillType();
            }
            return;
        case Type::kLine:
            out->moveTo(fLine.fP1);
            out->lineTo(fLine.fP2);
            return;
        default:
            SkUNREACHABLE;
    }
}
