/*
 * 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 "include/core/SkImageFilter.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkRasterHandleAllocator.h"
#include "include/core/SkShader.h"
#include "include/core/SkSurface.h"
#include "include/core/SkVertices.h"
#include "src/core/SkBitmapDevice.h"
#include "src/core/SkDraw.h"
#include "src/core/SkGlyphRun.h"
#include "src/core/SkImageFilterCache.h"
#include "src/core/SkImageFilter_Base.h"
#include "src/core/SkRasterClip.h"
#include "src/core/SkSpecialImage.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkTLazy.h"
#include "src/image/SkImage_Base.h"

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 {
    enum {
        // 8K is 1 too big, since 8K << supersample == 32768 which is too big for SkFixed
        kMaxDim = 8192 - 1
    };

    SkBitmapDevice* fDevice;
    SkPixmap        fRootPixmap;
    SkIRect         fSrcBounds;

    // Used for tiling and non-tiling
    SkDraw          fDraw;

    // fCurr... are only used if fNeedTiling
    SkTLazy<SkPostTranslateMatrixProvider> fTileMatrixProvider;
    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 (!dev->accessPixels(&fRootPixmap)) {
            // NoDrawDevice uses us (why?) so we have to catch this case w/ no pixels
            fRootPixmap.reset(dev->imageInfo(), nullptr, 0);
        }

        // do a quick check, so we don't even have to process "bounds" if there is no need
        const SkIRect clipR = dev->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 = dev->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 fMatrixProvider 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.fMatrixProvider = dev;
            fDraw.fRC = &dev->fRCStack.rc();
            fOrigin.set(0, 0);

            fDraw.fCoverage = dev->accessCoverage();
        }
    }

    bool needsTiling() const { return fNeedsTiling; }

    const SkDraw* 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.

        fDraw.fMatrixProvider = fTileMatrixProvider.init(fDevice->asMatrixProvider(),
                                                         SkIntToScalar(-fOrigin.x()),
                                                         SkIntToScalar(-fOrigin.y()));
        fDevice->fRCStack.rc().translate(-fOrigin.x(), -fOrigin.y(), &fTileRC);
        fTileRC.op(SkIRect::MakeWH(fDraw.fDst.width(), fDraw.fDst.height()),
                   SkRegion::kIntersect_Op);
    }
};

// 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 SkDraw* priv_draw = priv_tiler.next()) {   \
        priv_draw->code;                                    \
    }

// Helper to create an SkDraw from a device
class SkBitmapDevice::BDDraw : public SkDraw {
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);
        }
        fMatrixProvider = dev;
        fRC = &dev->fRCStack.rc();
        fCoverage = dev->accessCoverage();
    }
};

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)
        : INHERITED(bitmap.info(), SkSurfaceProps())
        , fBitmap(bitmap)
        , fRCStack(bitmap.width(), bitmap.height())
        , fGlyphPainter(this->surfaceProps(),
                        bitmap.colorType(),
                        bitmap.colorSpace(),
                        SkStrikeCache::GlobalStrikeCache()) {
    SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));
}

SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& info) {
    return Create(info, SkSurfaceProps());
}

SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkSurfaceProps& surfaceProps,
                               SkRasterHandleAllocator::Handle hndl, const SkBitmap* coverage)
        : INHERITED(bitmap.info(), surfaceProps)
        , fBitmap(bitmap)
        , fRasterHandle(hndl)
        , fRCStack(bitmap.width(), bitmap.height())
        , fGlyphPainter(this->surfaceProps(),
                        bitmap.colorType(),
                        bitmap.colorSpace(),
                        SkStrikeCache::GlobalStrikeCache()) {
    SkASSERT(valid_for_bitmap_device(bitmap.info(), nullptr));

    if (coverage) {
        SkASSERT(coverage->width() == bitmap.width());
        SkASSERT(coverage->height() == bitmap.height());
        fCoverage = std::make_unique<SkBitmap>(*coverage);
    }
}

SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
                                       const SkSurfaceProps& surfaceProps,
                                       bool trackCoverage,
                                       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;
        }
    }

    SkBitmap coverage;
    if (trackCoverage) {
        SkImageInfo ci =
                SkImageInfo::Make(info.dimensions(), kAlpha_8_SkColorType, kPremul_SkAlphaType);
        if (!coverage.tryAllocPixelsFlags(ci, SkBitmap::kZeroPixels_AllocFlag)) {
            return nullptr;
        }
    }

    return new SkBitmapDevice(bitmap, surfaceProps, hndl, trackCoverage ? &coverage : nullptr);
}

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)
    this->privateResize(fBitmap.info().width(), fBitmap.info().height());
}

SkBaseDevice* SkBitmapDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint* layerPaint) {
    const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), 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.fTrackCoverage, 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, size_t count,
                                const SkPoint pts[], const SkPaint& paint) {
    LOOP_TILER( drawPoints(mode, count, 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) {
    // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
    // required to override drawOval.
    this->drawPath(SkPath::Oval(oval), paint, true);
}

void SkBitmapDevice::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
#ifdef SK_IGNORE_BLURRED_RRECT_OPT
    // call the VIRTUAL version, so any subclasses who do handle drawPath aren't
    // required to override drawRRect.
    this->drawPath(SkPath::RRect(rrect), paint, true);
#else
    LOOP_TILER( drawRRect(rrect, paint), Bounder(rrect.getBounds(), paint))
#endif
}

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

void SkBitmapDevice::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
                                const SkRect* dstOrNull, const SkSamplingOptions& sampling,
                                const SkPaint& paint) {
    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), 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(dst.isFinite());
    SkASSERT(dst.isSorted());

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

    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::RectToRect(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.
    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;
        }
    }

    if (paint.getBlender()) {
        goto USE_SHADER;
    }

    if (src && !src->contains(bitmapBounds) &&
        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 (src) {
        // 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;

        // 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);
            return;
        }
    }

    USE_SHADER:

    // construct a shader, so we can call drawRect with the dst
    auto s = SkMakeBitmapShaderForPaint(paint, *bitmapPtr, SkTileMode::kClamp, SkTileMode::kClamp,
                                        sampling, &matrix, kNever_SkCopyPixelsMode);
    if (!s) {
        return;
    }

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

    // 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(const SkGlyphRunList& glyphRunList, const SkPaint& paint) {
    SkASSERT(!glyphRunList.hasRSXForm());
    LOOP_TILER( drawGlyphRunList(glyphRunList, paint, &fGlyphPainter), nullptr )
}

void SkBitmapDevice::drawVertices(const SkVertices* vertices, SkBlendMode bmode,
                                  const SkPaint& paint) {
    BDDraw(this).drawVertices(vertices, bmode, paint);
}

void SkBitmapDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[],
                               const SkRect tex[], const SkColor colors[], int count,
                               SkBlendMode mode, const SkSamplingOptions& sampling,
                               const SkPaint& paint) {
    // set this to true for performance comparisons with the old drawVertices way
    if (false) {
        this->INHERITED::drawAtlas(atlas, xform, tex, colors, count, mode, sampling, paint);
        return;
    }
    BDDraw(this).drawAtlas(atlas, xform, tex, colors, count, mode, sampling, paint);
}

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

void SkBitmapDevice::drawDevice(SkBaseDevice* device, const SkSamplingOptions& sampling,
                                const SkPaint& paint) {
    SkASSERT(!paint.getImageFilter());
    SkASSERT(!paint.getMaskFilter());

    // hack to test coverage
    SkBitmapDevice* src = static_cast<SkBitmapDevice*>(device);
    if (src->fCoverage) {
        SkDraw draw;
        SkSimpleMatrixProvider matrixProvider(device->getRelativeTransform(*this));
        draw.fDst = fBitmap.pixmap();
        draw.fMatrixProvider = &matrixProvider;
        draw.fRC = &fRCStack.rc();

        SkPaint deviceAsShader = paint;
        SkSamplingOptions nearest;    // nearest-neighbor, since we in sprite mode
        deviceAsShader.setShader(src->fBitmap.makeShader(nearest));
        draw.drawBitmap(*src->fCoverage, SkMatrix::I(), nullptr, sampling, deviceAsShader);
    } else {
        this->INHERITED::drawDevice(device, sampling, paint);
    }
}

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

    SkBitmap resultBM;
    if (src->getROPixels(&resultBM)) {
        SkDraw draw;
        SkSimpleMatrixProvider matrixProvider(localToDevice);
        draw.fDst = fBitmap.pixmap();
        draw.fMatrixProvider = &matrixProvider;
        draw.fRC = &fRCStack.rc();
        draw.drawBitmap(resultBM, SkMatrix::I(), nullptr, sampling, paint);
    }
}
sk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkBitmap& bitmap) {
    return SkSpecialImage::MakeFromRaster(bitmap.bounds(), bitmap, this->surfaceProps());
}

sk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkImage* image) {
    return SkSpecialImage::MakeFromImage(nullptr, SkIRect::MakeWH(image->width(), image->height()),
                                         image->makeNonTextureImage(), this->surfaceProps());
}

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

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

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

SkImageFilterCache* SkBitmapDevice::getImageFilterCache() {
    SkImageFilterCache* cache = SkImageFilterCache::Get();
    cache->ref();
    return cache;
}

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

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

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

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

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

void SkBitmapDevice::onClipPath(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::onClipRegion(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::onReplaceClip(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());
}

void SkBitmapDevice::onSetDeviceClipRestriction(SkIRect* mutableClipRestriction) {
    fRCStack.setDeviceClipRestriction(mutableClipRestriction);
    if (!mutableClipRestriction->isEmpty()) {
        SkRegion rgn(*mutableClipRestriction);
        fRCStack.clipRegion(rgn, SkClipOp::kIntersect);
    }
}

bool SkBitmapDevice::onClipIsWideOpen() 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::onClipIsAA() const {
    const SkRasterClip& rc = fRCStack.rc();
    return !rc.isEmpty() && rc.isAA();
}

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

void SkBitmapDevice::validateDevBounds(const SkIRect& drawClipBounds) {
#ifdef SK_DEBUG
    const SkIRect& stackBounds = fRCStack.rc().getBounds();
    SkASSERT(drawClipBounds == stackBounds);
#endif
}

SkBaseDevice::ClipType SkBitmapDevice::onGetClipType() const {
    const SkRasterClip& rc = fRCStack.rc();
    if (rc.isEmpty()) {
        return ClipType::kEmpty;
    } else if (rc.isRect()) {
        return ClipType::kRect;
    } else {
        return ClipType::kComplex;
    }
}

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