grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
new file mode 100644
index 0000000..6d7d581
--- /dev/null
+++ b/src/core/SkBitmapProcShader.cpp
@@ -0,0 +1,231 @@
+#include "SkBitmapProcShader.h"
+#include "SkColorPriv.h"
+#include "SkPixelRef.h"
+
+bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
+    switch (bm.config()) {
+        case SkBitmap::kA8_Config:
+        case SkBitmap::kRGB_565_Config:
+        case SkBitmap::kIndex8_Config:
+        case SkBitmap::kARGB_8888_Config:
+    //        if (tx == ty && (kClamp_TileMode == tx || kRepeat_TileMode == tx))
+                return true;
+        default:
+            break;
+    }
+    return false;
+}
+
+SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
+                                       TileMode tmx, TileMode tmy) {
+    fRawBitmap = src;
+    fState.fTileModeX = (uint8_t)tmx;
+    fState.fTileModeY = (uint8_t)tmy;
+}
+
+SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
+        : INHERITED(buffer) {
+    fRawBitmap.unflatten(buffer);
+    fState.fTileModeX = buffer.readU8();
+    fState.fTileModeY = buffer.readU8();
+}
+
+void SkBitmapProcShader::beginSession() {
+    this->INHERITED::beginSession();
+
+    fRawBitmap.lockPixels();
+}
+
+void SkBitmapProcShader::endSession() {
+    fRawBitmap.unlockPixels();
+
+    this->INHERITED::endSession();
+}
+
+bool SkBitmapProcShader::asABitmap(SkBitmap* texture, SkMatrix* texM,
+                                   TileMode xy[]) {
+    if (texture) {
+        *texture = fRawBitmap;
+    }
+    if (texM) {
+        texM->reset();
+    }
+    if (xy) {
+        xy[0] = (TileMode)fState.fTileModeX;
+        xy[1] = (TileMode)fState.fTileModeY;
+    }
+    return true;
+}
+
+void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) {
+    this->INHERITED::flatten(buffer);
+
+    fRawBitmap.flatten(buffer);
+    buffer.write8(fState.fTileModeX);
+    buffer.write8(fState.fTileModeY);
+}
+
+bool SkBitmapProcShader::setContext(const SkBitmap& device,
+                                    const SkPaint& paint,
+                                    const SkMatrix& matrix) {
+    // do this first, so we have a correct inverse matrix
+    if (!this->INHERITED::setContext(device, paint, matrix)) {
+        return false;
+    }
+
+    fState.fOrigBitmap = fRawBitmap;
+    fState.fOrigBitmap.lockPixels();
+    if (fState.fOrigBitmap.getPixels() == NULL) {
+        fState.fOrigBitmap.unlockPixels();
+        return false;
+    }
+
+    if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
+        return false;
+    }
+
+    bool bitmapIsOpaque = fState.fBitmap->isOpaque();
+    
+    // filtering doesn't guarantee that opaque stays opaque (finite precision)
+    // so pretend we're not opaque if we're being asked to filter. If we had
+    // more blit-procs, we could specialize on opaque src, and just OR in 0xFF
+    // after the filter to be sure...
+    if (paint.isFilterBitmap()) {
+        bitmapIsOpaque = false;
+    }
+
+    // update fFlags
+    fFlags = 0; // this should happen in SkShader.cpp
+
+    if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
+        fFlags |= kOpaqueAlpha_Flag;
+    }
+
+    switch (fState.fBitmap->config()) {
+        case SkBitmap::kRGB_565_Config:
+            fFlags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
+            break;
+        case SkBitmap::kIndex8_Config:
+        case SkBitmap::kARGB_8888_Config:
+            if (bitmapIsOpaque) {
+                fFlags |= kHasSpan16_Flag;
+            }
+            break;
+        case SkBitmap::kA8_Config:
+            break;  // never set kHasSpan16_Flag
+        default:
+            break;
+    }
+    return true;
+}
+
+#define BUF_MAX     128
+
+void SkBitmapProcShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
+    uint32_t buffer[BUF_MAX];
+
+    const SkBitmapProcState&        state = fState;
+    SkBitmapProcState::MatrixProc   mproc = state.fMatrixProc;
+    SkBitmapProcState::SampleProc32 sproc = state.fSampleProc32;
+    int max = fState.fDoFilter ? (BUF_MAX >> 1) : BUF_MAX;
+
+    SkASSERT(state.fBitmap->getPixels());
+    SkASSERT(state.fBitmap->pixelRef() == NULL ||
+             state.fBitmap->pixelRef()->getLockCount());
+
+    for (;;) {
+        int n = count;
+        if (n > max) {
+            n = max;
+        }
+        mproc(state, buffer, n, x, y);
+        sproc(state, buffer, n, dstC);
+        
+        if ((count -= n) == 0) {
+            break;
+        }
+        x += n;
+        dstC += n;
+    }
+}
+
+void SkBitmapProcShader::shadeSpan16(int x, int y, uint16_t dstC[], int count) {
+    uint32_t buffer[BUF_MAX];
+    
+    const SkBitmapProcState&        state = fState;
+    SkBitmapProcState::MatrixProc   mproc = state.fMatrixProc;
+    SkBitmapProcState::SampleProc16 sproc = state.fSampleProc16;
+    int max = fState.fDoFilter ? (BUF_MAX >> 1) : BUF_MAX;
+
+    SkASSERT(state.fBitmap->getPixels());
+    SkASSERT(state.fBitmap->pixelRef() == NULL ||
+             state.fBitmap->pixelRef()->getLockCount());
+
+    for (;;) {
+        int n = count;
+        if (n > max) {
+            n = max;
+        }
+        mproc(state, buffer, n, x, y);
+        sproc(state, buffer, n, dstC);
+        
+        if ((count -= n) == 0) {
+            break;
+        }
+        x += n;
+        dstC += n;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkTemplatesPriv.h"
+
+SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
+                                       TileMode tmx, TileMode tmy,
+                                       void* storage, size_t storageSize) {
+    SkShader* shader;
+    SK_PLACEMENT_NEW_ARGS(shader, SkBitmapProcShader, storage,
+                          storageSize, (src, tmx, tmy));
+    return shader;
+}
+
+static SkFlattenable::Registrar gBitmapProcShaderReg("SkBitmapProcShader",
+                                               SkBitmapProcShader::CreateProc);
+
+///////////////////////////////////////////////////////////////////////////////
+
+static const char* gTileModeName[] = {
+    "clamp", "repeat", "mirror"
+};
+
+bool SkBitmapProcShader::toDumpString(SkString* str) const {
+    str->printf("BitmapShader: [%d %d %d",
+                fRawBitmap.width(), fRawBitmap.height(),
+                fRawBitmap.bytesPerPixel());
+    
+    // add the pixelref
+    SkPixelRef* pr = fRawBitmap.pixelRef();
+    if (pr) {
+        const char* uri = pr->getURI();
+        if (uri) {
+            str->appendf(" \"%s\"", uri);
+        }
+    }
+    
+    // add the (optional) matrix
+    {
+        SkMatrix m;
+        if (this->getLocalMatrix(&m)) {
+            SkString info;
+            m.toDumpString(&info);
+            str->appendf(" %s", info.c_str());
+        }
+    }
+    
+    str->appendf(" [%s %s]]",
+                 gTileModeName[fState.fTileModeX],
+                 gTileModeName[fState.fTileModeY]);
+    return true;
+}
+