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

#include "src/core/SkBitmapDevice.h"

#include "include/core/SkAlphaType.h"
#include "include/core/SkBlender.h"
#include "include/core/SkClipOp.h"
#include "include/core/SkColorType.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRSXform.h"
#include "include/core/SkRasterHandleAllocator.h"
#include "include/core/SkRegion.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSurface.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTileMode.h"
#include "include/cpu/Recorder.h"
#include "include/private/SkAssert.h"
#include "include/private/SkTo.h"
#include "src/core/SkDraw.h"
#include "src/core/SkMaskFilterBase.h"
#include "src/core/SkMatrixPriv.h"
#include "src/core/SkRasterClip.h"
#include "src/core/SkSpecialImage.h"
#include "src/image/SkImage_Base.h"
#include "src/image/SkImage_Raster.h"
#include "src/shaders/SkImageShader.h"
#include "src/text/GlyphRun.h"

#include <utility>

class SkVertices;

struct Bounder {
    SkRect  fBounds;
    bool    fHasBounds;

    Bounder(const SkRect& r, const SkPaint& paint) {
        if ((fHasBounds = paint.canComputeFastBounds())) {
            fBounds = paint.computeFastBounds(r, &fBounds);
        }
    }

    bool hasBounds() const { return fHasBounds; }
    const SkRect* bounds() const { return fHasBounds ? &fBounds : nullptr; }
    operator const SkRect* () const { return this->bounds(); }
};

class SkDrawTiler {
    // 8K is 1 too big, since 8K << supersample == 32768 which is too big for SkFixed
    static constexpr int kMaxDim = 8192 - 1;

    SkBitmapDevice* fDevice;
    SkPixmap        fRootPixmap;
    SkIRect         fSrcBounds;

    // Used for tiling and non-tiling
    skcpu::Draw fDraw;

    // fTileMatrix... are only used if fNeedTiling
    std::optional<SkMatrix> fTileMatrix;
    SkRasterClip            fTileRC;
    SkIPoint                fOrigin;

    bool            fDone, fNeedsTiling;

public:
    static bool NeedsTiling(SkBitmapDevice* dev) {
        return dev->width() > kMaxDim || dev->height() > kMaxDim;
    }

    SkDrawTiler(SkBitmapDevice* dev, const SkRect* bounds) : fDevice(dev) {
        fDone = false;

        // we need fDst to be set, and if we're actually drawing, to dirty the genID
        if (!fDevice->accessPixels(&fRootPixmap)) {
            // NoDrawDevice uses us (why?) so we have to catch this case w/ no pixels
            fRootPixmap.reset(fDevice->imageInfo(), nullptr, 0);
        }

        // do a quick check, so we don't even have to process "bounds" if there is no need
        const SkIRect clipR = fDevice->fRCStack.rc().getBounds();
        fNeedsTiling = clipR.right() > kMaxDim || clipR.bottom() > kMaxDim;
        if (fNeedsTiling) {
            if (bounds) {
                // Make sure we round first, and then intersect. We can't rely on promoting the
                // clipR to floats (and then intersecting with devBounds) since promoting
                // int --> float can make the float larger than the int.
                // rounding(out) first runs the risk of clamping if the float is larger an intmax
                // but our roundOut() is saturating, which is fine for this use case
                //
                // e.g. the older version of this code did this:
                //    devBounds = mapRect(bounds);
                //    if (devBounds.intersect(SkRect::Make(clipR))) {
                //        fSrcBounds = devBounds.roundOut();
                // The problem being that the promotion of clipR to SkRect was unreliable
                //
                fSrcBounds = fDevice->localToDevice().mapRect(*bounds).roundOut();
                if (fSrcBounds.intersect(clipR)) {
                    // Check again, now that we have computed srcbounds.
                    fNeedsTiling = fSrcBounds.right() > kMaxDim || fSrcBounds.bottom() > kMaxDim;
                } else {
                    fNeedsTiling = false;
                    fDone = true;
                }
            } else {
                fSrcBounds = clipR;
            }
        }

        if (fNeedsTiling) {
            // fDraw.fDst and fCTM are reset each time in setupTileDraw()
            fDraw.fRC = &fTileRC;
            // we'll step/increase it before using it
            fOrigin.set(fSrcBounds.fLeft - kMaxDim, fSrcBounds.fTop);
        } else {
            // don't reference fSrcBounds, as it may not have been set
            fDraw.fDst = fRootPixmap;
            fDraw.fCTM = &fDevice->localToDevice();
            fDraw.fRC = &fDevice->fRCStack.rc();
            fOrigin.set(0, 0);
        }

        fDraw.fProps = &fDevice->surfaceProps();
    }

    bool needsTiling() const { return fNeedsTiling; }

    const skcpu::Draw* next() {
        if (fDone) {
            return nullptr;
        }
        if (fNeedsTiling) {
            do {
                this->stepAndSetupTileDraw();  // might set the clip to empty and fDone to true
            } while (!fDone && fTileRC.isEmpty());
            // if we exit the loop and we're still empty, we're (past) done
            if (fTileRC.isEmpty()) {
                SkASSERT(fDone);
                return nullptr;
            }
            SkASSERT(!fTileRC.isEmpty());
        } else {
            fDone = true;   // only draw untiled once
        }
        return &fDraw;
    }

private:
    void stepAndSetupTileDraw() {
        SkASSERT(!fDone);
        SkASSERT(fNeedsTiling);

        // We do fRootPixmap.width() - kMaxDim instead of fOrigin.fX + kMaxDim to avoid overflow.
        if (fOrigin.fX >= fSrcBounds.fRight - kMaxDim) {    // too far
            fOrigin.fX = fSrcBounds.fLeft;
            fOrigin.fY += kMaxDim;
        } else {
            fOrigin.fX += kMaxDim;
        }
        // fDone = next origin will be invalid.
        fDone = fOrigin.fX >= fSrcBounds.fRight - kMaxDim &&
                fOrigin.fY >= fSrcBounds.fBottom - kMaxDim;

        SkIRect bounds = SkIRect::MakeXYWH(fOrigin.x(), fOrigin.y(), kMaxDim, kMaxDim);
        SkASSERT(!bounds.isEmpty());
        bool success = fRootPixmap.extractSubset(&fDraw.fDst, bounds);
        SkASSERT_RELEASE(success);
        // now don't use bounds, since fDst has the clipped dimensions.

        fTileMatrix = fDevice->localToDevice();
        fTileMatrix->postTranslate(-fOrigin.x(), -fOrigin.y());
        fDraw.fCTM = &fTileMatrix.value();
        fDevice->fRCStack.rc().translate(-fOrigin.x(), -fOrigin.y(), &fTileRC);
        fTileRC.op(SkIRect::MakeSize(fDraw.fDst.dimensions()), SkClipOp::kIntersect);
    }
};

// Passing a bounds allows the tiler to only visit the dst-tiles that might intersect the
// drawing. If null is passed, the tiler has to visit everywhere. The bounds is expected to be
// in local coordinates, as the tiler itself will transform that into device coordinates.
//
#define LOOP_TILER(code, boundsPtr)                            \
    SkDrawTiler priv_tiler(this, boundsPtr);                   \
    while (const skcpu::Draw* priv_draw = priv_tiler.next()) { \
        priv_draw->code;                                       \
    }

// Helper to create an skcpu::Draw from a device
class SkBitmapDevice::BDDraw : public skcpu::Draw {
public:
    BDDraw(SkBitmapDevice* dev) {
        // we need fDst to be set, and if we're actually drawing, to dirty the genID
        if (!dev->accessPixels(&fDst)) {
            // NoDrawDevice uses us (why?) so we have to catch this case w/ no pixels
            fDst.reset(dev->imageInfo(), nullptr, 0);
        }
        fCTM = &dev->localToDevice();
        fRC = &dev->fRCStack.rc();
    }
};

static bool valid_for_bitmap_device(const SkImageInfo& info,
                                    SkAlphaType* newAlphaType) {
    if (info.width() < 0 || info.height() < 0 || kUnknown_SkColorType == info.colorType()) {
        return false;
    }

    if (newAlphaType) {
        *newAlphaType = SkColorTypeIsAlwaysOpaque(info.colorType()) ? kOpaque_SkAlphaType
                                                                    : info.alphaType();
    }

    return true;
}

SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
        : SkBitmapDevice(skcpu::Recorder::TODO(), bitmap) {}

SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap,
                               const SkSurfaceProps& surfaceProps,
                               SkRasterHandleAllocator::Handle hndl)
        : SkBitmapDevice(skcpu::Recorder::TODO(), bitmap, surfaceProps, hndl) {}

SkBitmapDevice::SkBitmapDevice(skcpu::Recorder* recorder, const SkBitmap& bitmap)
        : SkDevice(bitmap.info(), SkSurfaceProps())
        , fRecorder(recorder)
        , fBitmap(bitmap)
        , fRCStack(bitmap.width(), bitmap.height())
        , fGlyphPainter(this->surfaceProps(), bitmap.colorType(), bitmap.colorSpace()) {
    SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
}

SkBitmapDevice::SkBitmapDevice(skcpu::Recorder* recorder,
                               const SkBitmap& bitmap,
                               const SkSurfaceProps& surfaceProps,
                               SkRasterHandleAllocator::Handle hndl)
        : SkDevice(bitmap.info(), surfaceProps)
        , fRasterHandle(hndl)
        , fRecorder(recorder)
        , fBitmap(bitmap)
        , fRCStack(bitmap.width(), bitmap.height())
        , fGlyphPainter(this->surfaceProps(), bitmap.colorType(), bitmap.colorSpace()) {
    SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
}

SkRecorder* SkBitmapDevice::baseRecorder() const { return fRecorder; }

sk_sp<SkBitmapDevice> SkBitmapDevice::Create(const SkImageInfo& origInfo,
                                             const SkSurfaceProps& surfaceProps,
                                             SkRasterHandleAllocator* allocator) {
    SkAlphaType newAT = origInfo.alphaType();
    if (!valid_for_bitmap_device(origInfo, &newAT)) {
        return nullptr;
    }

    SkRasterHandleAllocator::Handle hndl = nullptr;
    const SkImageInfo info = origInfo.makeAlphaType(newAT);
    SkBitmap bitmap;

    if (kUnknown_SkColorType == info.colorType()) {
        if (!bitmap.setInfo(info)) {
            return nullptr;
        }
    } else if (allocator) {
        hndl = allocator->allocBitmap(info, &bitmap);
        if (!hndl) {
            return nullptr;
        }
    } else if (info.isOpaque()) {
        // If this bitmap is opaque, we don't have any sensible default color,
        // so we just return uninitialized pixels.
        if (!bitmap.tryAllocPixels(info)) {
            return nullptr;
        }
    } else {
        // This bitmap has transparency, so we'll zero the pixels (to transparent).
        // We use the flag as a faster alloc-then-eraseColor(SK_ColorTRANSPARENT).
        if (!bitmap.tryAllocPixelsFlags(info, SkBitmap::kZeroPixels_AllocFlag)) {
            return nullptr;
        }
    }

    return sk_make_sp<SkBitmapDevice>(bitmap, surfaceProps, hndl);
}

void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
    SkASSERT(bm.width() == fBitmap.width());
    SkASSERT(bm.height() == fBitmap.height());
    fBitmap = bm;   // intent is to use bm's pixelRef (and rowbytes/config)
}

sk_sp<SkDevice> SkBitmapDevice::createDevice(const CreateInfo& cinfo, const SkPaint* layerPaint) {
    const SkSurfaceProps surfaceProps =
        this->surfaceProps().cloneWithPixelGeometry(cinfo.fPixelGeometry);

    // Need to force L32 for now if we have an image filter.
    // If filters ever support other colortypes, e.g. F16, we can modify this check.
    SkImageInfo info = cinfo.fInfo;
    if (layerPaint && layerPaint->getImageFilter()) {
        // TODO: can we query the imagefilter, to see if it can handle floats (so we don't always
        //       use N32 when the layer itself was float)?
        info = info.makeColorType(kN32_SkColorType);
    }

    return SkBitmapDevice::Create(info, surfaceProps, cinfo.fAllocator);
}

bool SkBitmapDevice::onAccessPixels(SkPixmap* pmap) {
    if (this->onPeekPixels(pmap)) {
        fBitmap.notifyPixelsChanged();
        return true;
    }
    return false;
}

bool SkBitmapDevice::onPeekPixels(SkPixmap* pmap) {
    const SkImageInfo info = fBitmap.info();
    if (fBitmap.getPixels() && (kUnknown_SkColorType != info.colorType())) {
        pmap->reset(fBitmap.info(), fBitmap.getPixels(), fBitmap.rowBytes());
        return true;
    }
    return false;
}

bool SkBitmapDevice::onWritePixels(const SkPixmap& pm, int x, int y) {
    // since we don't stop creating un-pixeled devices yet, check for no pixels here
    if (nullptr == fBitmap.getPixels()) {
        return false;
    }

    if (fBitmap.writePixels(pm, x, y)) {
        fBitmap.notifyPixelsChanged();
        return true;
    }
    return false;
}

bool SkBitmapDevice::onReadPixels(const SkPixmap& pm, int x, int y) {
    return fBitmap.readPixels(pm, x, y);
}

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

void SkBitmapDevice::drawPaint(const SkPaint& paint) {
    BDDraw(this).drawPaint(paint);
}

void SkBitmapDevice::drawPoints(SkCanvas::PointMode mode, SkSpan<const SkPoint> pts,
                                const SkPaint& paint) {
    LOOP_TILER( drawPoints(mode, pts, paint, nullptr), nullptr)
}

void SkBitmapDevice::drawRect(const SkRect& r, const SkPaint& paint) {
    LOOP_TILER( drawRect(r, paint), Bounder(r, paint))
}

void SkBitmapDevice::drawOval(const SkRect& oval, const SkPaint& paint) {
    LOOP_TILER( drawOval(oval, paint), Bounder(oval, paint))
}

void SkBitmapDevice::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    LOOP_TILER( drawRRect(rrect, paint), Bounder(rrect.getBounds(), paint))
}

void SkBitmapDevice::drawPath(const SkPath& path, const SkPaint& paint) {
    const SkRect* bounds = nullptr;
    if (SkDrawTiler::NeedsTiling(this) && !path.isInverseFillType()) {
        bounds = &path.getBounds();
    }
    SkDrawTiler tiler(this, bounds ? Bounder(*bounds, paint).bounds() : nullptr);
    while (const skcpu::Draw* draw = tiler.next()) {
        draw->drawPath(path, paint, nullptr);
    }
}

void SkBitmapDevice::drawBitmap(const SkBitmap& bitmap,
                                const SkMatrix& matrix,
                                const SkRect* dstOrNull,
                                const SkSamplingOptions& sampling,
                                const SkPaint& paint,
                                sk_sp<SkMipmap> mips) {
    const SkRect* bounds = dstOrNull;
    SkRect storage;
    if (!bounds && SkDrawTiler::NeedsTiling(this)) {
        matrix.mapRect(&storage, SkRect::MakeIWH(bitmap.width(), bitmap.height()));
        Bounder b(storage, paint);
        if (b.hasBounds()) {
            storage = *b.bounds();
            bounds = &storage;
        }
    }
    LOOP_TILER(drawBitmap(bitmap, matrix, dstOrNull, sampling, paint, mips), bounds)
}

static inline bool CanApplyDstMatrixAsCTM(const SkMatrix& m, const SkPaint& paint) {
    if (!paint.getMaskFilter()) {
        return true;
    }

    // Some mask filters parameters (sigma) depend on the CTM/scale.
    return m.getType() <= SkMatrix::kTranslate_Mask;
}

void SkBitmapDevice::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
                                   const SkSamplingOptions& sampling, const SkPaint& paint,
                                   SkCanvas::SrcRectConstraint constraint) {
    SkASSERT(image);
    SkASSERT(dst.isFinite());
    SkASSERT(dst.isSorted());

    SkBitmap bitmap;
    // TODO: Elevate direct context requirement to public API and remove cheat.
    auto imageBase = as_IB(image);
    auto dContext = imageBase->directContext();
    if (!imageBase->getROPixels(dContext, &bitmap)) {
        return;
    }
    sk_sp<SkMipmap> mips = imageBase->refMips();

    SkRect      bitmapBounds, tmpSrc, tmpDst;
    SkBitmap    tmpBitmap;

    bitmapBounds.setIWH(bitmap.width(), bitmap.height());

    // Compute matrix from the two rectangles
    if (src) {
        tmpSrc = *src;
    } else {
        tmpSrc = bitmapBounds;
    }
    SkMatrix matrix = SkMatrix::RectToRectOrIdentity(tmpSrc, dst);

    const SkRect* dstPtr = &dst;
    const SkBitmap* bitmapPtr = &bitmap;

    // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
    // needed (if the src was clipped). No check needed if src==null.
    bool srcIsSubset = false;
    if (src) {
        if (!bitmapBounds.contains(*src)) {
            if (!tmpSrc.intersect(bitmapBounds)) {
                return; // nothing to draw
            }
            // recompute dst, based on the smaller tmpSrc
            matrix.mapRect(&tmpDst, tmpSrc);
            if (!tmpDst.isFinite()) {
                return;
            }
            dstPtr = &tmpDst;
        }
        srcIsSubset = !tmpSrc.contains(bitmapBounds);
    }

    if (srcIsSubset &&
        SkCanvas::kFast_SrcRectConstraint == constraint &&
        sampling != SkSamplingOptions()) {
        // src is smaller than the bounds of the bitmap, and we are filtering, so we don't know
        // how much more of the bitmap we need, so we can't use extractSubset or drawBitmap,
        // but we must use a shader w/ dst bounds (which can access all of the bitmap needed).
        goto USE_SHADER;
    }

    if (srcIsSubset) {
        // since we may need to clamp to the borders of the src rect within
        // the bitmap, we extract a subset.
        const SkIRect srcIR = tmpSrc.roundOut();
        if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
            return;
        }
        bitmapPtr = &tmpBitmap;
        mips = nullptr;

        // Since we did an extract, we need to adjust the matrix accordingly
        SkScalar dx = 0, dy = 0;
        if (srcIR.fLeft > 0) {
            dx = SkIntToScalar(srcIR.fLeft);
        }
        if (srcIR.fTop > 0) {
            dy = SkIntToScalar(srcIR.fTop);
        }
        if (dx || dy) {
            matrix.preTranslate(dx, dy);
        }

#ifdef SK_DRAWBITMAPRECT_FAST_OFFSET
        SkRect extractedBitmapBounds = SkRect::MakeXYWH(dx, dy,
                                                        SkIntToScalar(bitmapPtr->width()),
                                                        SkIntToScalar(bitmapPtr->height()));
#else
        SkRect extractedBitmapBounds;
        extractedBitmapBounds.setIWH(bitmapPtr->width(), bitmapPtr->height());
#endif
        if (extractedBitmapBounds == tmpSrc) {
            // no fractional part in src, we can just call drawBitmap
            goto USE_DRAWBITMAP;
        }
    } else {
        USE_DRAWBITMAP:
        // We can go faster by just calling drawBitmap, which will concat the
        // matrix with the CTM, and try to call drawSprite if it can. If not,
        // it will make a shader and call drawRect, as we do below.
        if (CanApplyDstMatrixAsCTM(matrix, paint)) {
            this->drawBitmap(*bitmapPtr, matrix, dstPtr, sampling, paint, mips);
            return;
        }
    }

    USE_SHADER:

    // construct a shader, so we can call drawRect with the dst
    auto img = SkImage_Raster::MakeFromBitmap(*bitmapPtr, SkCopyPixelsMode::kNever, mips);
    auto shader = img->makeShaderForPaint(
            paint, SkTileMode::kClamp, SkTileMode::kClamp, sampling, &matrix);
    if (!shader) {
        return;
    }

    SkPaint paintWithShader(paint);
    paintWithShader.setStyle(SkPaint::kFill_Style);
    paintWithShader.setShader(std::move(shader));

    // Call ourself, in case the subclass wanted to share this setup code
    // but handle the drawRect code themselves.
    this->drawRect(*dstPtr, paintWithShader);
}

void SkBitmapDevice::onDrawGlyphRunList(SkCanvas* canvas,
                                        const sktext::GlyphRunList& glyphRunList,
                                        const SkPaint& paint) {
    SkASSERT(!glyphRunList.hasRSXForm());
    LOOP_TILER( drawGlyphRunList(canvas, &fGlyphPainter, glyphRunList, paint), nullptr )
}

void SkBitmapDevice::drawVertices(const SkVertices* vertices,
                                  sk_sp<SkBlender> blender,
                                  const SkPaint& paint,
                                  bool skipColorXform) {
#ifdef SK_LEGACY_IGNORE_DRAW_VERTICES_BLEND_WITH_NO_SHADER
    if (!paint.getShader()) {
        blender = SkBlender::Mode(SkBlendMode::kDst);
    }
#endif
    BDDraw(this).drawVertices(vertices, std::move(blender), paint, skipColorXform);
}

void SkBitmapDevice::drawMesh(const SkMesh&, sk_sp<SkBlender>, const SkPaint&) {
    // TODO: Implement, maybe with a subclass of BitmapDevice that has SkSL support.
}

void SkBitmapDevice::drawAtlas(SkSpan<const SkRSXform> xform,
                               SkSpan<const SkRect> tex,
                               SkSpan<const SkColor> colors,
                               sk_sp<SkBlender> blender,
                               const SkPaint& paint) {
    BDDraw(this).drawAtlas(xform, tex, colors, std::move(blender), paint);
}

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

void SkBitmapDevice::drawSpecial(SkSpecialImage* src,
                                 const SkMatrix& localToDevice,
                                 const SkSamplingOptions& sampling,
                                 const SkPaint& paint,
                                 SkCanvas::SrcRectConstraint) {
    SkASSERT(!paint.getImageFilter());
    SkASSERT(!paint.getMaskFilter());
    SkASSERT(!src->isGaneshBacked());
    SkASSERT(!src->isGraphiteBacked());

    SkBitmap resultBM;
    if (SkSpecialImages::AsBitmap(src, &resultBM)) {
        skcpu::Draw draw;
        if (!this->accessPixels(&draw.fDst)) {
          return; // no pixels to draw to so skip it
        }
        draw.fCTM = &localToDevice;
        draw.fRC = &fRCStack.rc();
        draw.drawBitmap(resultBM, SkMatrix::I(), nullptr, sampling, paint, nullptr);
    }
}

void SkBitmapDevice::drawCoverageMask(const SkSpecialImage* mask,
                                      const SkMatrix& maskToDevice,
                                      const SkSamplingOptions& sampling,
                                      const SkPaint& paint) {
    SkASSERT(!mask->isGaneshBacked());
    SkASSERT(!mask->isGraphiteBacked());

    SkBitmap maskBM;
    if (!SkSpecialImages::AsBitmap(mask, &maskBM)) {
        return;
    }

    skcpu::Draw draw;
    if (!this->accessPixels(&draw.fDst)) {
      return; // no pixels to draw to so skip it
    }
    draw.fRC = &fRCStack.rc();
    draw.fCTM = &maskToDevice;
    draw.drawBitmapAsMask(maskBM, sampling, paint, &this->localToDevice());
}

// Try to filter as nine patch as a fast path.
bool SkBitmapDevice::drawBlurredRRect(const SkRRect& rrect, const SkPaint& paint,
                                      SkV2 /*localSigma*/, float /*deviceSigma*/) {
    // If there is more than just translation, rotation, and uniform scale, then the results of
    // analytic blurring will be different than mask filter blurring.
    if (!this->localToDevice().isSimilarity()) {
        return false;
    }

    SkASSERT(paint.getMaskFilter()
             && as_MFB(paint.getMaskFilter())->type() == SkMaskFilterBase::Type::kBlur);

    SkDrawTiler tiler(this, Bounder(rrect.getBounds(), paint));
    // Check if the tiler only needs one iteration (common case). If there are multiple
    // tiles, we just return false and fall back to the general mask filter path as we
    // don't want to be in the scenario where only a subset fail/succeed.
    if (!tiler.needsTiling()) {
        if (const skcpu::Draw* draw = tiler.next()) {
            return draw->drawRRectNinePatch(rrect, paint);
        }
    }

    return false;
}

sk_sp<SkSpecialImage> SkBitmapDevice::snapSpecial(const SkIRect& bounds, bool forceCopy) {
    if (forceCopy) {
        return SkSpecialImages::CopyFromRaster(bounds, fBitmap, this->surfaceProps());
    } else {
        return SkSpecialImages::MakeFromRaster(bounds, fBitmap, this->surfaceProps());
    }
}

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

sk_sp<SkSurface> SkBitmapDevice::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
    return SkSurfaces::Raster(info, &props);
}

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

void SkBitmapDevice::pushClipStack() {
    fRCStack.save();
}

void SkBitmapDevice::popClipStack() {
    fRCStack.restore();
}

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

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

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

void SkBitmapDevice::onClipShader(sk_sp<SkShader> sh) {
    fRCStack.clipShader(std::move(sh));
}

void SkBitmapDevice::clipRegion(const SkRegion& rgn, SkClipOp op) {
    SkIPoint origin = this->getOrigin();
    SkRegion tmp;
    const SkRegion* ptr = &rgn;
    if (origin.fX | origin.fY) {
        // translate from "global/canvas" coordinates to relative to this device
        rgn.translate(-origin.fX, -origin.fY, &tmp);
        ptr = &tmp;
    }
    fRCStack.clipRegion(*ptr, op);
}

void SkBitmapDevice::replaceClip(const SkIRect& rect) {
    // Transform from "global/canvas" coordinates to relative to this device
    SkRect deviceRect = SkMatrixPriv::MapRect(this->globalToDevice(), SkRect::Make(rect));
    fRCStack.replaceClip(deviceRect.round());
}

bool SkBitmapDevice::isClipWideOpen() const {
    const SkRasterClip& rc = fRCStack.rc();
    // If we're AA, we can't be wide-open (we would represent that as BW)
    return rc.isBW() && rc.bwRgn().isRect() &&
           rc.bwRgn().getBounds() == SkIRect{0, 0, this->width(), this->height()};
}

bool SkBitmapDevice::isClipEmpty() const {
    return fRCStack.rc().isEmpty();
}

bool SkBitmapDevice::isClipRect() const {
    const SkRasterClip& rc = fRCStack.rc();
    return !rc.isEmpty() && rc.isRect() && !SkToBool(rc.clipShader());
}

bool SkBitmapDevice::isClipAntiAliased() const {
    const SkRasterClip& rc = fRCStack.rc();
    return !rc.isEmpty() && rc.isAA();
}

void SkBitmapDevice::android_utils_clipAsRgn(SkRegion* rgn) const {
    const SkRasterClip& rc = fRCStack.rc();
    if (rc.isAA()) {
        rgn->setRect(   rc.getBounds());
    } else {
        *rgn = rc.bwRgn();
    }
}

SkIRect SkBitmapDevice::devClipBounds() const {
    return fRCStack.rc().getBounds();
}
