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

#include "src/core/SkClipStackDevice.h"

#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRegion.h"
#include "include/core/SkShader.h"
#include "include/private/base/SkAssert.h"
#include "src/core/SkMatrixPriv.h"

#include <utility>

class SkRRect;
enum class SkClipOp;

SkIRect SkClipStackDevice::devClipBounds() const {
    SkIRect r = fClipStack.bounds(this->imageInfo().bounds()).roundOut();
    if (!r.isEmpty()) {
        SkASSERT(this->imageInfo().bounds().contains(r));
    }
    return r;
}

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

void SkClipStackDevice::pushClipStack() {
    fClipStack.save();
}

void SkClipStackDevice::popClipStack() {
    fClipStack.restore();
}

void SkClipStackDevice::clipRect(const SkRect& rect, SkClipOp op, bool aa) {
    fClipStack.clipRect(rect, this->localToDevice(), op, aa);
}

void SkClipStackDevice::clipRRect(const SkRRect& rrect, SkClipOp op, bool aa) {
    fClipStack.clipRRect(rrect, this->localToDevice(), op, aa);
}

void SkClipStackDevice::clipPath(const SkPath& path, SkClipOp op, bool aa) {
    fClipStack.clipPath(path, this->localToDevice(), op, aa);
}

void SkClipStackDevice::onClipShader(sk_sp<SkShader> shader) {
    fClipStack.clipShader(std::move(shader));
}

void SkClipStackDevice::clipRegion(const SkRegion& rgn, SkClipOp op) {
    SkIPoint origin = this->getOrigin();
    SkRegion tmp;
    SkPathBuilder builder;
    rgn.addBoundaryPath(&builder);
    builder.transform(SkMatrix::Translate(-origin));
    fClipStack.clipPath(builder.detach(), SkMatrix::I(), op, false);
}

void SkClipStackDevice::replaceClip(const SkIRect& rect) {
    SkRect deviceRect = SkMatrixPriv::MapRect(this->globalToDevice(), SkRect::Make(rect));
    fClipStack.replaceClip(deviceRect, /*doAA=*/false);
}

bool SkClipStackDevice::isClipAntiAliased() const {
    SkClipStack::B2TIter        iter(fClipStack);
    const SkClipStack::Element* element;

    while ((element = iter.next()) != nullptr) {
        if (element->isAA()) {
            return true;
        }
    }
    return false;
}

bool SkClipStackDevice::isClipWideOpen() const {
    return fClipStack.quickContains(SkRect::MakeIWH(this->width(), this->height()));
}

bool SkClipStackDevice::isClipEmpty() const {
    return fClipStack.isEmpty(SkIRect::MakeWH(this->width(), this->height()));
}

bool SkClipStackDevice::isClipRect() const {
    if (this->isClipWideOpen()) {
        return true;
    } else if (this->isClipEmpty()) {
        return false;
    }

    SkClipStack::BoundsType boundType;
    bool isIntersectionOfRects;
    SkRect bounds;
    fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects);
    return isIntersectionOfRects && boundType == SkClipStack::kNormal_BoundsType;
}

void SkClipStackDevice::android_utils_clipAsRgn(SkRegion* rgn) const {
    SkClipStack::BoundsType boundType;
    bool isIntersectionOfRects;
    SkRect bounds;
    fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects);
    if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) {
        rgn->setRect(bounds.round());
    } else {
        SkRegion boundsRgn({0, 0, this->width(), this->height()});

        *rgn = boundsRgn;
        SkClipStack::B2TIter iter(fClipStack);
        while (auto elem = iter.next()) {
            SkPath tmpPath = elem->asDeviceSpacePath();
            SkRegion tmpRgn;
            tmpRgn.setPath(tmpPath, boundsRgn);
            if (elem->isReplaceOp()) {
                // All replace elements are rectangles
                // TODO: SkClipStack can be simplified to be I,D,R ops now, which means element
                // iteration can be from top of the stack to the most recent replace element.
                // When that's done, this loop will be simplifiable.
                rgn->setRect(elem->getDeviceSpaceRect().round());
            } else {
                rgn->op(tmpRgn, static_cast<SkRegion::Op>(elem->getOp()));
            }
        }
    }
}
