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