SkSurface_Raster.cpp revision e5ea500d4714a7d84de2bf913e81be3b65d2de68
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 "SkSurface_Base.h" 9#include "SkImagePriv.h" 10#include "SkCanvas.h" 11#include "SkDevice.h" 12#include "SkMallocPixelRef.h" 13 14static const size_t kIgnoreRowBytesValue = (size_t)~0; 15 16class SkSurface_Raster : public SkSurface_Base { 17public: 18 static bool Valid(const SkImageInfo&, size_t rb = kIgnoreRowBytesValue); 19 20 SkSurface_Raster(const SkImageInfo&, void*, size_t rb, 21 void (*releaseProc)(void* pixels, void* context), void* context); 22 SkSurface_Raster(SkPixelRef*); 23 24 virtual SkCanvas* onNewCanvas() SK_OVERRIDE; 25 virtual SkSurface* onNewSurface(const SkImageInfo&) SK_OVERRIDE; 26 virtual SkImage* onNewImageSnapshot() SK_OVERRIDE; 27 virtual void onDraw(SkCanvas*, SkScalar x, SkScalar y, 28 const SkPaint*) SK_OVERRIDE; 29 virtual void onCopyOnWrite(ContentChangeMode) SK_OVERRIDE; 30 31private: 32 SkBitmap fBitmap; 33 bool fWeOwnThePixels; 34 35 typedef SkSurface_Base INHERITED; 36}; 37 38/////////////////////////////////////////////////////////////////////////////// 39 40bool SkSurface_Raster::Valid(const SkImageInfo& info, size_t rowBytes) { 41 static const size_t kMaxTotalSize = SK_MaxS32; 42 43 int shift = 0; 44 switch (info.colorType()) { 45 case kAlpha_8_SkColorType: 46 shift = 0; 47 break; 48 case kRGB_565_SkColorType: 49 shift = 1; 50 break; 51 case kN32_SkColorType: 52 shift = 2; 53 break; 54 default: 55 return false; 56 } 57 58 if (kIgnoreRowBytesValue == rowBytes) { 59 return true; 60 } 61 62 uint64_t minRB = (uint64_t)info.width() << shift; 63 if (minRB > rowBytes) { 64 return false; 65 } 66 67 size_t alignedRowBytes = rowBytes >> shift << shift; 68 if (alignedRowBytes != rowBytes) { 69 return false; 70 } 71 72 uint64_t size = sk_64_mul(info.height(), rowBytes); 73 if (size > kMaxTotalSize) { 74 return false; 75 } 76 77 return true; 78} 79 80SkSurface_Raster::SkSurface_Raster(const SkImageInfo& info, void* pixels, size_t rb, 81 void (*releaseProc)(void* pixels, void* context), void* context) 82 : INHERITED(info) 83{ 84 fBitmap.installPixels(info, pixels, rb, NULL, releaseProc, context); 85 fWeOwnThePixels = false; // We are "Direct" 86} 87 88SkSurface_Raster::SkSurface_Raster(SkPixelRef* pr) 89 : INHERITED(pr->info().width(), pr->info().height()) 90{ 91 const SkImageInfo& info = pr->info(); 92 93 fBitmap.setInfo(info, info.minRowBytes()); 94 fBitmap.setPixelRef(pr); 95 fWeOwnThePixels = true; 96 97 if (!info.isOpaque()) { 98 fBitmap.eraseColor(SK_ColorTRANSPARENT); 99 } 100} 101 102SkCanvas* SkSurface_Raster::onNewCanvas() { 103 return SkNEW_ARGS(SkCanvas, (fBitmap)); 104} 105 106SkSurface* SkSurface_Raster::onNewSurface(const SkImageInfo& info) { 107 return SkSurface::NewRaster(info); 108} 109 110void SkSurface_Raster::onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, 111 const SkPaint* paint) { 112 canvas->drawBitmap(fBitmap, x, y, paint); 113} 114 115SkImage* SkSurface_Raster::onNewImageSnapshot() { 116 return SkNewImageFromBitmap(fBitmap, fWeOwnThePixels); 117} 118 119void SkSurface_Raster::onCopyOnWrite(ContentChangeMode mode) { 120 // are we sharing pixelrefs with the image? 121 SkASSERT(NULL != this->getCachedImage()); 122 if (SkBitmapImageGetPixelRef(this->getCachedImage()) == fBitmap.pixelRef()) { 123 SkASSERT(fWeOwnThePixels); 124 if (kDiscard_ContentChangeMode == mode) { 125 fBitmap.setPixelRef(NULL); 126 fBitmap.allocPixels(); 127 } else { 128 SkBitmap prev(fBitmap); 129 prev.deepCopyTo(&fBitmap); 130 } 131 // Now fBitmap is a deep copy of itself (and therefore different from 132 // what is being used by the image. Next we update the canvas to use 133 // this as its backend, so we can't modify the image's pixels anymore. 134 SkASSERT(NULL != this->getCachedCanvas()); 135 this->getCachedCanvas()->getDevice()->replaceBitmapBackendForRasterSurface(fBitmap); 136 } 137} 138 139/////////////////////////////////////////////////////////////////////////////// 140 141SkSurface* SkSurface::NewRasterDirectReleaseProc(const SkImageInfo& info, void* pixels, size_t rb, 142 void (*releaseProc)(void* pixels, void* context), 143 void* context) { 144 if (NULL == releaseProc) { 145 context = NULL; 146 } 147 if (!SkSurface_Raster::Valid(info, rb)) { 148 return NULL; 149 } 150 if (NULL == pixels) { 151 return NULL; 152 } 153 154 return SkNEW_ARGS(SkSurface_Raster, (info, pixels, rb, releaseProc, context)); 155} 156 157SkSurface* SkSurface::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) { 158 return NewRasterDirectReleaseProc(info, pixels, rowBytes, NULL, NULL); 159} 160 161SkSurface* SkSurface::NewRaster(const SkImageInfo& info) { 162 if (!SkSurface_Raster::Valid(info)) { 163 return NULL; 164 } 165 166 SkAutoTUnref<SkPixelRef> pr(SkMallocPixelRef::NewAllocate(info, 0, NULL)); 167 if (NULL == pr.get()) { 168 return NULL; 169 } 170 return SkNEW_ARGS(SkSurface_Raster, (pr)); 171} 172