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