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