Home | History | Annotate | Download | only in core
      1 /* libs/graphics/sgl/SkShader.cpp
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #include "SkShader.h"
     19 #include "SkPaint.h"
     20 
     21 SkShader::SkShader() : fLocalMatrix(NULL) {
     22     SkDEBUGCODE(fInSession = false;)
     23 }
     24 
     25 SkShader::SkShader(SkFlattenableReadBuffer& buffer)
     26         : INHERITED(buffer), fLocalMatrix(NULL) {
     27     if (buffer.readBool()) {
     28         SkMatrix matrix;
     29         buffer.read(&matrix, sizeof(matrix));
     30         setLocalMatrix(matrix);
     31     }
     32     SkDEBUGCODE(fInSession = false;)
     33 }
     34 
     35 SkShader::~SkShader() {
     36     SkASSERT(!fInSession);
     37     sk_free(fLocalMatrix);
     38 }
     39 
     40 void SkShader::beginSession() {
     41     SkASSERT(!fInSession);
     42     SkDEBUGCODE(fInSession = true;)
     43 }
     44 
     45 void SkShader::endSession() {
     46     SkASSERT(fInSession);
     47     SkDEBUGCODE(fInSession = false;)
     48 }
     49 
     50 void SkShader::flatten(SkFlattenableWriteBuffer& buffer) {
     51     this->INHERITED::flatten(buffer);
     52     buffer.writeBool(fLocalMatrix != NULL);
     53     if (fLocalMatrix) {
     54         buffer.writeMul4(fLocalMatrix, sizeof(SkMatrix));
     55     }
     56 }
     57 
     58 bool SkShader::getLocalMatrix(SkMatrix* localM) const {
     59     if (fLocalMatrix) {
     60         if (localM) {
     61             *localM = *fLocalMatrix;
     62         }
     63         return true;
     64     } else {
     65         if (localM) {
     66             localM->reset();
     67         }
     68         return false;
     69     }
     70 }
     71 
     72 void SkShader::setLocalMatrix(const SkMatrix& localM) {
     73     if (localM.isIdentity()) {
     74         this->resetLocalMatrix();
     75     } else {
     76         if (fLocalMatrix == NULL) {
     77             fLocalMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix));
     78         }
     79         *fLocalMatrix = localM;
     80     }
     81 }
     82 
     83 void SkShader::resetLocalMatrix() {
     84     if (fLocalMatrix) {
     85         sk_free(fLocalMatrix);
     86         fLocalMatrix = NULL;
     87     }
     88 }
     89 
     90 bool SkShader::setContext(const SkBitmap& device,
     91                           const SkPaint& paint,
     92                           const SkMatrix& matrix) {
     93     const SkMatrix* m = &matrix;
     94     SkMatrix        total;
     95 
     96     fDeviceConfig = SkToU8(device.getConfig());
     97     fPaintAlpha = paint.getAlpha();
     98     if (fLocalMatrix) {
     99         total.setConcat(matrix, *fLocalMatrix);
    100         m = &total;
    101     }
    102     if (m->invert(&fTotalInverse)) {
    103         fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
    104         return true;
    105     }
    106     return false;
    107 }
    108 
    109 #include "SkColorPriv.h"
    110 
    111 void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) {
    112     SkASSERT(span16);
    113     SkASSERT(count > 0);
    114     SkASSERT(this->canCallShadeSpan16());
    115 
    116     // basically, if we get here, the subclass screwed up
    117     SkASSERT(!"kHasSpan16 flag is set, but shadeSpan16() not implemented");
    118 }
    119 
    120 #define kTempColorQuadCount 6   // balance between speed (larger) and saving stack-space
    121 #define kTempColorCount     (kTempColorQuadCount << 2)
    122 
    123 #ifdef SK_CPU_BENDIAN
    124     #define SkU32BitShiftToByteOffset(shift)    (3 - ((shift) >> 3))
    125 #else
    126     #define SkU32BitShiftToByteOffset(shift)    ((shift) >> 3)
    127 #endif
    128 
    129 void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
    130     SkASSERT(count > 0);
    131 
    132     SkPMColor   colors[kTempColorCount];
    133 
    134     while ((count -= kTempColorCount) >= 0) {
    135         this->shadeSpan(x, y, colors, kTempColorCount);
    136         x += kTempColorCount;
    137 
    138         const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
    139         int quads = kTempColorQuadCount;
    140         do {
    141             U8CPU a0 = srcA[0];
    142             U8CPU a1 = srcA[4];
    143             U8CPU a2 = srcA[8];
    144             U8CPU a3 = srcA[12];
    145             srcA += 4*4;
    146             *alpha++ = SkToU8(a0);
    147             *alpha++ = SkToU8(a1);
    148             *alpha++ = SkToU8(a2);
    149             *alpha++ = SkToU8(a3);
    150         } while (--quads != 0);
    151     }
    152     SkASSERT(count < 0);
    153     SkASSERT(count + kTempColorCount >= 0);
    154     if (count += kTempColorCount) {
    155         this->shadeSpan(x, y, colors, count);
    156 
    157         const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
    158         do {
    159             *alpha++ = *srcA;
    160             srcA += 4;
    161         } while (--count != 0);
    162     }
    163 #if 0
    164     do {
    165         int n = count;
    166         if (n > kTempColorCount)
    167             n = kTempColorCount;
    168         SkASSERT(n > 0);
    169 
    170         this->shadeSpan(x, y, colors, n);
    171         x += n;
    172         count -= n;
    173 
    174         const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
    175         do {
    176             *alpha++ = *srcA;
    177             srcA += 4;
    178         } while (--n != 0);
    179     } while (count > 0);
    180 #endif
    181 }
    182 
    183 SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
    184     MatrixClass mc = kLinear_MatrixClass;
    185 
    186     if (mat.getType() & SkMatrix::kPerspective_Mask) {
    187         if (mat.fixedStepInX(0, NULL, NULL)) {
    188             mc = kFixedStepInX_MatrixClass;
    189         } else {
    190             mc = kPerspective_MatrixClass;
    191         }
    192     }
    193     return mc;
    194 }
    195 
    196 //////////////////////////////////////////////////////////////////////////////
    197 
    198 bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) {
    199     return false;
    200 }
    201 
    202 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
    203                                        TileMode tmx, TileMode tmy) {
    204     return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
    205 }
    206 
    207 //////////////////////////////////////////////////////////////////////////////
    208 
    209 #include "SkColorShader.h"
    210 #include "SkUtils.h"
    211 
    212 SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
    213     fFlags = 0; // computed in setContext
    214     fInheritColor = b.readU8();
    215     if (fInheritColor) {
    216         return;
    217     }
    218     fColor = b.readU32();
    219 }
    220 
    221 void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
    222     this->INHERITED::flatten(buffer);
    223     buffer.write8(fInheritColor);
    224     if (fInheritColor) {
    225         return;
    226     }
    227     buffer.write32(fColor);
    228 }
    229 
    230 uint8_t SkColorShader::getSpan16Alpha() const {
    231     return SkGetPackedA32(fPMColor);
    232 }
    233 
    234 bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
    235                                const SkMatrix& matrix) {
    236     if (!this->INHERITED::setContext(device, paint, matrix)) {
    237         return false;
    238     }
    239 
    240     SkColor c;
    241     unsigned a;
    242 
    243     if (fInheritColor) {
    244         c = paint.getColor();
    245         a = SkColorGetA(c);
    246     } else {
    247         c = fColor;
    248         a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha()));
    249     }
    250 
    251     unsigned r = SkColorGetR(c);
    252     unsigned g = SkColorGetG(c);
    253     unsigned b = SkColorGetB(c);
    254 
    255     // we want this before we apply any alpha
    256     fColor16 = SkPack888ToRGB16(r, g, b);
    257 
    258     if (a != 255) {
    259         r = SkMulDiv255Round(r, a);
    260         g = SkMulDiv255Round(g, a);
    261         b = SkMulDiv255Round(b, a);
    262     }
    263     fPMColor = SkPackARGB32(a, r, g, b);
    264 
    265     fFlags = kConstInY32_Flag;
    266     if (255 == a) {
    267         fFlags |= kOpaqueAlpha_Flag;
    268         if (paint.isDither() == false) {
    269             fFlags |= kHasSpan16_Flag;
    270         }
    271     }
    272 
    273     return true;
    274 }
    275 
    276 void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
    277     sk_memset32(span, fPMColor, count);
    278 }
    279 
    280 void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
    281     sk_memset16(span, fColor16, count);
    282 }
    283 
    284 void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
    285     memset(alpha, SkGetPackedA32(fPMColor), count);
    286 }
    287 
    288