LCOV - code coverage report
Current view: directory - gfx/skia/include/core - SkColorPriv.h (source / functions) Found Hit Coverage
Test: app.info Lines: 203 0 0.0 %
Date: 2012-06-02 Functions: 46 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                 : #ifndef SkColorPriv_DEFINED
      11                 : #define SkColorPriv_DEFINED
      12                 : 
      13                 : // turn this own for extra debug checking when blending onto 565
      14                 : #ifdef SK_DEBUG
      15                 :     #define CHECK_FOR_565_OVERFLOW
      16                 : #endif
      17                 : 
      18                 : #include "SkColor.h"
      19                 : #include "SkMath.h"
      20                 : 
      21                 : /** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
      22                 :     byte into a scale value, so that we can say scale * value >> 8 instead of
      23                 :     alpha * value / 255.
      24                 : 
      25                 :     In debugging, asserts that alpha is 0..255
      26                 : */
      27               0 : static inline unsigned SkAlpha255To256(U8CPU alpha) {
      28               0 :     SkASSERT(SkToU8(alpha) == alpha);
      29                 :     // this one assues that blending on top of an opaque dst keeps it that way
      30                 :     // even though it is less accurate than a+(a>>7) for non-opaque dsts
      31               0 :     return alpha + 1;
      32                 : }
      33                 : 
      34                 : /** Multiplify value by 0..256, and shift the result down 8
      35                 :     (i.e. return (value * alpha256) >> 8)
      36                 :  */
      37                 : #define SkAlphaMul(value, alpha256)     (SkMulS16(value, alpha256) >> 8)
      38                 : 
      39                 : //  The caller may want negative values, so keep all params signed (int)
      40                 : //  so we don't accidentally slip into unsigned math and lose the sign
      41                 : //  extension when we shift (in SkAlphaMul)
      42               0 : static inline int SkAlphaBlend(int src, int dst, int scale256) {
      43               0 :     SkASSERT((unsigned)scale256 <= 256);
      44               0 :     return dst + SkAlphaMul(src - dst, scale256);
      45                 : }
      46                 : 
      47                 : /**
      48                 :  *  Returns (src * alpha + dst * (255 - alpha)) / 255
      49                 :  *
      50                 :  *  This is more accurate than SkAlphaBlend, but slightly slower
      51                 :  */
      52                 : static inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) {
      53                 :     SkASSERT((int16_t)src == src);
      54                 :     SkASSERT((int16_t)dst == dst);
      55                 :     SkASSERT((uint8_t)alpha == alpha);
      56                 :     
      57                 :     int prod = SkMulS16(src - dst, alpha) + 128;
      58                 :     prod = (prod + (prod >> 8)) >> 8;
      59                 :     return dst + prod;
      60                 : }
      61                 : 
      62                 : #define SK_R16_BITS     5
      63                 : #define SK_G16_BITS     6
      64                 : #define SK_B16_BITS     5
      65                 : 
      66                 : #define SK_R16_SHIFT    (SK_B16_BITS + SK_G16_BITS)
      67                 : #define SK_G16_SHIFT    (SK_B16_BITS)
      68                 : #define SK_B16_SHIFT    0
      69                 : 
      70                 : #define SK_R16_MASK     ((1 << SK_R16_BITS) - 1)
      71                 : #define SK_G16_MASK     ((1 << SK_G16_BITS) - 1)
      72                 : #define SK_B16_MASK     ((1 << SK_B16_BITS) - 1)
      73                 : 
      74                 : #define SkGetPackedR16(color)   (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
      75                 : #define SkGetPackedG16(color)   (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
      76                 : #define SkGetPackedB16(color)   (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
      77                 : 
      78                 : #define SkR16Assert(r)  SkASSERT((unsigned)(r) <= SK_R16_MASK)
      79                 : #define SkG16Assert(g)  SkASSERT((unsigned)(g) <= SK_G16_MASK)
      80                 : #define SkB16Assert(b)  SkASSERT((unsigned)(b) <= SK_B16_MASK)
      81                 : 
      82               0 : static inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
      83               0 :     SkASSERT(r <= SK_R16_MASK);
      84               0 :     SkASSERT(g <= SK_G16_MASK);
      85               0 :     SkASSERT(b <= SK_B16_MASK);
      86                 : 
      87               0 :     return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
      88                 : }
      89                 : 
      90                 : #define SK_R16_MASK_IN_PLACE        (SK_R16_MASK << SK_R16_SHIFT)
      91                 : #define SK_G16_MASK_IN_PLACE        (SK_G16_MASK << SK_G16_SHIFT)
      92                 : #define SK_B16_MASK_IN_PLACE        (SK_B16_MASK << SK_B16_SHIFT)
      93                 : 
      94                 : /** Expand the 16bit color into a 32bit value that can be scaled all at once
      95                 :     by a value up to 32. Used in conjunction with SkCompact_rgb_16.
      96                 : */
      97               0 : static inline uint32_t SkExpand_rgb_16(U16CPU c) {
      98               0 :     SkASSERT(c == (uint16_t)c);
      99                 : 
     100               0 :     return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
     101                 : }
     102                 : 
     103                 : /** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit
     104                 :     color value. The computation yields only 16bits of valid data, but we claim
     105                 :     to return 32bits, so that the compiler won't generate extra instructions to
     106                 :     "clean" the top 16bits. However, the top 16 can contain garbage, so it is
     107                 :     up to the caller to safely ignore them.
     108                 : */
     109               0 : static inline U16CPU SkCompact_rgb_16(uint32_t c) {
     110               0 :     return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
     111                 : }
     112                 : 
     113                 : /** Scale the 16bit color value by the 0..256 scale parameter.
     114                 :     The computation yields only 16bits of valid data, but we claim
     115                 :     to return 32bits, so that the compiler won't generate extra instructions to
     116                 :     "clean" the top 16bits.
     117                 : */
     118               0 : static inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
     119               0 :     return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
     120                 : }
     121                 : 
     122                 : // this helper explicitly returns a clean 16bit value (but slower)
     123                 : #define SkAlphaMulRGB16_ToU16(c, s)  (uint16_t)SkAlphaMulRGB16(c, s)
     124                 : 
     125                 : /** Blend src and dst 16bit colors by the 0..256 scale parameter.
     126                 :     The computation yields only 16bits of valid data, but we claim
     127                 :     to return 32bits, so that the compiler won't generate extra instructions to
     128                 :     "clean" the top 16bits.
     129                 : */
     130               0 : static inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
     131               0 :     SkASSERT((unsigned)srcScale <= 256);
     132                 : 
     133               0 :     srcScale >>= 3;
     134                 : 
     135               0 :     uint32_t src32 = SkExpand_rgb_16(src);
     136               0 :     uint32_t dst32 = SkExpand_rgb_16(dst);
     137               0 :     return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
     138                 : }
     139                 : 
     140               0 : static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
     141                 :                                 int srcScale, int count) {
     142               0 :     SkASSERT(count > 0);
     143               0 :     SkASSERT((unsigned)srcScale <= 256);
     144                 : 
     145               0 :     srcScale >>= 3;
     146                 : 
     147               0 :     do {
     148               0 :         uint32_t src32 = SkExpand_rgb_16(*src++);
     149               0 :         uint32_t dst32 = SkExpand_rgb_16(*dst);
     150               0 :         *dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
     151                 :     } while (--count > 0);
     152               0 : }
     153                 : 
     154                 : #ifdef SK_DEBUG
     155                 :     static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
     156                 :         SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
     157                 :         SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
     158                 :         SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
     159                 : 
     160                 :         return a + b;
     161                 :     }
     162                 : #else
     163                 :     #define SkRGB16Add(a, b)  ((a) + (b))
     164                 : #endif
     165                 : 
     166                 : ///////////////////////////////////////////////////////////////////////////////
     167                 : 
     168                 : #define SK_A32_BITS     8
     169                 : #define SK_R32_BITS     8
     170                 : #define SK_G32_BITS     8
     171                 : #define SK_B32_BITS     8
     172                 : 
     173                 : #define SK_A32_MASK     ((1 << SK_A32_BITS) - 1)
     174                 : #define SK_R32_MASK     ((1 << SK_R32_BITS) - 1)
     175                 : #define SK_G32_MASK     ((1 << SK_G32_BITS) - 1)
     176                 : #define SK_B32_MASK     ((1 << SK_B32_BITS) - 1)
     177                 : 
     178                 : #define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
     179                 : #define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
     180                 : #define SkGetPackedG32(packed)      ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
     181                 : #define SkGetPackedB32(packed)      ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
     182                 : 
     183                 : #define SkA32Assert(a)  SkASSERT((unsigned)(a) <= SK_A32_MASK)
     184                 : #define SkR32Assert(r)  SkASSERT((unsigned)(r) <= SK_R32_MASK)
     185                 : #define SkG32Assert(g)  SkASSERT((unsigned)(g) <= SK_G32_MASK)
     186                 : #define SkB32Assert(b)  SkASSERT((unsigned)(b) <= SK_B32_MASK)
     187                 : 
     188                 : #ifdef SK_DEBUG
     189               0 :     static inline void SkPMColorAssert(SkPMColor c) {
     190               0 :         unsigned a = SkGetPackedA32(c);
     191               0 :         unsigned r = SkGetPackedR32(c);
     192               0 :         unsigned g = SkGetPackedG32(c);
     193               0 :         unsigned b = SkGetPackedB32(c);
     194                 : 
     195               0 :         SkA32Assert(a);
     196               0 :         SkASSERT(r <= a);
     197               0 :         SkASSERT(g <= a);
     198               0 :         SkASSERT(b <= a);
     199               0 :     }
     200                 : #else
     201                 :     #define SkPMColorAssert(c)
     202                 : #endif
     203                 : 
     204                 : /**
     205                 :  *  Pack the components into a SkPMColor, checking (in the debug version) that
     206                 :  *  the components are 0..255, and are already premultiplied (i.e. alpha >= color)
     207                 :  */
     208               0 : static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
     209               0 :     SkA32Assert(a);
     210               0 :     SkASSERT(r <= a);
     211               0 :     SkASSERT(g <= a);
     212               0 :     SkASSERT(b <= a);
     213                 : 
     214                 :     return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
     215               0 :            (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
     216                 : }
     217                 : 
     218                 : /**
     219                 :  *  Same as SkPackARGB32, but this version guarantees to not check that the
     220                 :  *  values are premultiplied in the debug version.
     221                 :  */
     222               0 : static inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
     223                 :     return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
     224               0 :            (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
     225                 : }
     226                 : 
     227                 : static inline
     228               0 : SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
     229               0 :     SkA32Assert(a);
     230               0 :     SkA32Assert(r);
     231               0 :     SkA32Assert(g);
     232               0 :     SkA32Assert(b);
     233                 : 
     234               0 :     if (a != 255) {
     235               0 :         r = SkMulDiv255Round(r, a);
     236               0 :         g = SkMulDiv255Round(g, a);
     237               0 :         b = SkMulDiv255Round(b, a);
     238                 :     }
     239               0 :     return SkPackARGB32(a, r, g, b);
     240                 : }
     241                 : 
     242                 : SK_API extern const uint32_t gMask_00FF00FF;
     243                 : 
     244               0 : static inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
     245               0 :     uint32_t mask = gMask_00FF00FF;
     246                 : //    uint32_t mask = 0xFF00FF;
     247                 : 
     248               0 :     uint32_t rb = ((c & mask) * scale) >> 8;
     249               0 :     uint32_t ag = ((c >> 8) & mask) * scale;
     250               0 :     return (rb & mask) | (ag & ~mask);
     251                 : }
     252                 : 
     253               0 : static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
     254               0 :     return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
     255                 : }
     256                 : 
     257               0 : static inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
     258               0 :     SkASSERT((unsigned)aa <= 255);
     259                 : 
     260               0 :     unsigned src_scale = SkAlpha255To256(aa);
     261               0 :     unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale));
     262                 : 
     263               0 :     return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale);
     264                 : }
     265                 : 
     266                 : ////////////////////////////////////////////////////////////////////////////////////////////
     267                 : // Convert a 32bit pixel to a 16bit pixel (no dither)
     268                 : 
     269                 : #define SkR32ToR16_MACRO(r)   ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
     270                 : #define SkG32ToG16_MACRO(g)   ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
     271                 : #define SkB32ToB16_MACRO(b)   ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
     272                 : 
     273                 : #ifdef SK_DEBUG
     274               0 :     static inline unsigned SkR32ToR16(unsigned r) {
     275               0 :         SkR32Assert(r);
     276               0 :         return SkR32ToR16_MACRO(r);
     277                 :     }
     278               0 :     static inline unsigned SkG32ToG16(unsigned g) {
     279               0 :         SkG32Assert(g);
     280               0 :         return SkG32ToG16_MACRO(g);
     281                 :     }
     282               0 :     static inline unsigned SkB32ToB16(unsigned b) {
     283               0 :         SkB32Assert(b);
     284               0 :         return SkB32ToB16_MACRO(b);
     285                 :     }
     286                 : #else
     287                 :     #define SkR32ToR16(r)   SkR32ToR16_MACRO(r)
     288                 :     #define SkG32ToG16(g)   SkG32ToG16_MACRO(g)
     289                 :     #define SkB32ToB16(b)   SkB32ToB16_MACRO(b)
     290                 : #endif
     291                 : 
     292                 : #define SkPacked32ToR16(c)  (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
     293                 : #define SkPacked32ToG16(c)  (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
     294                 : #define SkPacked32ToB16(c)  (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
     295                 : 
     296               0 : static inline U16CPU SkPixel32ToPixel16(SkPMColor c) {
     297               0 :     unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
     298               0 :     unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
     299               0 :     unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
     300               0 :     return r | g | b;
     301                 : }
     302                 : 
     303               0 : static inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
     304               0 :     return  (SkR32ToR16(r) << SK_R16_SHIFT) |
     305               0 :             (SkG32ToG16(g) << SK_G16_SHIFT) |
     306               0 :             (SkB32ToB16(b) << SK_B16_SHIFT);
     307                 : }
     308                 : 
     309                 : #define SkPixel32ToPixel16_ToU16(src)   SkToU16(SkPixel32ToPixel16(src))
     310                 : 
     311                 : /////////////////////////////////////////////////////////////////////////////////////////
     312                 : // Fast dither from 32->16
     313                 : 
     314                 : #define SkShouldDitherXY(x, y)  (((x) ^ (y)) & 1)
     315                 : 
     316               0 : static inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
     317               0 :     r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
     318               0 :     g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
     319               0 :     b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
     320                 : 
     321               0 :     return SkPackRGB16(r, g, b);
     322                 : }
     323                 : 
     324                 : static inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) {
     325                 :     return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
     326                 : }
     327                 : 
     328                 : /*  Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
     329                 :     It is now suitable for combining with a scaled expanded_rgb_16 color
     330                 :     as in SkSrcOver32To16().
     331                 :     We must do this 565 high-bit replication, in order for the subsequent add
     332                 :     to saturate properly (and not overflow). If we take the 8 bits as is, it is
     333                 :     possible to overflow.
     334                 : */
     335                 : static inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) {
     336                 :     unsigned sr = SkPacked32ToR16(c);
     337                 :     unsigned sg = SkPacked32ToG16(c);
     338                 :     unsigned sb = SkPacked32ToB16(c);
     339                 : 
     340                 :     sr = (sr << 5) | sr;
     341                 :     sg = (sg << 5) | (sg >> 1);
     342                 :     sb = (sb << 5) | sb;
     343                 :     return (sr << 11) | (sg << 21) | (sb << 0);
     344                 : }
     345                 : 
     346                 : /*  SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
     347                 :     (with dirt in the high 16bits, so caller beware).
     348                 : */
     349               0 : static inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
     350               0 :     unsigned sr = SkGetPackedR32(src);
     351               0 :     unsigned sg = SkGetPackedG32(src);
     352               0 :     unsigned sb = SkGetPackedB32(src);
     353                 : 
     354               0 :     unsigned dr = SkGetPackedR16(dst);
     355               0 :     unsigned dg = SkGetPackedG16(dst);
     356               0 :     unsigned db = SkGetPackedB16(dst);
     357                 : 
     358               0 :     unsigned isa = 255 - SkGetPackedA32(src);
     359                 : 
     360               0 :     dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
     361               0 :     dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
     362               0 :     db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
     363                 : 
     364               0 :     return SkPackRGB16(dr, dg, db);
     365                 : }
     366                 : 
     367                 : ////////////////////////////////////////////////////////////////////////////////////////////
     368                 : // Convert a 16bit pixel to a 32bit pixel
     369                 : 
     370               0 : static inline unsigned SkR16ToR32(unsigned r) {
     371               0 :     return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
     372                 : }
     373                 : 
     374               0 : static inline unsigned SkG16ToG32(unsigned g) {
     375               0 :     return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
     376                 : }
     377                 : 
     378               0 : static inline unsigned SkB16ToB32(unsigned b) {
     379               0 :     return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
     380                 : }
     381                 : 
     382                 : #define SkPacked16ToR32(c)      SkR16ToR32(SkGetPackedR16(c))
     383                 : #define SkPacked16ToG32(c)      SkG16ToG32(SkGetPackedG16(c))
     384                 : #define SkPacked16ToB32(c)      SkB16ToB32(SkGetPackedB16(c))
     385                 : 
     386               0 : static inline SkPMColor SkPixel16ToPixel32(U16CPU src) {
     387               0 :     SkASSERT(src == SkToU16(src));
     388                 : 
     389               0 :     unsigned    r = SkPacked16ToR32(src);
     390               0 :     unsigned    g = SkPacked16ToG32(src);
     391               0 :     unsigned    b = SkPacked16ToB32(src);
     392                 : 
     393               0 :     SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
     394               0 :     SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
     395               0 :     SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
     396                 : 
     397               0 :     return SkPackARGB32(0xFF, r, g, b);
     398                 : }
     399                 : 
     400                 : // similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor
     401               0 : static inline SkColor SkPixel16ToColor(U16CPU src) {
     402               0 :     SkASSERT(src == SkToU16(src));
     403                 : 
     404               0 :     unsigned    r = SkPacked16ToR32(src);
     405               0 :     unsigned    g = SkPacked16ToG32(src);
     406               0 :     unsigned    b = SkPacked16ToB32(src);
     407                 : 
     408               0 :     SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
     409               0 :     SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
     410               0 :     SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
     411                 : 
     412               0 :     return SkColorSetRGB(r, g, b);
     413                 : }
     414                 : 
     415                 : ///////////////////////////////////////////////////////////////////////////////
     416                 : 
     417                 : typedef uint16_t SkPMColor16;
     418                 : 
     419                 : // Put in OpenGL order (r g b a)
     420                 : #define SK_A4444_SHIFT    0
     421                 : #define SK_R4444_SHIFT    12
     422                 : #define SK_G4444_SHIFT    8
     423                 : #define SK_B4444_SHIFT    4
     424                 : 
     425                 : #define SkA32To4444(a)  ((unsigned)(a) >> 4)
     426                 : #define SkR32To4444(r)  ((unsigned)(r) >> 4)
     427                 : #define SkG32To4444(g)  ((unsigned)(g) >> 4)
     428                 : #define SkB32To4444(b)  ((unsigned)(b) >> 4)
     429                 : 
     430               0 : static inline U8CPU SkReplicateNibble(unsigned nib) {
     431               0 :     SkASSERT(nib <= 0xF);
     432               0 :     return (nib << 4) | nib;
     433                 : }
     434                 : 
     435                 : #define SkA4444ToA32(a)     SkReplicateNibble(a)
     436                 : #define SkR4444ToR32(r)     SkReplicateNibble(r)
     437                 : #define SkG4444ToG32(g)     SkReplicateNibble(g)
     438                 : #define SkB4444ToB32(b)     SkReplicateNibble(b)
     439                 : 
     440                 : #define SkGetPackedA4444(c)     (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
     441                 : #define SkGetPackedR4444(c)     (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
     442                 : #define SkGetPackedG4444(c)     (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
     443                 : #define SkGetPackedB4444(c)     (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
     444                 : 
     445                 : #define SkPacked4444ToA32(c)    SkReplicateNibble(SkGetPackedA4444(c))
     446                 : #define SkPacked4444ToR32(c)    SkReplicateNibble(SkGetPackedR4444(c))
     447                 : #define SkPacked4444ToG32(c)    SkReplicateNibble(SkGetPackedG4444(c))
     448                 : #define SkPacked4444ToB32(c)    SkReplicateNibble(SkGetPackedB4444(c))
     449                 : 
     450                 : #ifdef SK_DEBUG
     451                 : static inline void SkPMColor16Assert(U16CPU c) {
     452                 :     unsigned a = SkGetPackedA4444(c);
     453                 :     unsigned r = SkGetPackedR4444(c);
     454                 :     unsigned g = SkGetPackedG4444(c);
     455                 :     unsigned b = SkGetPackedB4444(c);
     456                 : 
     457                 :     SkASSERT(a <= 0xF);
     458                 :     SkASSERT(r <= a);
     459                 :     SkASSERT(g <= a);
     460                 :     SkASSERT(b <= a);
     461                 : }
     462                 : #else
     463                 : #define SkPMColor16Assert(c)
     464                 : #endif
     465                 : 
     466               0 : static inline unsigned SkAlpha15To16(unsigned a) {
     467               0 :     SkASSERT(a <= 0xF);
     468               0 :     return a + (a >> 3);
     469                 : }
     470                 : 
     471                 : #ifdef SK_DEBUG
     472               0 :     static inline int SkAlphaMul4(int value, int scale) {
     473               0 :         SkASSERT((unsigned)scale <= 0x10);
     474               0 :         return value * scale >> 4;
     475                 :     }
     476                 : #else
     477                 :     #define SkAlphaMul4(value, scale)   ((value) * (scale) >> 4)
     478                 : #endif
     479                 : 
     480               0 : static inline unsigned SkR4444ToR565(unsigned r) {
     481               0 :     SkASSERT(r <= 0xF);
     482               0 :     return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
     483                 : }
     484                 : 
     485               0 : static inline unsigned SkG4444ToG565(unsigned g) {
     486               0 :     SkASSERT(g <= 0xF);
     487               0 :     return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
     488                 : }
     489                 : 
     490               0 : static inline unsigned SkB4444ToB565(unsigned b) {
     491               0 :     SkASSERT(b <= 0xF);
     492               0 :     return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
     493                 : }
     494                 : 
     495               0 : static inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
     496                 :                                          unsigned g, unsigned b) {
     497               0 :     SkASSERT(a <= 0xF);
     498               0 :     SkASSERT(r <= a);
     499               0 :     SkASSERT(g <= a);
     500               0 :     SkASSERT(b <= a);
     501                 : 
     502                 :     return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
     503               0 :                          (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
     504                 : }
     505                 : 
     506                 : extern const uint16_t gMask_0F0F;
     507                 : 
     508               0 : static inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale) {
     509               0 :     SkASSERT(scale <= 16);
     510                 : 
     511               0 :     const unsigned mask = 0xF0F;    //gMask_0F0F;
     512                 : 
     513                 : #if 0
     514                 :     unsigned rb = ((c & mask) * scale) >> 4;
     515                 :     unsigned ag = ((c >> 4) & mask) * scale;
     516                 :     return (rb & mask) | (ag & ~mask);
     517                 : #else
     518               0 :     c = (c & mask) | ((c & (mask << 4)) << 12);
     519               0 :     c = c * scale >> 4;
     520               0 :     return (c & mask) | ((c >> 12) & (mask << 4));
     521                 : #endif
     522                 : }
     523                 : 
     524                 : /** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
     525                 :     once by a value up to 16. Used in conjunction with SkCompact_4444.
     526                 : */
     527               0 : static inline uint32_t SkExpand_4444(U16CPU c) {
     528               0 :     SkASSERT(c == (uint16_t)c);
     529                 : 
     530               0 :     const unsigned mask = 0xF0F;    //gMask_0F0F;
     531               0 :     return (c & mask) | ((c & ~mask) << 12);
     532                 : }
     533                 : 
     534                 : /** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16.
     535                 :     NOTE: this explicitly does not clean the top 16 bits (which may be garbage).
     536                 :     It does this for speed, since if it is being written directly to 16bits of
     537                 :     memory, the top 16bits will be ignored. Casting the result to uint16_t here
     538                 :     would add 2 more instructions, slow us down. It is up to the caller to
     539                 :     perform the cast if needed.
     540                 : */
     541               0 : static inline U16CPU SkCompact_4444(uint32_t c) {
     542               0 :     const unsigned mask = 0xF0F;    //gMask_0F0F;
     543               0 :     return (c & mask) | ((c >> 12) & ~mask);
     544                 : }
     545                 : 
     546               0 : static inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) {
     547               0 :     unsigned sa = SkGetPackedA4444(s);
     548               0 :     unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
     549               0 :     unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
     550               0 :     unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
     551                 : 
     552                 :     // To avoid overflow, we have to clear the low bit of the synthetic sg
     553                 :     // if the src alpha is <= 7.
     554                 :     // to see why, try blending 0x4444 on top of 565-white and watch green
     555                 :     // overflow (sum == 64)
     556               0 :     sg &= ~(~(sa >> 3) & 1);
     557                 : 
     558               0 :     unsigned scale = SkAlpha15To16(15 - sa);
     559               0 :     unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
     560               0 :     unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
     561               0 :     unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
     562                 : 
     563                 : #if 0
     564                 :     if (sg + dg > 63) {
     565                 :         SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
     566                 :     }
     567                 : #endif
     568               0 :     return SkPackRGB16(sr + dr, sg + dg, sb + db);
     569                 : }
     570                 : 
     571               0 : static inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) {
     572               0 :     SkASSERT((unsigned)scale16 <= 16);
     573                 : 
     574               0 :     return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
     575                 : }
     576                 : 
     577                 : static inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16) {
     578                 :     SkASSERT((unsigned)scale16 <= 16);
     579                 : 
     580                 :     uint32_t src32 = SkExpand_4444(src) * scale16;
     581                 :     // the scaled srcAlpha is the bottom byte
     582                 : #ifdef SK_DEBUG
     583                 :     {
     584                 :         unsigned srcA = SkGetPackedA4444(src) * scale16;
     585                 :         SkASSERT(srcA == (src32 & 0xFF));
     586                 :     }
     587                 : #endif
     588                 :     unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4;
     589                 :     uint32_t dst32 = SkExpand_4444(dst) * dstScale;
     590                 :     return SkCompact_4444((src32 + dst32) >> 4);
     591                 : }
     592                 : 
     593               0 : static inline SkPMColor SkPixel4444ToPixel32(U16CPU c) {
     594                 :     uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
     595                 :                  (SkGetPackedR4444(c) << SK_R32_SHIFT) |
     596                 :                  (SkGetPackedG4444(c) << SK_G32_SHIFT) |
     597               0 :                  (SkGetPackedB4444(c) << SK_B32_SHIFT);
     598               0 :     return d | (d << 4);
     599                 : }
     600                 : 
     601               0 : static inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) {
     602                 :     return  (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
     603                 :     (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
     604                 :     (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
     605               0 :     (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
     606                 : }
     607                 : 
     608                 : // cheap 2x2 dither
     609               0 : static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
     610                 :                                                U8CPU g, U8CPU b) {
     611                 :     // to ensure that we stay a legal premultiplied color, we take the max()
     612                 :     // of the truncated and dithered alpha values. If we didn't, cases like
     613                 :     // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...)
     614                 :     // which is not legal premultiplied, since a < color
     615               0 :     unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
     616               0 :     a = SkMax32(a >> 4, dithered_a);
     617                 :     // these we just dither in place
     618               0 :     r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
     619               0 :     g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
     620               0 :     b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
     621                 : 
     622               0 :     return SkPackARGB4444(a, r, g, b);
     623                 : }
     624                 : 
     625               0 : static inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) {
     626                 :     return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
     627               0 :                                 SkGetPackedG32(c), SkGetPackedB32(c));
     628                 : }
     629                 : 
     630                 : /*  Assumes 16bit is in standard RGBA order.
     631                 :     Transforms a normal ARGB_8888 into the same byte order as
     632                 :     expanded ARGB_4444, but keeps each component 8bits
     633                 : */
     634               0 : static inline uint32_t SkExpand_8888(SkPMColor c) {
     635                 :     return  (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
     636                 :             (((c >> SK_G32_SHIFT) & 0xFF) <<  8) |
     637                 :             (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
     638               0 :             (((c >> SK_A32_SHIFT) & 0xFF) <<  0);
     639                 : }
     640                 : 
     641                 : /*  Undo the operation of SkExpand_8888, turning the argument back into
     642                 :     a SkPMColor.
     643                 : */
     644               0 : static inline SkPMColor SkCompact_8888(uint32_t c) {
     645                 :     return  (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
     646                 :             (((c >>  8) & 0xFF) << SK_G32_SHIFT) |
     647                 :             (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
     648               0 :             (((c >>  0) & 0xFF) << SK_A32_SHIFT);
     649                 : }
     650                 : 
     651                 : /*  Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
     652                 :     but this routine just keeps the high 4bits of each component in the low
     653                 :     4bits of the result (just like a newly expanded PMColor16).
     654                 : */
     655               0 : static inline uint32_t SkExpand32_4444(SkPMColor c) {
     656                 :     return  (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
     657                 :             (((c >> (SK_G32_SHIFT + 4)) & 0xF) <<  8) |
     658                 :             (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
     659               0 :             (((c >> (SK_A32_SHIFT + 4)) & 0xF) <<  0);
     660                 : }
     661                 : 
     662                 : // takes two values and alternamtes them as part of a memset16
     663                 : // used for cheap 2x2 dithering when the colors are opaque
     664                 : void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
     665                 : 
     666                 : #endif
     667                 : 

Generated by: LCOV version 1.7