11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project 40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkColorPriv_DEFINED 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkColorPriv_DEFINED 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// turn this own for extra debug checking when blending onto 565 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project #define CHECK_FOR_565_OVERFLOW 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColor.h" 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMath.h" 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project byte into a scale value, so that we can say scale * value >> 8 instead of 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project alpha * value / 255. 2440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project In debugging, asserts that alpha is 0..255 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline unsigned SkAlpha255To256(U8CPU alpha) { 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(SkToU8(alpha) == alpha); 29f95abb54afa5469c53d3ac899ecbce8a386471c1Mike Reed // this one assues that blending on top of an opaque dst keeps it that way 30f95abb54afa5469c53d3ac899ecbce8a386471c1Mike Reed // even though it is less accurate than a+(a>>7) for non-opaque dsts 31f95abb54afa5469c53d3ac899ecbce8a386471c1Mike Reed return alpha + 1; 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Multiplify value by 0..256, and shift the result down 8 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (i.e. return (value * alpha256) >> 8) 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkAlphaMul(value, alpha256) (SkMulS16(value, alpha256) >> 8) 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// The caller may want negative values, so keep all params signed (int) 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// so we don't accidentally slip into unsigned math and lose the sign 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// extension when we shift (in SkAlphaMul) 4224fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline int SkAlphaBlend(int src, int dst, int scale256) { 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)scale256 <= 256); 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return dst + SkAlphaMul(src - dst, scale256); 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/** 481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Returns (src * alpha + dst * (255 - alpha)) / 255 491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * 501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * This is more accurate than SkAlphaBlend, but slightly slower 511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) { 531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT((int16_t)src == src); 541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT((int16_t)dst == dst); 551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT((uint8_t)alpha == alpha); 561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int prod = SkMulS16(src - dst, alpha) + 128; 581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger prod = (prod + (prod >> 8)) >> 8; 591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return dst + prod; 601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_R16_BITS 5 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_G16_BITS 6 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_B16_BITS 5 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_R16_SHIFT (SK_B16_BITS + SK_G16_BITS) 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_G16_SHIFT (SK_B16_BITS) 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_B16_SHIFT 0 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_R16_MASK ((1 << SK_R16_BITS) - 1) 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_G16_MASK ((1 << SK_G16_BITS) - 1) 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_B16_MASK ((1 << SK_B16_BITS) - 1) 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedR16(color) (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK) 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedG16(color) (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK) 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedB16(color) (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK) 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkR16Assert(r) SkASSERT((unsigned)(r) <= SK_R16_MASK) 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkG16Assert(g) SkASSERT((unsigned)(g) <= SK_G16_MASK) 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkB16Assert(b) SkASSERT((unsigned)(b) <= SK_B16_MASK) 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) { 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(r <= SK_R16_MASK); 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(g <= SK_G16_MASK); 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(b <= SK_B16_MASK); 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT)); 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_R16_MASK_IN_PLACE (SK_R16_MASK << SK_R16_SHIFT) 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_G16_MASK_IN_PLACE (SK_G16_MASK << SK_G16_SHIFT) 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_B16_MASK_IN_PLACE (SK_B16_MASK << SK_B16_SHIFT) 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Expand the 16bit color into a 32bit value that can be scaled all at once 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project by a value up to 32. Used in conjunction with SkCompact_rgb_16. 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline uint32_t SkExpand_rgb_16(U16CPU c) { 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(c == (uint16_t)c); 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE); 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project color value. The computation yields only 16bits of valid data, but we claim 1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project to return 32bits, so that the compiler won't generate extra instructions to 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project "clean" the top 16bits. However, the top 16 can contain garbage, so it is 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project up to the caller to safely ignore them. 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline U16CPU SkCompact_rgb_16(uint32_t c) { 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE); 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Scale the 16bit color value by the 0..256 scale parameter. 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project The computation yields only 16bits of valid data, but we claim 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project to return 32bits, so that the compiler won't generate extra instructions to 1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project "clean" the top 16bits. 1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) { 1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5); 1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// this helper explicitly returns a clean 16bit value (but slower) 1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkAlphaMulRGB16_ToU16(c, s) (uint16_t)SkAlphaMulRGB16(c, s) 1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Blend src and dst 16bit colors by the 0..256 scale parameter. 1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project The computation yields only 16bits of valid data, but we claim 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project to return 32bits, so that the compiler won't generate extra instructions to 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project "clean" the top 16bits. 1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) { 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)srcScale <= 256); 1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcScale >>= 3; 1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t src32 = SkExpand_rgb_16(src); 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t dst32 = SkExpand_rgb_16(dst); 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)); 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[], 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int srcScale, int count) { 1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(count > 0); 1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)srcScale <= 256); 14440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcScale >>= 3; 1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { 1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t src32 = SkExpand_rgb_16(*src++); 1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t dst32 = SkExpand_rgb_16(*dst); 1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)); 1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (--count > 0); 1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) { 1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK); 1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK); 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK); 15940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return a + b; 1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project #define SkRGB16Add(a, b) ((a) + (b)) 1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_A32_BITS 8 1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_R32_BITS 8 1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_G32_BITS 8 1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_B32_BITS 8 1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_A32_MASK ((1 << SK_A32_BITS) - 1) 1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_R32_MASK ((1 << SK_R32_BITS) - 1) 1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_G32_MASK ((1 << SK_G32_BITS) - 1) 1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_B32_MASK ((1 << SK_B32_BITS) - 1) 1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedA32(packed) ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24) 1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedR32(packed) ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24) 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedG32(packed) ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24) 1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedB32(packed) ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24) 1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkA32Assert(a) SkASSERT((unsigned)(a) <= SK_A32_MASK) 1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkR32Assert(r) SkASSERT((unsigned)(r) <= SK_R32_MASK) 1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkG32Assert(g) SkASSERT((unsigned)(g) <= SK_G32_MASK) 1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkB32Assert(b) SkASSERT((unsigned)(b) <= SK_B32_MASK) 1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 18924fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed static inline void SkPMColorAssert(SkPMColor c) { 1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned a = SkGetPackedA32(c); 1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned r = SkGetPackedR32(c); 1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned g = SkGetPackedG32(c); 1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned b = SkGetPackedB32(c); 19440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkA32Assert(a); 1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(r <= a); 1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(g <= a); 1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(b <= a); 1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project #define SkPMColorAssert(c) 2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 20440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger/** 20540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger * Pack the components into a SkPMColor, checking (in the debug version) that 20640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger * the components are 0..255, and are already premultiplied (i.e. alpha >= color) 20740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger */ 20824fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { 2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkA32Assert(a); 2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(r <= a); 2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(g <= a); 2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(b <= a); 2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) | 2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT); 2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger/** 2194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * Abstract 4-byte interpolation, implemented on top of SkPMColor 2204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * utility functions. Third parameter controls blending of the first two: 2214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * (src, dst, 0) returns dst 2224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * (src, dst, 0xFF) returns src 2234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */ 2244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst, 2254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger U8CPU srcWeight) { 2264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger unsigned scale = SkAlpha255To256(srcWeight); 2274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 2284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale); 2294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale); 2304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale); 2314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale); 2324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 2334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return SkPackARGB32(a, r, g, b); 2344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 2354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 2364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/** 2374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * 32b optimized version; currently appears to be 10% faster even on 64b 2384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * architectures than an equivalent 64b version and 30% faster than 2394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * SkFourByteInterp(). Third parameter controls blending of the first two: 2404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * (src, dst, 0) returns dst 2414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * (src, dst, 0xFF) returns src 2424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * ** Does not match the results of SkFourByteInterp() because we use 2434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * a more accurate scale computation! 2444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * TODO: migrate Skia function to using an accurate 255->266 alpha 2454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * conversion. 2464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */ 2474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic inline SkPMColor SkFastFourByteInterp(SkPMColor src, 2484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkPMColor dst, 2494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger U8CPU srcWeight) { 2504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkASSERT(srcWeight < 256); 2514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 2524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // Reorders ARGB to AG-RB in order to reduce the number of operations. 2534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const uint32_t mask = 0xFF00FF; 2544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger uint32_t src_rb = src & mask; 2554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger uint32_t src_ag = (src >> 8) & mask; 2564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger uint32_t dst_rb = dst & mask; 2574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger uint32_t dst_ag = (dst >> 8) & mask; 2584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 2594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // scale = srcWeight + (srcWeight >> 7) is more accurate than 2604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // scale = srcWeight + 1, but 7% slower 2614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int scale = srcWeight + (srcWeight >> 7); 2624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 2634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb; 2644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag; 2654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 2664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return (ret_ag & ~mask) | ((ret_rb & ~mask) >> 8); 2674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 2684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 2694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/** 27040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger * Same as SkPackARGB32, but this version guarantees to not check that the 27140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger * values are premultiplied in the debug version. 27240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger */ 27340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { 27440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) | 27540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT); 27640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 27740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 2781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic inline 2791cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) { 2801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkA32Assert(a); 2811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkA32Assert(r); 2821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkA32Assert(g); 2831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkA32Assert(b); 2841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (a != 255) { 2861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger r = SkMulDiv255Round(r, a); 2871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger g = SkMulDiv255Round(g, a); 2881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger b = SkMulDiv255Round(b, a); 2891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 2901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return SkPackARGB32(a, r, g, b); 2911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 2921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 293137a4ca42423bbb6d683067ea544c9a48f18f06cDerek SollenbergerSK_API extern const uint32_t gMask_00FF00FF; 2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 29524fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) { 2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t mask = gMask_00FF00FF; 2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// uint32_t mask = 0xFF00FF; 2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t rb = ((c & mask) * scale) >> 8; 3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t ag = ((c >> 8) & mask) * scale; 3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (rb & mask) | (ag & ~mask); 3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 30424fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) { 3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 30824fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) { 3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)aa <= 255); 3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned src_scale = SkAlpha255To256(aa); 3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale)); 3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale); 3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////////////////// 3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// Convert a 32bit pixel to a 16bit pixel (no dither) 3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkR32ToR16_MACRO(r) ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS)) 3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkG32ToG16_MACRO(g) ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS)) 3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkB32ToB16_MACRO(b) ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS)) 3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 32524fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed static inline unsigned SkR32ToR16(unsigned r) { 3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkR32Assert(r); 3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkR32ToR16_MACRO(r); 3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 32924fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed static inline unsigned SkG32ToG16(unsigned g) { 3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkG32Assert(g); 3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkG32ToG16_MACRO(g); 3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 33324fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed static inline unsigned SkB32ToB16(unsigned b) { 3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkB32Assert(b); 3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkB32ToB16_MACRO(b); 3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project #define SkR32ToR16(r) SkR32ToR16_MACRO(r) 3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project #define SkG32ToG16(g) SkG32ToG16_MACRO(g) 3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project #define SkB32ToB16(b) SkB32ToB16_MACRO(b) 3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPacked32ToR16(c) (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK) 3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPacked32ToG16(c) (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK) 3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPacked32ToB16(c) (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK) 3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 34724fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline U16CPU SkPixel32ToPixel16(SkPMColor c) { 3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT; 3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT; 3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT; 3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return r | g | b; 3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 35424fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) { 3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (SkR32ToR16(r) << SK_R16_SHIFT) | 3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (SkG32ToG16(g) << SK_G16_SHIFT) | 3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (SkB32ToB16(b) << SK_B16_SHIFT); 3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPixel32ToPixel16_ToU16(src) SkToU16(SkPixel32ToPixel16(src)) 3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////////////// 3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// Fast dither from 32->16 3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkShouldDitherXY(x, y) (((x) ^ (y)) & 1) 3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 36724fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) { 3680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS); 3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS); 3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS); 37140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkPackRGB16(r, g, b); 3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 37524fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) { 3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c)); 3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits) 3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project It is now suitable for combining with a scaled expanded_rgb_16 color 3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project as in SkSrcOver32To16(). 3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project We must do this 565 high-bit replication, in order for the subsequent add 3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project to saturate properly (and not overflow). If we take the 8 bits as is, it is 3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project possible to overflow. 3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 38624fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) { 3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sr = SkPacked32ToR16(c); 3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sg = SkPacked32ToG16(c); 3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sb = SkPacked32ToB16(c); 39040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sr = (sr << 5) | sr; 3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sg = (sg << 5) | (sg >> 1); 3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sb = (sb << 5) | sb; 3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (sr << 11) | (sg << 21) | (sb << 0); 3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* SrcOver the 32bit src color with the 16bit dst, returning a 16bit value 3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (with dirt in the high 16bits, so caller beware). 3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) { 4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sr = SkGetPackedR32(src); 4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sg = SkGetPackedG32(src); 4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sb = SkGetPackedB32(src); 40440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned dr = SkGetPackedR16(dst); 4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned dg = SkGetPackedG16(dst); 4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned db = SkGetPackedB16(dst); 40840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned isa = 255 - SkGetPackedA32(src); 41040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS); 4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS); 4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS); 41440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkPackRGB16(dr, dg, db); 4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////////////////// 4190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// Convert a 16bit pixel to a 32bit pixel 4200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 42124fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline unsigned SkR16ToR32(unsigned r) { 4220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8)); 4230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 42424fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed 42524fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline unsigned SkG16ToG32(unsigned g) { 4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8)); 4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 42824fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed 42924fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline unsigned SkB16ToB32(unsigned b) { 4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8)); 4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPacked16ToR32(c) SkR16ToR32(SkGetPackedR16(c)) 4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPacked16ToG32(c) SkG16ToG32(SkGetPackedG16(c)) 4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPacked16ToB32(c) SkB16ToB32(SkGetPackedB16(c)) 4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 43724fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline SkPMColor SkPixel16ToPixel32(U16CPU src) { 4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(src == SkToU16(src)); 4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned r = SkPacked16ToR32(src); 4410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned g = SkPacked16ToG32(src); 4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned b = SkPacked16ToB32(src); 4430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src)); 4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src)); 4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src)); 4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkPackARGB32(0xFF, r, g, b); 4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 451d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed// similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor 452d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reedstatic inline SkColor SkPixel16ToColor(U16CPU src) { 453d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed SkASSERT(src == SkToU16(src)); 45440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 455d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed unsigned r = SkPacked16ToR32(src); 456d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed unsigned g = SkPacked16ToG32(src); 457d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed unsigned b = SkPacked16ToB32(src); 45840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 459d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src)); 460d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src)); 461d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src)); 46240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 463d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed return SkColorSetRGB(r, g, b); 464d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed} 465d183501476bf8c4b92b1681857f0a96c487d9b40Mike Reed 4660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 4670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projecttypedef uint16_t SkPMColor16; 4690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// Put in OpenGL order (r g b a) 4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_A4444_SHIFT 0 4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_R4444_SHIFT 12 4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_G4444_SHIFT 8 4740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_B4444_SHIFT 4 4750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkA32To4444(a) ((unsigned)(a) >> 4) 4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkR32To4444(r) ((unsigned)(r) >> 4) 4780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkG32To4444(g) ((unsigned)(g) >> 4) 4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkB32To4444(b) ((unsigned)(b) >> 4) 4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 48124fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline U8CPU SkReplicateNibble(unsigned nib) { 4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(nib <= 0xF); 4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (nib << 4) | nib; 4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkA4444ToA32(a) SkReplicateNibble(a) 4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkR4444ToR32(r) SkReplicateNibble(r) 4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkG4444ToG32(g) SkReplicateNibble(g) 4890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkB4444ToB32(b) SkReplicateNibble(b) 4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedA4444(c) (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF) 4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedR4444(c) (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF) 4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedG4444(c) (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF) 4940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkGetPackedB4444(c) (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF) 4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPacked4444ToA32(c) SkReplicateNibble(SkGetPackedA4444(c)) 4970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPacked4444ToR32(c) SkReplicateNibble(SkGetPackedR4444(c)) 4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPacked4444ToG32(c) SkReplicateNibble(SkGetPackedG4444(c)) 4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPacked4444ToB32(c) SkReplicateNibble(SkGetPackedB4444(c)) 5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 50224fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline void SkPMColor16Assert(U16CPU c) { 5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned a = SkGetPackedA4444(c); 5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned r = SkGetPackedR4444(c); 5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned g = SkGetPackedG4444(c); 5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned b = SkGetPackedB4444(c); 50740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(a <= 0xF); 5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(r <= a); 5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(g <= a); 5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(b <= a); 5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkPMColor16Assert(c) 5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 51724fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline unsigned SkAlpha15To16(unsigned a) { 5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(a <= 0xF); 5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return a + (a >> 3); 5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 52324fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed static inline int SkAlphaMul4(int value, int scale) { 5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)scale <= 0x10); 5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return value * scale >> 4; 5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project #define SkAlphaMul4(value, scale) ((value) * (scale) >> 4) 5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 53124fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline unsigned SkR4444ToR565(unsigned r) { 5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(r <= 0xF); 5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS)); 5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 53624fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline unsigned SkG4444ToG565(unsigned g) { 5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(g <= 0xF); 5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS)); 5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 54124fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline unsigned SkB4444ToB565(unsigned b) { 5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(b <= 0xF); 5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS)); 5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r, 54724fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed unsigned g, unsigned b) { 5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(a <= 0xF); 5490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(r <= a); 5500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(g <= a); 5510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(b <= a); 55240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) | 5540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT)); 5550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectextern const uint16_t gMask_0F0F; 5580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 55924fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale) { 5600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(scale <= 16); 5610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const unsigned mask = 0xF0F; //gMask_0F0F; 56340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 5640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0 5650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned rb = ((c & mask) * scale) >> 4; 5660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned ag = ((c >> 4) & mask) * scale; 5670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (rb & mask) | (ag & ~mask); 5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project c = (c & mask) | ((c & (mask << 4)) << 12); 5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project c = c * scale >> 4; 5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (c & mask) | ((c >> 12) & (mask << 4)); 5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Expand the SkPMColor16 color into a 32bit value that can be scaled all at 5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project once by a value up to 16. Used in conjunction with SkCompact_4444. 5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 57824fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline uint32_t SkExpand_4444(U16CPU c) { 5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(c == (uint16_t)c); 58040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const unsigned mask = 0xF0F; //gMask_0F0F; 5820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (c & mask) | ((c & ~mask) << 12); 5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16. 5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project NOTE: this explicitly does not clean the top 16 bits (which may be garbage). 5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project It does this for speed, since if it is being written directly to 16bits of 5880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memory, the top 16bits will be ignored. Casting the result to uint16_t here 5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project would add 2 more instructions, slow us down. It is up to the caller to 5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project perform the cast if needed. 5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 59224fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline U16CPU SkCompact_4444(uint32_t c) { 5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const unsigned mask = 0xF0F; //gMask_0F0F; 5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (c & mask) | ((c >> 12) & ~mask); 5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 59724fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) { 5980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sa = SkGetPackedA4444(s); 5990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sr = SkR4444ToR565(SkGetPackedR4444(s)); 6000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sg = SkG4444ToG565(SkGetPackedG4444(s)); 6010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sb = SkB4444ToB565(SkGetPackedB4444(s)); 6020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // To avoid overflow, we have to clear the low bit of the synthetic sg 6040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // if the src alpha is <= 7. 6050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // to see why, try blending 0x4444 on top of 565-white and watch green 6060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // overflow (sum == 64) 6070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sg &= ~(~(sa >> 3) & 1); 6080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned scale = SkAlpha15To16(15 - sa); 6100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale); 6110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale); 6120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale); 61340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 6140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0 6150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (sg + dg > 63) { 6160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg); 6170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkPackRGB16(sr + dr, sg + dg, sb + db); 6200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 62224fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) { 6230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)scale16 <= 16); 62440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 6250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst); 6260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 62824fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16) { 6290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)scale16 <= 16); 63040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 6310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t src32 = SkExpand_4444(src) * scale16; 6320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // the scaled srcAlpha is the bottom byte 6330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 6340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 6350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned srcA = SkGetPackedA4444(src) * scale16; 6360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(srcA == (src32 & 0xFF)); 6370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 6390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4; 6400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t dst32 = SkExpand_4444(dst) * dstScale; 6410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkCompact_4444((src32 + dst32) >> 4); 6420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 64424fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline SkPMColor SkPixel4444ToPixel32(U16CPU c) { 6450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) | 6460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (SkGetPackedR4444(c) << SK_R32_SHIFT) | 6470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (SkGetPackedG4444(c) << SK_G32_SHIFT) | 6480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (SkGetPackedB4444(c) << SK_B32_SHIFT); 6490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return d | (d << 4); 6500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 65224fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) { 6530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) | 6540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) | 6550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) | 6560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT); 6570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// cheap 2x2 dither 6600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r, 66124fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed U8CPU g, U8CPU b) { 662a41d49cff9677406effa435c8e99117f38fb287fMike Reed // to ensure that we stay a legal premultiplied color, we take the max() 663a41d49cff9677406effa435c8e99117f38fb287fMike Reed // of the truncated and dithered alpha values. If we didn't, cases like 664a41d49cff9677406effa435c8e99117f38fb287fMike Reed // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...) 665a41d49cff9677406effa435c8e99117f38fb287fMike Reed // which is not legal premultiplied, since a < color 666a41d49cff9677406effa435c8e99117f38fb287fMike Reed unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4; 667a41d49cff9677406effa435c8e99117f38fb287fMike Reed a = SkMax32(a >> 4, dithered_a); 668a41d49cff9677406effa435c8e99117f38fb287fMike Reed // these we just dither in place 6690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4; 6700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4; 6710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4; 67240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 6730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkPackARGB4444(a, r, g, b); 6740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 67624fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) { 6770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c), 6780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkGetPackedG32(c), SkGetPackedB32(c)); 6790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* Assumes 16bit is in standard RGBA order. 6820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Transforms a normal ARGB_8888 into the same byte order as 6830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project expanded ARGB_4444, but keeps each component 8bits 6840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 68524fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline uint32_t SkExpand_8888(SkPMColor c) { 6860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (((c >> SK_R32_SHIFT) & 0xFF) << 24) | 6870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> SK_G32_SHIFT) & 0xFF) << 8) | 6880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> SK_B32_SHIFT) & 0xFF) << 16) | 6890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> SK_A32_SHIFT) & 0xFF) << 0); 6900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* Undo the operation of SkExpand_8888, turning the argument back into 6930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project a SkPMColor. 6940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 69524fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline SkPMColor SkCompact_8888(uint32_t c) { 6960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (((c >> 24) & 0xFF) << SK_R32_SHIFT) | 6970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> 8) & 0xFF) << SK_G32_SHIFT) | 6980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> 16) & 0xFF) << SK_B32_SHIFT) | 6990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> 0) & 0xFF) << SK_A32_SHIFT); 7000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 7010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format, 7030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project but this routine just keeps the high 4bits of each component in the low 7040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4bits of the result (just like a newly expanded PMColor16). 7050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 70624fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reedstatic inline uint32_t SkExpand32_4444(SkPMColor c) { 7070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) | 7080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> (SK_G32_SHIFT + 4)) & 0xF) << 8) | 7090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) | 7100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (((c >> (SK_A32_SHIFT + 4)) & 0xF) << 0); 7110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 7120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// takes two values and alternamtes them as part of a memset16 7140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// used for cheap 2x2 dithering when the colors are opaque 7150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n); 7160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 7184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic inline int SkUpscale31To32(int value) { 7204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkASSERT((unsigned)value <= 31); 7214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return value + (value >> 4); 7224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 7234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic inline int SkBlend32(int src, int dst, int scale) { 7254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkASSERT((unsigned)src <= 0xFF); 7264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkASSERT((unsigned)dst <= 0xFF); 7274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkASSERT((unsigned)scale <= 32); 7284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return dst + ((src - dst) * scale >> 5); 7294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 7304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic inline SkPMColor SkBlendLCD16(int srcA, int srcR, int srcG, int srcB, 7324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkPMColor dst, uint16_t mask) { 7334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (mask == 0) { 7344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return dst; 7354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 7364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger /* We want all of these in 5bits, hence the shifts in case one of them 7384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * (green) is 6bits. 7394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */ 7404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5); 7414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5); 7424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5); 7434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // Now upscale them to 0..32, so we can use blend32 7454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger maskR = SkUpscale31To32(maskR); 7464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger maskG = SkUpscale31To32(maskG); 7474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger maskB = SkUpscale31To32(maskB); 7484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // srcA has been upscaled to 256 before passed into this function 7504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger maskR = maskR * srcA >> 8; 7514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger maskG = maskG * srcA >> 8; 7524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger maskB = maskB * srcA >> 8; 7534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int dstR = SkGetPackedR32(dst); 7554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int dstG = SkGetPackedG32(dst); 7564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int dstB = SkGetPackedB32(dst); 7574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // LCD blitting is only supported if the dst is known/required 7594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // to be opaque 7604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return SkPackARGB32(0xFF, 7614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkBlend32(srcR, dstR, maskR), 7624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkBlend32(srcG, dstG, maskG), 7634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkBlend32(srcB, dstB, maskB)); 7644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 7654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic inline SkPMColor SkBlendLCD16Opaque(int srcR, int srcG, int srcB, 7674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkPMColor dst, uint16_t mask, 7684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkPMColor opaqueDst) { 7694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (mask == 0) { 7704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return dst; 7714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 7724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (0xFFFF == mask) { 7744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return opaqueDst; 7754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 7764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger /* We want all of these in 5bits, hence the shifts in case one of them 7784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * (green) is 6bits. 7794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */ 7804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5); 7814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5); 7824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5); 7834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // Now upscale them to 0..32, so we can use blend32 7854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger maskR = SkUpscale31To32(maskR); 7864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger maskG = SkUpscale31To32(maskG); 7874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger maskB = SkUpscale31To32(maskB); 7884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int dstR = SkGetPackedR32(dst); 7904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int dstG = SkGetPackedG32(dst); 7914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int dstB = SkGetPackedB32(dst); 7924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 7934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // LCD blitting is only supported if the dst is known/required 7944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // to be opaque 7954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return SkPackARGB32(0xFF, 7964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkBlend32(srcR, dstR, maskR), 7974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkBlend32(srcG, dstG, maskG), 7984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkBlend32(srcB, dstB, maskB)); 7994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 8004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 8014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t src[], 8024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkColor color, int width, SkPMColor) { 8034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int srcA = SkColorGetA(color); 8044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int srcR = SkColorGetR(color); 8054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int srcG = SkColorGetG(color); 8064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int srcB = SkColorGetB(color); 8074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 8084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger srcA = SkAlpha255To256(srcA); 8094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 8104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger for (int i = 0; i < width; i++) { 8114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], src[i]); 8124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 8134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 8144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 8154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t src[], 8164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkColor color, int width, 8174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkPMColor opaqueDst) { 8184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int srcR = SkColorGetR(color); 8194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int srcG = SkColorGetG(color); 8204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int srcB = SkColorGetB(color); 8214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 8224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger for (int i = 0; i < width; i++) { 8234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], src[i], 8244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger opaqueDst); 8254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 8264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 8274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 8280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 8290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 830