/*
 * 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 "include/effects/SkOpPathEffect.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) || as_PEB(fOne)->computeFastBounds(nullptr)) &&
               (!SkToBool(fTwo) || as_PEB(fTwo)->computeFastBounds(nullptr));
    }

    // bounds will hold the result of the fOne while b2 holds the result of fTwo's fast bounds
    SkRect b2 = *bounds;
    if (fOne && !as_PEB(fOne)->computeFastBounds(bounds)) {
        return false;
    }
    if (fTwo && !as_PEB(fTwo)->computeFastBounds(&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();
}
