158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com/* 258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com * Copyright 2012 Google Inc. 358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com * 458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com * Use of this source code is governed by a BSD-style license that can be 558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com * found in the LICENSE file. 658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com */ 758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com#include "SkImage_Base.h" 958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com#include "SkImagePriv.h" 1058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com#include "SkBitmap.h" 1158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com#include "SkCanvas.h" 1258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com#include "SkData.h" 131bed687f6b8fc67336f0f5d6fb5a5b38dd0fdff9halcanary@google.com#include "SkMallocPixelRef.h" 1458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 1558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.comclass SkImage_Raster : public SkImage_Base { 1658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.compublic: 17b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org static bool ValidArgs(const Info& info, size_t rowBytes) { 1858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com const int maxDimension = SK_MaxS32 >> 2; 1958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com const size_t kMaxPixelByteSize = SK_MaxS32; 2058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 2158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com if (info.fWidth < 0 || info.fHeight < 0) { 2258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return false; 2358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 2458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com if (info.fWidth > maxDimension || info.fHeight > maxDimension) { 2558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return false; 2658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 272bd8b8100529c96c81c30f749f672f4caf775b04reed@google.com if ((unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType) { 2858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return false; 2958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 30d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com if ((unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType) { 3158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return false; 3258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 3358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 34a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org if (kUnknown_SkColorType == info.colorType()) { 3558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return false; 3658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 37fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com // TODO: check colorspace 39fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com if (rowBytes < SkImageMinRowBytes(info)) { 4158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return false; 4258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 43fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com int64_t size = (int64_t)info.fHeight * rowBytes; 45d9e0181405c9853ffd20502555200205a5ab09b1bsalomon@google.com if (size > (int64_t)kMaxPixelByteSize) { 4658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return false; 4758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 4858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return true; 4958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 5058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 5158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com static SkImage* NewEmpty(); 5258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 532bd8b8100529c96c81c30f749f672f4caf775b04reed@google.com SkImage_Raster(const SkImageInfo&, SkData*, size_t rb); 5458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com virtual ~SkImage_Raster(); 5558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 5658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE; 57dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org virtual void onDrawRectToRect(SkCanvas*, const SkRect*, const SkRect&, const SkPaint*) SK_OVERRIDE; 584f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com virtual bool onReadPixels(SkBitmap*, const SkIRect&) const SK_OVERRIDE; 594f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com virtual const void* onPeekPixels(SkImageInfo*, size_t* /*rowBytes*/) const SK_OVERRIDE; 604b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.com virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE; 6158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 6258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com // exposed for SkSurface_Raster via SkNewImageFromPixelRef 63e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org SkImage_Raster(const SkImageInfo&, SkPixelRef*, size_t rowBytes); 6458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 6597af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); } 6697af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com 6758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.comprivate: 6858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com SkImage_Raster() : INHERITED(0, 0) {} 6958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 7058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com SkBitmap fBitmap; 7158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 7258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com typedef SkImage_Base INHERITED; 7358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com}; 7458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 7558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com/////////////////////////////////////////////////////////////////////////////// 7658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 7758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.comSkImage* SkImage_Raster::NewEmpty() { 7858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com // Returns lazily created singleton 7958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com static SkImage* gEmpty; 8058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com if (NULL == gEmpty) { 8158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com gEmpty = SkNEW(SkImage_Raster); 8258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 8358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com gEmpty->ref(); 8458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return gEmpty; 8558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com} 8658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 874f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.comstatic void release_data(void* addr, void* context) { 884f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com SkData* data = static_cast<SkData*>(context); 894f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com data->unref(); 904f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com} 914f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com 92b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.orgSkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes) 934f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com : INHERITED(info.fWidth, info.fHeight) 944f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com{ 954f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com data->ref(); 964f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com void* addr = const_cast<void*>(data->data()); 9700f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org SkColorTable* ctable = NULL; 984f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com 9900f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org fBitmap.installPixels(info, addr, rowBytes, ctable, release_data, data); 10058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com fBitmap.setImmutable(); 1014f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com fBitmap.lockPixels(); 10258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com} 10358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 104e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.orgSkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes) 105e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org : INHERITED(info.fWidth, info.fHeight) 106f1901788d8753332c5748a30e8d14e290c155bd1commit-bot@chromium.org{ 107a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org fBitmap.setInfo(info, rowBytes); 108e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org fBitmap.setPixelRef(pr); 1094f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com fBitmap.lockPixels(); 11058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com} 11158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 11258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.comSkImage_Raster::~SkImage_Raster() {} 11358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 11458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.comvoid SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) { 11558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com canvas->drawBitmap(fBitmap, x, y, paint); 11658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com} 11758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 1184f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.comvoid SkImage_Raster::onDrawRectToRect(SkCanvas* canvas, const SkRect* src, 1194f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com const SkRect& dst, const SkPaint* paint) { 120dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org canvas->drawBitmapRectToRect(fBitmap, src, dst, paint); 121dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org} 122dfec28d4a9e05d1d525f377b380b4df3c5e07c7bcommit-bot@chromium.org 1234f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.combool SkImage_Raster::onReadPixels(SkBitmap* dst, const SkIRect& subset) const { 1244f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com if (dst->pixelRef()) { 1254f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com return this->INHERITED::onReadPixels(dst, subset); 1264f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com } else { 1274f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com SkBitmap src; 1284f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com if (!fBitmap.extractSubset(&src, subset)) { 1294f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com return false; 1304f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com } 1318a2ad3cae710f05cca57e48dd1732d575dba2dc7commit-bot@chromium.org return src.copyTo(dst, src.colorType()); 1324f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com } 1334f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com} 1344f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com 1354f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.comconst void* SkImage_Raster::onPeekPixels(SkImageInfo* infoPtr, 1364f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com size_t* rowBytesPtr) const { 137466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org const SkImageInfo info = fBitmap.info(); 138466f5f3e44e703ca58b43ac1c4ac3bfa0e1ff024commit-bot@chromium.org if ((kUnknown_SkColorType == info.colorType()) || !fBitmap.getPixels()) { 1392776e01d2c8ae6a23718cd4f4d9a4bf368a8e46breed@google.com return NULL; 1404f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com } 1414f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com *infoPtr = info; 1424f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com *rowBytesPtr = fBitmap.rowBytes(); 1434f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com return fBitmap.getPixels(); 1444f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com} 1454f7c61583b16e3056cf3350fcef42dcc6d3483b7reed@google.com 1464b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.combool SkImage_Raster::getROPixels(SkBitmap* dst) const { 1474b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.com *dst = fBitmap; 1484b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.com return true; 1494b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.com} 1504b0757b7489ee5d6bd7149bbcdb0b2af6b7a21cbreed@google.com 15158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com/////////////////////////////////////////////////////////////////////////////// 15258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 1532bd8b8100529c96c81c30f749f672f4caf775b04reed@google.comSkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes) { 154b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org if (!SkImage_Raster::ValidArgs(info, rowBytes)) { 15558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return NULL; 15658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 15758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com if (0 == info.fWidth && 0 == info.fHeight) { 15858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return SkImage_Raster::NewEmpty(); 15958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 16058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com // check this after empty-check 16158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com if (NULL == pixels) { 16258b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return NULL; 16358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 164fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 16558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com // Here we actually make a copy of the caller's pixel data 16658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.fHeight * rowBytes)); 167b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes)); 16858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com} 16958b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 17058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 171999da9c5e45fb533efe8782c9096794b9ad1c1b3reed@google.comSkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* data, size_t rowBytes) { 172b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org if (!SkImage_Raster::ValidArgs(info, rowBytes)) { 17358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return NULL; 17458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 17558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com if (0 == info.fWidth && 0 == info.fHeight) { 17658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return SkImage_Raster::NewEmpty(); 17758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 17858b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com // check this after empty-check 179999da9c5e45fb533efe8782c9096794b9ad1c1b3reed@google.com if (NULL == data) { 18058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return NULL; 18158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 182fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 18358b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com // did they give us enough data? 18458b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com size_t size = info.fHeight * rowBytes; 185999da9c5e45fb533efe8782c9096794b9ad1c1b3reed@google.com if (data->size() < size) { 18658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com return NULL; 18758b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com } 188fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 189b947625800a26194fcf63d7b57dadb1a63677f6amike@reedtribe.org return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes)); 19058b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com} 19158b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 192e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.orgSkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr, 193e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org size_t rowBytes) { 194e13af711d4ff9031c9ed3054a4c33a56a0c62e1fcommit-bot@chromium.org return SkNEW_ARGS(SkImage_Raster, (info, pr, rowBytes)); 19558b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com} 19658b21ec7f06cfa8b7d7403a6108c0216345b3510reed@google.com 19797af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.comSkPixelRef* SkBitmapImageGetPixelRef(SkImage* image) { 19897af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com return ((SkImage_Raster*)image)->getPixelRef(); 19997af1a64ae6bdddd346d8babfd9f188279dd6644reed@google.com} 200