grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
new file mode 100644
index 0000000..dd9c859
--- /dev/null
+++ b/src/core/SkShader.cpp
@@ -0,0 +1,284 @@
+/* libs/graphics/sgl/SkShader.cpp
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#include "SkShader.h"
+#include "SkPaint.h"
+
+SkShader::SkShader() : fLocalMatrix(NULL) {
+    SkDEBUGCODE(fInSession = false;)
+}
+
+SkShader::SkShader(SkFlattenableReadBuffer& buffer)
+        : INHERITED(buffer), fLocalMatrix(NULL) {
+    if (buffer.readBool()) {
+        SkMatrix matrix;
+        buffer.read(&matrix, sizeof(matrix));
+        setLocalMatrix(matrix);
+    }
+    SkDEBUGCODE(fInSession = false;)
+}
+
+SkShader::~SkShader() {
+    SkASSERT(!fInSession);
+    sk_free(fLocalMatrix);
+}
+
+void SkShader::beginSession() {
+    SkASSERT(!fInSession);
+    SkDEBUGCODE(fInSession = true;)
+}
+
+void SkShader::endSession() {
+    SkASSERT(fInSession);
+    SkDEBUGCODE(fInSession = false;)
+}
+
+void SkShader::flatten(SkFlattenableWriteBuffer& buffer) {
+    this->INHERITED::flatten(buffer);
+    buffer.writeBool(fLocalMatrix != NULL);
+    if (fLocalMatrix) {
+        buffer.writeMul4(fLocalMatrix, sizeof(SkMatrix));
+    }
+}
+
+bool SkShader::getLocalMatrix(SkMatrix* localM) const {
+    if (fLocalMatrix) {
+        if (localM) {
+            *localM = *fLocalMatrix;
+        }
+        return true;
+    } else {
+        if (localM) {
+            localM->reset();
+        }
+        return false;
+    }
+}
+
+void SkShader::setLocalMatrix(const SkMatrix& localM) {
+    if (localM.isIdentity()) {
+        this->resetLocalMatrix();
+    } else {
+        if (fLocalMatrix == NULL) {
+            fLocalMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix));
+        }
+        *fLocalMatrix = localM;
+    }
+}
+
+void SkShader::resetLocalMatrix() {
+    if (fLocalMatrix) {
+        sk_free(fLocalMatrix);
+        fLocalMatrix = NULL;
+    }
+}
+
+bool SkShader::setContext(const SkBitmap& device,
+                          const SkPaint& paint,
+                          const SkMatrix& matrix) {
+    const SkMatrix* m = &matrix;
+    SkMatrix        total;
+
+    fDeviceConfig = SkToU8(device.getConfig());
+    fPaintAlpha = paint.getAlpha();
+    if (fLocalMatrix) {
+        total.setConcat(matrix, *fLocalMatrix);
+        m = &total;
+    }
+    if (m->invert(&fTotalInverse)) {
+        fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
+        return true;
+    }
+    return false;
+}
+
+#include "SkColorPriv.h"
+
+void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) {
+    SkASSERT(span16);
+    SkASSERT(count > 0);
+    SkASSERT(this->canCallShadeSpan16());
+
+    // basically, if we get here, the subclass screwed up
+    SkASSERT(!"kHasSpan16 flag is set, but shadeSpan16() not implemented");
+}
+
+#define kTempColorQuadCount 6   // balance between speed (larger) and saving stack-space
+#define kTempColorCount     (kTempColorQuadCount << 2)  
+
+#ifdef SK_CPU_BENDIAN
+    #define SkU32BitShiftToByteOffset(shift)    (3 - ((shift) >> 3))
+#else
+    #define SkU32BitShiftToByteOffset(shift)    ((shift) >> 3)
+#endif
+
+void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
+    SkASSERT(count > 0);
+
+    SkPMColor   colors[kTempColorCount];
+
+    while ((count -= kTempColorCount) >= 0) {
+        this->shadeSpan(x, y, colors, kTempColorCount);
+        x += kTempColorCount;
+
+        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
+        int quads = kTempColorQuadCount;
+        do {
+            U8CPU a0 = srcA[0];
+            U8CPU a1 = srcA[4];
+            U8CPU a2 = srcA[8];
+            U8CPU a3 = srcA[12];
+            srcA += 4*4;
+            *alpha++ = SkToU8(a0);
+            *alpha++ = SkToU8(a1);
+            *alpha++ = SkToU8(a2);
+            *alpha++ = SkToU8(a3);
+        } while (--quads != 0);
+    }
+    SkASSERT(count < 0);
+    SkASSERT(count + kTempColorCount >= 0);
+    if (count += kTempColorCount) {
+        this->shadeSpan(x, y, colors, count);
+
+        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
+        do {
+            *alpha++ = *srcA;
+            srcA += 4;
+        } while (--count != 0);
+    }
+#if 0
+    do {
+        int n = count;
+        if (n > kTempColorCount)
+            n = kTempColorCount;
+        SkASSERT(n > 0);
+
+        this->shadeSpan(x, y, colors, n);
+        x += n;
+        count -= n;
+
+        const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
+        do {
+            *alpha++ = *srcA;
+            srcA += 4;
+        } while (--n != 0);
+    } while (count > 0);
+#endif
+}
+
+SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
+    MatrixClass mc = kLinear_MatrixClass;
+
+    if (mat.getType() & SkMatrix::kPerspective_Mask) {
+        if (mat.fixedStepInX(0, NULL, NULL)) {
+            mc = kFixedStepInX_MatrixClass;
+        } else {
+            mc = kPerspective_MatrixClass;
+        }
+    }
+    return mc;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) {
+    return false;
+}
+
+SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
+                                       TileMode tmx, TileMode tmy) {
+    return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+#include "SkColorShader.h"
+#include "SkUtils.h"
+
+SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
+    fInheritColor = b.readU8(); 
+    if (fInheritColor) {
+        return;
+    }
+    fColor = b.readU32();
+}
+
+void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
+    this->INHERITED::flatten(buffer);
+    buffer.write8(fInheritColor);
+    if (fInheritColor) {
+        return;
+    }
+    buffer.write32(fColor);
+}
+
+uint32_t SkColorShader::getFlags() {
+    return (SkGetPackedA32(fPMColor) == 255 ? kOpaqueAlpha_Flag : 0) |
+            kHasSpan16_Flag;
+}
+
+uint8_t SkColorShader::getSpan16Alpha() const {
+    return SkGetPackedA32(fPMColor);
+}
+
+bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
+                               const SkMatrix& matrix) {
+    if (!this->INHERITED::setContext(device, paint, matrix)) {
+        return false;
+    }
+
+    SkColor c;
+    unsigned a;
+    
+    if (fInheritColor) {
+        c = paint.getColor();
+        a = SkColorGetA(c);
+    } else {
+        c = fColor;
+        a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha()));
+    }
+
+    unsigned r = SkColorGetR(c);
+    unsigned g = SkColorGetG(c);
+    unsigned b = SkColorGetB(c);
+
+    // we want this before we apply any alpha
+    fColor16 = SkPack888ToRGB16(r, g, b);
+
+    if (a != 255) {
+        a = SkAlpha255To256(a);
+        r = SkAlphaMul(r, a);
+        g = SkAlphaMul(g, a);
+        b = SkAlphaMul(b, a);
+    }
+    fPMColor = SkPackARGB32(a, r, g, b);
+
+    return true;
+}
+
+void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
+    sk_memset32(span, fPMColor, count);
+}
+
+void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
+    sk_memset16(span, fColor16, count);
+}
+
+void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
+    memset(alpha, SkGetPackedA32(fPMColor), count);
+}
+