/*
 * 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/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++; // 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 {
                    *key++ = fGenID;
                }
                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:
    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;
}
