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

#include "include/core/SkStrokeRec.h"
#include "src/core/SkPathEffectPriv.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkRectPriv.h"
#include "src/core/SkWriteBuffer.h"
#include "src/effects/SkOpPE.h"

sk_sp<SkPathEffect> SkMergePathEffect::Make(sk_sp<SkPathEffect> one, sk_sp<SkPathEffect> two,
                                            SkPathOp op) {
    return sk_sp<SkPathEffect>(new SkOpPE(std::move(one), std::move(two), op));
}

SkOpPE::SkOpPE(sk_sp<SkPathEffect> one, sk_sp<SkPathEffect> two, SkPathOp op)
    : fOne(std::move(one)), fTwo(std::move(two)), fOp(op) {}

bool SkOpPE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
                          const SkRect* cull) const {
    SkPath one, two;
    if (fOne) {
        if (!fOne->filterPath(&one, src, rec, cull)) {
            return false;
        }
    } else {
        one = src;
    }
    if (fTwo) {
        if (!fTwo->filterPath(&two, src, rec, cull)) {
            return false;
        }
    } else {
        two = src;
    }
    return Op(one, two, fOp, dst);
}

bool SkOpPE::computeFastBounds(SkRect* bounds) const {
    if (!bounds) {
        return (!SkToBool(fOne) || SkPathEffectPriv::ComputeFastBounds(fOne.get(), nullptr)) &&
               (!SkToBool(fTwo) || SkPathEffectPriv::ComputeFastBounds(fTwo.get(), nullptr));
    }

    // bounds will hold the result of the fOne while b2 holds the result of fTwo's fast bounds
    SkRect b2 = *bounds;
    if (fOne && !SkPathEffectPriv::ComputeFastBounds(fOne.get(), bounds)) {
        return false;
    }
    if (fTwo && !SkPathEffectPriv::ComputeFastBounds(fTwo.get(), &b2)) {
        return false;
    }

    switch (fOp) {
        case SkPathOp::kIntersect_SkPathOp:
            if (!bounds->intersect(b2)) {
                bounds->setEmpty();
            }
            break;
        case SkPathOp::kDifference_SkPathOp:
            // (one - two) conservatively leaves one's bounds unmodified
            break;
        case SkPathOp::kReverseDifference_SkPathOp:
            // (two - one) conservatively leaves two's bounds unmodified
            *bounds = b2;
            break;
        case SkPathOp::kXOR_SkPathOp:
            // fall through to union since XOR computes a subset of regular OR
        case SkPathOp::kUnion_SkPathOp:
            bounds->join(b2);
            break;
    }

    return true;
}

void SkOpPE::flatten(SkWriteBuffer& buffer) const {
    buffer.writeFlattenable(fOne.get());
    buffer.writeFlattenable(fTwo.get());
    buffer.write32(fOp);
}

sk_sp<SkFlattenable> SkOpPE::CreateProc(SkReadBuffer& buffer) {
    auto one = buffer.readPathEffect();
    auto two = buffer.readPathEffect();
    SkPathOp op = buffer.read32LE(kReverseDifference_SkPathOp);
    return buffer.isValid() ? SkMergePathEffect::Make(std::move(one), std::move(two), op) : nullptr;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

sk_sp<SkPathEffect> SkMatrixPathEffect::MakeTranslate(SkScalar dx, SkScalar dy) {
    if (!SkScalarsAreFinite(dx, dy)) {
        return nullptr;
    }
    return sk_sp<SkPathEffect>(new SkMatrixPE(SkMatrix::Translate(dx, dy)));
}

sk_sp<SkPathEffect> SkMatrixPathEffect::Make(const SkMatrix& matrix) {
    if (!matrix.isFinite()) {
        return nullptr;
    }
    return sk_sp<SkPathEffect>(new SkMatrixPE(matrix));
}

SkMatrixPE::SkMatrixPE(const SkMatrix& matrix) : fMatrix(matrix) {
    SkASSERT(matrix.isFinite());
}

bool SkMatrixPE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const {
    src.transform(fMatrix, dst);
    return true;
}

void SkMatrixPE::flatten(SkWriteBuffer& buffer) const {
    buffer.writeMatrix(fMatrix);
}

sk_sp<SkFlattenable> SkMatrixPE::CreateProc(SkReadBuffer& buffer) {
    SkMatrix mx;
    buffer.readMatrix(&mx);
    return buffer.isValid() ? SkMatrixPathEffect::Make(mx) : nullptr;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

sk_sp<SkPathEffect> SkStrokePathEffect::Make(SkScalar width, SkPaint::Join join, SkPaint::Cap cap,
                                             SkScalar miter) {
    if (!SkScalarsAreFinite(width, miter) || width < 0 || miter < 0) {
        return nullptr;
    }
    return sk_sp<SkPathEffect>(new SkStrokePE(width, join, cap, miter));
}

SkStrokePE::SkStrokePE(SkScalar width, SkPaint::Join join, SkPaint::Cap cap, SkScalar miter)
    : fWidth(width), fMiter(miter), fJoin(join), fCap(cap) {}

bool SkStrokePE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect*) const {
    SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
    rec.setStrokeStyle(fWidth);
    rec.setStrokeParams(fCap, fJoin, fMiter);
    return rec.applyToPath(dst, src);
}

bool SkStrokePE::computeFastBounds(SkRect* bounds) const {
    if (bounds) {
        SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
        rec.setStrokeStyle(fWidth);
        rec.setStrokeParams(fCap, fJoin, fMiter);
        bounds->outset(rec.getInflationRadius(), rec.getInflationRadius());
    }
    return true;
}

void SkStrokePE::flatten(SkWriteBuffer& buffer) const {
    buffer.writeScalar(fWidth);
    buffer.writeScalar(fMiter);
    buffer.write32(fJoin);
    buffer.write32(fCap);
}

sk_sp<SkFlattenable> SkStrokePE::CreateProc(SkReadBuffer& buffer) {
    SkScalar width = buffer.readScalar();
    SkScalar miter = buffer.readScalar();
    SkPaint::Join join = buffer.read32LE(SkPaint::kLast_Join);
    SkPaint::Cap cap = buffer.read32LE(SkPaint::kLast_Cap);
    return buffer.isValid() ? SkStrokePathEffect::Make(width, join, cap, miter) : nullptr;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

#include "include/effects/SkStrokeAndFillPathEffect.h"
#include "src/core/SkPathPriv.h"

sk_sp<SkPathEffect> SkStrokeAndFillPathEffect::Make() {
    static SkPathEffect* strokeAndFill = new SkStrokeAndFillPE;
    return sk_ref_sp(strokeAndFill);
}

void SkStrokeAndFillPE::flatten(SkWriteBuffer&) const {}

static bool known_to_be_opposite_directions(const SkPath& a, const SkPath& b) {
    auto a_dir = SkPathPriv::ComputeFirstDirection(a),
         b_dir = SkPathPriv::ComputeFirstDirection(b);

    return (a_dir == SkPathFirstDirection::kCCW &&
            b_dir == SkPathFirstDirection::kCW)
            ||
           (a_dir == SkPathFirstDirection::kCW &&
            b_dir == SkPathFirstDirection::kCCW);
}

bool SkStrokeAndFillPE::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
                                     const SkRect*) const {
    // This one is weird, since we exist to allow this paint-style to go away. If we see it,
    // just let the normal machine run its course.
    if (rec->getStyle() == SkStrokeRec::kStrokeAndFill_Style) {
        *dst = src;
        return true;
    }

    if (rec->getStyle() == SkStrokeRec::kStroke_Style) {
        if (!rec->applyToPath(dst, src)) {
            return false;
        }

        if (known_to_be_opposite_directions(src, *dst)) {
            dst->reverseAddPath(src);
        } else {
            dst->addPath(src);
        }
    } else {
        *dst = src;
    }
    rec->setFillStyle();
    return true;
}

sk_sp<SkFlattenable> SkStrokeAndFillPE::CreateProc(SkReadBuffer& buffer) {
    return SkStrokeAndFillPathEffect::Make();
}
