SkBitmapProcShader.cpp revision 0910916c0f7b951ee55c4b7c6358295b9bca0565
1#include "SkBitmapProcShader.h" 2#include "SkColorPriv.h" 3#include "SkPixelRef.h" 4 5bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) { 6 switch (bm.config()) { 7 case SkBitmap::kA8_Config: 8 case SkBitmap::kRGB_565_Config: 9 case SkBitmap::kIndex8_Config: 10 case SkBitmap::kARGB_8888_Config: 11 // if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx)) 12 return true; 13 default: 14 break; 15 } 16 return false; 17} 18 19SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, 20 TileMode tmx, TileMode tmy) { 21 fRawBitmap = src; 22 fState.fTileModeX = (uint8_t)tmx; 23 fState.fTileModeY = (uint8_t)tmy; 24} 25 26SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer) 27 : INHERITED(buffer) { 28 fRawBitmap.unflatten(buffer); 29 fState.fTileModeX = buffer.readU8(); 30 fState.fTileModeY = buffer.readU8(); 31} 32 33void SkBitmapProcShader::beginSession() { 34 this->INHERITED::beginSession(); 35 36 fRawBitmap.lockPixels(); 37} 38 39void SkBitmapProcShader::endSession() { 40 fRawBitmap.unlockPixels(); 41 42 this->INHERITED::endSession(); 43} 44 45bool SkBitmapProcShader::asABitmap(SkBitmap* texture, SkMatrix* texM, 46 TileMode xy[]) { 47 if (texture) { 48 *texture = fRawBitmap; 49 } 50 if (texM) { 51 texM->reset(); 52 } 53 if (xy) { 54 xy[0] = (TileMode)fState.fTileModeX; 55 xy[1] = (TileMode)fState.fTileModeY; 56 } 57 return true; 58} 59 60void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) { 61 this->INHERITED::flatten(buffer); 62 63 fRawBitmap.flatten(buffer); 64 buffer.write8(fState.fTileModeX); 65 buffer.write8(fState.fTileModeY); 66} 67 68bool SkBitmapProcShader::setContext(const SkBitmap& device, 69 const SkPaint& paint, 70 const SkMatrix& matrix) { 71 // do this first, so we have a correct inverse matrix 72 if (!this->INHERITED::setContext(device, paint, matrix)) { 73 return false; 74 } 75 76 fState.fOrigBitmap = fRawBitmap; 77 fState.fOrigBitmap.lockPixels(); 78 if (fState.fOrigBitmap.getPixels() == NULL) { 79 fState.fOrigBitmap.unlockPixels(); 80 return false; 81 } 82 83 if (!fState.chooseProcs(this->getTotalInverse(), paint)) { 84 return false; 85 } 86 87 bool bitmapIsOpaque = fState.fBitmap->isOpaque(); 88 89 // filtering doesn't guarantee that opaque stays opaque (finite precision) 90 // so pretend we're not opaque if we're being asked to filter. If we had 91 // more blit-procs, we could specialize on opaque src, and just OR in 0xFF 92 // after the filter to be sure... 93 if (paint.isFilterBitmap()) { 94 bitmapIsOpaque = false; 95 } 96 97 // update fFlags 98 fFlags = 0; // this should happen in SkShader.cpp 99 100 if (bitmapIsOpaque && (255 == this->getPaintAlpha())) { 101 fFlags |= kOpaqueAlpha_Flag; 102 } 103 104 switch (fState.fBitmap->config()) { 105 case SkBitmap::kRGB_565_Config: 106 fFlags |= (kHasSpan16_Flag | kIntrinsicly16_Flag); 107 break; 108 case SkBitmap::kIndex8_Config: 109 case SkBitmap::kARGB_8888_Config: 110 if (bitmapIsOpaque) { 111 fFlags |= kHasSpan16_Flag; 112 } 113 break; 114 case SkBitmap::kA8_Config: 115 break; // never set kHasSpan16_Flag 116 default: 117 break; 118 } 119 return true; 120} 121 122#define BUF_MAX 128 123 124void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 125 uint32_t buffer[BUF_MAX]; 126 127 const SkBitmapProcState& state = fState; 128 SkBitmapProcState::MatrixProc mproc = state.fMatrixProc; 129 SkBitmapProcState::SampleProc32 sproc = state.fSampleProc32; 130 int max = fState.fDoFilter ? (BUF_MAX >> 1) : BUF_MAX; 131 132 SkASSERT(state.fBitmap->getPixels()); 133 SkASSERT(state.fBitmap->pixelRef() == NULL || 134 state.fBitmap->pixelRef()->getLockCount()); 135 136 for (;;) { 137 int n = count; 138 if (n > max) { 139 n = max; 140 } 141 mproc(state, buffer, n, x, y); 142 sproc(state, buffer, n, dstC); 143 144 if ((count -= n) == 0) { 145 break; 146 } 147 x += n; 148 dstC += n; 149 } 150} 151 152void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) { 153 uint32_t buffer[BUF_MAX]; 154 155 const SkBitmapProcState& state = fState; 156 SkBitmapProcState::MatrixProc mproc = state.fMatrixProc; 157 SkBitmapProcState::SampleProc16 sproc = state.fSampleProc16; 158 int max = fState.fDoFilter ? (BUF_MAX >> 1) : BUF_MAX; 159 160 SkASSERT(state.fBitmap->getPixels()); 161 SkASSERT(state.fBitmap->pixelRef() == NULL || 162 state.fBitmap->pixelRef()->getLockCount()); 163 164 for (;;) { 165 int n = count; 166 if (n > max) { 167 n = max; 168 } 169 mproc(state, buffer, n, x, y); 170 sproc(state, buffer, n, dstC); 171 172 if ((count -= n) == 0) { 173 break; 174 } 175 x += n; 176 dstC += n; 177 } 178} 179 180/////////////////////////////////////////////////////////////////////////////// 181 182#include "SkTemplatesPriv.h" 183 184SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, 185 TileMode tmx, TileMode tmy, 186 void* storage, size_t storageSize) { 187 SkShader* shader; 188 SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage, 189 storageSize, (src, tmx, tmy)); 190 return shader; 191} 192 193static SkFlattenable::Registrar gBitmapProcShaderReg("SkBitmapProcShader", 194 SkBitmapProcShader::CreateProc); 195 196/////////////////////////////////////////////////////////////////////////////// 197 198static const char* gTileModeName[] = { 199 "clamp", "repeat", "mirror" 200}; 201 202bool SkBitmapProcShader::toDumpString(SkString* str) const { 203 str->printf("BitmapShader: [%d %d %d", 204 fRawBitmap.width(), fRawBitmap.height(), 205 fRawBitmap.bytesPerPixel()); 206 207 // add the pixelref 208 SkPixelRef* pr = fRawBitmap.pixelRef(); 209 if (pr) { 210 const char* uri = pr->getURI(); 211 if (uri) { 212 str->appendf(" \"%s\"", uri); 213 } 214 } 215 216 // add the (optional) matrix 217 { 218 SkMatrix m; 219 if (this->getLocalMatrix(&m)) { 220 SkString info; 221 m.toDumpString(&info); 222 str->appendf(" %s", info.c_str()); 223 } 224 } 225 226 str->appendf(" [%s %s]]", 227 gTileModeName[fState.fTileModeX], 228 gTileModeName[fState.fTileModeY]); 229 return true; 230} 231 232