Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkScalar.h"
     11 #include "SkShader.h"
     12 #include "SkPaint.h"
     13 #include "SkMallocPixelRef.h"
     14 
     15 SkShader::SkShader() : fLocalMatrix(NULL) {
     16     SkDEBUGCODE(fInSession = false;)
     17 }
     18 
     19 SkShader::SkShader(SkFlattenableReadBuffer& buffer)
     20         : INHERITED(buffer), fLocalMatrix(NULL) {
     21     if (buffer.readBool()) {
     22         SkMatrix matrix;
     23         SkReadMatrix(&buffer, &matrix);
     24         setLocalMatrix(matrix);
     25     }
     26     SkDEBUGCODE(fInSession = false;)
     27 }
     28 
     29 SkShader::~SkShader() {
     30     SkASSERT(!fInSession);
     31     sk_free(fLocalMatrix);
     32 }
     33 
     34 void SkShader::beginSession() {
     35     SkASSERT(!fInSession);
     36     SkDEBUGCODE(fInSession = true;)
     37 }
     38 
     39 void SkShader::endSession() {
     40     SkASSERT(fInSession);
     41     SkDEBUGCODE(fInSession = false;)
     42 }
     43 
     44 void SkShader::flatten(SkFlattenableWriteBuffer& buffer) {
     45     this->INHERITED::flatten(buffer);
     46     buffer.writeBool(fLocalMatrix != NULL);
     47     if (fLocalMatrix) {
     48         SkWriteMatrix(&buffer, *fLocalMatrix);
     49     }
     50 }
     51 
     52 bool SkShader::getLocalMatrix(SkMatrix* localM) const {
     53     if (fLocalMatrix) {
     54         if (localM) {
     55             *localM = *fLocalMatrix;
     56         }
     57         return true;
     58     } else {
     59         if (localM) {
     60             localM->reset();
     61         }
     62         return false;
     63     }
     64 }
     65 
     66 void SkShader::setLocalMatrix(const SkMatrix& localM) {
     67     if (localM.isIdentity()) {
     68         this->resetLocalMatrix();
     69     } else {
     70         if (fLocalMatrix == NULL) {
     71             fLocalMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix));
     72         }
     73         *fLocalMatrix = localM;
     74     }
     75 }
     76 
     77 void SkShader::resetLocalMatrix() {
     78     if (fLocalMatrix) {
     79         sk_free(fLocalMatrix);
     80         fLocalMatrix = NULL;
     81     }
     82 }
     83 
     84 bool SkShader::setContext(const SkBitmap& device,
     85                           const SkPaint& paint,
     86                           const SkMatrix& matrix) {
     87     const SkMatrix* m = &matrix;
     88     SkMatrix        total;
     89 
     90     fDeviceConfig = SkToU8(device.getConfig());
     91     fPaintAlpha = paint.getAlpha();
     92     if (fLocalMatrix) {
     93         total.setConcat(matrix, *fLocalMatrix);
     94         m = &total;
     95     }
     96     if (m->invert(&fTotalInverse)) {
     97         fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
     98         return true;
     99     }
    100     return false;
    101 }
    102 
    103 #include "SkColorPriv.h"
    104 
    105 void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) {
    106     SkASSERT(span16);
    107     SkASSERT(count > 0);
    108     SkASSERT(this->canCallShadeSpan16());
    109 
    110     // basically, if we get here, the subclass screwed up
    111     SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented");
    112 }
    113 
    114 #define kTempColorQuadCount 6   // balance between speed (larger) and saving stack-space
    115 #define kTempColorCount     (kTempColorQuadCount << 2)
    116 
    117 #ifdef SK_CPU_BENDIAN
    118     #define SkU32BitShiftToByteOffset(shift)    (3 - ((shift) >> 3))
    119 #else
    120     #define SkU32BitShiftToByteOffset(shift)    ((shift) >> 3)
    121 #endif
    122 
    123 void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
    124     SkASSERT(count > 0);
    125 
    126     SkPMColor   colors[kTempColorCount];
    127 
    128     while ((count -= kTempColorCount) >= 0) {
    129         this->shadeSpan(x, y, colors, kTempColorCount);
    130         x += kTempColorCount;
    131 
    132         const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
    133         int quads = kTempColorQuadCount;
    134         do {
    135             U8CPU a0 = srcA[0];
    136             U8CPU a1 = srcA[4];
    137             U8CPU a2 = srcA[8];
    138             U8CPU a3 = srcA[12];
    139             srcA += 4*4;
    140             *alpha++ = SkToU8(a0);
    141             *alpha++ = SkToU8(a1);
    142             *alpha++ = SkToU8(a2);
    143             *alpha++ = SkToU8(a3);
    144         } while (--quads != 0);
    145     }
    146     SkASSERT(count < 0);
    147     SkASSERT(count + kTempColorCount >= 0);
    148     if (count += kTempColorCount) {
    149         this->shadeSpan(x, y, colors, count);
    150 
    151         const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
    152         do {
    153             *alpha++ = *srcA;
    154             srcA += 4;
    155         } while (--count != 0);
    156     }
    157 #if 0
    158     do {
    159         int n = count;
    160         if (n > kTempColorCount)
    161             n = kTempColorCount;
    162         SkASSERT(n > 0);
    163 
    164         this->shadeSpan(x, y, colors, n);
    165         x += n;
    166         count -= n;
    167 
    168         const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
    169         do {
    170             *alpha++ = *srcA;
    171             srcA += 4;
    172         } while (--n != 0);
    173     } while (count > 0);
    174 #endif
    175 }
    176 
    177 SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
    178     MatrixClass mc = kLinear_MatrixClass;
    179 
    180     if (mat.hasPerspective()) {
    181         if (mat.fixedStepInX(0, NULL, NULL)) {
    182             mc = kFixedStepInX_MatrixClass;
    183         } else {
    184             mc = kPerspective_MatrixClass;
    185         }
    186     }
    187     return mc;
    188 }
    189 
    190 //////////////////////////////////////////////////////////////////////////////
    191 
    192 SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*,
    193                                          TileMode*, SkScalar*) const {
    194     return kNone_BitmapType;
    195 }
    196 
    197 SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
    198     return kNone_GradientType;
    199 }
    200 
    201 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
    202                                        TileMode tmx, TileMode tmy) {
    203     return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
    204 }
    205 
    206 //////////////////////////////////////////////////////////////////////////////
    207 
    208 #include "SkColorShader.h"
    209 #include "SkUtils.h"
    210 
    211 SkColorShader::SkColorShader() {
    212     fFlags = 0;
    213     fInheritColor = true;
    214 }
    215 
    216 SkColorShader::SkColorShader(SkColor c) {
    217     fFlags = 0;
    218     fColor = c;
    219     fInheritColor = false;
    220 }
    221 
    222 SkColorShader::~SkColorShader() {}
    223 
    224 bool SkColorShader::isOpaque() const {
    225     if (fInheritColor) {
    226         return true; // using paint's alpha
    227     }
    228     return SkColorGetA(fColor) == 255;
    229 }
    230 
    231 SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
    232     fFlags = 0; // computed in setContext
    233 
    234     fInheritColor = b.readU8();
    235     if (fInheritColor) {
    236         return;
    237     }
    238     fColor = b.readU32();
    239 }
    240 
    241 void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
    242     this->INHERITED::flatten(buffer);
    243     buffer.write8(fInheritColor);
    244     if (fInheritColor) {
    245         return;
    246     }
    247     buffer.write32(fColor);
    248 }
    249 
    250 SkFlattenable* SkColorShader::CreateProc(SkFlattenableReadBuffer& buffer) {
    251     return SkNEW_ARGS(SkColorShader, (buffer));
    252 }
    253 
    254 SkFlattenable::Factory SkColorShader::getFactory() {
    255     return CreateProc;
    256 }
    257 
    258 uint32_t SkColorShader::getFlags() {
    259     return fFlags;
    260 }
    261 
    262 uint8_t SkColorShader::getSpan16Alpha() const {
    263     return SkGetPackedA32(fPMColor);
    264 }
    265 
    266 bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
    267                                const SkMatrix& matrix) {
    268     if (!this->INHERITED::setContext(device, paint, matrix)) {
    269         return false;
    270     }
    271 
    272     unsigned a;
    273 
    274     if (fInheritColor) {
    275         fColor = paint.getColor();
    276         a = SkColorGetA(fColor);
    277     } else {
    278         a = SkAlphaMul(SkColorGetA(fColor), SkAlpha255To256(paint.getAlpha()));
    279     }
    280 
    281     unsigned r = SkColorGetR(fColor);
    282     unsigned g = SkColorGetG(fColor);
    283     unsigned b = SkColorGetB(fColor);
    284 
    285     // we want this before we apply any alpha
    286     fColor16 = SkPack888ToRGB16(r, g, b);
    287 
    288     if (a != 255) {
    289         r = SkMulDiv255Round(r, a);
    290         g = SkMulDiv255Round(g, a);
    291         b = SkMulDiv255Round(b, a);
    292     }
    293     fPMColor = SkPackARGB32(a, r, g, b);
    294 
    295     fFlags = kConstInY32_Flag;
    296     if (255 == a) {
    297         fFlags |= kOpaqueAlpha_Flag;
    298         if (paint.isDither() == false) {
    299             fFlags |= kHasSpan16_Flag;
    300         }
    301     }
    302 
    303     return true;
    304 }
    305 
    306 void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
    307     sk_memset32(span, fPMColor, count);
    308 }
    309 
    310 void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
    311     sk_memset16(span, fColor16, count);
    312 }
    313 
    314 void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
    315     memset(alpha, SkGetPackedA32(fPMColor), count);
    316 }
    317 
    318 // if we had a asAColor method, that would be more efficient...
    319 SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
    320                                               TileMode modes[],
    321                                       SkScalar* twoPointRadialParams) const {
    322     return kNone_BitmapType;
    323 }
    324 
    325 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
    326     if (info) {
    327         if (info->fColors && info->fColorCount >= 1) {
    328             info->fColors[0] = fColor;
    329         }
    330         info->fColorCount = 1;
    331         info->fTileMode = SkShader::kRepeat_TileMode;
    332     }
    333     return kColor_GradientType;
    334 }
    335 
    336 ///////////////////////////////////////////////////////////////////////////////
    337 
    338 #include "SkEmptyShader.h"
    339 
    340 SkEmptyShader::SkEmptyShader(SkFlattenableReadBuffer& b) : INHERITED(b) {}
    341 
    342 uint32_t SkEmptyShader::getFlags() { return 0; }
    343 uint8_t SkEmptyShader::getSpan16Alpha() const { return 0; }
    344 
    345 bool SkEmptyShader::setContext(const SkBitmap&, const SkPaint&,
    346                                const SkMatrix&) { return false; }
    347 
    348 void SkEmptyShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
    349     SkDEBUGFAIL("should never get called, since setContext() returned false");
    350 }
    351 
    352 void SkEmptyShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
    353     SkDEBUGFAIL("should never get called, since setContext() returned false");
    354 }
    355 
    356 void SkEmptyShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
    357     SkDEBUGFAIL("should never get called, since setContext() returned false");
    358 }
    359 
    360 SkFlattenable::Factory SkEmptyShader::getFactory() { return NULL; }
    361 
    362 void SkEmptyShader::flatten(SkFlattenableWriteBuffer& buffer) {
    363     this->INHERITED::flatten(buffer);
    364 }
    365 
    366