LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/core - SkColorPriv.h (source / functions) Hit Total Coverage
Test: output.info Lines: 120 295 40.7 %
Date: 2017-07-14 16:53:18 Functions: 21 59 35.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2006 The Android Open Source Project
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkColorPriv_DEFINED
       9             : #define SkColorPriv_DEFINED
      10             : 
      11             : // turn this own for extra debug checking when blending onto 565
      12             : #ifdef SK_DEBUG
      13             :     #define CHECK_FOR_565_OVERFLOW
      14             : #endif
      15             : 
      16             : #include "SkColor.h"
      17             : #include "SkMath.h"
      18             : 
      19             : //////////////////////////////////////////////////////////////////////////////
      20             : 
      21             : #define SkASSERT_IS_BYTE(x)     SkASSERT(0 == ((x) & ~0xFF))
      22             : 
      23             : /*
      24             :  *  Skia's 32bit backend only supports 1 sizzle order at a time (compile-time).
      25             :  *  This is specified by 4 defines SK_A32_SHIFT, SK_R32_SHIFT, ... for G and B.
      26             :  *
      27             :  *  For easier compatibility with Skia's GPU backend, we further restrict these
      28             :  *  to either (in memory-byte-order) RGBA or BGRA. Note that this "order" does
      29             :  *  not directly correspond to the same shift-order, since we have to take endianess
      30             :  *  into account.
      31             :  *
      32             :  *  Here we enforce this constraint.
      33             :  */
      34             : 
      35             : #ifdef SK_CPU_BENDIAN
      36             :     #define SK_RGBA_R32_SHIFT   24
      37             :     #define SK_RGBA_G32_SHIFT   16
      38             :     #define SK_RGBA_B32_SHIFT   8
      39             :     #define SK_RGBA_A32_SHIFT   0
      40             : 
      41             :     #define SK_BGRA_B32_SHIFT   24
      42             :     #define SK_BGRA_G32_SHIFT   16
      43             :     #define SK_BGRA_R32_SHIFT   8
      44             :     #define SK_BGRA_A32_SHIFT   0
      45             : #else
      46             :     #define SK_RGBA_R32_SHIFT   0
      47             :     #define SK_RGBA_G32_SHIFT   8
      48             :     #define SK_RGBA_B32_SHIFT   16
      49             :     #define SK_RGBA_A32_SHIFT   24
      50             : 
      51             :     #define SK_BGRA_B32_SHIFT   0
      52             :     #define SK_BGRA_G32_SHIFT   8
      53             :     #define SK_BGRA_R32_SHIFT   16
      54             :     #define SK_BGRA_A32_SHIFT   24
      55             : #endif
      56             : 
      57             : #if defined(SK_PMCOLOR_IS_RGBA) && defined(SK_PMCOLOR_IS_BGRA)
      58             :     #error "can't define PMCOLOR to be RGBA and BGRA"
      59             : #endif
      60             : 
      61             : #define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA  \
      62             :     (SK_A32_SHIFT == SK_RGBA_A32_SHIFT &&    \
      63             :      SK_R32_SHIFT == SK_RGBA_R32_SHIFT &&    \
      64             :      SK_G32_SHIFT == SK_RGBA_G32_SHIFT &&    \
      65             :      SK_B32_SHIFT == SK_RGBA_B32_SHIFT)
      66             : 
      67             : #define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA  \
      68             :     (SK_A32_SHIFT == SK_BGRA_A32_SHIFT &&    \
      69             :      SK_R32_SHIFT == SK_BGRA_R32_SHIFT &&    \
      70             :      SK_G32_SHIFT == SK_BGRA_G32_SHIFT &&    \
      71             :      SK_B32_SHIFT == SK_BGRA_B32_SHIFT)
      72             : 
      73             : 
      74             : #define SK_A_INDEX  (SK_A32_SHIFT/8)
      75             : #define SK_R_INDEX  (SK_R32_SHIFT/8)
      76             : #define SK_G_INDEX  (SK_G32_SHIFT/8)
      77             : #define SK_B_INDEX  (SK_B32_SHIFT/8)
      78             : 
      79             : #if defined(SK_PMCOLOR_IS_RGBA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
      80             :     #error "SK_PMCOLOR_IS_RGBA does not match SK_*32_SHIFT values"
      81             : #endif
      82             : 
      83             : #if defined(SK_PMCOLOR_IS_BGRA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
      84             :     #error "SK_PMCOLOR_IS_BGRA does not match SK_*32_SHIFT values"
      85             : #endif
      86             : 
      87             : #if !defined(SK_PMCOLOR_IS_RGBA) && !defined(SK_PMCOLOR_IS_BGRA)
      88             :     // deduce which to define from the _SHIFT defines
      89             : 
      90             :     #if LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
      91             :         #define SK_PMCOLOR_IS_RGBA
      92             :     #elif LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
      93             :         #define SK_PMCOLOR_IS_BGRA
      94             :     #else
      95             :         #error "need 32bit packing to be either RGBA or BGRA"
      96             :     #endif
      97             : #endif
      98             : 
      99             : // hide these now that we're done
     100             : #undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
     101             : #undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
     102             : 
     103             : //////////////////////////////////////////////////////////////////////////////
     104             : 
     105             : // Reverse the bytes coorsponding to RED and BLUE in a packed pixels. Note the
     106             : // pair of them are in the same 2 slots in both RGBA and BGRA, thus there is
     107             : // no need to pass in the colortype to this function.
     108           0 : static inline uint32_t SkSwizzle_RB(uint32_t c) {
     109             :     static const uint32_t kRBMask = (0xFF << SK_R32_SHIFT) | (0xFF << SK_B32_SHIFT);
     110             : 
     111           0 :     unsigned c0 = (c >> SK_R32_SHIFT) & 0xFF;
     112           0 :     unsigned c1 = (c >> SK_B32_SHIFT) & 0xFF;
     113           0 :     return (c & ~kRBMask) | (c0 << SK_B32_SHIFT) | (c1 << SK_R32_SHIFT);
     114             : }
     115             : 
     116           0 : static inline uint32_t SkPackARGB_as_RGBA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
     117           0 :     SkASSERT_IS_BYTE(a);
     118           0 :     SkASSERT_IS_BYTE(r);
     119           0 :     SkASSERT_IS_BYTE(g);
     120           0 :     SkASSERT_IS_BYTE(b);
     121           0 :     return (a << SK_RGBA_A32_SHIFT) | (r << SK_RGBA_R32_SHIFT) |
     122           0 :            (g << SK_RGBA_G32_SHIFT) | (b << SK_RGBA_B32_SHIFT);
     123             : }
     124             : 
     125           0 : static inline uint32_t SkPackARGB_as_BGRA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
     126           0 :     SkASSERT_IS_BYTE(a);
     127           0 :     SkASSERT_IS_BYTE(r);
     128           0 :     SkASSERT_IS_BYTE(g);
     129           0 :     SkASSERT_IS_BYTE(b);
     130           0 :     return (a << SK_BGRA_A32_SHIFT) | (r << SK_BGRA_R32_SHIFT) |
     131           0 :            (g << SK_BGRA_G32_SHIFT) | (b << SK_BGRA_B32_SHIFT);
     132             : }
     133             : 
     134           0 : static inline SkPMColor SkSwizzle_RGBA_to_PMColor(uint32_t c) {
     135             : #ifdef SK_PMCOLOR_IS_RGBA
     136             :     return c;
     137             : #else
     138           0 :     return SkSwizzle_RB(c);
     139             : #endif
     140             : }
     141             : 
     142           0 : static inline SkPMColor SkSwizzle_BGRA_to_PMColor(uint32_t c) {
     143             : #ifdef SK_PMCOLOR_IS_BGRA
     144           0 :     return c;
     145             : #else
     146             :     return SkSwizzle_RB(c);
     147             : #endif
     148             : }
     149             : 
     150             : //////////////////////////////////////////////////////////////////////////////
     151             : 
     152             : ///@{
     153             : /** See ITU-R Recommendation BT.709 at http://www.itu.int/rec/R-REC-BT.709/ .*/
     154             : #define SK_ITU_BT709_LUM_COEFF_R (0.2126f)
     155             : #define SK_ITU_BT709_LUM_COEFF_G (0.7152f)
     156             : #define SK_ITU_BT709_LUM_COEFF_B (0.0722f)
     157             : ///@}
     158             : 
     159             : ///@{
     160             : /** A float value which specifies this channel's contribution to luminance. */
     161             : #define SK_LUM_COEFF_R SK_ITU_BT709_LUM_COEFF_R
     162             : #define SK_LUM_COEFF_G SK_ITU_BT709_LUM_COEFF_G
     163             : #define SK_LUM_COEFF_B SK_ITU_BT709_LUM_COEFF_B
     164             : ///@}
     165             : 
     166             : /** Computes the luminance from the given r, g, and b in accordance with
     167             :     SK_LUM_COEFF_X. For correct results, r, g, and b should be in linear space.
     168             : */
     169           0 : static inline U8CPU SkComputeLuminance(U8CPU r, U8CPU g, U8CPU b) {
     170             :     //The following is
     171             :     //r * SK_LUM_COEFF_R + g * SK_LUM_COEFF_G + b * SK_LUM_COEFF_B
     172             :     //with SK_LUM_COEFF_X in 1.8 fixed point (rounding adjusted to sum to 256).
     173           0 :     return (r * 54 + g * 183 + b * 19) >> 8;
     174             : }
     175             : 
     176             : /** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
     177             :     byte into a scale value, so that we can say scale * value >> 8 instead of
     178             :     alpha * value / 255.
     179             : 
     180             :     In debugging, asserts that alpha is 0..255
     181             : */
     182       81567 : static inline unsigned SkAlpha255To256(U8CPU alpha) {
     183       81567 :     SkASSERT(SkToU8(alpha) == alpha);
     184             :     // this one assues that blending on top of an opaque dst keeps it that way
     185             :     // even though it is less accurate than a+(a>>7) for non-opaque dsts
     186       81567 :     return alpha + 1;
     187             : }
     188             : 
     189             : /**
     190             :  *  Turn a 0..255 value into a 0..256 value, rounding up if the value is >= 0x80.
     191             :  *  This is slightly more accurate than SkAlpha255To256.
     192             :  */
     193           0 : static inline unsigned Sk255To256(U8CPU value) {
     194           0 :     SkASSERT(SkToU8(value) == value);
     195           0 :     return value + (value >> 7);
     196             : }
     197             : 
     198             : /** Multiplify value by 0..256, and shift the result down 8
     199             :     (i.e. return (value * alpha256) >> 8)
     200             :  */
     201             : #define SkAlphaMul(value, alpha256)     (((value) * (alpha256)) >> 8)
     202             : 
     203             : /** Calculates 256 - (value * alpha256) / 255 in range [0,256],
     204             :  *  for [0,255] value and [0,256] alpha256.
     205             :  */
     206        2465 : static inline U16CPU SkAlphaMulInv256(U16CPU value, U16CPU alpha256) {
     207        2465 :     unsigned prod = 0xFFFF - value * alpha256;
     208        2465 :     return (prod + (prod >> 8)) >> 8;
     209             : }
     210             : 
     211             : //  The caller may want negative values, so keep all params signed (int)
     212             : //  so we don't accidentally slip into unsigned math and lose the sign
     213             : //  extension when we shift (in SkAlphaMul)
     214           0 : static inline int SkAlphaBlend(int src, int dst, int scale256) {
     215           0 :     SkASSERT((unsigned)scale256 <= 256);
     216           0 :     return dst + SkAlphaMul(src - dst, scale256);
     217             : }
     218             : 
     219             : /**
     220             :  *  Returns (src * alpha + dst * (255 - alpha)) / 255
     221             :  *
     222             :  *  This is more accurate than SkAlphaBlend, but slightly slower
     223             :  */
     224             : static inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) {
     225             :     SkASSERT((int16_t)src == src);
     226             :     SkASSERT((int16_t)dst == dst);
     227             :     SkASSERT((uint8_t)alpha == alpha);
     228             : 
     229             :     int prod = (src - dst) * alpha + 128;
     230             :     prod = (prod + (prod >> 8)) >> 8;
     231             :     return dst + prod;
     232             : }
     233             : 
     234             : static inline U8CPU SkUnitScalarClampToByte(SkScalar x) {
     235             :     return static_cast<U8CPU>(SkScalarPin(x, 0, 1) * 255 + 0.5);
     236             : }
     237             : 
     238             : #define SK_R16_BITS     5
     239             : #define SK_G16_BITS     6
     240             : #define SK_B16_BITS     5
     241             : 
     242             : #define SK_R16_SHIFT    (SK_B16_BITS + SK_G16_BITS)
     243             : #define SK_G16_SHIFT    (SK_B16_BITS)
     244             : #define SK_B16_SHIFT    0
     245             : 
     246             : #define SK_R16_MASK     ((1 << SK_R16_BITS) - 1)
     247             : #define SK_G16_MASK     ((1 << SK_G16_BITS) - 1)
     248             : #define SK_B16_MASK     ((1 << SK_B16_BITS) - 1)
     249             : 
     250             : #define SkGetPackedR16(color)   (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
     251             : #define SkGetPackedG16(color)   (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
     252             : #define SkGetPackedB16(color)   (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
     253             : 
     254             : #define SkR16Assert(r)  SkASSERT((unsigned)(r) <= SK_R16_MASK)
     255             : #define SkG16Assert(g)  SkASSERT((unsigned)(g) <= SK_G16_MASK)
     256             : #define SkB16Assert(b)  SkASSERT((unsigned)(b) <= SK_B16_MASK)
     257             : 
     258           0 : static inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
     259           0 :     SkASSERT(r <= SK_R16_MASK);
     260           0 :     SkASSERT(g <= SK_G16_MASK);
     261           0 :     SkASSERT(b <= SK_B16_MASK);
     262             : 
     263           0 :     return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
     264             : }
     265             : 
     266             : #define SK_R16_MASK_IN_PLACE        (SK_R16_MASK << SK_R16_SHIFT)
     267             : #define SK_G16_MASK_IN_PLACE        (SK_G16_MASK << SK_G16_SHIFT)
     268             : #define SK_B16_MASK_IN_PLACE        (SK_B16_MASK << SK_B16_SHIFT)
     269             : 
     270             : /** Expand the 16bit color into a 32bit value that can be scaled all at once
     271             :     by a value up to 32. Used in conjunction with SkCompact_rgb_16.
     272             : */
     273           0 : static inline uint32_t SkExpand_rgb_16(U16CPU c) {
     274           0 :     SkASSERT(c == (uint16_t)c);
     275             : 
     276           0 :     return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
     277             : }
     278             : 
     279             : /** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit
     280             :     color value. The computation yields only 16bits of valid data, but we claim
     281             :     to return 32bits, so that the compiler won't generate extra instructions to
     282             :     "clean" the top 16bits. However, the top 16 can contain garbage, so it is
     283             :     up to the caller to safely ignore them.
     284             : */
     285           0 : static inline U16CPU SkCompact_rgb_16(uint32_t c) {
     286           0 :     return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
     287             : }
     288             : 
     289             : /** Scale the 16bit color value by the 0..256 scale parameter.
     290             :     The computation yields only 16bits of valid data, but we claim
     291             :     to return 32bits, so that the compiler won't generate extra instructions to
     292             :     "clean" the top 16bits.
     293             : */
     294           0 : static inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
     295           0 :     return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
     296             : }
     297             : 
     298             : // this helper explicitly returns a clean 16bit value (but slower)
     299             : #define SkAlphaMulRGB16_ToU16(c, s)  (uint16_t)SkAlphaMulRGB16(c, s)
     300             : 
     301             : /** Blend pre-expanded RGB32 with 16bit color value by the 0..32 scale parameter.
     302             :     The computation yields only 16bits of valid data, but we claim to return
     303             :     32bits, so that the compiler won't generate extra instructions to "clean"
     304             :     the top 16bits.
     305             : */
     306           0 : static inline U16CPU SkBlend32_RGB16(uint32_t src_expand, uint16_t dst, unsigned scale) {
     307           0 :     uint32_t dst_expand = SkExpand_rgb_16(dst) * scale;
     308           0 :     return SkCompact_rgb_16((src_expand + dst_expand) >> 5);
     309             : }
     310             : 
     311             : /** Blend src and dst 16bit colors by the 0..256 scale parameter.
     312             :     The computation yields only 16bits of valid data, but we claim
     313             :     to return 32bits, so that the compiler won't generate extra instructions to
     314             :     "clean" the top 16bits.
     315             : */
     316           0 : static inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
     317           0 :     SkASSERT((unsigned)srcScale <= 256);
     318             : 
     319           0 :     srcScale >>= 3;
     320             : 
     321           0 :     uint32_t src32 = SkExpand_rgb_16(src);
     322           0 :     uint32_t dst32 = SkExpand_rgb_16(dst);
     323           0 :     return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
     324             : }
     325             : 
     326             : static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
     327             :                                 int srcScale, int count) {
     328             :     SkASSERT(count > 0);
     329             :     SkASSERT((unsigned)srcScale <= 256);
     330             : 
     331             :     srcScale >>= 3;
     332             : 
     333             :     do {
     334             :         uint32_t src32 = SkExpand_rgb_16(*src++);
     335             :         uint32_t dst32 = SkExpand_rgb_16(*dst);
     336             :         *dst++ = static_cast<uint16_t>(
     337             :             SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)));
     338             :     } while (--count > 0);
     339             : }
     340             : 
     341             : #ifdef SK_DEBUG
     342             :     static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
     343             :         SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
     344             :         SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
     345             :         SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
     346             : 
     347             :         return a + b;
     348             :     }
     349             : #else
     350             :     #define SkRGB16Add(a, b)  ((a) + (b))
     351             : #endif
     352             : 
     353             : ///////////////////////////////////////////////////////////////////////////////
     354             : 
     355             : #define SK_A32_BITS     8
     356             : #define SK_R32_BITS     8
     357             : #define SK_G32_BITS     8
     358             : #define SK_B32_BITS     8
     359             : 
     360             : #define SK_A32_MASK     ((1 << SK_A32_BITS) - 1)
     361             : #define SK_R32_MASK     ((1 << SK_R32_BITS) - 1)
     362             : #define SK_G32_MASK     ((1 << SK_G32_BITS) - 1)
     363             : #define SK_B32_MASK     ((1 << SK_B32_BITS) - 1)
     364             : 
     365             : #define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
     366             : #define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
     367             : #define SkGetPackedG32(packed)      ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
     368             : #define SkGetPackedB32(packed)      ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
     369             : 
     370             : #define SkA32Assert(a)  SkASSERT((unsigned)(a) <= SK_A32_MASK)
     371             : #define SkR32Assert(r)  SkASSERT((unsigned)(r) <= SK_R32_MASK)
     372             : #define SkG32Assert(g)  SkASSERT((unsigned)(g) <= SK_G32_MASK)
     373             : #define SkB32Assert(b)  SkASSERT((unsigned)(b) <= SK_B32_MASK)
     374             : 
     375             : #ifdef SK_DEBUG
     376             :     #define SkPMColorAssert(color_value)                                    \
     377             :         do {                                                                \
     378             :             SkPMColor pm_color_value = (color_value);                       \
     379             :             uint32_t alpha_color_value = SkGetPackedA32(pm_color_value);    \
     380             :             SkA32Assert(alpha_color_value);                                 \
     381             :             SkASSERT(SkGetPackedR32(pm_color_value) <= alpha_color_value);  \
     382             :             SkASSERT(SkGetPackedG32(pm_color_value) <= alpha_color_value);  \
     383             :             SkASSERT(SkGetPackedB32(pm_color_value) <= alpha_color_value);  \
     384             :         } while (false)
     385             : #else
     386             :     #define SkPMColorAssert(c)
     387             : #endif
     388             : 
     389             : static inline bool SkPMColorValid(SkPMColor c) {
     390             :     auto a = SkGetPackedA32(c);
     391             :     bool valid = a <= SK_A32_MASK
     392             :               && SkGetPackedR32(c) <= a
     393             :               && SkGetPackedG32(c) <= a
     394             :               && SkGetPackedB32(c) <= a;
     395             :     if (valid) {
     396             :         SkPMColorAssert(c);  // Make sure we're consistent when it counts.
     397             :     }
     398             :     return valid;
     399             : }
     400             : 
     401             : /**
     402             :  *  Pack the components into a SkPMColor, checking (in the debug version) that
     403             :  *  the components are 0..255, and are already premultiplied (i.e. alpha >= color)
     404             :  */
     405       30721 : static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
     406       30721 :     SkA32Assert(a);
     407       30721 :     SkASSERT(r <= a);
     408       30721 :     SkASSERT(g <= a);
     409       30721 :     SkASSERT(b <= a);
     410             : 
     411       61442 :     return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
     412       61442 :            (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
     413             : }
     414             : 
     415             : static inline uint32_t SkPackPMColor_as_RGBA(SkPMColor c) {
     416             :     return SkPackARGB_as_RGBA(SkGetPackedA32(c), SkGetPackedR32(c),
     417             :                               SkGetPackedG32(c), SkGetPackedB32(c));
     418             : }
     419             : 
     420             : static inline uint32_t SkPackPMColor_as_BGRA(SkPMColor c) {
     421             :     return SkPackARGB_as_BGRA(SkGetPackedA32(c), SkGetPackedR32(c),
     422             :                               SkGetPackedG32(c), SkGetPackedB32(c));
     423             : }
     424             : 
     425             : /**
     426             :  * Abstract 4-byte interpolation, implemented on top of SkPMColor
     427             :  * utility functions. Third parameter controls blending of the first two:
     428             :  *   (src, dst, 0) returns dst
     429             :  *   (src, dst, 0xFF) returns src
     430             :  *   srcWeight is [0..256], unlike SkFourByteInterp which takes [0..255]
     431             :  */
     432           0 : static inline SkPMColor SkFourByteInterp256(SkPMColor src, SkPMColor dst,
     433             :                                          unsigned scale) {
     434           0 :     unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
     435           0 :     unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
     436           0 :     unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
     437           0 :     unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
     438             : 
     439           0 :     return SkPackARGB32(a, r, g, b);
     440             : }
     441             : 
     442             : /**
     443             :  * Abstract 4-byte interpolation, implemented on top of SkPMColor
     444             :  * utility functions. Third parameter controls blending of the first two:
     445             :  *   (src, dst, 0) returns dst
     446             :  *   (src, dst, 0xFF) returns src
     447             :  */
     448           0 : static inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst,
     449             :                                          U8CPU srcWeight) {
     450           0 :     unsigned scale = SkAlpha255To256(srcWeight);
     451           0 :     return SkFourByteInterp256(src, dst, scale);
     452             : }
     453             : 
     454             : /**
     455             :  * 0xAARRGGBB -> 0x00AA00GG, 0x00RR00BB
     456             :  */
     457             : static inline void SkSplay(uint32_t color, uint32_t* ag, uint32_t* rb) {
     458             :     const uint32_t mask = 0x00FF00FF;
     459             :     *ag = (color >> 8) & mask;
     460             :     *rb = color & mask;
     461             : }
     462             : 
     463             : /**
     464             :  * 0xAARRGGBB -> 0x00AA00GG00RR00BB
     465             :  * (note, ARGB -> AGRB)
     466             :  */
     467       55924 : static inline uint64_t SkSplay(uint32_t color) {
     468       55924 :     const uint32_t mask = 0x00FF00FF;
     469       55924 :     uint64_t agrb = (color >> 8) & mask;  // 0x0000000000AA00GG
     470       55924 :     agrb <<= 32;                          // 0x00AA00GG00000000
     471       55924 :     agrb |= color & mask;                 // 0x00AA00GG00RR00BB
     472       55924 :     return agrb;
     473             : }
     474             : 
     475             : /**
     476             :  * 0xAAxxGGxx, 0xRRxxBBxx-> 0xAARRGGBB
     477             :  */
     478             : static inline uint32_t SkUnsplay(uint32_t ag, uint32_t rb) {
     479             :     const uint32_t mask = 0xFF00FF00;
     480             :     return (ag & mask) | ((rb & mask) >> 8);
     481             : }
     482             : 
     483             : /**
     484             :  * 0xAAxxGGxxRRxxBBxx -> 0xAARRGGBB
     485             :  * (note, AGRB -> ARGB)
     486             :  */
     487       27962 : static inline uint32_t SkUnsplay(uint64_t agrb) {
     488       27962 :     const uint32_t mask = 0xFF00FF00;
     489             :     return SkPMColor(
     490       27962 :         ((agrb & mask) >> 8) |   // 0x00RR00BB
     491       27962 :         ((agrb >> 32) & mask));  // 0xAARRGGBB
     492             : }
     493             : 
     494             : static inline SkPMColor SkFastFourByteInterp256_32(SkPMColor src, SkPMColor dst, unsigned scale) {
     495             :     SkASSERT(scale <= 256);
     496             : 
     497             :     // Two 8-bit blends per two 32-bit registers, with space to make sure the math doesn't collide.
     498             :     uint32_t src_ag, src_rb, dst_ag, dst_rb;
     499             :     SkSplay(src, &src_ag, &src_rb);
     500             :     SkSplay(dst, &dst_ag, &dst_rb);
     501             : 
     502             :     const uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag;
     503             :     const uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb;
     504             : 
     505             :     return SkUnsplay(ret_ag, ret_rb);
     506             : }
     507             : 
     508       27962 : static inline SkPMColor SkFastFourByteInterp256_64(SkPMColor src, SkPMColor dst, unsigned scale) {
     509       27962 :     SkASSERT(scale <= 256);
     510             :     // Four 8-bit blends in one 64-bit register, with space to make sure the math doesn't collide.
     511       27962 :     return SkUnsplay(SkSplay(src) * scale + (256-scale) * SkSplay(dst));
     512             : }
     513             : 
     514             : // TODO(mtklein): Replace slow versions with fast versions, using scale + (scale>>7) everywhere.
     515             : 
     516             : /**
     517             :  * Same as SkFourByteInterp256, but faster.
     518             :  */
     519       27962 : static inline SkPMColor SkFastFourByteInterp256(SkPMColor src, SkPMColor dst, unsigned scale) {
     520             :     // On a 64-bit machine, _64 is about 10% faster than _32, but ~40% slower on a 32-bit machine.
     521             :     if (sizeof(void*) == 4) {
     522             :         return SkFastFourByteInterp256_32(src, dst, scale);
     523             :     } else {
     524       27962 :         return SkFastFourByteInterp256_64(src, dst, scale);
     525             :     }
     526             : }
     527             : 
     528             : /**
     529             :  * Nearly the same as SkFourByteInterp, but faster and a touch more accurate, due to better
     530             :  * srcWeight scaling to [0, 256].
     531             :  */
     532        5632 : static inline SkPMColor SkFastFourByteInterp(SkPMColor src,
     533             :                                              SkPMColor dst,
     534             :                                              U8CPU srcWeight) {
     535        5632 :     SkASSERT(srcWeight <= 255);
     536             :     // scale = srcWeight + (srcWeight >> 7) is more accurate than
     537             :     // scale = srcWeight + 1, but 7% slower
     538        5632 :     return SkFastFourByteInterp256(src, dst, srcWeight + (srcWeight >> 7));
     539             : }
     540             : 
     541             : /**
     542             :  *  Same as SkPackARGB32, but this version guarantees to not check that the
     543             :  *  values are premultiplied in the debug version.
     544             :  */
     545          81 : static inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
     546         162 :     return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
     547         162 :            (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
     548             : }
     549             : 
     550             : static inline
     551       18830 : SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
     552       18830 :     SkA32Assert(a);
     553       18830 :     SkR32Assert(r);
     554       18830 :     SkG32Assert(g);
     555       18830 :     SkB32Assert(b);
     556             : 
     557       18830 :     if (a != 255) {
     558       18491 :         r = SkMulDiv255Round(r, a);
     559       18491 :         g = SkMulDiv255Round(g, a);
     560       18491 :         b = SkMulDiv255Round(b, a);
     561             :     }
     562       18830 :     return SkPackARGB32(a, r, g, b);
     563             : }
     564             : 
     565             : // When Android is compiled optimizing for size, SkAlphaMulQ doesn't get
     566             : // inlined; forcing inlining significantly improves performance.
     567             : static SK_ALWAYS_INLINE uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
     568       71721 :     uint32_t mask = 0xFF00FF;
     569             : 
     570       71721 :     uint32_t rb = ((c & mask) * scale) >> 8;
     571       71721 :     uint32_t ag = ((c >> 8) & mask) * scale;
     572       71721 :     return (rb & mask) | (ag & ~mask);
     573             : }
     574             : 
     575       46309 : static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
     576       92618 :     return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
     577             : }
     578             : 
     579             : /**
     580             :  * Interpolates between colors src and dst using [0,256] scale.
     581             :  */
     582       22330 : static inline SkPMColor SkPMLerp(SkPMColor src, SkPMColor dst, unsigned scale) {
     583       22330 :     return SkFastFourByteInterp256(src, dst, scale);
     584             : }
     585             : 
     586        2465 : static inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
     587        2465 :     SkASSERT((unsigned)aa <= 255);
     588             : 
     589        2465 :     unsigned src_scale = SkAlpha255To256(aa);
     590        2465 :     unsigned dst_scale = SkAlphaMulInv256(SkGetPackedA32(src), src_scale);
     591             : 
     592        2465 :     const uint32_t mask = 0xFF00FF;
     593             : 
     594        2465 :     uint32_t src_rb = (src & mask) * src_scale;
     595        2465 :     uint32_t src_ag = ((src >> 8) & mask) * src_scale;
     596             : 
     597        2465 :     uint32_t dst_rb = (dst & mask) * dst_scale;
     598        2465 :     uint32_t dst_ag = ((dst >> 8) & mask) * dst_scale;
     599             : 
     600        2465 :     return (((src_rb + dst_rb) >> 8) & mask) | ((src_ag + dst_ag) & ~mask);
     601             : }
     602             : 
     603             : ////////////////////////////////////////////////////////////////////////////////////////////
     604             : // Convert a 32bit pixel to a 16bit pixel (no dither)
     605             : 
     606             : #define SkR32ToR16_MACRO(r)   ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
     607             : #define SkG32ToG16_MACRO(g)   ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
     608             : #define SkB32ToB16_MACRO(b)   ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
     609             : 
     610             : #ifdef SK_DEBUG
     611       17191 :     static inline unsigned SkR32ToR16(unsigned r) {
     612       17191 :         SkR32Assert(r);
     613       17191 :         return SkR32ToR16_MACRO(r);
     614             :     }
     615       17191 :     static inline unsigned SkG32ToG16(unsigned g) {
     616       17191 :         SkG32Assert(g);
     617       17191 :         return SkG32ToG16_MACRO(g);
     618             :     }
     619       17191 :     static inline unsigned SkB32ToB16(unsigned b) {
     620       17191 :         SkB32Assert(b);
     621       17191 :         return SkB32ToB16_MACRO(b);
     622             :     }
     623             : #else
     624             :     #define SkR32ToR16(r)   SkR32ToR16_MACRO(r)
     625             :     #define SkG32ToG16(g)   SkG32ToG16_MACRO(g)
     626             :     #define SkB32ToB16(b)   SkB32ToB16_MACRO(b)
     627             : #endif
     628             : 
     629             : #define SkPacked32ToR16(c)  (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
     630             : #define SkPacked32ToG16(c)  (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
     631             : #define SkPacked32ToB16(c)  (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
     632             : 
     633           0 : static inline U16CPU SkPixel32ToPixel16(SkPMColor c) {
     634           0 :     unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
     635           0 :     unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
     636           0 :     unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
     637           0 :     return r | g | b;
     638             : }
     639             : 
     640       17191 : static inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
     641       34382 :     return  (SkR32ToR16(r) << SK_R16_SHIFT) |
     642       17191 :             (SkG32ToG16(g) << SK_G16_SHIFT) |
     643       17191 :             (SkB32ToB16(b) << SK_B16_SHIFT);
     644             : }
     645             : 
     646             : #define SkPixel32ToPixel16_ToU16(src)   SkToU16(SkPixel32ToPixel16(src))
     647             : 
     648             : /////////////////////////////////////////////////////////////////////////////////////////
     649             : // Fast dither from 32->16
     650             : 
     651             : #define SkShouldDitherXY(x, y)  (((x) ^ (y)) & 1)
     652             : 
     653           0 : static inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
     654           0 :     r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
     655           0 :     g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
     656           0 :     b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
     657             : 
     658           0 :     return SkPackRGB16(r, g, b);
     659             : }
     660             : 
     661             : static inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) {
     662             :     return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
     663             : }
     664             : 
     665             : /*  Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
     666             :     It is now suitable for combining with a scaled expanded_rgb_16 color
     667             :     as in SkSrcOver32To16().
     668             :     We must do this 565 high-bit replication, in order for the subsequent add
     669             :     to saturate properly (and not overflow). If we take the 8 bits as is, it is
     670             :     possible to overflow.
     671             : */
     672             : static inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) {
     673             :     unsigned sr = SkPacked32ToR16(c);
     674             :     unsigned sg = SkPacked32ToG16(c);
     675             :     unsigned sb = SkPacked32ToB16(c);
     676             : 
     677             :     sr = (sr << 5) | sr;
     678             :     sg = (sg << 5) | (sg >> 1);
     679             :     sb = (sb << 5) | sb;
     680             :     return (sr << 11) | (sg << 21) | (sb << 0);
     681             : }
     682             : 
     683             : /*  SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
     684             :     (with dirt in the high 16bits, so caller beware).
     685             : */
     686           0 : static inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
     687           0 :     unsigned sr = SkGetPackedR32(src);
     688           0 :     unsigned sg = SkGetPackedG32(src);
     689           0 :     unsigned sb = SkGetPackedB32(src);
     690             : 
     691           0 :     unsigned dr = SkGetPackedR16(dst);
     692           0 :     unsigned dg = SkGetPackedG16(dst);
     693           0 :     unsigned db = SkGetPackedB16(dst);
     694             : 
     695           0 :     unsigned isa = 255 - SkGetPackedA32(src);
     696             : 
     697           0 :     dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
     698           0 :     dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
     699           0 :     db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
     700             : 
     701           0 :     return SkPackRGB16(dr, dg, db);
     702             : }
     703             : 
     704             : ////////////////////////////////////////////////////////////////////////////////////////////
     705             : // Convert a 16bit pixel to a 32bit pixel
     706             : 
     707           0 : static inline unsigned SkR16ToR32(unsigned r) {
     708           0 :     return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
     709             : }
     710             : 
     711           0 : static inline unsigned SkG16ToG32(unsigned g) {
     712           0 :     return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
     713             : }
     714             : 
     715           0 : static inline unsigned SkB16ToB32(unsigned b) {
     716           0 :     return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
     717             : }
     718             : 
     719             : #define SkPacked16ToR32(c)      SkR16ToR32(SkGetPackedR16(c))
     720             : #define SkPacked16ToG32(c)      SkG16ToG32(SkGetPackedG16(c))
     721             : #define SkPacked16ToB32(c)      SkB16ToB32(SkGetPackedB16(c))
     722             : 
     723           0 : static inline SkPMColor SkPixel16ToPixel32(U16CPU src) {
     724           0 :     SkASSERT(src == SkToU16(src));
     725             : 
     726           0 :     unsigned    r = SkPacked16ToR32(src);
     727           0 :     unsigned    g = SkPacked16ToG32(src);
     728           0 :     unsigned    b = SkPacked16ToB32(src);
     729             : 
     730           0 :     SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
     731           0 :     SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
     732           0 :     SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
     733             : 
     734           0 :     return SkPackARGB32(0xFF, r, g, b);
     735             : }
     736             : 
     737             : // similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor
     738           0 : static inline SkColor SkPixel16ToColor(U16CPU src) {
     739           0 :     SkASSERT(src == SkToU16(src));
     740             : 
     741           0 :     unsigned    r = SkPacked16ToR32(src);
     742           0 :     unsigned    g = SkPacked16ToG32(src);
     743           0 :     unsigned    b = SkPacked16ToB32(src);
     744             : 
     745           0 :     SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
     746           0 :     SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
     747           0 :     SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
     748             : 
     749           0 :     return SkColorSetRGB(r, g, b);
     750             : }
     751             : 
     752             : ///////////////////////////////////////////////////////////////////////////////
     753             : 
     754             : typedef uint16_t SkPMColor16;
     755             : 
     756             : // Put in OpenGL order (r g b a)
     757             : #define SK_A4444_SHIFT    0
     758             : #define SK_R4444_SHIFT    12
     759             : #define SK_G4444_SHIFT    8
     760             : #define SK_B4444_SHIFT    4
     761             : 
     762             : #define SkA32To4444(a)  ((unsigned)(a) >> 4)
     763             : #define SkR32To4444(r)  ((unsigned)(r) >> 4)
     764             : #define SkG32To4444(g)  ((unsigned)(g) >> 4)
     765             : #define SkB32To4444(b)  ((unsigned)(b) >> 4)
     766             : 
     767           0 : static inline U8CPU SkReplicateNibble(unsigned nib) {
     768           0 :     SkASSERT(nib <= 0xF);
     769           0 :     return (nib << 4) | nib;
     770             : }
     771             : 
     772             : #define SkA4444ToA32(a)     SkReplicateNibble(a)
     773             : #define SkR4444ToR32(r)     SkReplicateNibble(r)
     774             : #define SkG4444ToG32(g)     SkReplicateNibble(g)
     775             : #define SkB4444ToB32(b)     SkReplicateNibble(b)
     776             : 
     777             : #define SkGetPackedA4444(c)     (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
     778             : #define SkGetPackedR4444(c)     (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
     779             : #define SkGetPackedG4444(c)     (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
     780             : #define SkGetPackedB4444(c)     (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
     781             : 
     782             : #define SkPacked4444ToA32(c)    SkReplicateNibble(SkGetPackedA4444(c))
     783             : #define SkPacked4444ToR32(c)    SkReplicateNibble(SkGetPackedR4444(c))
     784             : #define SkPacked4444ToG32(c)    SkReplicateNibble(SkGetPackedG4444(c))
     785             : #define SkPacked4444ToB32(c)    SkReplicateNibble(SkGetPackedB4444(c))
     786             : 
     787             : #ifdef SK_DEBUG
     788             : static inline void SkPMColor16Assert(U16CPU c) {
     789             :     unsigned a = SkGetPackedA4444(c);
     790             :     unsigned r = SkGetPackedR4444(c);
     791             :     unsigned g = SkGetPackedG4444(c);
     792             :     unsigned b = SkGetPackedB4444(c);
     793             : 
     794             :     SkASSERT(a <= 0xF);
     795             :     SkASSERT(r <= a);
     796             :     SkASSERT(g <= a);
     797             :     SkASSERT(b <= a);
     798             : }
     799             : #else
     800             : #define SkPMColor16Assert(c)
     801             : #endif
     802             : 
     803           0 : static inline unsigned SkAlpha15To16(unsigned a) {
     804           0 :     SkASSERT(a <= 0xF);
     805           0 :     return a + (a >> 3);
     806             : }
     807             : 
     808             : #ifdef SK_DEBUG
     809           0 :     static inline int SkAlphaMul4(int value, int scale) {
     810           0 :         SkASSERT((unsigned)scale <= 0x10);
     811           0 :         return value * scale >> 4;
     812             :     }
     813             : #else
     814             :     #define SkAlphaMul4(value, scale)   ((value) * (scale) >> 4)
     815             : #endif
     816             : 
     817           0 : static inline unsigned SkR4444ToR565(unsigned r) {
     818           0 :     SkASSERT(r <= 0xF);
     819           0 :     return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
     820             : }
     821             : 
     822           0 : static inline unsigned SkG4444ToG565(unsigned g) {
     823           0 :     SkASSERT(g <= 0xF);
     824           0 :     return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
     825             : }
     826             : 
     827           0 : static inline unsigned SkB4444ToB565(unsigned b) {
     828           0 :     SkASSERT(b <= 0xF);
     829           0 :     return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
     830             : }
     831             : 
     832             : static inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
     833             :                                          unsigned g, unsigned b) {
     834             :     SkASSERT(a <= 0xF);
     835             :     SkASSERT(r <= a);
     836             :     SkASSERT(g <= a);
     837             :     SkASSERT(b <= a);
     838             : 
     839             :     return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
     840             :                          (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
     841             : }
     842             : 
     843           0 : static inline SkPMColor16 SkAlphaMulQ4(SkPMColor16 c, int scale) {
     844           0 :     SkASSERT(scale <= 16);
     845             : 
     846           0 :     const unsigned mask = 0xF0F;    //gMask_0F0F;
     847             : 
     848             : #if 0
     849             :     unsigned rb = ((c & mask) * scale) >> 4;
     850             :     unsigned ag = ((c >> 4) & mask) * scale;
     851             :     return (rb & mask) | (ag & ~mask);
     852             : #else
     853           0 :     unsigned expanded_c = (c & mask) | ((c & (mask << 4)) << 12);
     854           0 :     unsigned scaled_c = (expanded_c * scale) >> 4;
     855           0 :     return (scaled_c & mask) | ((scaled_c >> 12) & (mask << 4));
     856             : #endif
     857             : }
     858             : 
     859             : /** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
     860             :     once by a value up to 16.
     861             : */
     862           0 : static inline uint32_t SkExpand_4444(U16CPU c) {
     863           0 :     SkASSERT(c == (uint16_t)c);
     864             : 
     865           0 :     const unsigned mask = 0xF0F;    //gMask_0F0F;
     866           0 :     return (c & mask) | ((c & ~mask) << 12);
     867             : }
     868             : 
     869           0 : static inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) {
     870           0 :     unsigned sa = SkGetPackedA4444(s);
     871           0 :     unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
     872           0 :     unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
     873           0 :     unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
     874             : 
     875             :     // To avoid overflow, we have to clear the low bit of the synthetic sg
     876             :     // if the src alpha is <= 7.
     877             :     // to see why, try blending 0x4444 on top of 565-white and watch green
     878             :     // overflow (sum == 64)
     879           0 :     sg &= ~(~(sa >> 3) & 1);
     880             : 
     881           0 :     unsigned scale = SkAlpha15To16(15 - sa);
     882           0 :     unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
     883           0 :     unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
     884           0 :     unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
     885             : 
     886             : #if 0
     887             :     if (sg + dg > 63) {
     888             :         SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
     889             :     }
     890             : #endif
     891           0 :     return SkPackRGB16(sr + dr, sg + dg, sb + db);
     892             : }
     893             : 
     894           0 : static inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) {
     895           0 :     SkASSERT((unsigned)scale16 <= 16);
     896             : 
     897           0 :     return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
     898             : }
     899             : 
     900           0 : static inline SkPMColor SkPixel4444ToPixel32(U16CPU c) {
     901           0 :     uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
     902           0 :                  (SkGetPackedR4444(c) << SK_R32_SHIFT) |
     903           0 :                  (SkGetPackedG4444(c) << SK_G32_SHIFT) |
     904           0 :                  (SkGetPackedB4444(c) << SK_B32_SHIFT);
     905           0 :     return d | (d << 4);
     906             : }
     907             : 
     908             : static inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) {
     909             :     return  (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
     910             :     (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
     911             :     (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
     912             :     (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
     913             : }
     914             : 
     915             : // cheap 2x2 dither
     916             : static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
     917             :                                                U8CPU g, U8CPU b) {
     918             :     // to ensure that we stay a legal premultiplied color, we take the max()
     919             :     // of the truncated and dithered alpha values. If we didn't, cases like
     920             :     // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...)
     921             :     // which is not legal premultiplied, since a < color
     922             :     unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
     923             :     a = SkMax32(a >> 4, dithered_a);
     924             :     // these we just dither in place
     925             :     r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
     926             :     g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
     927             :     b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
     928             : 
     929             :     return SkPackARGB4444(a, r, g, b);
     930             : }
     931             : 
     932             : static inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) {
     933             :     return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
     934             :                                 SkGetPackedG32(c), SkGetPackedB32(c));
     935             : }
     936             : 
     937             : /*  Assumes 16bit is in standard RGBA order.
     938             :     Transforms a normal ARGB_8888 into the same byte order as
     939             :     expanded ARGB_4444, but keeps each component 8bits
     940             : */
     941             : static inline uint32_t SkExpand_8888(SkPMColor c) {
     942             :     return  (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
     943             :             (((c >> SK_G32_SHIFT) & 0xFF) <<  8) |
     944             :             (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
     945             :             (((c >> SK_A32_SHIFT) & 0xFF) <<  0);
     946             : }
     947             : 
     948             : /*  Undo the operation of SkExpand_8888, turning the argument back into
     949             :     a SkPMColor.
     950             : */
     951           0 : static inline SkPMColor SkCompact_8888(uint32_t c) {
     952           0 :     return  (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
     953           0 :             (((c >>  8) & 0xFF) << SK_G32_SHIFT) |
     954           0 :             (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
     955           0 :             (((c >>  0) & 0xFF) << SK_A32_SHIFT);
     956             : }
     957             : 
     958             : /*  Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
     959             :     but this routine just keeps the high 4bits of each component in the low
     960             :     4bits of the result (just like a newly expanded PMColor16).
     961             : */
     962             : static inline uint32_t SkExpand32_4444(SkPMColor c) {
     963             :     return  (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
     964             :             (((c >> (SK_G32_SHIFT + 4)) & 0xF) <<  8) |
     965             :             (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
     966             :             (((c >> (SK_A32_SHIFT + 4)) & 0xF) <<  0);
     967             : }
     968             : 
     969             : // takes two values and alternamtes them as part of a memset16
     970             : // used for cheap 2x2 dithering when the colors are opaque
     971             : void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
     972             : 
     973             : ///////////////////////////////////////////////////////////////////////////////
     974             : 
     975       18642 : static inline int SkUpscale31To32(int value) {
     976       18642 :     SkASSERT((unsigned)value <= 31);
     977       18642 :     return value + (value >> 4);
     978             : }
     979             : 
     980       18642 : static inline int SkBlend32(int src, int dst, int scale) {
     981       18642 :     SkASSERT((unsigned)src <= 0xFF);
     982       18642 :     SkASSERT((unsigned)dst <= 0xFF);
     983       18642 :     SkASSERT((unsigned)scale <= 32);
     984       18642 :     return dst + ((src - dst) * scale >> 5);
     985             : }
     986             : 
     987        4812 : static inline SkPMColor SkBlendLCD16(int srcA, int srcR, int srcG, int srcB,
     988             :                                      SkPMColor dst, uint16_t mask) {
     989        4812 :     if (mask == 0) {
     990        2763 :         return dst;
     991             :     }
     992             : 
     993             :     /*  We want all of these in 5bits, hence the shifts in case one of them
     994             :      *  (green) is 6bits.
     995             :      */
     996        2049 :     int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
     997        2049 :     int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
     998        2049 :     int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
     999             : 
    1000             :     // Now upscale them to 0..32, so we can use blend32
    1001        2049 :     maskR = SkUpscale31To32(maskR);
    1002        2049 :     maskG = SkUpscale31To32(maskG);
    1003        2049 :     maskB = SkUpscale31To32(maskB);
    1004             : 
    1005             :     // srcA has been upscaled to 256 before passed into this function
    1006        2049 :     maskR = maskR * srcA >> 8;
    1007        2049 :     maskG = maskG * srcA >> 8;
    1008        2049 :     maskB = maskB * srcA >> 8;
    1009             : 
    1010        2049 :     int dstR = SkGetPackedR32(dst);
    1011        2049 :     int dstG = SkGetPackedG32(dst);
    1012        2049 :     int dstB = SkGetPackedB32(dst);
    1013             : 
    1014             :     // LCD blitting is only supported if the dst is known/required
    1015             :     // to be opaque
    1016        6147 :     return SkPackARGB32(0xFF,
    1017        2049 :                         SkBlend32(srcR, dstR, maskR),
    1018        2049 :                         SkBlend32(srcG, dstG, maskG),
    1019        4098 :                         SkBlend32(srcB, dstB, maskB));
    1020             : }
    1021             : 
    1022       11811 : static inline SkPMColor SkBlendLCD16Opaque(int srcR, int srcG, int srcB,
    1023             :                                            SkPMColor dst, uint16_t mask,
    1024             :                                            SkPMColor opaqueDst) {
    1025       11811 :     if (mask == 0) {
    1026        7001 :         return dst;
    1027             :     }
    1028             : 
    1029        4810 :     if (0xFFFF == mask) {
    1030         645 :         return opaqueDst;
    1031             :     }
    1032             : 
    1033             :     /*  We want all of these in 5bits, hence the shifts in case one of them
    1034             :      *  (green) is 6bits.
    1035             :      */
    1036        4165 :     int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
    1037        4165 :     int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
    1038        4165 :     int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
    1039             : 
    1040             :     // Now upscale them to 0..32, so we can use blend32
    1041        4165 :     maskR = SkUpscale31To32(maskR);
    1042        4165 :     maskG = SkUpscale31To32(maskG);
    1043        4165 :     maskB = SkUpscale31To32(maskB);
    1044             : 
    1045        4165 :     int dstR = SkGetPackedR32(dst);
    1046        4165 :     int dstG = SkGetPackedG32(dst);
    1047        4165 :     int dstB = SkGetPackedB32(dst);
    1048             : 
    1049             :     // LCD blitting is only supported if the dst is known/required
    1050             :     // to be opaque
    1051       12495 :     return SkPackARGB32(0xFF,
    1052        4165 :                         SkBlend32(srcR, dstR, maskR),
    1053        4165 :                         SkBlend32(srcG, dstG, maskG),
    1054        8330 :                         SkBlend32(srcB, dstB, maskB));
    1055             : }
    1056             : 
    1057           0 : static inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t mask[],
    1058             :                                   SkColor src, int width, SkPMColor) {
    1059           0 :     int srcA = SkColorGetA(src);
    1060           0 :     int srcR = SkColorGetR(src);
    1061           0 :     int srcG = SkColorGetG(src);
    1062           0 :     int srcB = SkColorGetB(src);
    1063             : 
    1064           0 :     srcA = SkAlpha255To256(srcA);
    1065             : 
    1066           0 :     for (int i = 0; i < width; i++) {
    1067           0 :         dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], mask[i]);
    1068             :     }
    1069           0 : }
    1070             : 
    1071           0 : static inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t mask[],
    1072             :                                         SkColor src, int width,
    1073             :                                         SkPMColor opaqueDst) {
    1074           0 :     int srcR = SkColorGetR(src);
    1075           0 :     int srcG = SkColorGetG(src);
    1076           0 :     int srcB = SkColorGetB(src);
    1077             : 
    1078           0 :     for (int i = 0; i < width; i++) {
    1079           0 :         dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], mask[i],
    1080             :                                     opaqueDst);
    1081             :     }
    1082           0 : }
    1083             : 
    1084             : #endif

Generated by: LCOV version 1.13