SkColorPriv.h revision ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976e
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkColorPriv_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkColorPriv_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// turn this own for extra debug checking when blending onto 565
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define CHECK_FOR_565_OVERFLOW
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColor.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMath.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    byte into a scale value, so that we can say scale * value >> 8 instead of
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    alpha * value / 255.
24e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    In debugging, asserts that alpha is 0..255
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline unsigned SkAlpha255To256(U8CPU alpha) {
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(SkToU8(alpha) == alpha);
299781ca586618cc8ea055f54021e706824313d4f5reed@android.com    // this one assues that blending on top of an opaque dst keeps it that way
309781ca586618cc8ea055f54021e706824313d4f5reed@android.com    // even though it is less accurate than a+(a>>7) for non-opaque dsts
319781ca586618cc8ea055f54021e706824313d4f5reed@android.com    return alpha + 1;
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Multiplify value by 0..256, and shift the result down 8
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (i.e. return (value * alpha256) >> 8)
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkAlphaMul(value, alpha256)     (SkMulS16(value, alpha256) >> 8)
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  The caller may want negative values, so keep all params signed (int)
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  so we don't accidentally slip into unsigned math and lose the sign
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  extension when we shift (in SkAlphaMul)
4234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline int SkAlphaBlend(int src, int dst, int scale256) {
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)scale256 <= 256);
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst + SkAlphaMul(src - dst, scale256);
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_BITS     5
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_BITS     6
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_BITS     5
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_SHIFT    (SK_B16_BITS + SK_G16_BITS)
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_SHIFT    (SK_B16_BITS)
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_SHIFT    0
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_MASK     ((1 << SK_R16_BITS) - 1)
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_MASK     ((1 << SK_G16_BITS) - 1)
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_MASK     ((1 << SK_B16_BITS) - 1)
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedR16(color)   (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedG16(color)   (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedB16(color)   (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR16Assert(r)  SkASSERT((unsigned)(r) <= SK_R16_MASK)
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG16Assert(g)  SkASSERT((unsigned)(g) <= SK_G16_MASK)
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB16Assert(b)  SkASSERT((unsigned)(b) <= SK_B16_MASK)
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= SK_R16_MASK);
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= SK_G16_MASK);
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= SK_B16_MASK);
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_MASK_IN_PLACE        (SK_R16_MASK << SK_R16_SHIFT)
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_MASK_IN_PLACE        (SK_G16_MASK << SK_G16_SHIFT)
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_MASK_IN_PLACE        (SK_B16_MASK << SK_B16_SHIFT)
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Expand the 16bit color into a 32bit value that can be scaled all at once
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by a value up to 32. Used in conjunction with SkCompact_rgb_16.
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint32_t SkExpand_rgb_16(U16CPU c) {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(c == (uint16_t)c);
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    color value. The computation yields only 16bits of valid data, but we claim
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to return 32bits, so that the compiler won't generate extra instructions to
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    "clean" the top 16bits. However, the top 16 can contain garbage, so it is
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    up to the caller to safely ignore them.
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkCompact_rgb_16(uint32_t c) {
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Scale the 16bit color value by the 0..256 scale parameter.
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The computation yields only 16bits of valid data, but we claim
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to return 32bits, so that the compiler won't generate extra instructions to
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    "clean" the top 16bits.
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this helper explicitly returns a clean 16bit value (but slower)
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkAlphaMulRGB16_ToU16(c, s)  (uint16_t)SkAlphaMulRGB16(c, s)
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Blend src and dst 16bit colors by the 0..256 scale parameter.
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The computation yields only 16bits of valid data, but we claim
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to return 32bits, so that the compiler won't generate extra instructions to
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    "clean" the top 16bits.
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)srcScale <= 256);
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcScale >>= 3;
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t src32 = SkExpand_rgb_16(src);
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t dst32 = SkExpand_rgb_16(dst);
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                int srcScale, int count) {
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count > 0);
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)srcScale <= 256);
129e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcScale >>= 3;
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t src32 = SkExpand_rgb_16(*src++);
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t dst32 = SkExpand_rgb_16(*dst);
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (--count > 0);
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
140fc25abdabff76f913fb9d4f373418c10a1eca92breed@android.com    static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
144e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return a + b;
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkRGB16Add(a, b)  ((a) + (b))
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15105ea1810a231b1f699c98a0b6272e08a4c93b06breed@google.com///////////////////////////////////////////////////////////////////////////////
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_A32_BITS     8
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R32_BITS     8
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G32_BITS     8
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B32_BITS     8
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_A32_MASK     ((1 << SK_A32_BITS) - 1)
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R32_MASK     ((1 << SK_R32_BITS) - 1)
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G32_MASK     ((1 << SK_G32_BITS) - 1)
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B32_MASK     ((1 << SK_B32_BITS) - 1)
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedG32(packed)      ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedB32(packed)      ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkA32Assert(a)  SkASSERT((unsigned)(a) <= SK_A32_MASK)
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR32Assert(r)  SkASSERT((unsigned)(r) <= SK_R32_MASK)
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG32Assert(g)  SkASSERT((unsigned)(g) <= SK_G32_MASK)
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB32Assert(b)  SkASSERT((unsigned)(b) <= SK_B32_MASK)
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
17434245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline void SkPMColorAssert(SkPMColor c) {
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned a = SkGetPackedA32(c);
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned r = SkGetPackedR32(c);
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned g = SkGetPackedG32(c);
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned b = SkGetPackedB32(c);
179e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkA32Assert(a);
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(r <= a);
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(g <= a);
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(b <= a);
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkPMColorAssert(c)
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
189e686322eba17fee0b5671393dc842e52f77109d9reed@google.com/**
190e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  Pack the components into a SkPMColor, checking (in the debug version) that
191e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  the components are 0..255, and are already premultiplied (i.e. alpha >= color)
192e686322eba17fee0b5671393dc842e52f77109d9reed@google.com */
19334245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkA32Assert(a);
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= a);
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= a);
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= a);
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
203e686322eba17fee0b5671393dc842e52f77109d9reed@google.com/**
204e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  Same as SkPackARGB32, but this version guarantees to not check that the
205e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  values are premultiplied in the debug version.
206e686322eba17fee0b5671393dc842e52f77109d9reed@google.com */
207e686322eba17fee0b5671393dc842e52f77109d9reed@google.comstatic inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
208e686322eba17fee0b5671393dc842e52f77109d9reed@google.com    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
209e686322eba17fee0b5671393dc842e52f77109d9reed@google.com           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
210e686322eba17fee0b5671393dc842e52f77109d9reed@google.com}
211e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
2120b8b3bb08330dd341acbd52c16e55455325e465areed@google.comstatic inline
2130b8b3bb08330dd341acbd52c16e55455325e465areed@google.comSkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
2140b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    SkA32Assert(a);
2155d2fef0d83f59fc982d78c91c8757d6016bd99c4reed@google.com    SkA32Assert(r);
2165d2fef0d83f59fc982d78c91c8757d6016bd99c4reed@google.com    SkA32Assert(g);
2175d2fef0d83f59fc982d78c91c8757d6016bd99c4reed@google.com    SkA32Assert(b);
2180b8b3bb08330dd341acbd52c16e55455325e465areed@google.com
2190b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    if (a != 255) {
2200b8b3bb08330dd341acbd52c16e55455325e465areed@google.com        r = SkMulDiv255Round(r, a);
2210b8b3bb08330dd341acbd52c16e55455325e465areed@google.com        g = SkMulDiv255Round(g, a);
2220b8b3bb08330dd341acbd52c16e55455325e465areed@google.com        b = SkMulDiv255Round(b, a);
2230b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    }
2240b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    return SkPackARGB32(a, r, g, b);
2250b8b3bb08330dd341acbd52c16e55455325e465areed@google.com}
2260b8b3bb08330dd341acbd52c16e55455325e465areed@google.com
2277ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgSK_API extern const uint32_t gMask_00FF00FF;
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t mask = gMask_00FF00FF;
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//    uint32_t mask = 0xFF00FF;
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t rb = ((c & mask) * scale) >> 8;
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t ag = ((c >> 8) & mask) * scale;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (rb & mask) | (ag & ~mask);
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)aa <= 255);
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned src_scale = SkAlpha255To256(aa);
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale));
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale);
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////////
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Convert a 32bit pixel to a 16bit pixel (no dither)
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR32ToR16_MACRO(r)   ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG32ToG16_MACRO(g)   ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB32ToB16_MACRO(b)   ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
25934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline unsigned SkR32ToR16(unsigned r) {
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkR32Assert(r);
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkR32ToR16_MACRO(r);
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26334245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline unsigned SkG32ToG16(unsigned g) {
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkG32Assert(g);
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkG32ToG16_MACRO(g);
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
26734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline unsigned SkB32ToB16(unsigned b) {
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkB32Assert(b);
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkB32ToB16_MACRO(b);
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkR32ToR16(r)   SkR32ToR16_MACRO(r)
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkG32ToG16(g)   SkG32ToG16_MACRO(g)
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkB32ToB16(b)   SkB32ToB16_MACRO(b)
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked32ToR16(c)  (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked32ToG16(c)  (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked32ToB16(c)  (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkPixel32ToPixel16(SkPMColor c) {
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return r | g | b;
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (SkR32ToR16(r) << SK_R16_SHIFT) |
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (SkG32ToG16(g) << SK_G16_SHIFT) |
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (SkB32ToB16(b) << SK_B16_SHIFT);
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPixel32ToPixel16_ToU16(src)   SkToU16(SkPixel32ToPixel16(src))
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////////////////
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Fast dither from 32->16
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkShouldDitherXY(x, y)  (((x) ^ (y)) & 1)
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
305e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(r, g, b);
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) {
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    It is now suitable for combining with a scaled expanded_rgb_16 color
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    as in SkSrcOver32To16().
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    We must do this 565 high-bit replication, in order for the subsequent add
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to saturate properly (and not overflow). If we take the 8 bits as is, it is
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    possible to overflow.
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
32034245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) {
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkPacked32ToR16(c);
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkPacked32ToG16(c);
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkPacked32ToB16(c);
324e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sr = (sr << 5) | sr;
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg = (sg << 5) | (sg >> 1);
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sb = (sb << 5) | sb;
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (sr << 11) | (sg << 21) | (sb << 0);
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (with dirt in the high 16bits, so caller beware).
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkGetPackedR32(src);
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkGetPackedG32(src);
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkGetPackedB32(src);
338e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dr = SkGetPackedR16(dst);
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dg = SkGetPackedG16(dst);
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned db = SkGetPackedB16(dst);
342e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned isa = 255 - SkGetPackedA32(src);
344e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
348e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(dr, dg, db);
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////////
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Convert a 16bit pixel to a 32bit pixel
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkR16ToR32(unsigned r) {
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
35834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com
35934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkG16ToG32(unsigned g) {
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
36234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com
36334245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkB16ToB32(unsigned b) {
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked16ToR32(c)      SkR16ToR32(SkGetPackedR16(c))
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked16ToG32(c)      SkG16ToG32(SkGetPackedG16(c))
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked16ToB32(c)      SkB16ToB32(SkGetPackedB16(c))
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
37134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPixel16ToPixel32(U16CPU src) {
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(src == SkToU16(src));
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    r = SkPacked16ToR32(src);
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    g = SkPacked16ToG32(src);
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    b = SkPacked16ToB32(src);
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackARGB32(0xFF, r, g, b);
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
385c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com// similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor
386c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.comstatic inline SkColor SkPixel16ToColor(U16CPU src) {
387c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT(src == SkToU16(src));
388e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
389c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    unsigned    r = SkPacked16ToR32(src);
390c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    unsigned    g = SkPacked16ToG32(src);
391c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    unsigned    b = SkPacked16ToB32(src);
392e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
393c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
394c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
395c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
396e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
397c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    return SkColorSetRGB(r, g, b);
398c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com}
399c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef uint16_t SkPMColor16;
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Put in OpenGL order (r g b a)
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_A4444_SHIFT    0
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R4444_SHIFT    12
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G4444_SHIFT    8
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B4444_SHIFT    4
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkA32To4444(a)  ((unsigned)(a) >> 4)
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR32To4444(r)  ((unsigned)(r) >> 4)
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG32To4444(g)  ((unsigned)(g) >> 4)
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB32To4444(b)  ((unsigned)(b) >> 4)
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
41534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U8CPU SkReplicateNibble(unsigned nib) {
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(nib <= 0xF);
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (nib << 4) | nib;
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkA4444ToA32(a)     SkReplicateNibble(a)
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR4444ToR32(r)     SkReplicateNibble(r)
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG4444ToG32(g)     SkReplicateNibble(g)
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB4444ToB32(b)     SkReplicateNibble(b)
4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedA4444(c)     (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedR4444(c)     (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedG4444(c)     (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedB4444(c)     (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToA32(c)    SkReplicateNibble(SkGetPackedA4444(c))
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToR32(c)    SkReplicateNibble(SkGetPackedR4444(c))
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToG32(c)    SkReplicateNibble(SkGetPackedG4444(c))
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToB32(c)    SkReplicateNibble(SkGetPackedB4444(c))
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
43634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline void SkPMColor16Assert(U16CPU c) {
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned a = SkGetPackedA4444(c);
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = SkGetPackedR4444(c);
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = SkGetPackedG4444(c);
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = SkGetPackedB4444(c);
441e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(a <= 0xF);
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= a);
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= a);
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= a);
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPMColor16Assert(c)
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkAlpha15To16(unsigned a) {
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(a <= 0xF);
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return a + (a >> 3);
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
45734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline int SkAlphaMul4(int value, int scale) {
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((unsigned)scale <= 0x10);
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return value * scale >> 4;
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkAlphaMul4(value, scale)   ((value) * (scale) >> 4)
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
46534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkR4444ToR565(unsigned r) {
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= 0xF);
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
47034245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkG4444ToG565(unsigned g) {
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= 0xF);
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
47534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkB4444ToB565(unsigned b) {
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= 0xF);
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
48134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com                                         unsigned g, unsigned b) {
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(a <= 0xF);
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= a);
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= a);
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= a);
486e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                         (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comextern const uint16_t gMask_0F0F;
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
49334245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale) {
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(scale <= 16);
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned mask = 0xF0F;    //gMask_0F0F;
497e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned rb = ((c & mask) * scale) >> 4;
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned ag = ((c >> 4) & mask) * scale;
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (rb & mask) | (ag & ~mask);
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    c = (c & mask) | ((c & (mask << 4)) << 12);
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    c = c * scale >> 4;
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (c & mask) | ((c >> 12) & (mask << 4));
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    once by a value up to 16. Used in conjunction with SkCompact_4444.
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
51234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkExpand_4444(U16CPU c) {
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(c == (uint16_t)c);
514e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned mask = 0xF0F;    //gMask_0F0F;
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (c & mask) | ((c & ~mask) << 12);
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16.
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NOTE: this explicitly does not clean the top 16 bits (which may be garbage).
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    It does this for speed, since if it is being written directly to 16bits of
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    memory, the top 16bits will be ignored. Casting the result to uint16_t here
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    would add 2 more instructions, slow us down. It is up to the caller to
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    perform the cast if needed.
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
52634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkCompact_4444(uint32_t c) {
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned mask = 0xF0F;    //gMask_0F0F;
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (c & mask) | ((c >> 12) & ~mask);
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) {
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sa = SkGetPackedA4444(s);
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // To avoid overflow, we have to clear the low bit of the synthetic sg
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if the src alpha is <= 7.
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // to see why, try blending 0x4444 on top of 565-white and watch green
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overflow (sum == 64)
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg &= ~(~(sa >> 3) & 1);
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned scale = SkAlpha15To16(15 - sa);
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
547e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (sg + dg > 63) {
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(sr + dr, sg + dg, sb + db);
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
55634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) {
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)scale16 <= 16);
558e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16) {
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)scale16 <= 16);
564e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t src32 = SkExpand_4444(src) * scale16;
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // the scaled srcAlpha is the bottom byte
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned srcA = SkGetPackedA4444(src) * scale16;
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(srcA == (src32 & 0xFF));
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4;
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t dst32 = SkExpand_4444(dst) * dstScale;
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkCompact_4444((src32 + dst32) >> 4);
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
57834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPixel4444ToPixel32(U16CPU c) {
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 (SkGetPackedR4444(c) << SK_R32_SHIFT) |
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 (SkGetPackedG4444(c) << SK_G32_SHIFT) |
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 (SkGetPackedB4444(c) << SK_B32_SHIFT);
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return d | (d << 4);
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) {
5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// cheap 2x2 dither
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
59534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com                                               U8CPU g, U8CPU b) {
596735b790150096c3d5e817854b228945a9b869e86reed@android.com    // to ensure that we stay a legal premultiplied color, we take the max()
597735b790150096c3d5e817854b228945a9b869e86reed@android.com    // of the truncated and dithered alpha values. If we didn't, cases like
598735b790150096c3d5e817854b228945a9b869e86reed@android.com    // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...)
599735b790150096c3d5e817854b228945a9b869e86reed@android.com    // which is not legal premultiplied, since a < color
600735b790150096c3d5e817854b228945a9b869e86reed@android.com    unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
601735b790150096c3d5e817854b228945a9b869e86reed@android.com    a = SkMax32(a >> 4, dithered_a);
602735b790150096c3d5e817854b228945a9b869e86reed@android.com    // these we just dither in place
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
606e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackARGB4444(a, r, g, b);
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
61034245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) {
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkGetPackedG32(c), SkGetPackedB32(c));
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Assumes 16bit is in standard RGBA order.
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Transforms a normal ARGB_8888 into the same byte order as
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    expanded ARGB_4444, but keeps each component 8bits
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
61934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkExpand_8888(SkPMColor c) {
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> SK_G32_SHIFT) & 0xFF) <<  8) |
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> SK_A32_SHIFT) & 0xFF) <<  0);
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Undo the operation of SkExpand_8888, turning the argument back into
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    a SkPMColor.
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
62934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkCompact_8888(uint32_t c) {
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >>  8) & 0xFF) << SK_G32_SHIFT) |
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >>  0) & 0xFF) << SK_A32_SHIFT);
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    but this routine just keeps the high 4bits of each component in the low
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    4bits of the result (just like a newly expanded PMColor16).
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
64034245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkExpand32_4444(SkPMColor c) {
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> (SK_G32_SHIFT + 4)) & 0xF) <<  8) |
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> (SK_A32_SHIFT + 4)) & 0xF) <<  0);
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// takes two values and alternamtes them as part of a memset16
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// used for cheap 2x2 dithering when the colors are opaque
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
653