Home | History | Annotate | Download | only in core
      1 #include "SkBitmapProcShader.h"
      2 #include "SkColorPriv.h"
      3 #include "SkPixelRef.h"
      4 
      5 bool 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 
     19 SkBitmapProcShader::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     fFlags = 0; // computed in setContext
     25 }
     26 
     27 SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
     28         : INHERITED(buffer) {
     29     fRawBitmap.unflatten(buffer);
     30     fState.fTileModeX = buffer.readU8();
     31     fState.fTileModeY = buffer.readU8();
     32     fFlags = 0; // computed in setContext
     33 }
     34 
     35 void SkBitmapProcShader::beginSession() {
     36     this->INHERITED::beginSession();
     37 
     38     fRawBitmap.lockPixels();
     39 }
     40 
     41 void SkBitmapProcShader::endSession() {
     42     fRawBitmap.unlockPixels();
     43 
     44     this->INHERITED::endSession();
     45 }
     46 
     47 SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
     48                                                    SkMatrix* texM,
     49                                                    TileMode xy[],
     50                                        SkScalar* twoPointRadialParams) const {
     51     if (texture) {
     52         *texture = fRawBitmap;
     53     }
     54     if (texM) {
     55         texM->reset();
     56     }
     57     if (xy) {
     58         xy[0] = (TileMode)fState.fTileModeX;
     59         xy[1] = (TileMode)fState.fTileModeY;
     60     }
     61     return kDefault_BitmapType;
     62 }
     63 
     64 void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) {
     65     this->INHERITED::flatten(buffer);
     66 
     67     fRawBitmap.flatten(buffer);
     68     buffer.write8(fState.fTileModeX);
     69     buffer.write8(fState.fTileModeY);
     70 }
     71 
     72 static bool only_scale_and_translate(const SkMatrix& matrix) {
     73     unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask;
     74     return (matrix.getType() & ~mask) == 0;
     75 }
     76 
     77 bool SkBitmapProcShader::setContext(const SkBitmap& device,
     78                                     const SkPaint& paint,
     79                                     const SkMatrix& matrix) {
     80     // do this first, so we have a correct inverse matrix
     81     if (!this->INHERITED::setContext(device, paint, matrix)) {
     82         return false;
     83     }
     84 
     85     fState.fOrigBitmap = fRawBitmap;
     86     fState.fOrigBitmap.lockPixels();
     87     if (!fState.fOrigBitmap.getTexture() && !fState.fOrigBitmap.readyToDraw()) {
     88         fState.fOrigBitmap.unlockPixels();
     89         return false;
     90     }
     91 
     92     if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
     93         return false;
     94     }
     95 
     96     const SkBitmap& bitmap = *fState.fBitmap;
     97     bool bitmapIsOpaque = bitmap.isOpaque();
     98 
     99     // update fFlags
    100     uint32_t flags = 0;
    101     if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
    102         flags |= kOpaqueAlpha_Flag;
    103     }
    104 
    105     switch (bitmap.config()) {
    106         case SkBitmap::kRGB_565_Config:
    107             flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
    108             break;
    109         case SkBitmap::kIndex8_Config:
    110         case SkBitmap::kARGB_8888_Config:
    111             if (bitmapIsOpaque) {
    112                 flags |= kHasSpan16_Flag;
    113             }
    114             break;
    115         case SkBitmap::kA8_Config:
    116             break;  // never set kHasSpan16_Flag
    117         default:
    118             break;
    119     }
    120 
    121     if (paint.isDither() && bitmap.config() != SkBitmap::kRGB_565_Config) {
    122         // gradients can auto-dither in their 16bit sampler, but we don't so
    123         // we clear the flag here.
    124         flags &= ~kHasSpan16_Flag;
    125     }
    126 
    127     // if we're only 1-pixel heigh, and we don't rotate, then we can claim this
    128     if (1 == bitmap.height() &&
    129             only_scale_and_translate(this->getTotalInverse())) {
    130         flags |= kConstInY32_Flag;
    131         if (flags & kHasSpan16_Flag) {
    132             flags |= kConstInY16_Flag;
    133         }
    134     }
    135 
    136     fFlags = flags;
    137     return true;
    138 }
    139 
    140 #define BUF_MAX     128
    141 
    142 #define TEST_BUFFER_OVERRITEx
    143 
    144 #ifdef TEST_BUFFER_OVERRITE
    145     #define TEST_BUFFER_EXTRA   32
    146     #define TEST_PATTERN    0x88888888
    147 #else
    148     #define TEST_BUFFER_EXTRA   0
    149 #endif
    150 
    151 void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
    152     const SkBitmapProcState& state = fState;
    153     if (state.fShaderProc32) {
    154         state.fShaderProc32(state, x, y, dstC, count);
    155         return;
    156     }
    157 
    158     uint32_t buffer[BUF_MAX + TEST_BUFFER_EXTRA];
    159     SkBitmapProcState::MatrixProc   mproc = state.fMatrixProc;
    160     SkBitmapProcState::SampleProc32 sproc = state.fSampleProc32;
    161     int max = fState.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX);
    162 
    163     SkASSERT(state.fBitmap->getPixels());
    164     SkASSERT(state.fBitmap->pixelRef() == NULL ||
    165              state.fBitmap->pixelRef()->getLockCount());
    166 
    167     for (;;) {
    168         int n = count;
    169         if (n > max) {
    170             n = max;
    171         }
    172         SkASSERT(n > 0 && n < BUF_MAX*2);
    173 #ifdef TEST_BUFFER_OVERRITE
    174         for (int i = 0; i < TEST_BUFFER_EXTRA; i++) {
    175             buffer[BUF_MAX + i] = TEST_PATTERN;
    176         }
    177 #endif
    178         mproc(state, buffer, n, x, y);
    179 #ifdef TEST_BUFFER_OVERRITE
    180         for (int j = 0; j < TEST_BUFFER_EXTRA; j++) {
    181             SkASSERT(buffer[BUF_MAX + j] == TEST_PATTERN);
    182         }
    183 #endif
    184         sproc(state, buffer, n, dstC);
    185 
    186         if ((count -= n) == 0) {
    187             break;
    188         }
    189         SkASSERT(count > 0);
    190         x += n;
    191         dstC += n;
    192     }
    193 }
    194 
    195 void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
    196     const SkBitmapProcState& state = fState;
    197     if (state.fShaderProc16) {
    198         state.fShaderProc16(state, x, y, dstC, count);
    199         return;
    200     }
    201 
    202     uint32_t buffer[BUF_MAX];
    203     SkBitmapProcState::MatrixProc   mproc = state.fMatrixProc;
    204     SkBitmapProcState::SampleProc16 sproc = state.fSampleProc16;
    205     int max = fState.maxCountForBufferSize(sizeof(buffer));
    206 
    207     SkASSERT(state.fBitmap->getPixels());
    208     SkASSERT(state.fBitmap->pixelRef() == NULL ||
    209              state.fBitmap->pixelRef()->getLockCount());
    210 
    211     for (;;) {
    212         int n = count;
    213         if (n > max) {
    214             n = max;
    215         }
    216         mproc(state, buffer, n, x, y);
    217         sproc(state, buffer, n, dstC);
    218 
    219         if ((count -= n) == 0) {
    220             break;
    221         }
    222         x += n;
    223         dstC += n;
    224     }
    225 }
    226 
    227 ///////////////////////////////////////////////////////////////////////////////
    228 
    229 #include "SkUnPreMultiply.h"
    230 #include "SkColorShader.h"
    231 
    232 // returns true and set color if the bitmap can be drawn as a single color
    233 // (for efficiency)
    234 static bool canUseColorShader(const SkBitmap& bm, SkColor* color) {
    235     if (1 != bm.width() || 1 != bm.height()) {
    236         return false;
    237     }
    238 
    239     SkAutoLockPixels alp(bm);
    240     if (!bm.readyToDraw()) {
    241         return false;
    242     }
    243 
    244     switch (bm.config()) {
    245         case SkBitmap::kARGB_8888_Config:
    246             *color = SkUnPreMultiply::PMColorToColor(*bm.getAddr32(0, 0));
    247             return true;
    248         case SkBitmap::kRGB_565_Config:
    249             *color = SkPixel16ToColor(*bm.getAddr16(0, 0));
    250             return true;
    251         case SkBitmap::kIndex8_Config:
    252             *color = SkUnPreMultiply::PMColorToColor(bm.getIndex8Color(0, 0));
    253             return true;
    254         default: // just skip the other configs for now
    255             break;
    256     }
    257     return false;
    258 }
    259 
    260 #include "SkTemplatesPriv.h"
    261 
    262 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
    263                                        TileMode tmx, TileMode tmy,
    264                                        void* storage, size_t storageSize) {
    265     SkShader* shader;
    266     SkColor color;
    267     if (canUseColorShader(src, &color)) {
    268         SK_PLACEMENT_NEW_ARGS(shader, SkColorShader, storage, storageSize,
    269                               (color));
    270     } else {
    271         SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
    272                               storageSize, (src, tmx, tmy));
    273     }
    274     return shader;
    275 }
    276 
    277 static SkFlattenable::Registrar gBitmapProcShaderReg("SkBitmapProcShader",
    278                                                SkBitmapProcShader::CreateProc);
    279 
    280 ///////////////////////////////////////////////////////////////////////////////
    281 
    282 static const char* gTileModeName[] = {
    283     "clamp", "repeat", "mirror"
    284 };
    285 
    286 bool SkBitmapProcShader::toDumpString(SkString* str) const {
    287     str->printf("BitmapShader: [%d %d %d",
    288                 fRawBitmap.width(), fRawBitmap.height(),
    289                 fRawBitmap.bytesPerPixel());
    290 
    291     // add the pixelref
    292     SkPixelRef* pr = fRawBitmap.pixelRef();
    293     if (pr) {
    294         const char* uri = pr->getURI();
    295         if (uri) {
    296             str->appendf(" \"%s\"", uri);
    297         }
    298     }
    299 
    300     // add the (optional) matrix
    301     {
    302         SkMatrix m;
    303         if (this->getLocalMatrix(&m)) {
    304             SkString info;
    305             m.toDumpString(&info);
    306             str->appendf(" %s", info.c_str());
    307         }
    308     }
    309 
    310     str->appendf(" [%s %s]]",
    311                  gTileModeName[fState.fTileModeX],
    312                  gTileModeName[fState.fTileModeY]);
    313     return true;
    314 }
    315 
    316