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