Home | History | Annotate | Download | only in effects
      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 "SkTransparentShader.h"
     11 #include "SkColorPriv.h"
     12 #include "SkString.h"
     13 
     14 bool SkTransparentShader::setContext(const SkBitmap& device,
     15                                      const SkPaint& paint,
     16                                      const SkMatrix& matrix) {
     17     fDevice = &device;
     18     fAlpha = paint.getAlpha();
     19 
     20     return this->INHERITED::setContext(device, paint, matrix);
     21 }
     22 
     23 uint32_t SkTransparentShader::getFlags() {
     24     uint32_t flags = this->INHERITED::getFlags();
     25 
     26     switch (fDevice->getConfig()) {
     27         case SkBitmap::kRGB_565_Config:
     28             flags |= kHasSpan16_Flag;
     29             if (fAlpha == 255)
     30                 flags |= kOpaqueAlpha_Flag;
     31             break;
     32         case SkBitmap::kARGB_8888_Config:
     33         case SkBitmap::kARGB_4444_Config:
     34             if (fAlpha == 255 && fDevice->isOpaque())
     35                 flags |= kOpaqueAlpha_Flag;
     36             break;
     37         default:
     38             break;
     39     }
     40     return flags;
     41 }
     42 
     43 void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
     44     unsigned scale = SkAlpha255To256(fAlpha);
     45 
     46     switch (fDevice->getConfig()) {
     47         case SkBitmap::kARGB_8888_Config:
     48             if (scale == 256) {
     49                 SkPMColor* src = fDevice->getAddr32(x, y);
     50                 if (src != span) {
     51                     memcpy(span, src, count * sizeof(SkPMColor));
     52                 }
     53             } else {
     54                 const SkPMColor* src = fDevice->getAddr32(x, y);
     55                 for (int i = count - 1; i >= 0; --i) {
     56                     span[i] = SkAlphaMulQ(src[i], scale);
     57                 }
     58             }
     59             break;
     60         case SkBitmap::kRGB_565_Config: {
     61             const uint16_t* src = fDevice->getAddr16(x, y);
     62             if (scale == 256) {
     63                 for (int i = count - 1; i >= 0; --i) {
     64                     span[i] = SkPixel16ToPixel32(src[i]);
     65                 }
     66             } else {
     67                 unsigned alpha = fAlpha;
     68                 for (int i = count - 1; i >= 0; --i) {
     69                     uint16_t c = src[i];
     70                     unsigned r = SkPacked16ToR32(c);
     71                     unsigned g = SkPacked16ToG32(c);
     72                     unsigned b = SkPacked16ToB32(c);
     73 
     74                     span[i] = SkPackARGB32( alpha,
     75                                             SkAlphaMul(r, scale),
     76                                             SkAlphaMul(g, scale),
     77                                             SkAlphaMul(b, scale));
     78                 }
     79             }
     80             break;
     81         }
     82         case SkBitmap::kARGB_4444_Config: {
     83             const uint16_t* src = fDevice->getAddr16(x, y);
     84             if (scale == 256) {
     85                 for (int i = count - 1; i >= 0; --i) {
     86                     span[i] = SkPixel4444ToPixel32(src[i]);
     87                 }
     88             } else {
     89                 unsigned scale16 = scale >> 4;
     90                 for (int i = count - 1; i >= 0; --i) {
     91                     uint32_t c = SkExpand_4444(src[i]) * scale16;
     92                     span[i] = SkCompact_8888(c);
     93                 }
     94             }
     95             break;
     96         }
     97         case SkBitmap::kIndex8_Config:
     98             SkDEBUGFAIL("index8 not supported as a destination device");
     99             break;
    100         case SkBitmap::kA8_Config: {
    101             const uint8_t* src = fDevice->getAddr8(x, y);
    102             if (scale == 256) {
    103                 for (int i = count - 1; i >= 0; --i) {
    104                     span[i] = SkPackARGB32(src[i], 0, 0, 0);
    105                 }
    106             } else {
    107                 for (int i = count - 1; i >= 0; --i) {
    108                     span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0);
    109                 }
    110             }
    111             break;
    112         }
    113         case SkBitmap::kA1_Config:
    114             SkDEBUGFAIL("kA1_Config umimplemented at this time");
    115             break;
    116         default:    // to avoid warnings
    117             break;
    118     }
    119 }
    120 
    121 void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
    122     SkASSERT(fDevice->getConfig() == SkBitmap::kRGB_565_Config);
    123 
    124     uint16_t* src = fDevice->getAddr16(x, y);
    125     if (src != span) {
    126         memcpy(span, src, count << 1);
    127     }
    128 }
    129 
    130 #ifdef SK_DEVELOPER
    131 void SkTransparentShader::toString(SkString* str) const {
    132     str->append("SkTransparentShader: (");
    133 
    134     this->INHERITED::toString(str);
    135 
    136     str->append(")");
    137 }
    138 #endif
    139