SkColorPriv.h revision 13e812c69a9e2b2550871573786fc72b17bdd766
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
470abb499dafb2550ad81afe11ffede5cab4904575reed@google.com/**
480abb499dafb2550ad81afe11ffede5cab4904575reed@google.com *  Returns (src * alpha + dst * (255 - alpha)) / 255
490abb499dafb2550ad81afe11ffede5cab4904575reed@google.com *
500abb499dafb2550ad81afe11ffede5cab4904575reed@google.com *  This is more accurate than SkAlphaBlend, but slightly slower
510abb499dafb2550ad81afe11ffede5cab4904575reed@google.com */
520abb499dafb2550ad81afe11ffede5cab4904575reed@google.comstatic inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) {
530abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    SkASSERT((int16_t)src == src);
540abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    SkASSERT((int16_t)dst == dst);
550abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    SkASSERT((uint8_t)alpha == alpha);
560abb499dafb2550ad81afe11ffede5cab4904575reed@google.com
570abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    int prod = SkMulS16(src - dst, alpha) + 128;
580abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    prod = (prod + (prod >> 8)) >> 8;
590abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    return dst + prod;
600abb499dafb2550ad81afe11ffede5cab4904575reed@google.com}
610abb499dafb2550ad81afe11ffede5cab4904575reed@google.com
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_BITS     5
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_BITS     6
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_BITS     5
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_SHIFT    (SK_B16_BITS + SK_G16_BITS)
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_SHIFT    (SK_B16_BITS)
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_SHIFT    0
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_MASK     ((1 << SK_R16_BITS) - 1)
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_MASK     ((1 << SK_G16_BITS) - 1)
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_MASK     ((1 << SK_B16_BITS) - 1)
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedR16(color)   (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedG16(color)   (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedB16(color)   (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR16Assert(r)  SkASSERT((unsigned)(r) <= SK_R16_MASK)
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG16Assert(g)  SkASSERT((unsigned)(g) <= SK_G16_MASK)
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB16Assert(b)  SkASSERT((unsigned)(b) <= SK_B16_MASK)
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= SK_R16_MASK);
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= SK_G16_MASK);
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= SK_B16_MASK);
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_MASK_IN_PLACE        (SK_R16_MASK << SK_R16_SHIFT)
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_MASK_IN_PLACE        (SK_G16_MASK << SK_G16_SHIFT)
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_MASK_IN_PLACE        (SK_B16_MASK << SK_B16_SHIFT)
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Expand the 16bit color into a 32bit value that can be scaled all at once
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by a value up to 32. Used in conjunction with SkCompact_rgb_16.
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint32_t SkExpand_rgb_16(U16CPU c) {
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(c == (uint16_t)c);
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    color value. The computation yields only 16bits of valid data, but we claim
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to return 32bits, so that the compiler won't generate extra instructions to
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    "clean" the top 16bits. However, the top 16 can contain garbage, so it is
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    up to the caller to safely ignore them.
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkCompact_rgb_16(uint32_t c) {
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Scale the 16bit color value by the 0..256 scale parameter.
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The computation yields only 16bits of valid data, but we claim
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to return 32bits, so that the compiler won't generate extra instructions to
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    "clean" the top 16bits.
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this helper explicitly returns a clean 16bit value (but slower)
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkAlphaMulRGB16_ToU16(c, s)  (uint16_t)SkAlphaMulRGB16(c, s)
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Blend src and dst 16bit colors by the 0..256 scale parameter.
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The computation yields only 16bits of valid data, but we claim
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to return 32bits, so that the compiler won't generate extra instructions to
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    "clean" the top 16bits.
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)srcScale <= 256);
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcScale >>= 3;
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t src32 = SkExpand_rgb_16(src);
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t dst32 = SkExpand_rgb_16(dst);
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                int srcScale, int count) {
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count > 0);
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)srcScale <= 256);
144e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcScale >>= 3;
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t src32 = SkExpand_rgb_16(*src++);
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t dst32 = SkExpand_rgb_16(*dst);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (--count > 0);
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
155fc25abdabff76f913fb9d4f373418c10a1eca92breed@android.com    static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
159e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return a + b;
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkRGB16Add(a, b)  ((a) + (b))
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16605ea1810a231b1f699c98a0b6272e08a4c93b06breed@google.com///////////////////////////////////////////////////////////////////////////////
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_A32_BITS     8
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R32_BITS     8
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G32_BITS     8
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B32_BITS     8
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_A32_MASK     ((1 << SK_A32_BITS) - 1)
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R32_MASK     ((1 << SK_R32_BITS) - 1)
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G32_MASK     ((1 << SK_G32_BITS) - 1)
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B32_MASK     ((1 << SK_B32_BITS) - 1)
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedG32(packed)      ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedB32(packed)      ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkA32Assert(a)  SkASSERT((unsigned)(a) <= SK_A32_MASK)
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR32Assert(r)  SkASSERT((unsigned)(r) <= SK_R32_MASK)
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG32Assert(g)  SkASSERT((unsigned)(g) <= SK_G32_MASK)
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB32Assert(b)  SkASSERT((unsigned)(b) <= SK_B32_MASK)
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
18934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline void SkPMColorAssert(SkPMColor c) {
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned a = SkGetPackedA32(c);
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned r = SkGetPackedR32(c);
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned g = SkGetPackedG32(c);
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned b = SkGetPackedB32(c);
194e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkA32Assert(a);
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(r <= a);
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(g <= a);
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(b <= a);
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkPMColorAssert(c)
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
204e686322eba17fee0b5671393dc842e52f77109d9reed@google.com/**
205e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  Pack the components into a SkPMColor, checking (in the debug version) that
206e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  the components are 0..255, and are already premultiplied (i.e. alpha >= color)
207e686322eba17fee0b5671393dc842e52f77109d9reed@google.com */
20834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkA32Assert(a);
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= a);
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= a);
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= a);
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
218e686322eba17fee0b5671393dc842e52f77109d9reed@google.com/**
21913e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * Abstract 4-byte interpolation, implemented on top of SkPMColor
22013e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * utility functions. Third parameter controls blending of the first two:
22113e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com *   (src, dst, 0) returns dst
22213e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com *   (src, dst, 0xFF) returns src
22313e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com */
22413e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.comstatic inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst,
22513e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com                                         U8CPU srcWeight) {
22613e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    unsigned scale = SkAlpha255To256(srcWeight);
22713e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
22813e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
22913e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
23013e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
23113e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
23213e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
23313e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    return SkPackARGB32(a, r, g, b);
23413e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com}
23513e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
23613e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com/**
23713e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * 32b optimized version; currently appears to be 10% faster even on 64b
23813e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * architectures than an equivalent 64b version and 30% faster than
23913e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * SkFourByteInterp(). Third parameter controls blending of the first two:
24013e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com *   (src, dst, 0) returns dst
24113e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com *   (src, dst, 0xFF) returns src
24213e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * ** Does not match the results of SkFourByteInterp() because we use
24313e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * a more accurate scale computation!
24413e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * TODO: migrate Skia function to using an accurate 255->266 alpha
24513e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * conversion.
24613e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com */
24713e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.comstatic inline SkPMColor SkFastFourByteInterp(SkPMColor src,
24813e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com                                             SkPMColor dst,
24913e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com                                             U8CPU srcWeight) {
25013e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    SkASSERT(srcWeight < 256);
25113e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
25213e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    // Reorders ARGB to AG-RB in order to reduce the number of operations.
25313e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    const uint32_t mask = 0xFF00FF;
25413e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    uint32_t src_rb = src & mask;
25513e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    uint32_t src_ag = (src >> 8) & mask;
25613e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    uint32_t dst_rb = dst & mask;
25713e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    uint32_t dst_ag = (dst >> 8) & mask;
25813e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
25913e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    // scale = srcWeight + (srcWeight >> 7) is more accurate than
26013e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    // scale = srcWeight + 1, but 7% slower
26113e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    int scale = srcWeight + (srcWeight >> 7);
26213e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
26313e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb;
26413e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag;
26513e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
26613e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    return (ret_ag & ~mask) | ((ret_rb & ~mask) >> 8);
26713e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com}
26813e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
26913e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com/**
270e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  Same as SkPackARGB32, but this version guarantees to not check that the
271e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  values are premultiplied in the debug version.
272e686322eba17fee0b5671393dc842e52f77109d9reed@google.com */
273e686322eba17fee0b5671393dc842e52f77109d9reed@google.comstatic inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
274e686322eba17fee0b5671393dc842e52f77109d9reed@google.com    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
275e686322eba17fee0b5671393dc842e52f77109d9reed@google.com           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
276e686322eba17fee0b5671393dc842e52f77109d9reed@google.com}
277e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
2780b8b3bb08330dd341acbd52c16e55455325e465areed@google.comstatic inline
2790b8b3bb08330dd341acbd52c16e55455325e465areed@google.comSkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
2800b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    SkA32Assert(a);
2815d2fef0d83f59fc982d78c91c8757d6016bd99c4reed@google.com    SkA32Assert(r);
2825d2fef0d83f59fc982d78c91c8757d6016bd99c4reed@google.com    SkA32Assert(g);
2835d2fef0d83f59fc982d78c91c8757d6016bd99c4reed@google.com    SkA32Assert(b);
2840b8b3bb08330dd341acbd52c16e55455325e465areed@google.com
2850b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    if (a != 255) {
2860b8b3bb08330dd341acbd52c16e55455325e465areed@google.com        r = SkMulDiv255Round(r, a);
2870b8b3bb08330dd341acbd52c16e55455325e465areed@google.com        g = SkMulDiv255Round(g, a);
2880b8b3bb08330dd341acbd52c16e55455325e465areed@google.com        b = SkMulDiv255Round(b, a);
2890b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    }
2900b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    return SkPackARGB32(a, r, g, b);
2910b8b3bb08330dd341acbd52c16e55455325e465areed@google.com}
2920b8b3bb08330dd341acbd52c16e55455325e465areed@google.com
2937ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgSK_API extern const uint32_t gMask_00FF00FF;
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t mask = gMask_00FF00FF;
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//    uint32_t mask = 0xFF00FF;
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t rb = ((c & mask) * scale) >> 8;
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t ag = ((c >> 8) & mask) * scale;
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (rb & mask) | (ag & ~mask);
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30434245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)aa <= 255);
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned src_scale = SkAlpha255To256(aa);
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale));
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale);
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////////
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Convert a 32bit pixel to a 16bit pixel (no dither)
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR32ToR16_MACRO(r)   ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG32ToG16_MACRO(g)   ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB32ToB16_MACRO(b)   ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
32534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline unsigned SkR32ToR16(unsigned r) {
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkR32Assert(r);
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkR32ToR16_MACRO(r);
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
32934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline unsigned SkG32ToG16(unsigned g) {
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkG32Assert(g);
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkG32ToG16_MACRO(g);
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
33334245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline unsigned SkB32ToB16(unsigned b) {
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkB32Assert(b);
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkB32ToB16_MACRO(b);
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkR32ToR16(r)   SkR32ToR16_MACRO(r)
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkG32ToG16(g)   SkG32ToG16_MACRO(g)
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkB32ToB16(b)   SkB32ToB16_MACRO(b)
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked32ToR16(c)  (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked32ToG16(c)  (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked32ToB16(c)  (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkPixel32ToPixel16(SkPMColor c) {
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return r | g | b;
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35434245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (SkR32ToR16(r) << SK_R16_SHIFT) |
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (SkG32ToG16(g) << SK_G16_SHIFT) |
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (SkB32ToB16(b) << SK_B16_SHIFT);
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPixel32ToPixel16_ToU16(src)   SkToU16(SkPixel32ToPixel16(src))
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////////////////
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Fast dither from 32->16
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkShouldDitherXY(x, y)  (((x) ^ (y)) & 1)
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
36734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
371e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(r, g, b);
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
37534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) {
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    It is now suitable for combining with a scaled expanded_rgb_16 color
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    as in SkSrcOver32To16().
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    We must do this 565 high-bit replication, in order for the subsequent add
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to saturate properly (and not overflow). If we take the 8 bits as is, it is
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    possible to overflow.
3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
38634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) {
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkPacked32ToR16(c);
3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkPacked32ToG16(c);
3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkPacked32ToB16(c);
390e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sr = (sr << 5) | sr;
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg = (sg << 5) | (sg >> 1);
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sb = (sb << 5) | sb;
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (sr << 11) | (sg << 21) | (sb << 0);
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (with dirt in the high 16bits, so caller beware).
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkGetPackedR32(src);
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkGetPackedG32(src);
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkGetPackedB32(src);
404e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dr = SkGetPackedR16(dst);
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dg = SkGetPackedG16(dst);
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned db = SkGetPackedB16(dst);
408e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned isa = 255 - SkGetPackedA32(src);
410e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
414e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(dr, dg, db);
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////////
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Convert a 16bit pixel to a 32bit pixel
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkR16ToR32(unsigned r) {
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
42434245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com
42534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkG16ToG32(unsigned g) {
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
42834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com
42934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkB16ToB32(unsigned b) {
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked16ToR32(c)      SkR16ToR32(SkGetPackedR16(c))
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked16ToG32(c)      SkG16ToG32(SkGetPackedG16(c))
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked16ToB32(c)      SkB16ToB32(SkGetPackedB16(c))
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
43734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPixel16ToPixel32(U16CPU src) {
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(src == SkToU16(src));
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    r = SkPacked16ToR32(src);
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    g = SkPacked16ToG32(src);
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    b = SkPacked16ToB32(src);
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackARGB32(0xFF, r, g, b);
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
451c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com// similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor
452c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.comstatic inline SkColor SkPixel16ToColor(U16CPU src) {
453c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT(src == SkToU16(src));
454e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
455c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    unsigned    r = SkPacked16ToR32(src);
456c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    unsigned    g = SkPacked16ToG32(src);
457c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    unsigned    b = SkPacked16ToB32(src);
458e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
459c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
460c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
461c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
462e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
463c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    return SkColorSetRGB(r, g, b);
464c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com}
465c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef uint16_t SkPMColor16;
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Put in OpenGL order (r g b a)
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_A4444_SHIFT    0
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R4444_SHIFT    12
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G4444_SHIFT    8
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B4444_SHIFT    4
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkA32To4444(a)  ((unsigned)(a) >> 4)
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR32To4444(r)  ((unsigned)(r) >> 4)
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG32To4444(g)  ((unsigned)(g) >> 4)
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB32To4444(b)  ((unsigned)(b) >> 4)
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
48134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U8CPU SkReplicateNibble(unsigned nib) {
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(nib <= 0xF);
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (nib << 4) | nib;
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkA4444ToA32(a)     SkReplicateNibble(a)
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR4444ToR32(r)     SkReplicateNibble(r)
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG4444ToG32(g)     SkReplicateNibble(g)
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB4444ToB32(b)     SkReplicateNibble(b)
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedA4444(c)     (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedR4444(c)     (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedG4444(c)     (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedB4444(c)     (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToA32(c)    SkReplicateNibble(SkGetPackedA4444(c))
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToR32(c)    SkReplicateNibble(SkGetPackedR4444(c))
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToG32(c)    SkReplicateNibble(SkGetPackedG4444(c))
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToB32(c)    SkReplicateNibble(SkGetPackedB4444(c))
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
50234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline void SkPMColor16Assert(U16CPU c) {
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned a = SkGetPackedA4444(c);
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = SkGetPackedR4444(c);
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = SkGetPackedG4444(c);
5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = SkGetPackedB4444(c);
507e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(a <= 0xF);
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= a);
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= a);
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= a);
5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPMColor16Assert(c)
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
51734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkAlpha15To16(unsigned a) {
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(a <= 0xF);
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return a + (a >> 3);
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
52334245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline int SkAlphaMul4(int value, int scale) {
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((unsigned)scale <= 0x10);
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return value * scale >> 4;
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkAlphaMul4(value, scale)   ((value) * (scale) >> 4)
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkR4444ToR565(unsigned r) {
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= 0xF);
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkG4444ToG565(unsigned g) {
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= 0xF);
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkB4444ToB565(unsigned b) {
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= 0xF);
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
54734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com                                         unsigned g, unsigned b) {
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(a <= 0xF);
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= a);
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= a);
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= a);
552e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                         (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comextern const uint16_t gMask_0F0F;
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
55934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale) {
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(scale <= 16);
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned mask = 0xF0F;    //gMask_0F0F;
563e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned rb = ((c & mask) * scale) >> 4;
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned ag = ((c >> 4) & mask) * scale;
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (rb & mask) | (ag & ~mask);
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    c = (c & mask) | ((c & (mask << 4)) << 12);
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    c = c * scale >> 4;
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (c & mask) | ((c >> 12) & (mask << 4));
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    once by a value up to 16. Used in conjunction with SkCompact_4444.
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
57834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkExpand_4444(U16CPU c) {
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(c == (uint16_t)c);
580e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned mask = 0xF0F;    //gMask_0F0F;
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (c & mask) | ((c & ~mask) << 12);
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16.
5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NOTE: this explicitly does not clean the top 16 bits (which may be garbage).
5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    It does this for speed, since if it is being written directly to 16bits of
5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    memory, the top 16bits will be ignored. Casting the result to uint16_t here
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    would add 2 more instructions, slow us down. It is up to the caller to
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    perform the cast if needed.
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
59234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkCompact_4444(uint32_t c) {
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned mask = 0xF0F;    //gMask_0F0F;
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (c & mask) | ((c >> 12) & ~mask);
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
59734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) {
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sa = SkGetPackedA4444(s);
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // To avoid overflow, we have to clear the low bit of the synthetic sg
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if the src alpha is <= 7.
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // to see why, try blending 0x4444 on top of 565-white and watch green
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overflow (sum == 64)
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg &= ~(~(sa >> 3) & 1);
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned scale = SkAlpha15To16(15 - sa);
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
613e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (sg + dg > 63) {
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(sr + dr, sg + dg, sb + db);
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) {
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)scale16 <= 16);
624e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16) {
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)scale16 <= 16);
630e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t src32 = SkExpand_4444(src) * scale16;
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // the scaled srcAlpha is the bottom byte
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned srcA = SkGetPackedA4444(src) * scale16;
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(srcA == (src32 & 0xFF));
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4;
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t dst32 = SkExpand_4444(dst) * dstScale;
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkCompact_4444((src32 + dst32) >> 4);
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
64434245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPixel4444ToPixel32(U16CPU c) {
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 (SkGetPackedR4444(c) << SK_R32_SHIFT) |
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 (SkGetPackedG4444(c) << SK_G32_SHIFT) |
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 (SkGetPackedB4444(c) << SK_B32_SHIFT);
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return d | (d << 4);
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) {
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// cheap 2x2 dither
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
66134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com                                               U8CPU g, U8CPU b) {
662735b790150096c3d5e817854b228945a9b869e86reed@android.com    // to ensure that we stay a legal premultiplied color, we take the max()
663735b790150096c3d5e817854b228945a9b869e86reed@android.com    // of the truncated and dithered alpha values. If we didn't, cases like
664735b790150096c3d5e817854b228945a9b869e86reed@android.com    // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...)
665735b790150096c3d5e817854b228945a9b869e86reed@android.com    // which is not legal premultiplied, since a < color
666735b790150096c3d5e817854b228945a9b869e86reed@android.com    unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
667735b790150096c3d5e817854b228945a9b869e86reed@android.com    a = SkMax32(a >> 4, dithered_a);
668735b790150096c3d5e817854b228945a9b869e86reed@android.com    // these we just dither in place
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
672e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackARGB4444(a, r, g, b);
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
67634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) {
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkGetPackedG32(c), SkGetPackedB32(c));
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Assumes 16bit is in standard RGBA order.
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Transforms a normal ARGB_8888 into the same byte order as
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    expanded ARGB_4444, but keeps each component 8bits
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
68534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkExpand_8888(SkPMColor c) {
6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> SK_G32_SHIFT) & 0xFF) <<  8) |
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> SK_A32_SHIFT) & 0xFF) <<  0);
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Undo the operation of SkExpand_8888, turning the argument back into
6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    a SkPMColor.
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
69534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkCompact_8888(uint32_t c) {
6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >>  8) & 0xFF) << SK_G32_SHIFT) |
6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >>  0) & 0xFF) << SK_A32_SHIFT);
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    but this routine just keeps the high 4bits of each component in the low
7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    4bits of the result (just like a newly expanded PMColor16).
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
70634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkExpand32_4444(SkPMColor c) {
7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> (SK_G32_SHIFT + 4)) & 0xF) <<  8) |
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> (SK_A32_SHIFT + 4)) & 0xF) <<  0);
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// takes two values and alternamtes them as part of a memset16
7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// used for cheap 2x2 dithering when the colors are opaque
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
719