LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkBlitter_4444.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 237 0 0.0 %
Date: 2012-06-02 Functions: 19 0 0.0 %

       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 "SkDither.h"
      13                 : #include "SkShader.h"
      14                 : #include "SkTemplatesPriv.h"
      15                 : #include "SkUtils.h"
      16                 : #include "SkXfermode.h"
      17                 : 
      18               0 : static inline SkPMColor SkBlendARGB4444(SkPMColor16 src, SkPMColor16 dst,
      19                 :                                         U8CPU aa) {
      20               0 :     SkASSERT((unsigned)aa <= 255);
      21                 : 
      22               0 :     unsigned src_scale = SkAlpha255To256(aa) >> 4;
      23               0 :     unsigned dst_scale = SkAlpha15To16(15 - SkAlphaMul4(SkGetPackedA4444(src), src_scale));
      24                 : 
      25               0 :     uint32_t src32 = SkExpand_4444(src) * src_scale;
      26               0 :     uint32_t dst32 = SkExpand_4444(dst) * dst_scale;
      27               0 :     return SkCompact_4444((src32 + dst32) >> 4);
      28                 : }
      29                 : 
      30                 : ///////////////////////////////////////////////////////////////////////////////
      31                 : 
      32               0 : class SkARGB4444_Blitter : public SkRasterBlitter {
      33                 : public:
      34                 :     SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint);
      35                 :     virtual void blitH(int x, int y, int width);
      36                 :     virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
      37                 :                            const int16_t runs[]);
      38                 :     virtual void blitV(int x, int y, int height, SkAlpha alpha);
      39                 :     virtual void blitRect(int x, int y, int width, int height);
      40                 :     virtual void blitMask(const SkMask&, const SkIRect&);
      41                 :     virtual const SkBitmap* justAnOpaqueColor(uint32_t*);
      42                 : 
      43                 : protected:
      44                 :     SkPMColor16 fPMColor16, fPMColor16Other;
      45                 :     SkPMColor16 fRawColor16, fRawColor16Other;
      46                 :     uint8_t     fScale16;
      47                 : 
      48                 : private:
      49                 :     // illegal
      50                 :     SkARGB4444_Blitter& operator=(const SkARGB4444_Blitter&);
      51                 : 
      52                 :     typedef SkRasterBlitter INHERITED;
      53                 : };
      54                 : 
      55                 : 
      56               0 : SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device,
      57               0 :                                    const SkPaint& paint) : INHERITED(device) {
      58                 :     // cache premultiplied versions in 4444
      59               0 :     SkPMColor c = SkPreMultiplyColor(paint.getColor());
      60               0 :     fPMColor16 = SkPixel32ToPixel4444(c);
      61               0 :     if (paint.isDither()) {
      62               0 :         fPMColor16Other = SkDitherPixel32To4444(c);
      63                 :     } else {
      64               0 :         fPMColor16Other = fPMColor16;
      65                 :     }
      66                 : 
      67                 :     // cache raw versions in 4444
      68                 :     fRawColor16 = SkPackARGB4444(0xFF >> 4, SkColorGetR(c) >> 4,
      69               0 :                                  SkColorGetG(c) >> 4, SkColorGetB(c) >> 4);
      70               0 :     if (paint.isDither()) {
      71                 :         fRawColor16Other = SkDitherARGB32To4444(0xFF, SkColorGetR(c),
      72               0 :                                                 SkColorGetG(c), SkColorGetB(c));
      73                 :     } else {
      74               0 :         fRawColor16Other = fRawColor16;
      75                 :     }
      76                 : 
      77               0 :     fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other));
      78               0 :     if (16 == fScale16) {
      79                 :         // force the original to also be opaque
      80               0 :         fPMColor16 |= (0xF << SK_A4444_SHIFT);
      81                 :     }
      82               0 : }
      83                 : 
      84               0 : const SkBitmap* SkARGB4444_Blitter::justAnOpaqueColor(uint32_t* value) {
      85               0 :     if (16 == fScale16) {
      86               0 :         *value = fPMColor16;
      87               0 :         return &fDevice;
      88                 :     }
      89               0 :     return NULL;
      90                 : }
      91                 : 
      92               0 : static void src_over_4444(SkPMColor16 dst[], SkPMColor16 color,
      93                 :                           SkPMColor16 other, unsigned invScale, int count) {
      94               0 :     int twice = count >> 1;
      95               0 :     while (--twice >= 0) {
      96               0 :         *dst = color + SkAlphaMulQ4(*dst, invScale);
      97               0 :         dst++;
      98               0 :         *dst = other + SkAlphaMulQ4(*dst, invScale);
      99               0 :         dst++;
     100                 :     }
     101               0 :     if (count & 1) {
     102               0 :         *dst = color + SkAlphaMulQ4(*dst, invScale);
     103                 :     }
     104               0 : }
     105                 : 
     106               0 : static inline uint32_t SkExpand_4444_Replicate(SkPMColor16 c) {
     107               0 :     uint32_t c32 = SkExpand_4444(c);
     108               0 :     return c32 | (c32 << 4);
     109                 : }
     110                 : 
     111               0 : static void src_over_4444x(SkPMColor16 dst[], uint32_t color,
     112                 :                            uint32_t other, unsigned invScale, int count) {
     113               0 :     int twice = count >> 1;
     114                 :     uint32_t tmp;
     115               0 :     while (--twice >= 0) {
     116               0 :         tmp = SkExpand_4444(*dst) * invScale;
     117               0 :         *dst++ = SkCompact_4444((color + tmp) >> 4);
     118               0 :         tmp = SkExpand_4444(*dst) * invScale;
     119               0 :         *dst++ = SkCompact_4444((other + tmp) >> 4);
     120                 :     }
     121               0 :     if (count & 1) {
     122               0 :         tmp = SkExpand_4444(*dst) * invScale;
     123               0 :         *dst = SkCompact_4444((color + tmp) >> 4);
     124                 :     }
     125               0 : }
     126                 : 
     127               0 : void SkARGB4444_Blitter::blitH(int x, int y, int width) {
     128               0 :     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
     129                 : 
     130               0 :     if (0 == fScale16) {
     131               0 :         return;
     132                 :     }
     133                 : 
     134               0 :     SkPMColor16* device = fDevice.getAddr16(x, y);
     135               0 :     SkPMColor16  color = fPMColor16;
     136               0 :     SkPMColor16  other = fPMColor16Other;
     137                 : 
     138               0 :     if ((x ^ y) & 1) {
     139               0 :         SkTSwap<SkPMColor16>(color, other);
     140                 :     }
     141                 : 
     142               0 :     if (16 == fScale16) {
     143               0 :         sk_dither_memset16(device, color, other, width);
     144                 :     } else {
     145                 :         src_over_4444x(device, SkExpand_4444_Replicate(color),
     146                 :                        SkExpand_4444_Replicate(other),
     147               0 :                        16 - fScale16, width);
     148                 :     }
     149                 : }
     150                 : 
     151               0 : void SkARGB4444_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
     152               0 :     if (0 == alpha || 0 == fScale16) {
     153               0 :         return;
     154                 :     }
     155                 : 
     156               0 :     SkPMColor16* device = fDevice.getAddr16(x, y);
     157               0 :     SkPMColor16  color = fPMColor16;
     158               0 :     SkPMColor16  other = fPMColor16Other;
     159               0 :     unsigned     rb = fDevice.rowBytes();
     160                 : 
     161               0 :     if ((x ^ y) & 1) {
     162               0 :         SkTSwap<SkPMColor16>(color, other);
     163                 :     }
     164                 : 
     165               0 :     if (16 == fScale16 && 255 == alpha) {
     166               0 :         while (--height >= 0) {
     167               0 :             *device = color;
     168               0 :             device = (SkPMColor16*)((char*)device + rb);
     169               0 :             SkTSwap<SkPMColor16>(color, other);
     170                 :         }
     171                 :     } else {
     172               0 :         unsigned alphaScale = SkAlpha255To256(alpha);
     173               0 :         uint32_t c32 = SkExpand_4444(color) * (alphaScale >> 4);
     174                 :         // need to normalize the low nibble of each expanded component
     175                 :         // so we don't overflow the add with d32
     176               0 :         c32 = SkCompact_4444(c32 >> 4);
     177               0 :         unsigned invScale = 16 - SkAlpha15To16(SkGetPackedA4444(c32));
     178                 :         // now re-expand and replicate
     179               0 :         c32 = SkExpand_4444_Replicate(c32);
     180                 : 
     181               0 :         while (--height >= 0) {
     182               0 :             uint32_t d32 = SkExpand_4444(*device) * invScale;
     183               0 :             *device = SkCompact_4444((c32 + d32) >> 4);
     184               0 :             device = (SkPMColor16*)((char*)device + rb);
     185                 :         }
     186                 :     }
     187                 : }
     188                 : 
     189               0 : void SkARGB4444_Blitter::blitRect(int x, int y, int width, int height) {
     190               0 :     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() &&
     191                 :              y + height <= fDevice.height());
     192                 : 
     193               0 :     if (0 == fScale16) {
     194               0 :         return;
     195                 :     }
     196                 : 
     197               0 :     SkPMColor16* device = fDevice.getAddr16(x, y);
     198               0 :     SkPMColor16  color = fPMColor16;
     199               0 :     SkPMColor16  other = fPMColor16Other;
     200                 : 
     201               0 :     if ((x ^ y) & 1) {
     202               0 :         SkTSwap<SkPMColor16>(color, other);
     203                 :     }
     204                 : 
     205               0 :     if (16 == fScale16) {
     206               0 :         while (--height >= 0) {
     207               0 :             sk_dither_memset16(device, color, other, width);
     208               0 :             device = (SkPMColor16*)((char*)device + fDevice.rowBytes());
     209               0 :             SkTSwap<SkPMColor16>(color, other);
     210                 :         }
     211                 :     } else {
     212               0 :         unsigned invScale = 16 - fScale16;
     213                 : 
     214               0 :         uint32_t c32 = SkExpand_4444_Replicate(color);
     215               0 :         uint32_t o32 = SkExpand_4444_Replicate(other);
     216               0 :         while (--height >= 0) {
     217               0 :             src_over_4444x(device, c32, o32, invScale, width);
     218               0 :             device = (SkPMColor16*)((char*)device + fDevice.rowBytes());
     219               0 :             SkTSwap<uint32_t>(c32, o32);
     220                 :         }
     221                 :     }
     222                 : }
     223                 : 
     224               0 : void SkARGB4444_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
     225                 :                                    const int16_t runs[]) {
     226               0 :     if (0 == fScale16) {
     227               0 :         return;
     228                 :     }
     229                 : 
     230               0 :     SkPMColor16* device = fDevice.getAddr16(x, y);
     231               0 :     SkPMColor16  color = fPMColor16;
     232               0 :     SkPMColor16  other = fPMColor16Other;
     233                 : 
     234               0 :     if ((x ^ y) & 1) {
     235               0 :         SkTSwap<SkPMColor16>(color, other);
     236                 :     }
     237                 : 
     238               0 :     for (;;) {
     239               0 :         int count = runs[0];
     240               0 :         SkASSERT(count >= 0);
     241               0 :         if (count <= 0) {
     242               0 :             return;
     243                 :         }
     244                 : 
     245               0 :         unsigned aa = antialias[0];
     246               0 :         if (aa) {
     247               0 :             if (0xFF == aa) {
     248               0 :                 if (16 == fScale16) {
     249               0 :                     sk_dither_memset16(device, color, other, count);
     250                 :                 } else {
     251               0 :                     src_over_4444(device, color, other, 16 - fScale16, count);
     252                 :                 }
     253                 :             } else {
     254                 :                 // todo: respect dithering
     255               0 :                 aa = SkAlpha255To256(aa);   // FIX
     256               0 :                 SkPMColor16 src = SkAlphaMulQ4(color, aa >> 4);
     257               0 :                 unsigned dst_scale = SkAlpha15To16(15 - SkGetPackedA4444(src)); // FIX
     258               0 :                 int n = count;
     259               0 :                 do {
     260               0 :                     --n;
     261               0 :                     device[n] = src + SkAlphaMulQ4(device[n], dst_scale);
     262                 :                 } while (n > 0);
     263                 :             }
     264                 :         }
     265                 : 
     266               0 :         runs += count;
     267               0 :         antialias += count;
     268               0 :         device += count;
     269                 : 
     270               0 :         if (count & 1) {
     271               0 :             SkTSwap<SkPMColor16>(color, other);
     272                 :         }
     273                 :     }
     274                 : }
     275                 : 
     276                 : ///////////////////////////////////////////////////////////////////////////////
     277                 : 
     278                 : #define solid_8_pixels(mask, dst, color)    \
     279                 :     do {                                    \
     280                 :         if (mask & 0x80) dst[0] = color;    \
     281                 :         if (mask & 0x40) dst[1] = color;    \
     282                 :         if (mask & 0x20) dst[2] = color;    \
     283                 :         if (mask & 0x10) dst[3] = color;    \
     284                 :         if (mask & 0x08) dst[4] = color;    \
     285                 :         if (mask & 0x04) dst[5] = color;    \
     286                 :         if (mask & 0x02) dst[6] = color;    \
     287                 :         if (mask & 0x01) dst[7] = color;    \
     288                 :     } while (0)
     289                 : 
     290                 : #define SK_BLITBWMASK_NAME                  SkARGB4444_BlitBW
     291                 : #define SK_BLITBWMASK_ARGS                  , SkPMColor16 color
     292                 : #define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
     293                 : #define SK_BLITBWMASK_GETADDR               getAddr16
     294                 : #define SK_BLITBWMASK_DEVTYPE               uint16_t
     295                 : #include "SkBlitBWMaskTemplate.h"
     296                 : 
     297                 : #define blend_8_pixels(mask, dst, sc, dst_scale)                             \
     298                 :     do {                                                                     \
     299                 :         if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ4(dst[0], dst_scale); }  \
     300                 :         if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ4(dst[1], dst_scale); }  \
     301                 :         if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ4(dst[2], dst_scale); }  \
     302                 :         if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ4(dst[3], dst_scale); }  \
     303                 :         if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ4(dst[4], dst_scale); }  \
     304                 :         if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ4(dst[5], dst_scale); }  \
     305                 :         if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ4(dst[6], dst_scale); }  \
     306                 :         if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ4(dst[7], dst_scale); }  \
     307                 :     } while (0)
     308                 : 
     309                 : #define SK_BLITBWMASK_NAME                  SkARGB4444_BlendBW
     310                 : #define SK_BLITBWMASK_ARGS                  , uint16_t sc, unsigned dst_scale
     311                 : #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sc, dst_scale)
     312                 : #define SK_BLITBWMASK_GETADDR               getAddr16
     313                 : #define SK_BLITBWMASK_DEVTYPE               uint16_t
     314                 : #include "SkBlitBWMaskTemplate.h"
     315                 : 
     316               0 : void SkARGB4444_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
     317               0 :     SkASSERT(mask.fBounds.contains(clip));
     318                 : 
     319               0 :     if (0 == fScale16) {
     320               0 :         return;
     321                 :     }
     322                 : 
     323               0 :     if (mask.fFormat == SkMask::kBW_Format) {
     324               0 :         if (16 == fScale16) {
     325               0 :             SkARGB4444_BlitBW(fDevice, mask, clip, fPMColor16);
     326                 :         } else {
     327               0 :             SkARGB4444_BlendBW(fDevice, mask, clip, fPMColor16, 16 - fScale16);
     328                 :         }
     329               0 :         return;
     330                 :     }
     331                 : 
     332               0 :     int x = clip.fLeft;
     333               0 :     int y = clip.fTop;
     334               0 :     int width = clip.width();
     335               0 :     int height = clip.height();
     336                 : 
     337               0 :     SkPMColor16*    device = fDevice.getAddr16(x, y);
     338               0 :     const uint8_t*  alpha = mask.getAddr8(x, y);
     339               0 :     SkPMColor16     srcColor = fPMColor16;
     340               0 :     unsigned        devRB = fDevice.rowBytes() - (width << 1);
     341               0 :     unsigned        maskRB = mask.fRowBytes - width;
     342                 : 
     343               0 :     do {
     344               0 :         int w = width;
     345               0 :         do {
     346               0 :             unsigned aa = *alpha++;
     347               0 :             *device = SkBlendARGB4444(srcColor, *device, aa);
     348               0 :             device += 1;
     349                 :         } while (--w != 0);
     350               0 :         device = (SkPMColor16*)((char*)device + devRB);
     351               0 :         alpha += maskRB;
     352                 :     } while (--height != 0);
     353                 : }
     354                 : 
     355                 : ///////////////////////////////////////////////////////////////////////////////
     356                 : 
     357                 : class SkARGB4444_Shader_Blitter : public SkShaderBlitter {
     358                 :     SkXfermode*     fXfermode;
     359                 :     SkBlitRow::Proc fOpaqueProc;
     360                 :     SkBlitRow::Proc fAlphaProc;
     361                 :     SkPMColor*      fBuffer;
     362                 :     uint8_t*        fAAExpand;
     363                 : public:
     364                 : 
     365               0 : SkARGB4444_Shader_Blitter(const SkBitmap& device, const SkPaint& paint)
     366               0 :         : INHERITED(device, paint) {
     367               0 :     const int width = device.width();
     368               0 :     fBuffer = (SkPMColor*)sk_malloc_throw(width * sizeof(SkPMColor) + width);
     369               0 :     fAAExpand = (uint8_t*)(fBuffer + width);
     370                 : 
     371               0 :     fXfermode = paint.getXfermode();
     372               0 :     SkSafeRef(fXfermode);
     373                 : 
     374               0 :     unsigned flags = 0;
     375               0 :     if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
     376               0 :         flags |= SkBlitRow::kSrcPixelAlpha_Flag;
     377                 :     }
     378               0 :     if (paint.isDither()) {
     379               0 :         flags |= SkBlitRow::kDither_Flag;
     380                 :     }
     381               0 :     fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kARGB_4444_Config);
     382                 :     fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
     383               0 :                                     SkBitmap::kARGB_4444_Config);
     384               0 : }
     385                 : 
     386               0 : virtual ~SkARGB4444_Shader_Blitter() {
     387               0 :     SkSafeUnref(fXfermode);
     388               0 :     sk_free(fBuffer);
     389               0 : }
     390                 : 
     391               0 : virtual void blitH(int x, int y, int width) {
     392               0 :     SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
     393                 : 
     394               0 :     SkPMColor16* device = fDevice.getAddr16(x, y);
     395               0 :     SkPMColor*   span = fBuffer;
     396                 : 
     397               0 :     fShader->shadeSpan(x, y, span, width);
     398               0 :     if (fXfermode) {
     399               0 :         fXfermode->xfer4444(device, span, width, NULL);
     400                 :     } else {
     401               0 :         fOpaqueProc(device, span, width, 0xFF, x, y);
     402                 :     }
     403               0 : }
     404                 : 
     405               0 : virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
     406                 :                        const int16_t runs[]) {
     407               0 :     SkPMColor* SK_RESTRICT span = fBuffer;
     408               0 :     uint8_t* SK_RESTRICT aaExpand = fAAExpand;
     409               0 :     SkPMColor16* device = fDevice.getAddr16(x, y);
     410               0 :     SkShader*    shader = fShader;
     411               0 :     SkXfermode*  xfer = fXfermode;
     412                 : 
     413               0 :     if (NULL != xfer) {
     414               0 :         for (;;) {
     415               0 :             int count = *runs;
     416               0 :             if (count <= 0) {
     417                 :                 break;
     418                 :             }
     419               0 :             int aa = *antialias;
     420               0 :             if (aa) {
     421               0 :                 shader->shadeSpan(x, y, span, count);
     422               0 :                 if (255 == aa) {
     423               0 :                     xfer->xfer4444(device, span, count, NULL);
     424                 :                 } else {
     425               0 :                     const uint8_t* aaBuffer = antialias;
     426               0 :                     if (count > 1) {
     427               0 :                         memset(aaExpand, aa, count);
     428               0 :                         aaBuffer = aaExpand;
     429                 :                     }
     430               0 :                     xfer->xfer4444(device, span, count, aaBuffer);
     431                 :                 }
     432                 :             }
     433               0 :             device += count;
     434               0 :             runs += count;
     435               0 :             antialias += count;
     436               0 :             x += count;
     437                 :         }
     438                 :     } else {    // no xfermode
     439               0 :         for (;;) {
     440               0 :             int count = *runs;
     441               0 :             if (count <= 0) {
     442               0 :                 break;
     443                 :             }
     444               0 :             int aa = *antialias;
     445               0 :             if (aa) {
     446               0 :                 fShader->shadeSpan(x, y, span, count);
     447               0 :                 if (255 == aa) {
     448               0 :                     fOpaqueProc(device, span, count, aa, x, y);
     449                 :                 } else {
     450               0 :                     fAlphaProc(device, span, count, aa, x, y);
     451                 :                 }
     452                 :             }
     453               0 :             device += count;
     454               0 :             runs += count;
     455               0 :             antialias += count;
     456               0 :             x += count;
     457                 :         }
     458                 :     }
     459               0 : }
     460                 : 
     461                 : private:
     462                 :     typedef SkShaderBlitter INHERITED;
     463                 : };
     464                 : 
     465                 : ///////////////////////////////////////////////////////////////////////////////
     466                 : ///////////////////////////////////////////////////////////////////////////////
     467                 : 
     468               0 : SkBlitter* SkBlitter_ChooseD4444(const SkBitmap& device,
     469                 :                                  const SkPaint& paint,
     470                 :                                  void* storage, size_t storageSize)
     471                 : {
     472                 :     SkBlitter* blitter;
     473                 : 
     474               0 :     if (paint.getShader()) {
     475               0 :         SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Shader_Blitter, storage, storageSize, (device, paint));
     476                 :     } else {
     477               0 :         SK_PLACEMENT_NEW_ARGS(blitter, SkARGB4444_Blitter, storage, storageSize, (device, paint));
     478                 :     }
     479               0 :     return blitter;
     480                 : }
     481                 : 

Generated by: LCOV version 1.7