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 "SkSpriteBlitter.h"
     11 #include "SkBlitRow.h"
     12 #include "SkColorFilter.h"
     13 #include "SkColorPriv.h"
     14 #include "SkTemplates.h"
     15 #include "SkUtils.h"
     16 #include "SkXfermode.h"
     17 
     18 ///////////////////////////////////////////////////////////////////////////////
     19 
     20 class Sprite_D32_S32 : public SkSpriteBlitter {
     21 public:
     22     Sprite_D32_S32(const SkBitmap& src, U8CPU alpha)  : INHERITED(src) {
     23         SkASSERT(src.config() == SkBitmap::kARGB_8888_Config);
     24 
     25         unsigned flags32 = 0;
     26         if (255 != alpha) {
     27             flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
     28         }
     29         if (!src.isOpaque()) {
     30             flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
     31         }
     32 
     33         fProc32 = SkBlitRow::Factory32(flags32);
     34         fAlpha = alpha;
     35     }
     36 
     37     virtual void blitRect(int x, int y, int width, int height) {
     38         SkASSERT(width > 0 && height > 0);
     39         uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y);
     40         const uint32_t* SK_RESTRICT src = fSource->getAddr32(x - fLeft,
     41                                                              y - fTop);
     42         size_t dstRB = fDevice->rowBytes();
     43         size_t srcRB = fSource->rowBytes();
     44         SkBlitRow::Proc32 proc = fProc32;
     45         U8CPU             alpha = fAlpha;
     46 
     47         do {
     48             proc(dst, src, width, alpha);
     49             dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
     50             src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
     51         } while (--height != 0);
     52     }
     53 
     54 private:
     55     SkBlitRow::Proc32   fProc32;
     56     U8CPU               fAlpha;
     57 
     58     typedef SkSpriteBlitter INHERITED;
     59 };
     60 
     61 ///////////////////////////////////////////////////////////////////////////////
     62 
     63 class Sprite_D32_XferFilter : public SkSpriteBlitter {
     64 public:
     65     Sprite_D32_XferFilter(const SkBitmap& source, const SkPaint& paint)
     66         : SkSpriteBlitter(source) {
     67         fColorFilter = paint.getColorFilter();
     68         SkSafeRef(fColorFilter);
     69 
     70         fXfermode = paint.getXfermode();
     71         SkSafeRef(fXfermode);
     72 
     73         fBufferSize = 0;
     74         fBuffer = NULL;
     75 
     76         unsigned flags32 = 0;
     77         if (255 != paint.getAlpha()) {
     78             flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
     79         }
     80         if (!source.isOpaque()) {
     81             flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
     82         }
     83 
     84         fProc32 = SkBlitRow::Factory32(flags32);
     85         fAlpha = paint.getAlpha();
     86     }
     87 
     88     virtual ~Sprite_D32_XferFilter() {
     89         delete[] fBuffer;
     90         SkSafeUnref(fXfermode);
     91         SkSafeUnref(fColorFilter);
     92     }
     93 
     94     virtual void setup(const SkBitmap& device, int left, int top,
     95                        const SkPaint& paint) {
     96         this->INHERITED::setup(device, left, top, paint);
     97 
     98         int width = device.width();
     99         if (width > fBufferSize) {
    100             fBufferSize = width;
    101             delete[] fBuffer;
    102             fBuffer = new SkPMColor[width];
    103         }
    104     }
    105 
    106 protected:
    107     SkColorFilter*      fColorFilter;
    108     SkXfermode*         fXfermode;
    109     int                 fBufferSize;
    110     SkPMColor*          fBuffer;
    111     SkBlitRow::Proc32   fProc32;
    112     U8CPU               fAlpha;
    113 
    114 private:
    115     typedef SkSpriteBlitter INHERITED;
    116 };
    117 
    118 ///////////////////////////////////////////////////////////////////////////////
    119 
    120 class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter {
    121 public:
    122     Sprite_D32_S32A_XferFilter(const SkBitmap& source, const SkPaint& paint)
    123         : Sprite_D32_XferFilter(source, paint) {}
    124 
    125     virtual void blitRect(int x, int y, int width, int height) {
    126         SkASSERT(width > 0 && height > 0);
    127         uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y);
    128         const uint32_t* SK_RESTRICT src = fSource->getAddr32(x - fLeft,
    129                                                              y - fTop);
    130         size_t dstRB = fDevice->rowBytes();
    131         size_t srcRB = fSource->rowBytes();
    132         SkColorFilter* colorFilter = fColorFilter;
    133         SkXfermode* xfermode = fXfermode;
    134 
    135         do {
    136             const SkPMColor* tmp = src;
    137 
    138             if (NULL != colorFilter) {
    139                 colorFilter->filterSpan(src, width, fBuffer);
    140                 tmp = fBuffer;
    141             }
    142 
    143             if (NULL != xfermode) {
    144                 xfermode->xfer32(dst, tmp, width, NULL);
    145             } else {
    146                 fProc32(dst, tmp, width, fAlpha);
    147             }
    148 
    149             dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
    150             src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
    151         } while (--height != 0);
    152     }
    153 
    154 private:
    155     typedef Sprite_D32_XferFilter INHERITED;
    156 };
    157 
    158 static void fillbuffer(SkPMColor* SK_RESTRICT dst,
    159                        const SkPMColor16* SK_RESTRICT src, int count) {
    160     SkASSERT(count > 0);
    161 
    162     do {
    163         *dst++ = SkPixel4444ToPixel32(*src++);
    164     } while (--count != 0);
    165 }
    166 
    167 class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter {
    168 public:
    169     Sprite_D32_S4444_XferFilter(const SkBitmap& source, const SkPaint& paint)
    170         : Sprite_D32_XferFilter(source, paint) {}
    171 
    172     virtual void blitRect(int x, int y, int width, int height) {
    173         SkASSERT(width > 0 && height > 0);
    174         SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
    175         const SkPMColor16* SK_RESTRICT src = fSource->getAddr16(x - fLeft,
    176                                                                 y - fTop);
    177         size_t dstRB = fDevice->rowBytes();
    178         size_t srcRB = fSource->rowBytes();
    179         SkPMColor* SK_RESTRICT buffer = fBuffer;
    180         SkColorFilter* colorFilter = fColorFilter;
    181         SkXfermode* xfermode = fXfermode;
    182 
    183         do {
    184             fillbuffer(buffer, src, width);
    185 
    186             if (NULL != colorFilter) {
    187                 colorFilter->filterSpan(buffer, width, buffer);
    188             }
    189             if (NULL != xfermode) {
    190                 xfermode->xfer32(dst, buffer, width, NULL);
    191             } else {
    192                 fProc32(dst, buffer, width, fAlpha);
    193             }
    194 
    195             dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
    196             src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
    197         } while (--height != 0);
    198     }
    199 
    200 private:
    201     typedef Sprite_D32_XferFilter INHERITED;
    202 };
    203 
    204 ///////////////////////////////////////////////////////////////////////////////
    205 
    206 static void src_row(SkPMColor* SK_RESTRICT dst,
    207                     const SkPMColor16* SK_RESTRICT src, int count) {
    208     do {
    209         *dst = SkPixel4444ToPixel32(*src);
    210         src += 1;
    211         dst += 1;
    212     } while (--count != 0);
    213 }
    214 
    215 class Sprite_D32_S4444_Opaque : public SkSpriteBlitter {
    216 public:
    217     Sprite_D32_S4444_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {}
    218 
    219     virtual void blitRect(int x, int y, int width, int height) {
    220         SkASSERT(width > 0 && height > 0);
    221         SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
    222         const SkPMColor16* SK_RESTRICT src = fSource->getAddr16(x - fLeft,
    223                                                                 y - fTop);
    224         size_t dstRB = fDevice->rowBytes();
    225         size_t srcRB = fSource->rowBytes();
    226 
    227         do {
    228             src_row(dst, src, width);
    229             dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
    230             src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
    231         } while (--height != 0);
    232     }
    233 };
    234 
    235 static void srcover_row(SkPMColor* SK_RESTRICT dst,
    236                         const SkPMColor16* SK_RESTRICT src, int count) {
    237     do {
    238         *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst);
    239         src += 1;
    240         dst += 1;
    241     } while (--count != 0);
    242 }
    243 
    244 class Sprite_D32_S4444 : public SkSpriteBlitter {
    245 public:
    246     Sprite_D32_S4444(const SkBitmap& source) : SkSpriteBlitter(source) {}
    247 
    248     virtual void blitRect(int x, int y, int width, int height) {
    249         SkASSERT(width > 0 && height > 0);
    250         SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
    251         const SkPMColor16* SK_RESTRICT src = fSource->getAddr16(x - fLeft,
    252                                                                 y - fTop);
    253         size_t dstRB = fDevice->rowBytes();
    254         size_t srcRB = fSource->rowBytes();
    255 
    256         do {
    257             srcover_row(dst, src, width);
    258             dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
    259             src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
    260         } while (--height != 0);
    261     }
    262 };
    263 
    264 ///////////////////////////////////////////////////////////////////////////////
    265 
    266 #include "SkTemplatesPriv.h"
    267 
    268 SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source,
    269                                             const SkPaint& paint,
    270                                             void* storage, size_t storageSize) {
    271     if (paint.getMaskFilter() != NULL) {
    272         return NULL;
    273     }
    274 
    275     U8CPU       alpha = paint.getAlpha();
    276     SkXfermode* xfermode = paint.getXfermode();
    277     SkColorFilter* filter = paint.getColorFilter();
    278     SkSpriteBlitter* blitter = NULL;
    279 
    280     switch (source.config()) {
    281         case SkBitmap::kARGB_4444_Config:
    282             if (alpha != 0xFF) {
    283                 return NULL;    // we only have opaque sprites
    284             }
    285             if (xfermode || filter) {
    286                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_XferFilter,
    287                                       storage, storageSize, (source, paint));
    288             } else if (source.isOpaque()) {
    289                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444_Opaque,
    290                                       storage, storageSize, (source));
    291             } else {
    292                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S4444,
    293                                       storage, storageSize, (source));
    294             }
    295             break;
    296         case SkBitmap::kARGB_8888_Config:
    297             if (xfermode || filter) {
    298                 if (255 == alpha) {
    299                     // this can handle xfermode or filter, but not alpha
    300                     SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32A_XferFilter,
    301                                       storage, storageSize, (source, paint));
    302                 }
    303             } else {
    304                 // this can handle alpha, but not xfermode or filter
    305                 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D32_S32,
    306                               storage, storageSize, (source, alpha));
    307             }
    308             break;
    309         default:
    310             break;
    311     }
    312     return blitter;
    313 }
    314