1 /* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkImage_Base.h" 9 #include "SkImagePriv.h" 10 #include "SkBitmap.h" 11 #include "SkCanvas.h" 12 #include "SkData.h" 13 #include "SkDataPixelRef.h" 14 15 class SkImage_Raster : public SkImage_Base { 16 public: 17 static bool ValidArgs(const Info& info, size_t rowBytes) { 18 const int maxDimension = SK_MaxS32 >> 2; 19 const size_t kMaxPixelByteSize = SK_MaxS32; 20 21 if (info.fWidth < 0 || info.fHeight < 0) { 22 return false; 23 } 24 if (info.fWidth > maxDimension || info.fHeight > maxDimension) { 25 return false; 26 } 27 if ((unsigned)info.fColorType > (unsigned)kLastEnum_SkColorType) { 28 return false; 29 } 30 if ((unsigned)info.fAlphaType > (unsigned)kLastEnum_SkAlphaType) { 31 return false; 32 } 33 34 if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) { 35 return false; 36 } 37 38 // TODO: check colorspace 39 40 if (rowBytes < SkImageMinRowBytes(info)) { 41 return false; 42 } 43 44 int64_t size = (int64_t)info.fHeight * rowBytes; 45 if (size > (int64_t)kMaxPixelByteSize) { 46 return false; 47 } 48 return true; 49 } 50 51 static SkImage* NewEmpty(); 52 53 SkImage_Raster(const SkImageInfo&, SkData*, size_t rb); 54 virtual ~SkImage_Raster(); 55 56 virtual void onDraw(SkCanvas*, SkScalar, SkScalar, const SkPaint*) SK_OVERRIDE; 57 virtual void onDrawRectToRect(SkCanvas*, const SkRect*, const SkRect&, const SkPaint*) SK_OVERRIDE; 58 virtual bool getROPixels(SkBitmap*) const SK_OVERRIDE; 59 60 // exposed for SkSurface_Raster via SkNewImageFromPixelRef 61 SkImage_Raster(const SkImageInfo&, SkPixelRef*, size_t rowBytes); 62 63 SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); } 64 65 private: 66 SkImage_Raster() : INHERITED(0, 0) {} 67 68 SkBitmap fBitmap; 69 70 typedef SkImage_Base INHERITED; 71 }; 72 73 /////////////////////////////////////////////////////////////////////////////// 74 75 SkImage* SkImage_Raster::NewEmpty() { 76 // Returns lazily created singleton 77 static SkImage* gEmpty; 78 if (NULL == gEmpty) { 79 gEmpty = SkNEW(SkImage_Raster); 80 } 81 gEmpty->ref(); 82 return gEmpty; 83 } 84 85 SkImage_Raster::SkImage_Raster(const Info& info, SkData* data, size_t rowBytes) 86 : INHERITED(info.fWidth, info.fHeight) { 87 fBitmap.setConfig(info, rowBytes); 88 fBitmap.setPixelRef(SkNEW_ARGS(SkDataPixelRef, (info, data)))->unref(); 89 fBitmap.setImmutable(); 90 } 91 92 SkImage_Raster::SkImage_Raster(const Info& info, SkPixelRef* pr, size_t rowBytes) 93 : INHERITED(info.fWidth, info.fHeight) { 94 SkBitmap::Config config = SkImageInfoToBitmapConfig(info); 95 96 fBitmap.setConfig(config, info.fWidth, info.fHeight, rowBytes, info.fAlphaType); 97 fBitmap.setPixelRef(pr); 98 } 99 100 SkImage_Raster::~SkImage_Raster() {} 101 102 void SkImage_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) { 103 canvas->drawBitmap(fBitmap, x, y, paint); 104 } 105 106 void SkImage_Raster::onDrawRectToRect(SkCanvas* canvas, const SkRect* src, const SkRect& dst, const SkPaint* paint) { 107 canvas->drawBitmapRectToRect(fBitmap, src, dst, paint); 108 } 109 110 bool SkImage_Raster::getROPixels(SkBitmap* dst) const { 111 *dst = fBitmap; 112 return true; 113 } 114 115 /////////////////////////////////////////////////////////////////////////////// 116 117 SkImage* SkImage::NewRasterCopy(const SkImageInfo& info, const void* pixels, size_t rowBytes) { 118 if (!SkImage_Raster::ValidArgs(info, rowBytes)) { 119 return NULL; 120 } 121 if (0 == info.fWidth && 0 == info.fHeight) { 122 return SkImage_Raster::NewEmpty(); 123 } 124 // check this after empty-check 125 if (NULL == pixels) { 126 return NULL; 127 } 128 129 // Here we actually make a copy of the caller's pixel data 130 SkAutoDataUnref data(SkData::NewWithCopy(pixels, info.fHeight * rowBytes)); 131 return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes)); 132 } 133 134 135 SkImage* SkImage::NewRasterData(const SkImageInfo& info, SkData* pixelData, size_t rowBytes) { 136 if (!SkImage_Raster::ValidArgs(info, rowBytes)) { 137 return NULL; 138 } 139 if (0 == info.fWidth && 0 == info.fHeight) { 140 return SkImage_Raster::NewEmpty(); 141 } 142 // check this after empty-check 143 if (NULL == pixelData) { 144 return NULL; 145 } 146 147 // did they give us enough data? 148 size_t size = info.fHeight * rowBytes; 149 if (pixelData->size() < size) { 150 return NULL; 151 } 152 153 SkAutoDataUnref data(pixelData); 154 return SkNEW_ARGS(SkImage_Raster, (info, data, rowBytes)); 155 } 156 157 SkImage* SkNewImageFromPixelRef(const SkImageInfo& info, SkPixelRef* pr, 158 size_t rowBytes) { 159 return SkNEW_ARGS(SkImage_Raster, (info, pr, rowBytes)); 160 } 161 162 SkPixelRef* SkBitmapImageGetPixelRef(SkImage* image) { 163 return ((SkImage_Raster*)image)->getPixelRef(); 164 } 165