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 "SkCoreBlitters.h"
     11 #include "SkColorPriv.h"
     12 #include "SkShader.h"
     13 #include "SkXfermode.h"
     14 
     15 SkA8_Blitter::SkA8_Blitter(const SkBitmap& device, const SkPaint& paint)
     16         : INHERITED(device) {
     17     fSrcA = paint.getAlpha();
     18 }
     19 
     20 const SkBitmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) {
     21     if (255 == fSrcA) {
     22         *value = 255;
     23         return &fDevice;
     24     }
     25     return NULL;
     26 }
     27 
     28 void SkA8_Blitter::blitH(int x, int y, int width) {
     29     SkASSERT(x >= 0 && y >= 0 &&
     30              (unsigned)(x + width) <= (unsigned)fDevice.width());
     31 
     32     if (fSrcA == 0) {
     33         return;
     34     }
     35 
     36     uint8_t* device = fDevice.getAddr8(x, y);
     37 
     38     if (fSrcA == 255) {
     39         memset(device, 0xFF, width);
     40     } else {
     41         unsigned scale = 256 - SkAlpha255To256(fSrcA);
     42         unsigned srcA = fSrcA;
     43 
     44         for (int i = 0; i < width; i++) {
     45             device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
     46         }
     47     }
     48 }
     49 
     50 void SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
     51                              const int16_t runs[]) {
     52     if (fSrcA == 0) {
     53         return;
     54     }
     55 
     56     uint8_t*    device = fDevice.getAddr8(x, y);
     57     unsigned    srcA = fSrcA;
     58 
     59     for (;;) {
     60         int count = runs[0];
     61         SkASSERT(count >= 0);
     62         if (count == 0) {
     63             return;
     64         }
     65         unsigned aa = antialias[0];
     66 
     67         if (aa == 255 && srcA == 255) {
     68             memset(device, 0xFF, count);
     69         } else {
     70             unsigned sa = SkAlphaMul(srcA, SkAlpha255To256(aa));
     71             unsigned scale = 256 - sa;
     72 
     73             for (int i = 0; i < count; i++) {
     74                 device[i] = SkToU8(sa + SkAlphaMul(device[i], scale));
     75             }
     76         }
     77         runs += count;
     78         antialias += count;
     79         device += count;
     80     }
     81 }
     82 
     83 /////////////////////////////////////////////////////////////////////////////////////
     84 
     85 #define solid_8_pixels(mask, dst)           \
     86     do {                                    \
     87         if (mask & 0x80) dst[0] = 0xFF;     \
     88         if (mask & 0x40) dst[1] = 0xFF;     \
     89         if (mask & 0x20) dst[2] = 0xFF;     \
     90         if (mask & 0x10) dst[3] = 0xFF;     \
     91         if (mask & 0x08) dst[4] = 0xFF;     \
     92         if (mask & 0x04) dst[5] = 0xFF;     \
     93         if (mask & 0x02) dst[6] = 0xFF;     \
     94         if (mask & 0x01) dst[7] = 0xFF;     \
     95     } while (0)
     96 
     97 #define SK_BLITBWMASK_NAME                  SkA8_BlitBW
     98 #define SK_BLITBWMASK_ARGS
     99 #define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst)
    100 #define SK_BLITBWMASK_GETADDR               getAddr8
    101 #define SK_BLITBWMASK_DEVTYPE               uint8_t
    102 #include "SkBlitBWMaskTemplate.h"
    103 
    104 static inline void blend_8_pixels(U8CPU bw, uint8_t dst[], U8CPU sa,
    105                                   unsigned dst_scale) {
    106     if (bw & 0x80) dst[0] = SkToU8(sa + SkAlphaMul(dst[0], dst_scale));
    107     if (bw & 0x40) dst[1] = SkToU8(sa + SkAlphaMul(dst[1], dst_scale));
    108     if (bw & 0x20) dst[2] = SkToU8(sa + SkAlphaMul(dst[2], dst_scale));
    109     if (bw & 0x10) dst[3] = SkToU8(sa + SkAlphaMul(dst[3], dst_scale));
    110     if (bw & 0x08) dst[4] = SkToU8(sa + SkAlphaMul(dst[4], dst_scale));
    111     if (bw & 0x04) dst[5] = SkToU8(sa + SkAlphaMul(dst[5], dst_scale));
    112     if (bw & 0x02) dst[6] = SkToU8(sa + SkAlphaMul(dst[6], dst_scale));
    113     if (bw & 0x01) dst[7] = SkToU8(sa + SkAlphaMul(dst[7], dst_scale));
    114 }
    115 
    116 #define SK_BLITBWMASK_NAME                  SkA8_BlendBW
    117 #define SK_BLITBWMASK_ARGS                  , U8CPU sa, unsigned dst_scale
    118 #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sa, dst_scale)
    119 #define SK_BLITBWMASK_GETADDR               getAddr8
    120 #define SK_BLITBWMASK_DEVTYPE               uint8_t
    121 #include "SkBlitBWMaskTemplate.h"
    122 
    123 void SkA8_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    124     if (fSrcA == 0) {
    125         return;
    126     }
    127 
    128     if (mask.fFormat == SkMask::kBW_Format) {
    129         if (fSrcA == 0xFF) {
    130             SkA8_BlitBW(fDevice, mask, clip);
    131         } else {
    132             SkA8_BlendBW(fDevice, mask, clip, fSrcA,
    133                          SkAlpha255To256(255 - fSrcA));
    134         }
    135         return;
    136     }
    137 
    138     int x = clip.fLeft;
    139     int y = clip.fTop;
    140     int width = clip.width();
    141     int height = clip.height();
    142     uint8_t* device = fDevice.getAddr8(x, y);
    143     const uint8_t* alpha = mask.getAddr8(x, y);
    144     unsigned    srcA = fSrcA;
    145 
    146     while (--height >= 0) {
    147         for (int i = width - 1; i >= 0; --i) {
    148             unsigned sa;
    149             // scale our src by the alpha value
    150             {
    151                 int aa = alpha[i];
    152                 if (aa == 0) {
    153                     continue;
    154                 }
    155                 if (aa == 255) {
    156                     if (srcA == 255) {
    157                         device[i] = 0xFF;
    158                         continue;
    159                     }
    160                     sa = srcA;
    161                 } else {
    162                     sa = SkAlphaMul(srcA, SkAlpha255To256(aa));
    163                 }
    164             }
    165 
    166             int scale = 256 - SkAlpha255To256(sa);
    167             device[i] = SkToU8(sa + SkAlphaMul(device[i], scale));
    168         }
    169         device += fDevice.rowBytes();
    170         alpha += mask.fRowBytes;
    171     }
    172 }
    173 
    174 ///////////////////////////////////////////////////////////////////////////////
    175 
    176 void SkA8_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
    177     if (fSrcA == 0) {
    178         return;
    179     }
    180 
    181     unsigned sa = SkAlphaMul(fSrcA, SkAlpha255To256(alpha));
    182     uint8_t* device = fDevice.getAddr8(x, y);
    183     size_t   rowBytes = fDevice.rowBytes();
    184 
    185     if (sa == 0xFF) {
    186         for (int i = 0; i < height; i++) {
    187             *device = SkToU8(sa);
    188             device += rowBytes;
    189         }
    190     } else {
    191         unsigned scale = 256 - SkAlpha255To256(sa);
    192 
    193         for (int i = 0; i < height; i++) {
    194             *device = SkToU8(sa + SkAlphaMul(*device, scale));
    195             device += rowBytes;
    196         }
    197     }
    198 }
    199 
    200 void SkA8_Blitter::blitRect(int x, int y, int width, int height) {
    201     SkASSERT(x >= 0 && y >= 0 &&
    202              (unsigned)(x + width) <= (unsigned)fDevice.width() &&
    203              (unsigned)(y + height) <= (unsigned)fDevice.height());
    204 
    205     if (fSrcA == 0) {
    206         return;
    207     }
    208 
    209     uint8_t*    device = fDevice.getAddr8(x, y);
    210     unsigned    srcA = fSrcA;
    211 
    212     if (srcA == 255) {
    213         while (--height >= 0) {
    214             memset(device, 0xFF, width);
    215             device += fDevice.rowBytes();
    216         }
    217     } else {
    218         unsigned scale = 256 - SkAlpha255To256(srcA);
    219 
    220         while (--height >= 0) {
    221             for (int i = 0; i < width; i++) {
    222                 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
    223             }
    224             device += fDevice.rowBytes();
    225         }
    226     }
    227 }
    228 
    229 ///////////////////////////////////////////////////////////////////////
    230 
    231 SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint)
    232     : INHERITED(device, paint) {
    233     if ((fXfermode = paint.getXfermode()) != NULL) {
    234         fXfermode->ref();
    235         SkASSERT(fShader);
    236     }
    237 
    238     int width = device.width();
    239     fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4(width) >> 2)));
    240     fAAExpand = (uint8_t*)(fBuffer + width);
    241 }
    242 
    243 SkA8_Shader_Blitter::~SkA8_Shader_Blitter() {
    244     if (fXfermode) SkSafeUnref(fXfermode);
    245     sk_free(fBuffer);
    246 }
    247 
    248 void SkA8_Shader_Blitter::blitH(int x, int y, int width) {
    249     SkASSERT(x >= 0 && y >= 0 &&
    250              (unsigned)(x + width) <= (unsigned)fDevice.width());
    251 
    252     uint8_t* device = fDevice.getAddr8(x, y);
    253 
    254     if ((fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) {
    255         memset(device, 0xFF, width);
    256     } else {
    257         SkPMColor*  span = fBuffer;
    258 
    259         fShader->shadeSpan(x, y, span, width);
    260         if (fXfermode) {
    261             fXfermode->xferA8(device, span, width, NULL);
    262         } else {
    263             for (int i = width - 1; i >= 0; --i) {
    264                 unsigned    srcA = SkGetPackedA32(span[i]);
    265                 unsigned    scale = 256 - SkAlpha255To256(srcA);
    266 
    267                 device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
    268             }
    269         }
    270     }
    271 }
    272 
    273 static inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) {
    274     SkASSERT((unsigned)aa <= 255);
    275 
    276     int src_scale = SkAlpha255To256(aa);
    277     int sa = SkGetPackedA32(src);
    278     int dst_scale = 256 - SkAlphaMul(sa, src_scale);
    279 
    280     return SkToU8((sa * src_scale + da * dst_scale) >> 8);
    281 }
    282 
    283 void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
    284                                     const int16_t runs[]) {
    285     SkShader*   shader = fShader;
    286     SkXfermode* mode = fXfermode;
    287     uint8_t*    aaExpand = fAAExpand;
    288     SkPMColor*  span = fBuffer;
    289     uint8_t*    device = fDevice.getAddr8(x, y);
    290     int         opaque = fShader->getFlags() & SkShader::kOpaqueAlpha_Flag;
    291 
    292     for (;;) {
    293         int count = *runs;
    294         if (count == 0) {
    295             break;
    296         }
    297         int aa = *antialias;
    298         if (aa) {
    299             if (opaque && aa == 255 && mode == NULL) {
    300                 memset(device, 0xFF, count);
    301             } else {
    302                 shader->shadeSpan(x, y, span, count);
    303                 if (mode) {
    304                     memset(aaExpand, aa, count);
    305                     mode->xferA8(device, span, count, aaExpand);
    306                 } else {
    307                     for (int i = count - 1; i >= 0; --i) {
    308                         device[i] = aa_blend8(span[i], device[i], aa);
    309                     }
    310                 }
    311             }
    312         }
    313         device += count;
    314         runs += count;
    315         antialias += count;
    316         x += count;
    317     }
    318 }
    319 
    320 void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    321     if (mask.fFormat == SkMask::kBW_Format) {
    322         this->INHERITED::blitMask(mask, clip);
    323         return;
    324     }
    325 
    326     int x = clip.fLeft;
    327     int y = clip.fTop;
    328     int width = clip.width();
    329     int height = clip.height();
    330     uint8_t* device = fDevice.getAddr8(x, y);
    331     const uint8_t* alpha = mask.getAddr8(x, y);
    332 
    333     SkPMColor*  span = fBuffer;
    334 
    335     while (--height >= 0) {
    336         fShader->shadeSpan(x, y, span, width);
    337         if (fXfermode) {
    338             fXfermode->xferA8(device, span, width, alpha);
    339         }
    340 
    341         y += 1;
    342         device += fDevice.rowBytes();
    343         alpha += mask.fRowBytes;
    344     }
    345 }
    346