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