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