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