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