/*
 * 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/geometry/GrStyledShape.h"

#include "include/private/SkIDChangeListener.h"

#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.isValid()) {
        fInheritedPathForListeners.set(*that.fInheritedPathForListeners.get());
    } 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.isValid()) {
        result.fInheritedPathForListeners.set(*original.fInheritedPathForListeners.get());
    }

    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;
    }

    // Sanity check 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 int pointCnt = path.countPoints();
    const int conicWeightCnt = SkPathPriv::ConicWeightCnt(path);

    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.
    const int verbCnt = path.countVerbs();
    const int pointCnt = path.countPoints();
    const int conicWeightCnt = SkPathPriv::ConicWeightCnt(path);
    SkASSERT(verbCnt <= GrStyledShape::kMaxKeyFromDataVerbCnt);
    SkASSERT(pointCnt && verbCnt);
    *key++ = verbCnt;
    memcpy(key, SkPathPriv::VerbData(path), verbCnt * sizeof(uint8_t));
    int verbKeySize = SkAlign4(verbCnt);
    // pad out to uint32_t alignment using value that will stand out when debugging.
    uint8_t* pad = reinterpret_cast<uint8_t*>(key)+ verbCnt;
    memset(pad, 0xDE, verbKeySize - verbCnt);
    key += verbKeySize >> 2;

    memcpy(key, SkPathPriv::PointData(path), sizeof(SkPoint) * pointCnt);
    static_assert(sizeof(SkPoint) == 2 * sizeof(uint32_t));
    key += 2 * pointCnt;
    sk_careful_memcpy(key, SkPathPriv::ConicWeightData(path), sizeof(SkScalar) * conicWeightCnt);
    static_assert(sizeof(SkScalar) == sizeof(uint32_t));
    SkDEBUGCODE(key += conicWeightCnt);
    SkASSERT(key - origKey == path_key_from_data_size(path));
}

int GrStyledShape::unstyledKeySize() const {
    if (fInheritedKey.count()) {
        return fInheritedKey.count();
    }

    int 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(GrArc) % sizeof(uint32_t));
            count += sizeof(GrArc) / 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 -1; // volatile, so won't be keyed
            }
            int dataKeySize = path_key_from_data_size(fShape.path());
            if (dataKeySize >= 0) {
                count += 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(GrArc) / sizeof(uint32_t) - 1);
                // Then write the final bool as an int, to make sure upper bits are set
                *key++ = fShape.arc().fUseCenter ? 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) {
    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 < 0) {
                // 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;
        }
        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.isValid()) {
        return fInheritedPathForListeners.get();
    } 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 SkRect& oval, SkScalar startAngleDegrees,
                                     SkScalar sweepAngleDegrees, bool useCenter,
                                     const GrStyle& style) {
    GrStyledShape result;
    result.fShape.setArc({oval.makeSorted(), startAngleDegrees, sweepAngleDegrees, useCenter});
    result.fStyle = style;
    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.isValid()) {
        fInheritedPathForListeners.set(*that.fInheritedPathForListeners.get());
    }
}

GrStyledShape::GrStyledShape(const GrStyledShape& parent, GrStyle::Apply apply, SkScalar 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();
    SkTLazy<SkPath> tmpPath;
    const GrStyledShape* parentForKey = &parent;
    SkTLazy<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.init();
            parent.asPath(tmpPath.get());
        }
        // 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.init(*srcForPathEffect, GrStyle(strokeRec, nullptr));
            *this = tmpParent.get()->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.init(fShape.path(), GrStyle(strokeRec, nullptr));
            tmpParent.get()->setInheritedKey(parent, GrStyle::Apply::kPathEffectOnly, scale);
            if (!tmpPath.isValid()) {
                tmpPath.init();
            }
            tmpParent.get()->asPath(tmpPath.get());
            SkStrokeRec::InitStyle fillOrHairline;
            // The parent shape may have simplified away the strokeRec, check for that here.
            if (tmpParent.get()->style().applies()) {
                SkAssertResult(tmpParent.get()->style().applyToPath(&fShape.path(), &fillOrHairline,
                                                                    *tmpPath.get(), scale));
            } else if (tmpParent.get()->style().isSimpleFill()) {
                fillOrHairline = SkStrokeRec::kFill_InitStyle;
            } else {
                SkASSERT(tmpParent.get()->style().isSimpleHairline());
                fillOrHairline = SkStrokeRec::kHairline_InitStyle;
            }
            fStyle.resetToInitStyle(fillOrHairline);
            parentForKey = tmpParent.get();
        } else {
            fStyle = GrStyle(strokeRec, nullptr);
        }
    } else {
        const SkPath* srcForParentStyle;
        if (parent.fShape.isPath()) {
            srcForParentStyle = &parent.fShape.path();
        } else {
            srcForParentStyle = tmpPath.init();
            parent.asPath(tmpPath.get());
        }
        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.isValid()) {
        fInheritedPathForListeners.set(*parent.fInheritedPathForListeners.get());
    } else if (parent.fShape.isPath() && !parent.fShape.path().isVolatile()) {
        fInheritedPathForListeners.set(parent.fShape.path());
    }
    this->simplify();
    this->setInheritedKey(*parentForKey, apply, scale);
}

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

    // Sanity check here, if we don't have a path effect on the style, we should have passed
    // appropriate flags to GrShape::simplify() to have reset these parameters.
    SkASSERT(fStyle.hasPathEffect() || (fShape.dir() == GrShape::kDefaultDir &&
                                        fShape.startIndex() == GrShape::kDefaultStart));

    // If the shape is a regular rect, map to round rect winding parameters, including accounting
    // for the automatic sorting of edges that SkRRect::MakeRect() performs.
    if (fShape.isRect()) {
        if (rrect) {
            *rrect = SkRRect::MakeRect(fShape.rect());
        }
        // Don't bother mapping these if we don't have a path effect, however.
        if (!fStyle.hasPathEffect()) {
            if (dir) {
                *dir = GrShape::kDefaultDir;
            }
            if (start) {
                *start = GrShape::kDefaultStart;
            }
        } else {
            // In SkPath a rect starts at index 0 by default. This is the top left corner. However,
            // we store rects as rrects. RRects don't preserve the invertedness, but rather sort the
            // rect edges. Thus, we may need to modify the rrect's start index and direction.
            SkPathDirection rectDir = fShape.dir();
            unsigned rectStart = fShape.startIndex();

            if (fShape.rect().fLeft > fShape.rect().fRight) {
                // Toggle direction, and modify index by mapping through the array
                static const unsigned kMapping[] = {1, 0, 3, 2};
                rectDir = rectDir == SkPathDirection::kCCW ? SkPathDirection::kCW
                                                           : SkPathDirection::kCCW;
                rectStart = kMapping[rectStart];
            }
            if (fShape.rect().fTop > fShape.rect().fBottom) {
                // Toggle direction and map index by 3 - start
                // NOTE: if we earlier flipped for X as well, this results in no net direction
                // change and effectively flipping the start index to the diagonal corners of the
                // rect (matching what we'd expect for a rect with both X and Y flipped).
                rectDir = rectDir == SkPathDirection::kCCW ? SkPathDirection::kCW
                                                           : SkPathDirection::kCCW;
                rectStart = 3 - rectStart;
            }

            if (dir) {
                *dir = rectDir;
            }
            if (start) {
                // Convert to round rect indexing
                *start = 2 * rectStart;
            }
        }
    } else {
        // Straight forward export
        if (rrect) {
            *rrect = fShape.rrect();
        }
        if (dir) {
            *dir = fShape.dir();
        }
        if (start) {
            *start = fShape.startIndex();
            // Canonicalize the index if the rrect is an oval, which GrShape doesn't treat special
            // but we do for dashing placement
            if (fShape.rrect().isOval()) {
                *start &= 0b110;
            }
        }
    }

    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;
}

void GrStyledShape::simplify() {
    // Dashing ignores inverseness skbug.com/5421.
    bool inverted = !fStyle.isDashed() && fShape.inverted();

    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();
    bool wasClosed = 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/5421)
            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
        fSimplified |= this->simplifyStroke(wasClosed);
    }

    // Restore invertedness after any modifications were made to the shape type
    fShape.setInverted(inverted);
    SkASSERT(!fShape.isPath() || inverted == fShape.path().isInverseFillType());
}

bool GrStyledShape::simplifyStroke(bool originallyClosed) {
    // 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 false;
        }

        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();
        return true;
    }

    // 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 false;
    }

    // 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 false;
        }
        // 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.
        originallyClosed = 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.
    bool strokeAndFilled = false;
    if (fStyle.isSimpleFill()) {
        fShape.reset();
        return true;
    } 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;
        strokeAndFilled = 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 (originallyClosed) {
        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 (fShape.isPoint() && fStyle.strokeRec().getJoin() == SkPaint::kMiter_Join &&
                   !strokeAndFilled) {
            // Use a square cap for miter join + stroked points, which matches raster's behavior and
            // expectations from Chrome masking tests, although it could be argued to just always
            // use a butt cap. This behavior, though, ensures that the default stroked paint draws
            // something with empty geometry.
            cap = SkPaint::kSquare_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.
            return styleSimplified;
        }
        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();
    return true;
}
