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