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

#include "include/core/SkPathUtils.h"

#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkStrokeRec.h"
#include "src/core/SkMatrixPriv.h"

namespace skpathutils {

#ifdef SK_SUPPORT_MUTABLE_PATHEFFECT
bool FillPathWithPaint(const SkPath& src, const SkPaint& paint, SkPath* dst) {
    return skpathutils::FillPathWithPaint(src, paint, dst, nullptr, 1);
}

bool FillPathWithPaint(const SkPath& src, const SkPaint& paint, SkPath* dst,
                       const SkRect* cullRect, SkScalar resScale) {
    return skpathutils::FillPathWithPaint(src, paint, dst, cullRect,
                                          SkMatrix::Scale(resScale, resScale));
}

bool FillPathWithPaint(const SkPath& src, const SkPaint& paint, SkPath* dst,
                       const SkRect* cullRect, const SkMatrix& ctm) {
    SkPathBuilder builder;
    bool isFilled = FillPathWithPaint(src, paint, &builder, cullRect, ctm);
    *dst = builder.detach();
    return isFilled;
}
#endif

bool FillPathWithPaint(const SkPath& origSrc, const SkPaint& paint, SkPathBuilder* builder,
                       const SkRect* cullRect, const SkMatrix& ctm) {
    builder->reset();
    if (!origSrc.isFinite()) {
        return false;
    }

    const SkScalar resScale = SkMatrixPriv::ComputeResScaleForStroking(ctm);
    SkStrokeRec rec(paint, resScale);

#if defined(SK_BUILD_FOR_FUZZER)
    // Prevent lines with small widths from timing out.
    if (rec.getStyle() == SkStrokeRec::Style::kStroke_Style && rec.getWidth() < 0.001) {
        return false;
    }
#endif

    const SkPath* srcPtr = &origSrc;
    SkPath pathStorage;
    SkPathEffect* pe = paint.getPathEffect();
    if (pe && pe->filterPath(builder, origSrc, &rec, cullRect, ctm)) {
        pathStorage = builder->detach();
        srcPtr = &pathStorage;
    }
    if (!rec.applyToPath(builder, *srcPtr)) {
        *builder = *srcPtr;
    }

    if (!builder->isFinite()) {
        builder->reset();
    }
    return !rec.isHairlineStyle();
}

bool FillPathWithPaint(const SkPath& src, const SkPaint& paint, SkPathBuilder* dst) {
    return FillPathWithPaint(src, paint, dst, nullptr, SkMatrix::I());
}

SkPath FillPathWithPaint(const SkPath& src, const SkPaint& paint, bool* isFillPtr) {
    SkPathBuilder builder;
    bool isFill = FillPathWithPaint(src, paint, &builder);
    if (isFillPtr) {
        *isFillPtr = isFill;
    }
    return builder.detach();
}


} // namespace skpathutils
