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