blob: e0a13f915bdef3116ef2f212eb5c17d4445f2c5a [file] [log] [blame]
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkImagePriv.h"
#include "SkImage_Base.h"
static SkImage_Base* as_IB(SkImage* image) {
return static_cast<SkImage_Base*>(image);
}
static const SkImage_Base* as_IB(const SkImage* image) {
return static_cast<const SkImage_Base*>(image);
}
uint32_t SkImage::NextUniqueID() {
static int32_t gUniqueID;
// never return 0;
uint32_t id;
do {
id = sk_atomic_inc(&gUniqueID) + 1;
} while (0 == id);
return id;
}
void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y,
const SkPaint* paint) {
as_IB(this)->onDraw(canvas, x, y, paint);
}
void SkImage::draw(SkCanvas* canvas, const SkRect* src, const SkRect& dst,
const SkPaint* paint) {
as_IB(this)->onDrawRectToRect(canvas, src, dst, paint);
}
const void* SkImage::peekPixels(SkImageInfo* info, size_t* rowBytes) const {
SkImageInfo infoStorage;
size_t rowBytesStorage;
if (NULL == info) {
info = &infoStorage;
}
if (NULL == rowBytes) {
rowBytes = &rowBytesStorage;
}
return as_IB(this)->onPeekPixels(info, rowBytes);
}
bool SkImage::readPixels(SkBitmap* bitmap, const SkIRect* subset) const {
if (NULL == bitmap) {
return false;
}
SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
// trim against the bitmap, if its already been allocated
if (bitmap->pixelRef()) {
bounds.fRight = SkMin32(bounds.fRight, bitmap->width());
bounds.fBottom = SkMin32(bounds.fBottom, bitmap->height());
if (bounds.isEmpty()) {
return false;
}
}
if (subset && !bounds.intersect(*subset)) {
// perhaps we could return true + empty-bitmap?
return false;
}
return as_IB(this)->onReadPixels(bitmap, bounds);
}
GrTexture* SkImage::getTexture() {
return as_IB(this)->onGetTexture();
}
SkData* SkImage::encode(SkImageEncoder::Type type, int quality) const {
SkBitmap bm;
if (as_IB(this)->getROPixels(&bm)) {
return SkImageEncoder::EncodeData(bm, type, quality);
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
static bool raster_canvas_supports(const SkImageInfo& info) {
switch (info.fColorType) {
case kN32_SkColorType:
return kUnpremul_SkAlphaType != info.fAlphaType;
case kRGB_565_SkColorType:
return true;
case kAlpha_8_SkColorType:
return true;
default:
break;
}
return false;
}
bool SkImage_Base::onReadPixels(SkBitmap* bitmap, const SkIRect& subset) const {
if (bitmap->pixelRef()) {
const SkImageInfo info = bitmap->info();
if (kUnknown_SkColorType == info.colorType()) {
return false;
}
if (!raster_canvas_supports(info)) {
return false;
}
} else {
const SkImageInfo info = SkImageInfo::MakeN32Premul(subset.width(), subset.height());
SkBitmap tmp;
if (!tmp.allocPixels(info)) {
return false;
}
*bitmap = tmp;
}
SkRect srcR, dstR;
srcR.set(subset);
dstR = srcR;
dstR.offset(-dstR.left(), -dstR.top());
SkCanvas canvas(*bitmap);
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kClear_Mode);
canvas.drawRect(dstR, paint);
const_cast<SkImage_Base*>(this)->onDrawRectToRect(&canvas, &srcR, dstR, NULL);
return true;
}