180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SkColorPriv_DEFINED 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkColorPriv_DEFINED 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// turn this own for extra debug checking when blending onto 565 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define CHECK_FOR_565_OVERFLOW 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkColor.h" 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMath.h" 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///@{ 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** See ITU-R Recommendation BT.709 at http://www.itu.int/rec/R-REC-BT.709/ .*/ 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_ITU_BT709_LUM_COEFF_R (0.2126f) 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_ITU_BT709_LUM_COEFF_G (0.7152f) 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_ITU_BT709_LUM_COEFF_B (0.0722f) 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///@} 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///@{ 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** A float value which specifies this channel's contribution to luminance. */ 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_LUM_COEFF_R SK_ITU_BT709_LUM_COEFF_R 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_LUM_COEFF_G SK_ITU_BT709_LUM_COEFF_G 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_LUM_COEFF_B SK_ITU_BT709_LUM_COEFF_B 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///@} 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Computes the luminance from the given r, g, and b in accordance with 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SK_LUM_COEFF_X. For correct results, r, g, and b should be in linear space. 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline U8CPU SkComputeLuminance(U8CPU r, U8CPU g, U8CPU b) { 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //The following is 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //r * SK_LUM_COEFF_R + g * SK_LUM_COEFF_G + b * SK_LUM_COEFF_B 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru //with SK_LUM_COEFF_X in 1.8 fixed point (rounding adjusted to sum to 256). 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (r * 54 + g * 183 + b * 19) >> 8; 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru byte into a scale value, so that we can say scale * value >> 8 instead of 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru alpha * value / 255. 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru In debugging, asserts that alpha is 0..255 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline unsigned SkAlpha255To256(U8CPU alpha) { 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(SkToU8(alpha) == alpha); 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // this one assues that blending on top of an opaque dst keeps it that way 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // even though it is less accurate than a+(a>>7) for non-opaque dsts 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return alpha + 1; 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Multiplify value by 0..256, and shift the result down 8 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (i.e. return (value * alpha256) >> 8) 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkAlphaMul(value, alpha256) (SkMulS16(value, alpha256) >> 8) 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// The caller may want negative values, so keep all params signed (int) 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// so we don't accidentally slip into unsigned math and lose the sign 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// extension when we shift (in SkAlphaMul) 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int SkAlphaBlend(int src, int dst, int scale256) { 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)scale256 <= 256); 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst + SkAlphaMul(src - dst, scale256); 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Returns (src * alpha + dst * (255 - alpha)) / 255 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * This is more accurate than SkAlphaBlend, but slightly slower 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) { 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((int16_t)src == src); 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((int16_t)dst == dst); 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((uint8_t)alpha == alpha); 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int prod = SkMulS16(src - dst, alpha) + 128; 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru prod = (prod + (prod >> 8)) >> 8; 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst + prod; 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_R16_BITS 5 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_G16_BITS 6 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_B16_BITS 5 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_R16_SHIFT (SK_B16_BITS + SK_G16_BITS) 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_G16_SHIFT (SK_B16_BITS) 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_B16_SHIFT 0 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_R16_MASK ((1 << SK_R16_BITS) - 1) 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_G16_MASK ((1 << SK_G16_BITS) - 1) 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_B16_MASK ((1 << SK_B16_BITS) - 1) 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedR16(color) (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK) 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedG16(color) (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK) 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedB16(color) (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK) 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkR16Assert(r) SkASSERT((unsigned)(r) <= SK_R16_MASK) 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkG16Assert(g) SkASSERT((unsigned)(g) <= SK_G16_MASK) 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkB16Assert(b) SkASSERT((unsigned)(b) <= SK_B16_MASK) 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) { 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(r <= SK_R16_MASK); 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(g <= SK_G16_MASK); 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(b <= SK_B16_MASK); 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT)); 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_R16_MASK_IN_PLACE (SK_R16_MASK << SK_R16_SHIFT) 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_G16_MASK_IN_PLACE (SK_G16_MASK << SK_G16_SHIFT) 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_B16_MASK_IN_PLACE (SK_B16_MASK << SK_B16_SHIFT) 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Expand the 16bit color into a 32bit value that can be scaled all at once 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru by a value up to 32. Used in conjunction with SkCompact_rgb_16. 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint32_t SkExpand_rgb_16(U16CPU c) { 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(c == (uint16_t)c); 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE); 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru color value. The computation yields only 16bits of valid data, but we claim 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru to return 32bits, so that the compiler won't generate extra instructions to 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru "clean" the top 16bits. However, the top 16 can contain garbage, so it is 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru up to the caller to safely ignore them. 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline U16CPU SkCompact_rgb_16(uint32_t c) { 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE); 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Scale the 16bit color value by the 0..256 scale parameter. 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru The computation yields only 16bits of valid data, but we claim 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru to return 32bits, so that the compiler won't generate extra instructions to 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru "clean" the top 16bits. 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) { 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5); 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// this helper explicitly returns a clean 16bit value (but slower) 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkAlphaMulRGB16_ToU16(c, s) (uint16_t)SkAlphaMulRGB16(c, s) 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Blend src and dst 16bit colors by the 0..256 scale parameter. 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru The computation yields only 16bits of valid data, but we claim 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru to return 32bits, so that the compiler won't generate extra instructions to 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru "clean" the top 16bits. 15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) { 15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)srcScale <= 256); 15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru srcScale >>= 3; 15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t src32 = SkExpand_rgb_16(src); 16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t dst32 = SkExpand_rgb_16(dst); 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)); 16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[], 16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int srcScale, int count) { 16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(count > 0); 16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)srcScale <= 256); 16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru srcScale >>= 3; 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru do { 17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t src32 = SkExpand_rgb_16(*src++); 17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t dst32 = SkExpand_rgb_16(*dst); 17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)); 17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } while (--count > 0); 17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG 17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) { 18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK); 18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK); 18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK); 18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return a + b; 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkRGB16Add(a, b) ((a) + (b)) 18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_A32_BITS 8 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_R32_BITS 8 19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_G32_BITS 8 19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_B32_BITS 8 19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_A32_MASK ((1 << SK_A32_BITS) - 1) 19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_R32_MASK ((1 << SK_R32_BITS) - 1) 19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_G32_MASK ((1 << SK_G32_BITS) - 1) 20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_B32_MASK ((1 << SK_B32_BITS) - 1) 20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedA32(packed) ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24) 20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedR32(packed) ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24) 20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedG32(packed) ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24) 20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedB32(packed) ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24) 20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkA32Assert(a) SkASSERT((unsigned)(a) <= SK_A32_MASK) 20880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkR32Assert(r) SkASSERT((unsigned)(r) <= SK_R32_MASK) 20980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkG32Assert(g) SkASSERT((unsigned)(g) <= SK_G32_MASK) 21080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkB32Assert(b) SkASSERT((unsigned)(b) <= SK_B32_MASK) 21180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 21280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG 21380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static inline void SkPMColorAssert(SkPMColor c) { 21480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned a = SkGetPackedA32(c); 21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned r = SkGetPackedR32(c); 21680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned g = SkGetPackedG32(c); 21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned b = SkGetPackedB32(c); 21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 21980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkA32Assert(a); 22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(r <= a); 22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(g <= a); 22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(b <= a); 22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkPMColorAssert(c) 22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Pack the components into a SkPMColor, checking (in the debug version) that 23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * the components are 0..255, and are already premultiplied (i.e. alpha >= color) 23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { 23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkA32Assert(a); 23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(r <= a); 23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(g <= a); 23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(b <= a); 23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) | 23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT); 24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Abstract 4-byte interpolation, implemented on top of SkPMColor 24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * utility functions. Third parameter controls blending of the first two: 24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * (src, dst, 0) returns dst 24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * (src, dst, 0xFF) returns src 24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * srcWeight is [0..256], unlike SkFourByteInterp which takes [0..255] 24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkFourByteInterp256(SkPMColor src, SkPMColor dst, 25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned scale) { 25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale); 25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale); 25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale); 25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale); 25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkPackARGB32(a, r, g, b); 25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Abstract 4-byte interpolation, implemented on top of SkPMColor 26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * utility functions. Third parameter controls blending of the first two: 26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * (src, dst, 0) returns dst 26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * (src, dst, 0xFF) returns src 26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst, 26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru U8CPU srcWeight) { 26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned scale = SkAlpha255To256(srcWeight); 26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkFourByteInterp256(src, dst, scale); 26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 272910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * 0xAARRGGBB -> 0x00AA00GG, 0x00RR00BB 273910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger */ 274910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic inline void SkSplay(uint32_t color, uint32_t* ag, uint32_t* rb) { 275910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const uint32_t mask = 0x00FF00FF; 276910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *ag = (color >> 8) & mask; 277910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger *rb = color & mask; 278910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 279910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 280910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger/** 281910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * 0xAARRGGBB -> 0x00AA00GG00RR00BB 282910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * (note, ARGB -> AGRB) 283910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger */ 284910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic inline uint64_t SkSplay(uint32_t color) { 285910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const uint32_t mask = 0x00FF00FF; 286910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger uint64_t agrb = (color >> 8) & mask; // 0x0000000000AA00GG 287910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger agrb <<= 32; // 0x00AA00GG00000000 288910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger agrb |= color & mask; // 0x00AA00GG00RR00BB 289910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger return agrb; 290910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 291910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 292910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger/** 293910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * 0xAAxxGGxx, 0xRRxxBBxx-> 0xAARRGGBB 294910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger */ 295910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic inline uint32_t SkUnsplay(uint32_t ag, uint32_t rb) { 296910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const uint32_t mask = 0xFF00FF00; 297910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger return (ag & mask) | ((rb & mask) >> 8); 298910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 299910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 300910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger/** 301910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * 0xAAxxGGxxRRxxBBxx -> 0xAARRGGBB 302910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * (note, AGRB -> ARGB) 30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 304910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic inline uint32_t SkUnsplay(uint64_t agrb) { 305910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const uint32_t mask = 0xFF00FF00; 306910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger return SkPMColor( 307910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger ((agrb & mask) >> 8) | // 0x00RR00BB 308910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger ((agrb >> 32) & mask)); // 0xAARRGGBB 309910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 310910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 311910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic inline SkPMColor SkFastFourByteInterp256_32(SkPMColor src, SkPMColor dst, unsigned scale) { 3127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(scale <= 256); 31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 314910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // Two 8-bit blends per two 32-bit registers, with space to make sure the math doesn't collide. 315910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger uint32_t src_ag, src_rb, dst_ag, dst_rb; 316910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkSplay(src, &src_ag, &src_rb); 317910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkSplay(dst, &dst_ag, &dst_rb); 31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 319910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag; 320910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger const uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb; 32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 322910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger return SkUnsplay(ret_ag, ret_rb); 32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 325910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic inline SkPMColor SkFastFourByteInterp256_64(SkPMColor src, SkPMColor dst, unsigned scale) { 326910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger SkASSERT(scale <= 256); 327910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // Four 8-bit blends in one 64-bit register, with space to make sure the math doesn't collide. 328910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger return SkUnsplay(SkSplay(src) * scale + (256-scale) * SkSplay(dst)); 329910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 330910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 331910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger// TODO(mtklein): Replace slow versions with fast versions, using scale + (scale>>7) everywhere. 332910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 333910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger/** 334910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * Same as SkFourByteInterp256, but faster. 335910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger */ 336910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenbergerstatic inline SkPMColor SkFastFourByteInterp256(SkPMColor src, SkPMColor dst, unsigned scale) { 337910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger // On a 64-bit machine, _64 is about 10% faster than _32, but ~40% slower on a 32-bit machine. 338910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger if (sizeof(void*) == 4) { 339910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger return SkFastFourByteInterp256_32(src, dst, scale); 340910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger } else { 341910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger return SkFastFourByteInterp256_64(src, dst, scale); 342910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger } 343910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger} 344910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger 345910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger/** 346910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * Nearly the same as SkFourByteInterp, but faster and a touch more accurate, due to better 347910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger * srcWeight scaling to [0, 256]. 348910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger */ 3497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic inline SkPMColor SkFastFourByteInterp(SkPMColor src, 3507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkPMColor dst, 3517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger U8CPU srcWeight) { 3527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(srcWeight <= 255); 3537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // scale = srcWeight + (srcWeight >> 7) is more accurate than 3547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // scale = srcWeight + 1, but 7% slower 3557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return SkFastFourByteInterp256(src, dst, srcWeight + (srcWeight >> 7)); 3567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 3577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Same as SkPackARGB32, but this version guarantees to not check that the 36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * values are premultiplied in the debug version. 36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { 36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) | 36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT); 36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline 36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { 36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkA32Assert(a); 37058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkR32Assert(r); 37158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkG32Assert(g); 37258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkB32Assert(b); 37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (a != 255) { 37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru r = SkMulDiv255Round(r, a); 37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru g = SkMulDiv255Round(g, a); 37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru b = SkMulDiv255Round(b, a); 37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkPackARGB32(a, r, g, b); 38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSK_API extern const uint32_t gMask_00FF00FF; 38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) { 38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t mask = gMask_00FF00FF; 38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t rb = ((c & mask) * scale) >> 8; 38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t ag = ((c >> 8) & mask) * scale; 38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (rb & mask) | (ag & ~mask); 39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) { 39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) { 39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)aa <= 255); 39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned src_scale = SkAlpha255To256(aa); 40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale)); 40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale); 40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////////////////////////////////////////////////////////////////////////////////////// 40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Convert a 32bit pixel to a 16bit pixel (no dither) 40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkR32ToR16_MACRO(r) ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS)) 40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkG32ToG16_MACRO(g) ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS)) 41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkB32ToB16_MACRO(b) ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS)) 41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG 41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static inline unsigned SkR32ToR16(unsigned r) { 41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkR32Assert(r); 41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkR32ToR16_MACRO(r); 41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static inline unsigned SkG32ToG16(unsigned g) { 41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkG32Assert(g); 41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkG32ToG16_MACRO(g); 42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static inline unsigned SkB32ToB16(unsigned b) { 42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkB32Assert(b); 42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkB32ToB16_MACRO(b); 42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkR32ToR16(r) SkR32ToR16_MACRO(r) 42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkG32ToG16(g) SkG32ToG16_MACRO(g) 42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkB32ToB16(b) SkB32ToB16_MACRO(b) 42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPacked32ToR16(c) (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK) 43280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPacked32ToG16(c) (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK) 43380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPacked32ToB16(c) (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK) 43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline U16CPU SkPixel32ToPixel16(SkPMColor c) { 43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT; 43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT; 43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT; 43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return r | g | b; 44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) { 44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (SkR32ToR16(r) << SK_R16_SHIFT) | 44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (SkG32ToG16(g) << SK_G16_SHIFT) | 44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (SkB32ToB16(b) << SK_B16_SHIFT); 44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 44780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 44880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPixel32ToPixel16_ToU16(src) SkToU16(SkPixel32ToPixel16(src)) 44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////////////// 45180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Fast dither from 32->16 45280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkShouldDitherXY(x, y) (((x) ^ (y)) & 1) 45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) { 45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS); 45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS); 45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS); 45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkPackRGB16(r, g, b); 46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 46280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) { 46480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c)); 46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits) 46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru It is now suitable for combining with a scaled expanded_rgb_16 color 46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru as in SkSrcOver32To16(). 47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru We must do this 565 high-bit replication, in order for the subsequent add 47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru to saturate properly (and not overflow). If we take the 8 bits as is, it is 47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru possible to overflow. 47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 47480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) { 47580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned sr = SkPacked32ToR16(c); 47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned sg = SkPacked32ToG16(c); 47780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned sb = SkPacked32ToB16(c); 47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sr = (sr << 5) | sr; 48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sg = (sg << 5) | (sg >> 1); 48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sb = (sb << 5) | sb; 48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (sr << 11) | (sg << 21) | (sb << 0); 48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* SrcOver the 32bit src color with the 16bit dst, returning a 16bit value 48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (with dirt in the high 16bits, so caller beware). 48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) { 48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned sr = SkGetPackedR32(src); 49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned sg = SkGetPackedG32(src); 49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned sb = SkGetPackedB32(src); 49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned dr = SkGetPackedR16(dst); 49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned dg = SkGetPackedG16(dst); 49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned db = SkGetPackedB16(dst); 49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned isa = 255 - SkGetPackedA32(src); 49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS); 50080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS); 50180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS); 50280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 50380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkPackRGB16(dr, dg, db); 50480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 50580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 50680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru//////////////////////////////////////////////////////////////////////////////////////////// 50780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Convert a 16bit pixel to a 32bit pixel 50880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 50980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline unsigned SkR16ToR32(unsigned r) { 51080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8)); 51180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 51280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 51380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline unsigned SkG16ToG32(unsigned g) { 51480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8)); 51580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 51680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 51780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline unsigned SkB16ToB32(unsigned b) { 51880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8)); 51980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 52080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 52180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPacked16ToR32(c) SkR16ToR32(SkGetPackedR16(c)) 52280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPacked16ToG32(c) SkG16ToG32(SkGetPackedG16(c)) 52380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPacked16ToB32(c) SkB16ToB32(SkGetPackedB16(c)) 52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 52580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkPixel16ToPixel32(U16CPU src) { 52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(src == SkToU16(src)); 52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned r = SkPacked16ToR32(src); 52980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned g = SkPacked16ToG32(src); 53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned b = SkPacked16ToB32(src); 53180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 53280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src)); 53380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src)); 53480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src)); 53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 53680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkPackARGB32(0xFF, r, g, b); 53780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 53880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 53980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor 54080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkColor SkPixel16ToColor(U16CPU src) { 54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(src == SkToU16(src)); 54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned r = SkPacked16ToR32(src); 54480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned g = SkPacked16ToG32(src); 54580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned b = SkPacked16ToB32(src); 54680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src)); 54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src)); 54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src)); 55080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 55180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkColorSetRGB(r, g, b); 55280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 55380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutypedef uint16_t SkPMColor16; 55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Put in OpenGL order (r g b a) 55980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_A4444_SHIFT 0 56080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_R4444_SHIFT 12 56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_G4444_SHIFT 8 56280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SK_B4444_SHIFT 4 56380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkA32To4444(a) ((unsigned)(a) >> 4) 56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkR32To4444(r) ((unsigned)(r) >> 4) 56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkG32To4444(g) ((unsigned)(g) >> 4) 56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkB32To4444(b) ((unsigned)(b) >> 4) 56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 56980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline U8CPU SkReplicateNibble(unsigned nib) { 57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(nib <= 0xF); 57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (nib << 4) | nib; 57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 57380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 57480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkA4444ToA32(a) SkReplicateNibble(a) 57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkR4444ToR32(r) SkReplicateNibble(r) 57680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkG4444ToG32(g) SkReplicateNibble(g) 57780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkB4444ToB32(b) SkReplicateNibble(b) 57880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedA4444(c) (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF) 58080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedR4444(c) (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF) 58180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedG4444(c) (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF) 58280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkGetPackedB4444(c) (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF) 58380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPacked4444ToA32(c) SkReplicateNibble(SkGetPackedA4444(c)) 58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPacked4444ToR32(c) SkReplicateNibble(SkGetPackedR4444(c)) 58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPacked4444ToG32(c) SkReplicateNibble(SkGetPackedG4444(c)) 58780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPacked4444ToB32(c) SkReplicateNibble(SkGetPackedB4444(c)) 58880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 58980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG 59080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline void SkPMColor16Assert(U16CPU c) { 59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned a = SkGetPackedA4444(c); 59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned r = SkGetPackedR4444(c); 59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned g = SkGetPackedG4444(c); 59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned b = SkGetPackedB4444(c); 59580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 59680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(a <= 0xF); 59780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(r <= a); 59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(g <= a); 59980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(b <= a); 60080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkPMColor16Assert(c) 60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline unsigned SkAlpha15To16(unsigned a) { 60680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(a <= 0xF); 60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return a + (a >> 3); 60880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 60980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 61080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG 61180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static inline int SkAlphaMul4(int value, int scale) { 61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)scale <= 0x10); 61380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return value * scale >> 4; 61480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 61580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 61680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define SkAlphaMul4(value, scale) ((value) * (scale) >> 4) 61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline unsigned SkR4444ToR565(unsigned r) { 62080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(r <= 0xF); 62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS)); 62280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 62380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline unsigned SkG4444ToG565(unsigned g) { 62580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(g <= 0xF); 62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS)); 62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline unsigned SkB4444ToB565(unsigned b) { 63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(b <= 0xF); 63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS)); 63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 63380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 63480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r, 63580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned g, unsigned b) { 63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(a <= 0xF); 63780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(r <= a); 63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(g <= a); 63980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(b <= a); 64080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 64180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) | 64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT)); 64380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruextern const uint16_t gMask_0F0F; 64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale) { 64880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(scale <= 16); 64980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const unsigned mask = 0xF0F; //gMask_0F0F; 65180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 65280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0 65380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned rb = ((c & mask) * scale) >> 4; 65480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned ag = ((c >> 4) & mask) * scale; 65580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (rb & mask) | (ag & ~mask); 65680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 65780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c = (c & mask) | ((c & (mask << 4)) << 12); 65880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru c = c * scale >> 4; 65980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (c & mask) | ((c >> 12) & (mask << 4)); 66080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Expand the SkPMColor16 color into a 32bit value that can be scaled all at 66480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru once by a value up to 16. Used in conjunction with SkCompact_4444. 66580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 66680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint32_t SkExpand_4444(U16CPU c) { 66780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(c == (uint16_t)c); 66880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 66980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const unsigned mask = 0xF0F; //gMask_0F0F; 67080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (c & mask) | ((c & ~mask) << 12); 67180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 67280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 67380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16. 67480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru NOTE: this explicitly does not clean the top 16 bits (which may be garbage). 67580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru It does this for speed, since if it is being written directly to 16bits of 67680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru memory, the top 16bits will be ignored. Casting the result to uint16_t here 67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru would add 2 more instructions, slow us down. It is up to the caller to 67880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru perform the cast if needed. 67980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 68080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline U16CPU SkCompact_4444(uint32_t c) { 68180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru const unsigned mask = 0xF0F; //gMask_0F0F; 68280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (c & mask) | ((c >> 12) & ~mask); 68380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 68480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 68580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) { 68680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned sa = SkGetPackedA4444(s); 68780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned sr = SkR4444ToR565(SkGetPackedR4444(s)); 68880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned sg = SkG4444ToG565(SkGetPackedG4444(s)); 68980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned sb = SkB4444ToB565(SkGetPackedB4444(s)); 69080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 69180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // To avoid overflow, we have to clear the low bit of the synthetic sg 69280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // if the src alpha is <= 7. 69380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // to see why, try blending 0x4444 on top of 565-white and watch green 69480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // overflow (sum == 64) 69580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru sg &= ~(~(sa >> 3) & 1); 69680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 69780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned scale = SkAlpha15To16(15 - sa); 69880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale); 69980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale); 70080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale); 70180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 70280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0 70380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (sg + dg > 63) { 70480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg); 70580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 70680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkPackRGB16(sr + dr, sg + dg, sb + db); 70880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) { 71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)scale16 <= 16); 71280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 71380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst); 71480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 71580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 71680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16) { 71780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)scale16 <= 16); 71880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 71980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t src32 = SkExpand_4444(src) * scale16; 72080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // the scaled srcAlpha is the bottom byte 72180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG 72280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru { 72380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned srcA = SkGetPackedA4444(src) * scale16; 72480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(srcA == (src32 & 0xFF)); 72580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 72680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 72780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4; 72880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t dst32 = SkExpand_4444(dst) * dstScale; 72980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkCompact_4444((src32 + dst32) >> 4); 73080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 73180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 73280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkPixel4444ToPixel32(U16CPU c) { 73380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) | 73480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (SkGetPackedR4444(c) << SK_R32_SHIFT) | 73580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (SkGetPackedG4444(c) << SK_G32_SHIFT) | 73680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (SkGetPackedB4444(c) << SK_B32_SHIFT); 73780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return d | (d << 4); 73880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 73980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 74080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) { 74180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) | 74280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) | 74380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) | 74480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT); 74580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 74680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 74780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// cheap 2x2 dither 74880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r, 74980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru U8CPU g, U8CPU b) { 75080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // to ensure that we stay a legal premultiplied color, we take the max() 75180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // of the truncated and dithered alpha values. If we didn't, cases like 75280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...) 75380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // which is not legal premultiplied, since a < color 75480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4; 75580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru a = SkMax32(a >> 4, dithered_a); 75680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // these we just dither in place 75780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4; 75880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4; 75980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4; 76080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 76180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkPackARGB4444(a, r, g, b); 76280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 76380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 76480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) { 76580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c), 76680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkGetPackedG32(c), SkGetPackedB32(c)); 76780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 76880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 76980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* Assumes 16bit is in standard RGBA order. 77080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Transforms a normal ARGB_8888 into the same byte order as 77180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru expanded ARGB_4444, but keeps each component 8bits 77280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 77380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint32_t SkExpand_8888(SkPMColor c) { 77480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (((c >> SK_R32_SHIFT) & 0xFF) << 24) | 77580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> SK_G32_SHIFT) & 0xFF) << 8) | 77680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> SK_B32_SHIFT) & 0xFF) << 16) | 77780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> SK_A32_SHIFT) & 0xFF) << 0); 77880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 77980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 78080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* Undo the operation of SkExpand_8888, turning the argument back into 78180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru a SkPMColor. 78280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 78380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkCompact_8888(uint32_t c) { 78480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (((c >> 24) & 0xFF) << SK_R32_SHIFT) | 78580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> 8) & 0xFF) << SK_G32_SHIFT) | 78680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> 16) & 0xFF) << SK_B32_SHIFT) | 78780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> 0) & 0xFF) << SK_A32_SHIFT); 78880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 78980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 79080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format, 79180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru but this routine just keeps the high 4bits of each component in the low 79280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4bits of the result (just like a newly expanded PMColor16). 79380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 79480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline uint32_t SkExpand32_4444(SkPMColor c) { 79580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) | 79680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> (SK_G32_SHIFT + 4)) & 0xF) << 8) | 79780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) | 79880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru (((c >> (SK_A32_SHIFT + 4)) & 0xF) << 0); 79980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 80080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 80180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// takes two values and alternamtes them as part of a memset16 80280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// used for cheap 2x2 dithering when the colors are opaque 80380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n); 80480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 80580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/////////////////////////////////////////////////////////////////////////////// 80680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 80780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int SkUpscale31To32(int value) { 80880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)value <= 31); 80980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return value + (value >> 4); 81080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 81180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 81280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline int SkBlend32(int src, int dst, int scale) { 81380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)src <= 0xFF); 81480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)dst <= 0xFF); 81580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT((unsigned)scale <= 32); 81680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst + ((src - dst) * scale >> 5); 81780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 81880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 81980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkBlendLCD16(int srcA, int srcR, int srcG, int srcB, 82080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPMColor dst, uint16_t mask) { 82180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (mask == 0) { 82280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst; 82380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 82480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 82580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /* We want all of these in 5bits, hence the shifts in case one of them 82680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * (green) is 6bits. 82780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 82880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5); 82980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5); 83080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5); 83180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 83280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Now upscale them to 0..32, so we can use blend32 83380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru maskR = SkUpscale31To32(maskR); 83480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru maskG = SkUpscale31To32(maskG); 83580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru maskB = SkUpscale31To32(maskB); 83680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 83780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // srcA has been upscaled to 256 before passed into this function 83880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru maskR = maskR * srcA >> 8; 83980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru maskG = maskG * srcA >> 8; 84080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru maskB = maskB * srcA >> 8; 84180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 84280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int dstR = SkGetPackedR32(dst); 84380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int dstG = SkGetPackedG32(dst); 84480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int dstB = SkGetPackedB32(dst); 84580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 84680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // LCD blitting is only supported if the dst is known/required 84780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // to be opaque 84880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkPackARGB32(0xFF, 84980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBlend32(srcR, dstR, maskR), 85080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBlend32(srcG, dstG, maskG), 85180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBlend32(srcB, dstB, maskB)); 85280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 85380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 85480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic inline SkPMColor SkBlendLCD16Opaque(int srcR, int srcG, int srcB, 85580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPMColor dst, uint16_t mask, 85680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPMColor opaqueDst) { 85780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (mask == 0) { 85880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return dst; 85980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 86080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 86180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (0xFFFF == mask) { 86280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return opaqueDst; 86380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 86480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 86580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /* We want all of these in 5bits, hence the shifts in case one of them 86680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * (green) is 6bits. 86780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 86880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5); 86980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5); 87080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5); 87180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 87280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Now upscale them to 0..32, so we can use blend32 87380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru maskR = SkUpscale31To32(maskR); 87480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru maskG = SkUpscale31To32(maskG); 87580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru maskB = SkUpscale31To32(maskB); 87680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 87780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int dstR = SkGetPackedR32(dst); 87880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int dstG = SkGetPackedG32(dst); 87980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int dstB = SkGetPackedB32(dst); 88080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 88180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // LCD blitting is only supported if the dst is known/required 88280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // to be opaque 88380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return SkPackARGB32(0xFF, 88480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBlend32(srcR, dstR, maskR), 88580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBlend32(srcG, dstG, maskG), 88680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkBlend32(srcB, dstB, maskB)); 88780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 88880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 88958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t mask[], 89058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkColor src, int width, SkPMColor) { 89158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int srcA = SkColorGetA(src); 89258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int srcR = SkColorGetR(src); 89358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int srcG = SkColorGetG(src); 89458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int srcB = SkColorGetB(src); 89580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 89680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru srcA = SkAlpha255To256(srcA); 89780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 89880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = 0; i < width; i++) { 89958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], mask[i]); 90080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 90180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 90280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 90358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t mask[], 90458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkColor src, int width, 90580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkPMColor opaqueDst) { 90658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int srcR = SkColorGetR(src); 90758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int srcG = SkColorGetG(src); 90858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger int srcB = SkColorGetB(src); 90980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 91080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru for (int i = 0; i < width; i++) { 91158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], mask[i], 91280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru opaqueDst); 91380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 91480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 91580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 91680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 917