SkImage.cpp revision 70e359055240d0de93da4ba71bf5833164fb394c
1#include "SkImage.h" 2#include "SkImagePriv.h" 3#include "SkBitmap.h" 4#include "SkCanvas.h" 5 6/////////////////////////////////////////////////////////////////////////////// 7 8class SkImage_Base : public SkImage { 9public: 10 SkImage_Base(int width, int height) : INHERITED(width, height) {} 11 12 virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) = 0; 13 14private: 15 typedef SkImage INHERITED; 16}; 17 18static SkImage_Base* asIB(SkImage* image) { 19 return static_cast<SkImage_Base*>(image); 20} 21 22/////////////////////////////////////////////////////////////////////////////// 23 24 25class SkImage_Raster : public SkImage_Base { 26public: 27 static bool ValidArgs(const Info& info, SkColorSpace* cs, size_t rowBytes) { 28 const int maxDimension = SK_MaxS32 >> 2; 29 const size_t kMaxPixelByteSize = SK_MaxS32; 30 31 if (info.fWidth < 0 || info.fHeight < 0) { 32 return false; 33 } 34 if (info.fWidth > maxDimension || info.fHeight > maxDimension) { 35 return false; 36 } 37 if ((unsigned)info.fColorType > (unsigned)kLastEnum_ColorType) { 38 return false; 39 } 40 if ((unsigned)info.fAlphaType > (unsigned)kLastEnum_AlphaType) { 41 return false; 42 } 43 44 bool isOpaque; 45 if (SkImageInfoToBitmapConfig(info, &isOpaque) == SkBitmap::kNo_Config) { 46 return false; 47 } 48 49 // TODO: check colorspace 50 51 if (rowBytes < SkImageMinRowBytes(info)) { 52 return false; 53 } 54 55 int64_t size = (int64_t)info.fHeight * rowBytes; 56 if (size > kMaxPixelByteSize) { 57 return false; 58 } 59 return true; 60 } 61 62 static SkImage* NewEmpty(); 63 64 SkImage_Raster(const SkImage::Info&, SkColorSpace*, SkData*, size_t rb); 65 virtual ~SkImage_Raster(); 66 67 virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE; 68 69 // exposed for SkSurface_Raster via SkNewImageFromPixelRef 70 SkImage_Raster(const SkImage::Info&, SkPixelRef*, size_t rowBytes); 71 72private: 73 SkImage_Raster() : INHERITED(0, 0) {} 74 75 SkBitmap fBitmap; 76 77 typedef SkImage_Base INHERITED; 78}; 79 80SkImage* SkNewImageFromPixelRef(const SkImage::Info& info, SkPixelRef* pr, 81 size_t rowBytes) { 82 return SkNEW_ARGS(SkImage_Raster, (info, pr, rowBytes)); 83} 84 85/////////////////////////////////////////////////////////////////////////////// 86 87#include "SkData.h" 88#include "SkDataPixelRef.h" 89 90SkImage* SkImage_Raster::NewEmpty() { 91 // Returns lazily created singleton 92 static SkImage* gEmpty; 93 if (NULL == gEmpty) { 94 gEmpty = SkNEW(SkImage_Raster); 95 } 96 gEmpty->ref(); 97 return gEmpty; 98} 99 100SkImage_Raster::SkImage_Raster(const Info& info, SkColorSpace* cs, 101 SkData* data, size_t rowBytes) 102: INHERITED(info.fWidth, info.fHeight) { 103 bool isOpaque; 104 SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque); 105 106 fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes); 107 fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (data)))->unref(); 108 fBitmap.setIsOpaque(isOpaque); 109 fBitmap.setImmutable(); 110} 111 112SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes) 113 : INHERITED(info.fWidth, info.fHeight) { 114 SkASSERT(pr->isImmutable()); 115 116 bool isOpaque; 117 SkBitmap::Config config = SkImageInfoToBitmapConfig(info, &isOpaque); 118 119 fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes); 120 fBitmap.setPixelRef(pr); 121 fBitmap.setIsOpaque(isOpaque); 122 fBitmap.setImmutable(); 123} 124 125SkImage_Raster::~SkImage_Raster() {} 126 127void SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) { 128 canvas->drawBitmap(fBitmap, x, y, paint); 129} 130 131/////////////////////////////////////////////////////////////////////////////// 132 133#include "SkPicture.h" 134 135class SkImage_Picture : public SkImage_Base { 136public: 137 SkImage_Picture(SkPicture*); 138 virtual ~SkImage_Picture(); 139 140 virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE; 141 142private: 143 SkPicture* fPicture; 144 145 typedef SkImage_Base INHERITED; 146}; 147 148SkImage_Picture::SkImage_Picture(SkPicture* pict) : INHERITED(pict->width(), pict->height()) { 149 pict->endRecording(); 150 pict->ref(); 151 fPicture = pict; 152} 153 154SkImage_Picture::~SkImage_Picture() { 155 fPicture->unref(); 156} 157 158void SkImage_Picture::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, 159 const SkPaint* paint) { 160 SkImagePrivDrawPicture(canvas, fPicture, x, y, paint); 161} 162 163SkImage* SkNewImageFromPicture(SkPicture* pict) { 164 return SkNEW_ARGS(SkImage_Picture, (pict)); 165} 166 167/////////////////////////////////////////////////////////////////////////////// 168 169SkImage* SkImage::NewRasterCopy(const SkImage::Info& info, SkColorSpace* cs, 170 const void* pixels, size_t rowBytes) { 171 if (!SkImage_Raster::ValidArgs(info, cs, rowBytes)) { 172 return NULL; 173 } 174 if (0 == info.fWidth && 0 == info.fHeight) { 175 return SkImage_Raster::NewEmpty(); 176 } 177 // check this after empty-check 178 if (NULL == pixels) { 179 return NULL; 180 } 181 182 // Here we actually make a copy of the caller's pixel data 183 SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.fHeight * rowBytes)); 184 return SkNEW_ARGS(SkImage_Raster, (info, cs, data, rowBytes)); 185} 186 187 188SkImage* SkImage::NewRasterData(const SkImage::Info& info, SkColorSpace* cs, 189 SkData* pixelData, size_t rowBytes) { 190 if (!SkImage_Raster::ValidArgs(info, cs, rowBytes)) { 191 return NULL; 192 } 193 if (0 == info.fWidth && 0 == info.fHeight) { 194 return SkImage_Raster::NewEmpty(); 195 } 196 // check this after empty-check 197 if (NULL == pixelData) { 198 return NULL; 199 } 200 201 // did they give us enough data? 202 size_t size = info.fHeight * rowBytes; 203 if (pixelData->size() < size) { 204 return NULL; 205 } 206 207 SkAutoDataUnref data(pixelData); 208 return SkNEW_ARGS(SkImage_Raster, (info, cs, data, rowBytes)); 209} 210 211/////////////////////////////////////////////////////////////////////////////// 212 213#include "SkCanvas.h" 214 215uint32_t SkImage::NextUniqueID() { 216 static int32_t gUniqueID; 217 218 // never return 0; 219 uint32_t id; 220 do { 221 id = sk_atomic_inc(&gUniqueID) + 1; 222 } while (0 == id); 223 return id; 224} 225 226void SkImage::draw(SkCanvas* canvas, SkScalar x, SkScalar y, 227 const SkPaint* paint) { 228 asIB(this)->onDraw(canvas, x, y, paint); 229} 230 231