/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "src/gpu/ganesh/geometry/GrStyledShape.h"

#include "include/core/SkArc.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPoint.h"
#include "include/core/SkStrokeRec.h"
#include "include/private/SkAlign.h"
#include "include/private/SkDebug.h"
#include "include/private/SkIDChangeListener.h"
#include "include/private/SkMalloc.h"
#include "include/private/SkOnlyStackAllocatable.h"
#include "include/private/SkTo.h"

#include <algorithm>
#include <cstring>
#include <limits>
#include <utility>


GrStyledShape& GrStyledShape::operator=(const GrStyledShape& that) {
    fShape      = that.fShape;
    fStyle      = that.fStyle;
    fGenID      = that.fGenID;
    fSimplified = that.fSimplified;

    fInheritedKey.reset(that.fInheritedKey.count());
    sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(),
                      sizeof(uint32_t) * fInheritedKey.count());
    if (that.fInheritedPathForListeners.has_value()) {
        fInheritedPathForListeners = *that.fInheritedPathForListeners;
    } else {
        fInheritedPathForListeners.reset();
    }
    return *this;
}

static bool is_inverted(bool originalIsInverted, GrStyledShape::FillInversion inversion) {
    switch (inversion) {
        case GrStyledShape::FillInversion::kPreserve:
            return originalIsInverted;
        case GrStyledShape::FillInversion::kFlip:
            return !originalIsInverted;
        case GrStyledShape::FillInversion::kForceInverted:
            return true;
        case GrStyledShape::FillInversion::kForceNoninverted:
            return false;
    }
    return false;
}

GrStyledShape GrStyledShape::MakeFilled(const GrStyledShape& original, FillInversion inversion) {
    bool newIsInverted = is_inverted(original.fShape.inverted(), inversion);
    if (original.style().isSimpleFill() && newIsInverted == original.fShape.inverted()) {
        // By returning the original rather than falling through we can preserve any inherited style
        // key. Otherwise, we wipe it out below since the style change invalidates it.
        return original;
    }
    GrStyledShape result;
    SkASSERT(result.fStyle.isSimpleFill());
    if (original.fInheritedPathForListeners.has_value()) {
        result.fInheritedPathForListeners = *original.fInheritedPathForListeners;
    }

    result.fShape = original.fShape;
    result.fGenID = original.fGenID;
    result.fShape.setInverted(newIsInverted);

    if (!original.style().isSimpleFill()) {
        // Going from a non-filled style to fill may allow additional simplifications (e.g.
        // closing an open rect that wasn't closed in the original shape because it had
        // stroke style).
        result.simplify();
        // The above simplify() call only sets simplified to true if its geometry was changed,
        // since it already sees its style as a simple fill. Since the original style was not a
        // simple fill, MakeFilled always simplifies.
        result.fSimplified = true;
    }

    // Verify that lines/points were converted to empty by the style change
    SkASSERT((!original.fShape.isLine() && !original.fShape.isPoint()) || result.fShape.isEmpty());

    // We don't copy the inherited key since it can contain path effect information that we just
    // stripped.
    return result;
}

SkRect GrStyledShape::styledBounds() const {
    if (this->isEmpty() && !fStyle.hasNonDashPathEffect()) {
        return SkRect::MakeEmpty();
    }

    SkRect bounds;
    fStyle.adjustBounds(&bounds, this->bounds());
    return bounds;
}

// If the path is small enough to be keyed from its data this returns key length, otherwise -1.
static int path_key_from_data_size(const SkPath& path) {
    const int verbCnt = path.countVerbs();
    if (verbCnt > GrStyledShape::kMaxKeyFromDataVerbCnt) {
        return -1;
    }
    const size_t pointCnt = path.points().size();
    const size_t conicWeightCnt = path.conicWeights().size();

    static_assert(sizeof(SkPoint) == 2 * sizeof(uint32_t));
    static_assert(sizeof(SkScalar) == sizeof(uint32_t));
    // 1 is for the verb count. Each verb is a byte but we'll pad the verb data out to
    // a uint32_t length.
    return 1 + (SkAlign4(verbCnt) >> 2) + 2 * pointCnt + conicWeightCnt;
}

// Writes the path data key into the passed pointer.
static void write_path_key_from_data(const SkPath& path, uint32_t* origKey) {
    uint32_t* key = origKey;
    // The check below should take care of negative values casted positive.
    SkSpan<const SkPathVerb> verbs = path.verbs();
    SkSpan<const SkPoint> points = path.points();
    SkSpan<const float> conics = path.conicWeights();
    SkASSERT(verbs.size() <= GrStyledShape::kMaxKeyFromDataVerbCnt);
    SkASSERT(points.size() && verbs.size());
    *key++ = SkToInt(verbs.size());
    memcpy(key, verbs.data(), verbs.size_bytes());
    const size_t verbKeySize = SkAlign4(verbs.size());
    // pad out to uint32_t alignment using value that will stand out when debugging.
    uint8_t* pad = reinterpret_cast<uint8_t*>(key)+ verbs.size();
    memset(pad, 0xDE, verbKeySize - verbs.size());
    key += verbKeySize >> 2;

    memcpy(key, points.data(), points.size_bytes());
    static_assert(sizeof(SkPoint) == 2 * sizeof(uint32_t));
    key += 2 * points.size();
    sk_careful_memcpy(key, conics.data(), conics.size_bytes());
    static_assert(sizeof(SkScalar) == sizeof(uint32_t));
    SkDEBUGCODE(key += conics.size());
    SkASSERT(key - origKey == path_key_from_data_size(path));
}

uint16_t GrStyledShape::unstyledKeySize() const {
    if (fInheritedKey.count()) {
        return SkTo<uint16_t>(fInheritedKey.count());
    }

    uint16_t count = 1; // Every key has the state flags from the GrShape
    switch(fShape.type()) {
        case GrShape::Type::kPoint:
            static_assert(0 == sizeof(SkPoint) % sizeof(uint32_t));
            count += sizeof(SkPoint) / sizeof(uint32_t);
            break;
        case GrShape::Type::kRect:
            static_assert(0 == sizeof(SkRect) % sizeof(uint32_t));
            count += sizeof(SkRect) / sizeof(uint32_t);
            break;
        case GrShape::Type::kRRect:
            static_assert(0 == SkRRect::kSizeInMemory % sizeof(uint32_t));
            count += SkRRect::kSizeInMemory / sizeof(uint32_t);
            break;
        case GrShape::Type::kArc:
            static_assert(0 == sizeof(SkArc) % sizeof(uint32_t));
            count += sizeof(SkArc) / sizeof(uint32_t);
            break;
        case GrShape::Type::kLine:
            static_assert(0 == sizeof(GrLineSegment) % sizeof(uint32_t));
            count += sizeof(GrLineSegment) / sizeof(uint32_t);
            break;
        case GrShape::Type::kPath: {
            if (0 == fGenID) {
                return 0; // volatile, so won't be keyed
            }
            // When >= 0, `dataKeySize` is a reasonably small number bounded by
            // kMaxKeyFromDataVerbCnt since point count is derived from verb count.
            int dataKeySize = path_key_from_data_size(fShape.path());
            if (dataKeySize >= 0) {
                count += SkTo<uint16_t>(dataKeySize);
            } else {
                count += sizeof(uint64_t) / sizeof(uint32_t); // Just adds the gen ID.
            }
            break; }
        default:
            // else it's empty, which just needs the state flags for its key
            SkASSERT(fShape.isEmpty());
    }
    return count;
}

void GrStyledShape::writeUnstyledKey(uint32_t* key) const {
    SkASSERT(this->unstyledKeySize());
    SkDEBUGCODE(uint32_t* origKey = key;)
    if (fInheritedKey.count()) {
        memcpy(key, fInheritedKey.get(), sizeof(uint32_t) * fInheritedKey.count());
        SkDEBUGCODE(key += fInheritedKey.count();)
    } else {
        // Dir and start are only used for rect and rrect shapes, so are not included in other
        // shape type keys. Make sure that they are the defaults for other shapes so it doesn't
        // matter that we universally include them in the flag key value.
        SkASSERT((fShape.isRect() || fShape.isRRect()) ||
                 (fShape.dir() == GrShape::kDefaultDir &&
                  fShape.startIndex() == GrShape::kDefaultStart));

        // Every key starts with the state from the GrShape (this includes path fill type,
        // and any tracked winding, start, inversion, as well as the class of geometry).
        *key++ = fShape.stateKey();

        switch(fShape.type()) {
            case GrShape::Type::kPath: {
                SkASSERT(fGenID != 0);
                // Ensure that the path's inversion matches our state so that the path's key suffices.
                SkASSERT(fShape.inverted() == fShape.path().isInverseFillType());

                int dataKeySize = path_key_from_data_size(fShape.path());
                if (dataKeySize >= 0) {
                    write_path_key_from_data(fShape.path(), key);
                    return;
                } else {
                    memcpy(key, &fGenID, sizeof(uint64_t));
                    key += sizeof(uint64_t) / sizeof(uint32_t);
                }
                break; }
            case GrShape::Type::kPoint:
                memcpy(key, &fShape.point(), sizeof(SkPoint));
                key += sizeof(SkPoint) / sizeof(uint32_t);
                break;
            case GrShape::Type::kRect:
                memcpy(key, &fShape.rect(), sizeof(SkRect));
                key += sizeof(SkRect) / sizeof(uint32_t);
                break;
            case GrShape::Type::kRRect:
                fShape.rrect().writeToMemory(key);
                key += SkRRect::kSizeInMemory / sizeof(uint32_t);
                break;
            case GrShape::Type::kArc:
                // Write dense floats first
                memcpy(key, &fShape.arc(), sizeof(SkRect) + 2 * sizeof(float));
                key += (sizeof(SkArc) / sizeof(uint32_t) - 1);
                // Then write the final bool as an int, to make sure upper bits are set
                *key++ = fShape.arc().isWedge() ? 1 : 0;
                break;
            case GrShape::Type::kLine:
                memcpy(key, &fShape.line(), sizeof(GrLineSegment));
                key += sizeof(GrLineSegment) / sizeof(uint32_t);
                break;
            default:
                // Nothing other than the flag state is needed in the key for an empty shape
                SkASSERT(fShape.isEmpty());
        }
    }
    SkASSERT(key - origKey == this->unstyledKeySize());
}

void GrStyledShape::setInheritedKey(const GrStyledShape &parent, GrStyle::Apply apply,
                                    SkScalar scale) {
    static constexpr int kInheritedKeyLimit = 1024;
    SkASSERT(!fInheritedKey.count());
    // If the output shape turns out to be simple, then we will just use its geometric key
    if (fShape.isPath()) {
        // We want ApplyFullStyle(ApplyPathEffect(shape)) to have the same key as
        // ApplyFullStyle(shape).
        // The full key is structured as (geo,path_effect,stroke).
        // If we do ApplyPathEffect we get geo,path_effect as the inherited key. If we then
        // do ApplyFullStyle we'll memcpy geo,path_effect into the new inherited key
        // and then append the style key (which should now be stroke only) at the end.
        int parentCnt = parent.fInheritedKey.count();
        bool useParentGeoKey = !parentCnt;
        if (useParentGeoKey) {
            parentCnt = parent.unstyledKeySize();
            if (!parentCnt) {
                // The parent's geometry has no key so we will have no key.
                fGenID = 0;
                return;
            }
        }
        uint32_t styleKeyFlags = 0;
        if (parent.knownToBeClosed()) {
            styleKeyFlags |= GrStyle::kClosed_KeyFlag;
        }
        if (parent.asLine(nullptr, nullptr)) {
            styleKeyFlags |= GrStyle::kNoJoins_KeyFlag;
        }
        int styleCnt = GrStyle::KeySize(parent.fStyle, apply, styleKeyFlags);
        if (styleCnt < 0) {
            // The style doesn't allow a key, set the path gen ID to 0 so that we fail when
            // we try to get a key for the shape.
            fGenID = 0;
            return;
        } else if (parentCnt + styleCnt > kInheritedKeyLimit) {
            // Prevent chained path effects and styles from growing the key too large
            fGenID = 0;
            return;
        }

        fInheritedKey.reset(parentCnt + styleCnt);
        if (useParentGeoKey) {
            // This will be the geo key.
            parent.writeUnstyledKey(fInheritedKey.get());
        } else {
            // This should be (geo,path_effect).
            memcpy(fInheritedKey.get(), parent.fInheritedKey.get(),
                   parentCnt * sizeof(uint32_t));
        }
        // Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke)
        GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply, scale,
                          styleKeyFlags);
    }
}

const SkPath* GrStyledShape::originalPathForListeners() const {
    if (fInheritedPathForListeners.has_value()) {
        return &fInheritedPathForListeners.value();
    } else if (fShape.isPath() && !fShape.path().isVolatile()) {
        return &fShape.path();
    }
    return nullptr;
}

void GrStyledShape::addGenIDChangeListener(sk_sp<SkIDChangeListener> listener) const {
    if (const auto* lp = this->originalPathForListeners()) {
        SkPathPriv::AddGenIDChangeListener(*lp, std::move(listener));
    }
}

GrStyledShape GrStyledShape::MakeArc(const SkArc& arc,
                                     const GrStyle& style,
                                     DoSimplify doSimplify) {
    GrStyledShape result;
    result.fShape.setArc(
            SkArc::Make(arc.fOval.makeSorted(), arc.fStartAngle, arc.fSweepAngle, arc.fType));
    result.fStyle = style;
    if (doSimplify == DoSimplify::kYes) {
        result.simplify();
    }
    return result;
}

GrStyledShape::GrStyledShape(const GrStyledShape& that)
        : fShape(that.fShape)
        , fStyle(that.fStyle)
        , fGenID(that.fGenID)
        , fSimplified(that.fSimplified) {
    fInheritedKey.reset(that.fInheritedKey.count());
    sk_careful_memcpy(fInheritedKey.get(), that.fInheritedKey.get(),
                      sizeof(uint32_t) * fInheritedKey.count());
    if (that.fInheritedPathForListeners.has_value()) {
        fInheritedPathForListeners = *that.fInheritedPathForListeners;
    }
}

GrStyledShape::GrStyledShape(const GrStyledShape& parent, GrStyle::Apply apply, SkScalar scale) {
    SkASSERT(scale > 0 && std::isfinite(scale));
    // TODO: Add some quantization of scale for better cache performance here or leave that up
    // to caller?
    // TODO: For certain shapes and stroke params we could ignore the scale. (e.g. miter or bevel
    // stroke of a rect).
    if (!parent.style().applies() ||
        (GrStyle::Apply::kPathEffectOnly == apply && !parent.style().pathEffect())) {
        *this = parent;
        return;
    }

    SkPathEffect* pe = parent.fStyle.pathEffect();
    std::optional<SkPath> tmpPath;
    const GrStyledShape* parentForKey = &parent;
    std::optional<GrStyledShape> tmpParent;

    // Start out as an empty path that is filled in by the applied style
    fShape.setPath(SkPath());

    if (pe) {
        const SkPath* srcForPathEffect;
        if (parent.fShape.isPath()) {
            srcForPathEffect = &parent.fShape.path();
        } else {
            srcForPathEffect = &tmpPath.emplace(parent.asPath());
        }
        // Should we consider bounds? Would have to include in key, but it'd be nice to know
        // if the bounds actually modified anything before including in key.
        SkStrokeRec strokeRec = parent.fStyle.strokeRec();
        if (!parent.fStyle.applyPathEffectToPath(&fShape.path(), &strokeRec, *srcForPathEffect,
                                                 scale)) {
            tmpParent.emplace(*srcForPathEffect, GrStyle(strokeRec, nullptr));
            *this = tmpParent->applyStyle(apply, scale);
            return;
        }
        // A path effect has access to change the res scale but we aren't expecting it to and it
        // would mess up our key computation.
        SkASSERT(scale == strokeRec.getResScale());
        if (GrStyle::Apply::kPathEffectAndStrokeRec == apply && strokeRec.needToApply()) {
            // The intermediate shape may not be a general path. If we we're just applying
            // the path effect then attemptToReduceFromPath would catch it. This means that
            // when we subsequently applied the remaining strokeRec we would have a non-path
            // parent shape that would be used to determine the the stroked path's key.
            // We detect that case here and change parentForKey to a temporary that represents
            // the simpler shape so that applying both path effect and the strokerec all at
            // once produces the same key.
            tmpParent.emplace(fShape.path(), GrStyle(strokeRec, nullptr));
            tmpParent->setInheritedKey(parent, GrStyle::Apply::kPathEffectOnly, scale);
            if (!tmpPath.has_value()) {
                tmpPath.emplace();
            }
            tmpPath = tmpParent->asPath();
            SkStrokeRec::InitStyle fillOrHairline;
            // The parent shape may have simplified away the strokeRec, check for that here.
            if (tmpParent->style().applies()) {
                SkAssertResult(tmpParent->style().applyToPath(&fShape.path(), &fillOrHairline,
                                                              tmpPath.value(), scale));
            } else if (tmpParent->style().isSimpleFill()) {
                fillOrHairline = SkStrokeRec::kFill_InitStyle;
            } else {
                SkASSERT(tmpParent->style().isSimpleHairline());
                fillOrHairline = SkStrokeRec::kHairline_InitStyle;
            }
            fStyle.resetToInitStyle(fillOrHairline);
            parentForKey = &tmpParent.value();
        } else {
            fStyle = GrStyle(strokeRec, nullptr);
        }
    } else {
        const SkPath* srcForParentStyle;
        if (parent.fShape.isPath()) {
            srcForParentStyle = &parent.fShape.path();
        } else {
            srcForParentStyle = &tmpPath.emplace(parent.asPath());
        }
        SkStrokeRec::InitStyle fillOrHairline;
        SkASSERT(parent.fStyle.applies());
        SkASSERT(!parent.fStyle.pathEffect());
        SkAssertResult(parent.fStyle.applyToPath(&fShape.path(), &fillOrHairline,
                                                 *srcForParentStyle, scale));
        fStyle.resetToInitStyle(fillOrHairline);
    }

    if (parent.fInheritedPathForListeners.has_value()) {
        fInheritedPathForListeners = *parent.fInheritedPathForListeners;
    } else if (parent.fShape.isPath() && !parent.fShape.path().isVolatile()) {
        fInheritedPathForListeners = parent.fShape.path();
    }
    this->simplify();
    this->setInheritedKey(*parentForKey, apply, scale);
}

bool GrStyledShape::asRRect(SkRRect* rrect, bool* inverted) const {
    if (!fShape.isRRect() && !fShape.isRect()) {
        return false;
    }

    if (rrect) {
        *rrect = fShape.isRect() ? SkRRect::MakeRect(fShape.rect()) : fShape.rrect();
    }

    if (inverted) {
        *inverted = fShape.inverted();
    }

    return true;
}

bool GrStyledShape::asLine(SkPoint pts[2], bool* inverted) const {
    if (!fShape.isLine()) {
        return false;
    }

    if (pts) {
        pts[0] = fShape.line().fP1;
        pts[1] = fShape.line().fP2;
    }
    if (inverted) {
        *inverted = fShape.inverted();
    }
    return true;
}

bool GrStyledShape::asNestedRects(SkRect rects[2]) const {
    if (!fShape.isPath()) {
        return false;
    }

    // TODO: it would be better two store DRRects natively in the shape rather than converting
    // them to a path and then reextracting the nested rects
    if (fShape.path().isInverseFillType()) {
        return false;
    }

    SkPathDirection dirs[2];
    if (!SkPathPriv::IsNestedFillRects(fShape.path(), rects, dirs)) {
        return false;
    }

    if (SkPathFillType::kWinding == fShape.path().getFillType() && dirs[0] == dirs[1]) {
        // The two rects need to be wound opposite to each other
        return false;
    }

    // Right now, nested rects where the margin is not the same width
    // all around do not render correctly
    const SkScalar* outer = rects[0].asScalars();
    const SkScalar* inner = rects[1].asScalars();

    bool allEq = true;

    SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
    bool allGoE1 = margin >= SK_Scalar1;

    for (int i = 1; i < 4; ++i) {
        SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
        if (temp < SK_Scalar1) {
            allGoE1 = false;
        }
        if (!SkScalarNearlyEqual(margin, temp)) {
            allEq = false;
        }
    }

    return allEq || allGoE1;
}

class AutoRestoreInverseness {
public:
    SK_ONLY_STACK_ALLOCATABLE;

    AutoRestoreInverseness(GrShape* shape, const GrStyle& style)
            // Dashing ignores inverseness skbug.com/40036591.
            : fShape(shape), fInverted(!style.isDashed() && fShape->inverted()) {}

    ~AutoRestoreInverseness() {
        // Restore invertedness after any modifications were made to the shape type
        fShape->setInverted(fInverted);
        SkASSERT(!fShape->isPath() || fInverted == fShape->path().isInverseFillType());
    }

private:
    GrShape* fShape;
    bool fInverted;
};

void GrStyledShape::simplify() {
    AutoRestoreInverseness ari(&fShape, fStyle);

    unsigned simplifyFlags = 0;
    if (fStyle.isSimpleFill()) {
        simplifyFlags = GrShape::kAll_Flags;
    } else if (!fStyle.hasPathEffect()) {
        // Everything but arcs with caps that might extend beyond the oval edge can ignore winding
        if (!fShape.isArc() || fStyle.strokeRec().getCap() == SkPaint::kButt_Cap) {
            simplifyFlags |= GrShape::kIgnoreWinding_Flag;
        }
        simplifyFlags |= GrShape::kMakeCanonical_Flag;
    } // else if there's a path effect, every destructive simplification is disabledd

    // Remember if the original shape was closed; in the event we simplify to a point or line
    // because of degenerate geometry, we need to update joins and caps.
    GrShape::Type oldType = fShape.type();
    fClosed = fShape.simplify(simplifyFlags);
    fSimplified = oldType != fShape.type();

    if (fShape.isPath()) {
        // The shape remains a path, so configure the gen ID and canonicalize fill type if possible
        if (fInheritedKey.count() || fShape.path().isVolatile()) {
            fGenID = 0;
        } else {
            fGenID = fShape.path().getGenerationID();
        }
        if (!fStyle.hasNonDashPathEffect() &&
            (fStyle.strokeRec().getStyle() == SkStrokeRec::kStroke_Style ||
             fStyle.strokeRec().getStyle() == SkStrokeRec::kHairline_Style ||
             fShape.path().isConvex())) {
            // Stroke styles don't differentiate between winding and even/odd. There is no
            // distinction between even/odd and non-zero winding count for convex paths.
            // Moreover, dashing ignores inverseness (skbug.com/40036591)
            fShape.path().setFillType(GrShape::kDefaultFillType);
        }
    } else {
        fInheritedKey.reset(0);
        // Whenever we simplify to a non-path, break the chain so we no longer refer to the
        // original path. This prevents attaching genID listeners to temporary paths created when
        // drawing simple shapes.
        fInheritedPathForListeners.reset();
        // Further simplifications to the shape based on the style
        this->simplifyStroke();
    }
}

void GrStyledShape::simplifyStroke() {
    AutoRestoreInverseness ari(&fShape, fStyle);

    // For stroke+filled rects, a mitered shape becomes a larger rect and a rounded shape
    // becomes a round rect.
    if (!fStyle.hasPathEffect() && fShape.isRect() &&
        fStyle.strokeRec().getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
        if (fStyle.strokeRec().getJoin() == SkPaint::kBevel_Join ||
            (fStyle.strokeRec().getJoin() == SkPaint::kMiter_Join &&
             fStyle.strokeRec().getMiter() < SK_ScalarSqrt2)) {
            // Bevel-stroked rect needs path rendering
            return;
        }

        SkScalar r = fStyle.strokeRec().getWidth() / 2;
        fShape.rect().outset(r, r);
        if (fStyle.strokeRec().getJoin() == SkPaint::kRound_Join) {
            // There's no dashing to worry about if we got here, so it's okay that this resets
            // winding parameters
            fShape.setRRect(SkRRect::MakeRectXY(fShape.rect(), r, r));
        }
        fStyle = GrStyle::SimpleFill();
        fSimplified = true;
        return;
    }

    // Otherwise, if we're a point or a line, we might be able to explicitly apply some of the
    // stroking (and even some of the dashing). Any other shape+style is too complicated to reduce.
    if ((!fShape.isPoint() && !fShape.isLine()) || fStyle.hasNonDashPathEffect() ||
        fStyle.strokeRec().isHairlineStyle()) {
        return;
    }

    // Tracks style simplifications, even if the geometry can't be further simplified.
    bool styleSimplified = false;
    if (fStyle.isDashed()) {
        // For dashing a point, if the first interval is on, we can drop the dash and just draw
        // the caps. For dashing a line, if every off interval is 0 length, its a stroke.
        bool dropDash = false;
        if (fShape.isPoint()) {
            dropDash = fStyle.dashIntervalCnt() > 0 &&
                       SkToBool(fStyle.dashIntervals()[0]);
        } else {
            dropDash = true;
            for (int i = 1; i < fStyle.dashIntervalCnt(); i += 2) {
                if (SkToBool(fStyle.dashIntervals()[i])) {
                    // An off interval has non-zero length so this won't convert to a simple line
                    dropDash = false;
                    break;
                }
            }
        }

        if (!dropDash) {
            return;
        }
        // Fall through to modifying the shape to respect the new stroke geometry
        fStyle = GrStyle(fStyle.strokeRec(), nullptr);
        // Since the reduced the line or point after dashing is dependent on the caps of the dashes,
        // we reset to be unclosed so we don't override the style based on joins later.
        fClosed = false;
        styleSimplified = true;
    }

    // At this point, we're a line or point with no path effects. Any fill portion of the style
    // is empty, so a fill-only style can be empty, and a stroke+fill becomes a stroke.
    if (fStyle.isSimpleFill()) {
        fShape.reset();
        fSimplified = true;
        return;
    } else if (fStyle.strokeRec().getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
        // Stroke only
        SkStrokeRec rec = fStyle.strokeRec();
        rec.setStrokeStyle(fStyle.strokeRec().getWidth(), false);
        fStyle = GrStyle(rec, nullptr);
        styleSimplified = true;
    }

    // A point or line that was formed by a degenerate closed shape needs its style updated to
    // reflect the fact that it doesn't actually produce caps.
    if (fClosed) {
        SkPaint::Cap cap;
        if (fShape.isLine() && fStyle.strokeRec().getJoin() == SkPaint::kRound_Join) {
            // As a closed shape, the line moves from a to b and back to a, producing a 180 degree
            // turn. With round joins, this would make a semi-circle at each end, which is visually
            // identical to a round cap on the reduced line geometry.
            cap = SkPaint::kRound_Cap;
        } else {
            // If this were a closed line, the 180 degree turn either is a miter join that exceeds
            // the miter limit and becomes a bevel, or a bevel join. In either case, the bevel shape
            // of a 180 degreen corner is equivalent to a butt cap.
            //  - to match the SVG spec, the 0-length sides of an empty rectangle are skipped, so
            //    it fits this closed line description (it is not two 90 degree turns that could
            //    produce miter geometry).
            cap = SkPaint::kButt_Cap;
        }

        if (cap != fStyle.strokeRec().getCap() ||
            SkPaint::kDefault_Join != fStyle.strokeRec().getJoin()) {
            SkStrokeRec rec = fStyle.strokeRec();
            rec.setStrokeParams(cap, SkPaint::kDefault_Join, fStyle.strokeRec().getMiter());
            fStyle = GrStyle(rec, nullptr);
            styleSimplified = true;
        }
    }

    if (fShape.isPoint()) {
        // The drawn geometry is entirely based on the cap style and stroke width. A butt cap point
        // doesn't draw anything, a round cap is an oval and a square cap is a square.
        if (fStyle.strokeRec().getCap() == SkPaint::kButt_Cap) {
            fShape.reset();
        } else {
            SkScalar w = fStyle.strokeRec().getWidth() / 2.f;
            SkRect r = {fShape.point().fX, fShape.point().fY, fShape.point().fX, fShape.point().fY};
            r.outset(w, w);

            if (fStyle.strokeRec().getCap() == SkPaint::kRound_Cap) {
                fShape.setRRect(SkRRect::MakeOval(r));
            } else {
                fShape.setRect(r);
            }
        }
    } else {
        // Stroked lines reduce to rectangles or round rects when they are axis-aligned. If we
        // allowed rotation angle, this would work for any lines.
        SkRect rect;
        SkVector outset;
        if (fShape.line().fP1.fY == fShape.line().fP2.fY) {
            rect.fLeft = std::min(fShape.line().fP1.fX, fShape.line().fP2.fX);
            rect.fRight = std::max(fShape.line().fP1.fX, fShape.line().fP2.fX);
            rect.fTop = rect.fBottom = fShape.line().fP1.fY;
            outset.fY = fStyle.strokeRec().getWidth() / 2.f;
            outset.fX = SkPaint::kButt_Cap == fStyle.strokeRec().getCap() ? 0.f : outset.fY;
        } else if (fShape.line().fP1.fX == fShape.line().fP2.fX) {
            rect.fTop = std::min(fShape.line().fP1.fY, fShape.line().fP2.fY);
            rect.fBottom = std::max(fShape.line().fP1.fY, fShape.line().fP2.fY);
            rect.fLeft = rect.fRight = fShape.line().fP1.fX;
            outset.fX = fStyle.strokeRec().getWidth() / 2.f;
            outset.fY = SkPaint::kButt_Cap == fStyle.strokeRec().getCap() ? 0.f : outset.fX;
        } else {
            // Geometrically can't apply the style and turn into a fill, but might still be simpler
            // than before based solely on changes to fStyle.
            fSimplified |= styleSimplified;
            return;
        }
        rect.outset(outset.fX, outset.fY);
        if (rect.isEmpty()) {
            fShape.reset();
        } else if (fStyle.strokeRec().getCap() == SkPaint::kRound_Cap) {
            SkASSERT(outset.fX == outset.fY);
            fShape.setRRect(SkRRect::MakeRectXY(rect, outset.fX, outset.fY));
        } else {
            fShape.setRect(rect);
        }
    }
    // If we made it here, the stroke was fully applied to the new shape so we can become a fill.
    fStyle = GrStyle::SimpleFill();
    fSimplified = true;
}
