blob: 980265196ece24a999c8d9f187c62756d955ebfd [file] [log] [blame]
/*
* Copyright 2016 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/SkSpecialSurface.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMallocPixelRef.h"
#include "include/core/SkPixelRef.h"
#include "include/private/base/SkAssert.h"
#include "src/core/SkBitmapDevice.h"
#include "src/core/SkCanvasPriv.h"
#include "src/core/SkDevice.h"
#include "src/core/SkSpecialImage.h"
#include "src/core/SkSurfacePriv.h"
#include <memory>
#include <utility>
SkSpecialSurface::SkSpecialSurface(sk_sp<SkBaseDevice> device, const SkIRect& subset)
: fSubset(subset) {
SkASSERT(fSubset.width() > 0);
SkASSERT(fSubset.height() > 0);
fCanvas = std::make_unique<SkCanvas>(std::move(device));
fCanvas->clipRect(SkRect::Make(subset));
#ifdef SK_IS_BOT
fCanvas->clear(SK_ColorRED); // catch any imageFilter sloppiness
#endif
}
sk_sp<SkSpecialImage> SkSpecialSurface::makeImageSnapshot() {
fCanvas->restoreToCount(0);
// Because of the above 'restoreToCount(0)' we know we're getting the base device here.
SkBaseDevice* baseDevice = SkCanvasPriv::TopDevice(fCanvas.get());
if (!baseDevice) {
return nullptr;
}
sk_sp<SkSpecialImage> image = baseDevice->snapSpecial(this->subset());
fCanvas.reset();
return image;
}
///////////////////////////////////////////////////////////////////////////////
namespace SkSpecialSurfaces {
sk_sp<SkSpecialSurface> MakeRaster(const SkImageInfo& info,
const SkSurfaceProps& props) {
if (!SkSurfaceValidateRasterInfo(info)) {
return nullptr;
}
sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, 0);
if (!pr) {
return nullptr;
}
SkBitmap bitmap;
bitmap.setInfo(info, info.minRowBytes());
bitmap.setPixelRef(std::move(pr), 0, 0);
sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap,
{ props.flags(), kUnknown_SkPixelGeometry }));
if (!device) {
return nullptr;
}
const SkIRect subset = SkIRect::MakeSize(info.dimensions());
return sk_make_sp<SkSpecialSurface>(std::move(device), subset);
}
} // namespace SkSpecialSurfaces