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