18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkColorPriv_DEFINED
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkColorPriv_DEFINED
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// turn this own for extra debug checking when blending onto 565
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define CHECK_FOR_565_OVERFLOW
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColor.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMath.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
197111d463cee893a479280c7af41757e709e33ef5reed@google.com//////////////////////////////////////////////////////////////////////////////
207111d463cee893a479280c7af41757e709e33ef5reed@google.com
217111d463cee893a479280c7af41757e709e33ef5reed@google.com#define SkASSERT_IS_BYTE(x)     SkASSERT(0 == ((x) & ~0xFF))
227111d463cee893a479280c7af41757e709e33ef5reed@google.com
237111d463cee893a479280c7af41757e709e33ef5reed@google.com/*
247111d463cee893a479280c7af41757e709e33ef5reed@google.com *  Skia's 32bit backend only supports 1 sizzle order at a time (compile-time).
257111d463cee893a479280c7af41757e709e33ef5reed@google.com *  This is specified by 4 defines SK_A32_SHIFT, SK_R32_SHIFT, ... for G and B.
267111d463cee893a479280c7af41757e709e33ef5reed@google.com *
277111d463cee893a479280c7af41757e709e33ef5reed@google.com *  For easier compatibility with Skia's GPU backend, we further restrict these
287111d463cee893a479280c7af41757e709e33ef5reed@google.com *  to either (in memory-byte-order) RGBA or BGRA. Note that this "order" does
297111d463cee893a479280c7af41757e709e33ef5reed@google.com *  not directly correspond to the same shift-order, since we have to take endianess
307111d463cee893a479280c7af41757e709e33ef5reed@google.com *  into account.
317111d463cee893a479280c7af41757e709e33ef5reed@google.com *
327111d463cee893a479280c7af41757e709e33ef5reed@google.com *  Here we enforce this constraint.
337111d463cee893a479280c7af41757e709e33ef5reed@google.com */
347111d463cee893a479280c7af41757e709e33ef5reed@google.com
357111d463cee893a479280c7af41757e709e33ef5reed@google.com#ifdef SK_CPU_BENDIAN
367111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_RGBA_R32_SHIFT   24
377111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_RGBA_G32_SHIFT   16
387111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_RGBA_B32_SHIFT   8
397111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_RGBA_A32_SHIFT   0
407111d463cee893a479280c7af41757e709e33ef5reed@google.com
417111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_BGRA_B32_SHIFT   24
427111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_BGRA_G32_SHIFT   16
437111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_BGRA_R32_SHIFT   8
447111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_BGRA_A32_SHIFT   0
457111d463cee893a479280c7af41757e709e33ef5reed@google.com#else
467111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_RGBA_R32_SHIFT   0
477111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_RGBA_G32_SHIFT   8
487111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_RGBA_B32_SHIFT   16
497111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_RGBA_A32_SHIFT   24
507111d463cee893a479280c7af41757e709e33ef5reed@google.com
517111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_BGRA_B32_SHIFT   0
527111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_BGRA_G32_SHIFT   8
537111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_BGRA_R32_SHIFT   16
547111d463cee893a479280c7af41757e709e33ef5reed@google.com    #define SK_BGRA_A32_SHIFT   24
557111d463cee893a479280c7af41757e709e33ef5reed@google.com#endif
567111d463cee893a479280c7af41757e709e33ef5reed@google.com
577111d463cee893a479280c7af41757e709e33ef5reed@google.com#if defined(SK_PMCOLOR_IS_RGBA) && defined(SK_PMCOLOR_IS_BGRA)
587111d463cee893a479280c7af41757e709e33ef5reed@google.com    #error "can't define PMCOLOR to be RGBA and BGRA"
597111d463cee893a479280c7af41757e709e33ef5reed@google.com#endif
607111d463cee893a479280c7af41757e709e33ef5reed@google.com
617111d463cee893a479280c7af41757e709e33ef5reed@google.com#define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA  \
627111d463cee893a479280c7af41757e709e33ef5reed@google.com    (SK_A32_SHIFT == SK_RGBA_A32_SHIFT &&    \
637111d463cee893a479280c7af41757e709e33ef5reed@google.com     SK_R32_SHIFT == SK_RGBA_R32_SHIFT &&    \
647111d463cee893a479280c7af41757e709e33ef5reed@google.com     SK_G32_SHIFT == SK_RGBA_G32_SHIFT &&    \
657111d463cee893a479280c7af41757e709e33ef5reed@google.com     SK_B32_SHIFT == SK_RGBA_B32_SHIFT)
667111d463cee893a479280c7af41757e709e33ef5reed@google.com
677111d463cee893a479280c7af41757e709e33ef5reed@google.com#define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA  \
687111d463cee893a479280c7af41757e709e33ef5reed@google.com    (SK_A32_SHIFT == SK_BGRA_A32_SHIFT &&    \
697111d463cee893a479280c7af41757e709e33ef5reed@google.com     SK_R32_SHIFT == SK_BGRA_R32_SHIFT &&    \
707111d463cee893a479280c7af41757e709e33ef5reed@google.com     SK_G32_SHIFT == SK_BGRA_G32_SHIFT &&    \
717111d463cee893a479280c7af41757e709e33ef5reed@google.com     SK_B32_SHIFT == SK_BGRA_B32_SHIFT)
727111d463cee893a479280c7af41757e709e33ef5reed@google.com
737111d463cee893a479280c7af41757e709e33ef5reed@google.com
747111d463cee893a479280c7af41757e709e33ef5reed@google.com#if defined(SK_PMCOLOR_IS_RGBA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
757111d463cee893a479280c7af41757e709e33ef5reed@google.com    #error "SK_PMCOLOR_IS_RGBA does not match SK_*32_SHIFT values"
767111d463cee893a479280c7af41757e709e33ef5reed@google.com#endif
777111d463cee893a479280c7af41757e709e33ef5reed@google.com
787111d463cee893a479280c7af41757e709e33ef5reed@google.com#if defined(SK_PMCOLOR_IS_BGRA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
797111d463cee893a479280c7af41757e709e33ef5reed@google.com    #error "SK_PMCOLOR_IS_BGRA does not match SK_*32_SHIFT values"
807111d463cee893a479280c7af41757e709e33ef5reed@google.com#endif
817111d463cee893a479280c7af41757e709e33ef5reed@google.com
827111d463cee893a479280c7af41757e709e33ef5reed@google.com#if !defined(SK_PMCOLOR_IS_RGBA) && !defined(SK_PMCOLOR_IS_RGBA)
837111d463cee893a479280c7af41757e709e33ef5reed@google.com    // deduce which to define from the _SHIFT defines
847111d463cee893a479280c7af41757e709e33ef5reed@google.com
857111d463cee893a479280c7af41757e709e33ef5reed@google.com    #if LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
867111d463cee893a479280c7af41757e709e33ef5reed@google.com        #define SK_PMCOLOR_IS_RGBA
877111d463cee893a479280c7af41757e709e33ef5reed@google.com    #elif LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
887111d463cee893a479280c7af41757e709e33ef5reed@google.com        #define SK_PMCOLOR_IS_BGRA
897111d463cee893a479280c7af41757e709e33ef5reed@google.com    #else
907111d463cee893a479280c7af41757e709e33ef5reed@google.com        #error "need 32bit packing to be either RGBA or BGRA"
917111d463cee893a479280c7af41757e709e33ef5reed@google.com    #endif
927111d463cee893a479280c7af41757e709e33ef5reed@google.com#endif
937111d463cee893a479280c7af41757e709e33ef5reed@google.com
947111d463cee893a479280c7af41757e709e33ef5reed@google.com// hide these now that we're done
957111d463cee893a479280c7af41757e709e33ef5reed@google.com#undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
967111d463cee893a479280c7af41757e709e33ef5reed@google.com#undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
977111d463cee893a479280c7af41757e709e33ef5reed@google.com
987111d463cee893a479280c7af41757e709e33ef5reed@google.com//////////////////////////////////////////////////////////////////////////////
997111d463cee893a479280c7af41757e709e33ef5reed@google.com
1007111d463cee893a479280c7af41757e709e33ef5reed@google.com// Reverse the bytes coorsponding to RED and BLUE in a packed pixels. Note the
1017111d463cee893a479280c7af41757e709e33ef5reed@google.com// pair of them are in the same 2 slots in both RGBA and BGRA, thus there is
1027111d463cee893a479280c7af41757e709e33ef5reed@google.com// no need to pass in the colortype to this function.
1037111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic inline uint32_t SkSwizzle_RB(uint32_t c) {
1047111d463cee893a479280c7af41757e709e33ef5reed@google.com    static const uint32_t kRBMask = (0xFF << SK_R32_SHIFT) | (0xFF << SK_B32_SHIFT);
1057111d463cee893a479280c7af41757e709e33ef5reed@google.com
1067111d463cee893a479280c7af41757e709e33ef5reed@google.com    unsigned c0 = (c >> SK_R32_SHIFT) & 0xFF;
1077111d463cee893a479280c7af41757e709e33ef5reed@google.com    unsigned c1 = (c >> SK_B32_SHIFT) & 0xFF;
1087111d463cee893a479280c7af41757e709e33ef5reed@google.com    return (c & ~kRBMask) | (c0 << SK_B32_SHIFT) | (c1 << SK_R32_SHIFT);
1097111d463cee893a479280c7af41757e709e33ef5reed@google.com}
1107111d463cee893a479280c7af41757e709e33ef5reed@google.com
1117111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic inline uint32_t SkPackARGB_as_RGBA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
1127111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkASSERT_IS_BYTE(a);
1137111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkASSERT_IS_BYTE(r);
1147111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkASSERT_IS_BYTE(g);
1157111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkASSERT_IS_BYTE(b);
1167111d463cee893a479280c7af41757e709e33ef5reed@google.com    return (a << SK_RGBA_A32_SHIFT) | (r << SK_RGBA_R32_SHIFT) |
1177111d463cee893a479280c7af41757e709e33ef5reed@google.com           (g << SK_RGBA_G32_SHIFT) | (b << SK_RGBA_B32_SHIFT);
1187111d463cee893a479280c7af41757e709e33ef5reed@google.com}
1197111d463cee893a479280c7af41757e709e33ef5reed@google.com
1207111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic inline uint32_t SkPackARGB_as_BGRA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
1217111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkASSERT_IS_BYTE(a);
1227111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkASSERT_IS_BYTE(r);
1237111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkASSERT_IS_BYTE(g);
1247111d463cee893a479280c7af41757e709e33ef5reed@google.com    SkASSERT_IS_BYTE(b);
1257111d463cee893a479280c7af41757e709e33ef5reed@google.com    return (a << SK_BGRA_A32_SHIFT) | (r << SK_BGRA_R32_SHIFT) |
1267111d463cee893a479280c7af41757e709e33ef5reed@google.com           (g << SK_BGRA_G32_SHIFT) | (b << SK_BGRA_B32_SHIFT);
1277111d463cee893a479280c7af41757e709e33ef5reed@google.com}
1287111d463cee893a479280c7af41757e709e33ef5reed@google.com
1297111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic inline SkPMColor SkSwizzle_RGBA_to_PMColor(uint32_t c) {
1307111d463cee893a479280c7af41757e709e33ef5reed@google.com#ifdef SK_PMCOLOR_IS_RGBA
1317111d463cee893a479280c7af41757e709e33ef5reed@google.com    return c;
1327111d463cee893a479280c7af41757e709e33ef5reed@google.com#else
1337111d463cee893a479280c7af41757e709e33ef5reed@google.com    return SkSwizzle_RB(c);
1347111d463cee893a479280c7af41757e709e33ef5reed@google.com#endif
1357111d463cee893a479280c7af41757e709e33ef5reed@google.com}
1367111d463cee893a479280c7af41757e709e33ef5reed@google.com
1377111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic inline SkPMColor SkSwizzle_BGRA_to_PMColor(uint32_t c) {
1387111d463cee893a479280c7af41757e709e33ef5reed@google.com#ifdef SK_PMCOLOR_IS_BGRA
1397111d463cee893a479280c7af41757e709e33ef5reed@google.com    return c;
1407111d463cee893a479280c7af41757e709e33ef5reed@google.com#else
1417111d463cee893a479280c7af41757e709e33ef5reed@google.com    return SkSwizzle_RB(c);
1427111d463cee893a479280c7af41757e709e33ef5reed@google.com#endif
1437111d463cee893a479280c7af41757e709e33ef5reed@google.com}
1447111d463cee893a479280c7af41757e709e33ef5reed@google.com
1457111d463cee893a479280c7af41757e709e33ef5reed@google.com//////////////////////////////////////////////////////////////////////////////
1467111d463cee893a479280c7af41757e709e33ef5reed@google.com
14797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com///@{
14897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/** See ITU-R Recommendation BT.709 at http://www.itu.int/rec/R-REC-BT.709/ .*/
14997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#define SK_ITU_BT709_LUM_COEFF_R (0.2126f)
15097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#define SK_ITU_BT709_LUM_COEFF_G (0.7152f)
15197efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#define SK_ITU_BT709_LUM_COEFF_B (0.0722f)
15297efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com///@}
15397efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
15497efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com///@{
15597efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com/** A float value which specifies this channel's contribution to luminance. */
15697efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#define SK_LUM_COEFF_R SK_ITU_BT709_LUM_COEFF_R
15797efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#define SK_LUM_COEFF_G SK_ITU_BT709_LUM_COEFF_G
15897efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com#define SK_LUM_COEFF_B SK_ITU_BT709_LUM_COEFF_B
15997efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com///@}
16097efada074e4806479f1350ab1508939c2fdcb53bungeman@google.com
1611bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com/** Computes the luminance from the given r, g, and b in accordance with
1621bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com    SK_LUM_COEFF_X. For correct results, r, g, and b should be in linear space.
1631bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com*/
1641bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.comstatic inline U8CPU SkComputeLuminance(U8CPU r, U8CPU g, U8CPU b) {
1651bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com    //The following is
1661bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com    //r * SK_LUM_COEFF_R + g * SK_LUM_COEFF_G + b * SK_LUM_COEFF_B
1671bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com    //with SK_LUM_COEFF_X in 1.8 fixed point (rounding adjusted to sum to 256).
1681bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com    return (r * 54 + g * 183 + b * 19) >> 8;
1691bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com}
1701bfe01d06b896eca94c80d9af9a6bb30216b5e42bungeman@google.com
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    byte into a scale value, so that we can say scale * value >> 8 instead of
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    alpha * value / 255.
174e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    In debugging, asserts that alpha is 0..255
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline unsigned SkAlpha255To256(U8CPU alpha) {
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(SkToU8(alpha) == alpha);
1799781ca586618cc8ea055f54021e706824313d4f5reed@android.com    // this one assues that blending on top of an opaque dst keeps it that way
1809781ca586618cc8ea055f54021e706824313d4f5reed@android.com    // even though it is less accurate than a+(a>>7) for non-opaque dsts
1819781ca586618cc8ea055f54021e706824313d4f5reed@android.com    return alpha + 1;
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18406a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org/**
18506a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org *  Turn a 0..255 value into a 0..256 value, rounding up if the value is >= 0x80.
18606a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org *  This is slightly more accurate than SkAlpha255To256.
18706a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org */
18806a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.orgstatic inline unsigned Sk255To256(U8CPU value) {
18906a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org    SkASSERT(SkToU8(value) == value);
19006a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org    return value + (value >> 7);
19106a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org}
19206a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Multiplify value by 0..256, and shift the result down 8
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (i.e. return (value * alpha256) >> 8)
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkAlphaMul(value, alpha256)     (SkMulS16(value, alpha256) >> 8)
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  The caller may want negative values, so keep all params signed (int)
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  so we don't accidentally slip into unsigned math and lose the sign
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//  extension when we shift (in SkAlphaMul)
20134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline int SkAlphaBlend(int src, int dst, int scale256) {
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)scale256 <= 256);
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst + SkAlphaMul(src - dst, scale256);
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2060abb499dafb2550ad81afe11ffede5cab4904575reed@google.com/**
2070abb499dafb2550ad81afe11ffede5cab4904575reed@google.com *  Returns (src * alpha + dst * (255 - alpha)) / 255
2080abb499dafb2550ad81afe11ffede5cab4904575reed@google.com *
2090abb499dafb2550ad81afe11ffede5cab4904575reed@google.com *  This is more accurate than SkAlphaBlend, but slightly slower
2100abb499dafb2550ad81afe11ffede5cab4904575reed@google.com */
2110abb499dafb2550ad81afe11ffede5cab4904575reed@google.comstatic inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) {
2120abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    SkASSERT((int16_t)src == src);
2130abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    SkASSERT((int16_t)dst == dst);
2140abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    SkASSERT((uint8_t)alpha == alpha);
215fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2160abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    int prod = SkMulS16(src - dst, alpha) + 128;
2170abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    prod = (prod + (prod >> 8)) >> 8;
2180abb499dafb2550ad81afe11ffede5cab4904575reed@google.com    return dst + prod;
2190abb499dafb2550ad81afe11ffede5cab4904575reed@google.com}
2200abb499dafb2550ad81afe11ffede5cab4904575reed@google.com
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_BITS     5
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_BITS     6
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_BITS     5
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_SHIFT    (SK_B16_BITS + SK_G16_BITS)
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_SHIFT    (SK_B16_BITS)
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_SHIFT    0
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_MASK     ((1 << SK_R16_BITS) - 1)
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_MASK     ((1 << SK_G16_BITS) - 1)
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_MASK     ((1 << SK_B16_BITS) - 1)
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedR16(color)   (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedG16(color)   (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedB16(color)   (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR16Assert(r)  SkASSERT((unsigned)(r) <= SK_R16_MASK)
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG16Assert(g)  SkASSERT((unsigned)(g) <= SK_G16_MASK)
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB16Assert(b)  SkASSERT((unsigned)(b) <= SK_B16_MASK)
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= SK_R16_MASK);
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= SK_G16_MASK);
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= SK_B16_MASK);
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R16_MASK_IN_PLACE        (SK_R16_MASK << SK_R16_SHIFT)
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G16_MASK_IN_PLACE        (SK_G16_MASK << SK_G16_SHIFT)
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B16_MASK_IN_PLACE        (SK_B16_MASK << SK_B16_SHIFT)
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Expand the 16bit color into a 32bit value that can be scaled all at once
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    by a value up to 32. Used in conjunction with SkCompact_rgb_16.
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint32_t SkExpand_rgb_16(U16CPU c) {
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(c == (uint16_t)c);
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    color value. The computation yields only 16bits of valid data, but we claim
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to return 32bits, so that the compiler won't generate extra instructions to
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    "clean" the top 16bits. However, the top 16 can contain garbage, so it is
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    up to the caller to safely ignore them.
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkCompact_rgb_16(uint32_t c) {
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Scale the 16bit color value by the 0..256 scale parameter.
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The computation yields only 16bits of valid data, but we claim
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to return 32bits, so that the compiler won't generate extra instructions to
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    "clean" the top 16bits.
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this helper explicitly returns a clean 16bit value (but slower)
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkAlphaMulRGB16_ToU16(c, s)  (uint16_t)SkAlphaMulRGB16(c, s)
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Blend src and dst 16bit colors by the 0..256 scale parameter.
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    The computation yields only 16bits of valid data, but we claim
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to return 32bits, so that the compiler won't generate extra instructions to
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    "clean" the top 16bits.
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)srcScale <= 256);
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcScale >>= 3;
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t src32 = SkExpand_rgb_16(src);
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t dst32 = SkExpand_rgb_16(dst);
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                int srcScale, int count) {
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count > 0);
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)srcScale <= 256);
303e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    srcScale >>= 3;
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t src32 = SkExpand_rgb_16(*src++);
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t dst32 = SkExpand_rgb_16(*dst);
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (--count > 0);
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
314fc25abdabff76f913fb9d4f373418c10a1eca92breed@android.com    static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
318e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return a + b;
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkRGB16Add(a, b)  ((a) + (b))
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
32505ea1810a231b1f699c98a0b6272e08a4c93b06breed@google.com///////////////////////////////////////////////////////////////////////////////
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_A32_BITS     8
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R32_BITS     8
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G32_BITS     8
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B32_BITS     8
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_A32_MASK     ((1 << SK_A32_BITS) - 1)
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R32_MASK     ((1 << SK_R32_BITS) - 1)
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G32_MASK     ((1 << SK_G32_BITS) - 1)
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B32_MASK     ((1 << SK_B32_BITS) - 1)
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedG32(packed)      ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedB32(packed)      ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkA32Assert(a)  SkASSERT((unsigned)(a) <= SK_A32_MASK)
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR32Assert(r)  SkASSERT((unsigned)(r) <= SK_R32_MASK)
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG32Assert(g)  SkASSERT((unsigned)(g) <= SK_G32_MASK)
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB32Assert(b)  SkASSERT((unsigned)(b) <= SK_B32_MASK)
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
34834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline void SkPMColorAssert(SkPMColor c) {
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned a = SkGetPackedA32(c);
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned r = SkGetPackedR32(c);
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned g = SkGetPackedG32(c);
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned b = SkGetPackedB32(c);
353e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkA32Assert(a);
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(r <= a);
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(g <= a);
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(b <= a);
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkPMColorAssert(c)
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
363e686322eba17fee0b5671393dc842e52f77109d9reed@google.com/**
364e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  Pack the components into a SkPMColor, checking (in the debug version) that
365e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  the components are 0..255, and are already premultiplied (i.e. alpha >= color)
366e686322eba17fee0b5671393dc842e52f77109d9reed@google.com */
36734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkA32Assert(a);
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= a);
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= a);
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= a);
3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3777111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic inline uint32_t SkPackPMColor_as_RGBA(SkPMColor c) {
3787111d463cee893a479280c7af41757e709e33ef5reed@google.com    return SkPackARGB_as_RGBA(SkGetPackedA32(c), SkGetPackedR32(c),
3797111d463cee893a479280c7af41757e709e33ef5reed@google.com                              SkGetPackedG32(c), SkGetPackedB32(c));
3807111d463cee893a479280c7af41757e709e33ef5reed@google.com}
3817111d463cee893a479280c7af41757e709e33ef5reed@google.com
3827111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic inline uint32_t SkPackPMColor_as_BGRA(SkPMColor c) {
3837111d463cee893a479280c7af41757e709e33ef5reed@google.com    return SkPackARGB_as_BGRA(SkGetPackedA32(c), SkGetPackedR32(c),
3847111d463cee893a479280c7af41757e709e33ef5reed@google.com                              SkGetPackedG32(c), SkGetPackedB32(c));
3857111d463cee893a479280c7af41757e709e33ef5reed@google.com}
3867111d463cee893a479280c7af41757e709e33ef5reed@google.com
387e686322eba17fee0b5671393dc842e52f77109d9reed@google.com/**
38813e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * Abstract 4-byte interpolation, implemented on top of SkPMColor
38913e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com * utility functions. Third parameter controls blending of the first two:
39013e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com *   (src, dst, 0) returns dst
39113e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com *   (src, dst, 0xFF) returns src
3926adf79746f435df1463ce944598f189db7759cdfreed@google.com *   srcWeight is [0..256], unlike SkFourByteInterp which takes [0..255]
39313e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com */
3946adf79746f435df1463ce944598f189db7759cdfreed@google.comstatic inline SkPMColor SkFourByteInterp256(SkPMColor src, SkPMColor dst,
3956adf79746f435df1463ce944598f189db7759cdfreed@google.com                                         unsigned scale) {
39613e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
39713e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
39813e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
39913e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
400fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
40113e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com    return SkPackARGB32(a, r, g, b);
40213e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com}
40313e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
40413e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com/**
4056adf79746f435df1463ce944598f189db7759cdfreed@google.com * Abstract 4-byte interpolation, implemented on top of SkPMColor
4066adf79746f435df1463ce944598f189db7759cdfreed@google.com * utility functions. Third parameter controls blending of the first two:
4076adf79746f435df1463ce944598f189db7759cdfreed@google.com *   (src, dst, 0) returns dst
4086adf79746f435df1463ce944598f189db7759cdfreed@google.com *   (src, dst, 0xFF) returns src
4096adf79746f435df1463ce944598f189db7759cdfreed@google.com */
4106adf79746f435df1463ce944598f189db7759cdfreed@google.comstatic inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst,
4116adf79746f435df1463ce944598f189db7759cdfreed@google.com                                         U8CPU srcWeight) {
4126adf79746f435df1463ce944598f189db7759cdfreed@google.com    unsigned scale = SkAlpha255To256(srcWeight);
4136adf79746f435df1463ce944598f189db7759cdfreed@google.com    return SkFourByteInterp256(src, dst, scale);
4146adf79746f435df1463ce944598f189db7759cdfreed@google.com}
4156adf79746f435df1463ce944598f189db7759cdfreed@google.com
4166adf79746f435df1463ce944598f189db7759cdfreed@google.com/**
41755ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org * 0xAARRGGBB -> 0x00AA00GG, 0x00RR00BB
41855ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org */
419e76a3225d5d791a631f70a6a45f6772721710eeecommit-bot@chromium.orgstatic inline void SkSplay(uint32_t color, uint32_t* ag, uint32_t* rb) {
42055ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    const uint32_t mask = 0x00FF00FF;
42155ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    *ag = (color >> 8) & mask;
42255ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    *rb = color & mask;
42355ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org}
42455ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org
42555ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org/**
42655ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org * 0xAARRGGBB -> 0x00AA00GG00RR00BB
42755ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org * (note, ARGB -> AGRB)
42855ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org */
429e76a3225d5d791a631f70a6a45f6772721710eeecommit-bot@chromium.orgstatic inline uint64_t SkSplay(uint32_t color) {
43055ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    const uint32_t mask = 0x00FF00FF;
43155ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    uint64_t agrb = (color >> 8) & mask;  // 0x0000000000AA00GG
43255ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    agrb <<= 32;                          // 0x00AA00GG00000000
43355ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    agrb |= color & mask;                 // 0x00AA00GG00RR00BB
43455ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    return agrb;
43555ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org}
43655ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org
43755ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org/**
43855ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org * 0xAAxxGGxx, 0xRRxxBBxx-> 0xAARRGGBB
43955ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org */
440e76a3225d5d791a631f70a6a45f6772721710eeecommit-bot@chromium.orgstatic inline uint32_t SkUnsplay(uint32_t ag, uint32_t rb) {
44155ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    const uint32_t mask = 0xFF00FF00;
44255ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    return (ag & mask) | ((rb & mask) >> 8);
44355ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org}
44455ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org
44555ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org/**
44655ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org * 0xAAxxGGxxRRxxBBxx -> 0xAARRGGBB
44755ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org * (note, AGRB -> ARGB)
44813e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com */
449e76a3225d5d791a631f70a6a45f6772721710eeecommit-bot@chromium.orgstatic inline uint32_t SkUnsplay(uint64_t agrb) {
45055ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    const uint32_t mask = 0xFF00FF00;
451cb08f986938eeeeb57f950c94fee120aca965787mtklein@google.com    return SkPMColor(
452cb08f986938eeeeb57f950c94fee120aca965787mtklein@google.com        ((agrb & mask) >> 8) |   // 0x00RR00BB
453cb08f986938eeeeb57f950c94fee120aca965787mtklein@google.com        ((agrb >> 32) & mask));  // 0xAARRGGBB
45455ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org}
45555ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org
45655ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.orgstatic inline SkPMColor SkFastFourByteInterp256_32(SkPMColor src, SkPMColor dst, unsigned scale) {
457b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    SkASSERT(scale <= 256);
45813e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
45955ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    // Two 8-bit blends per two 32-bit registers, with space to make sure the math doesn't collide.
46055ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    uint32_t src_ag, src_rb, dst_ag, dst_rb;
46155ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    SkSplay(src, &src_ag, &src_rb);
46255ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    SkSplay(dst, &dst_ag, &dst_rb);
46313e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
46455ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    const uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag;
46555ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    const uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb;
46613e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
46755ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    return SkUnsplay(ret_ag, ret_rb);
46813e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com}
46913e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com
47055ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.orgstatic inline SkPMColor SkFastFourByteInterp256_64(SkPMColor src, SkPMColor dst, unsigned scale) {
47155ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    SkASSERT(scale <= 256);
47255ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    // Four 8-bit blends in one 64-bit register, with space to make sure the math doesn't collide.
47355ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    return SkUnsplay(SkSplay(src) * scale + (256-scale) * SkSplay(dst));
47455ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org}
47555ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org
47655ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org// TODO(mtklein): Replace slow versions with fast versions, using scale + (scale>>7) everywhere.
47755ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org
47855ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org/**
47955ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org * Same as SkFourByteInterp256, but faster.
48055ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org */
48155ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.orgstatic inline SkPMColor SkFastFourByteInterp256(SkPMColor src, SkPMColor dst, unsigned scale) {
48255ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    // On a 64-bit machine, _64 is about 10% faster than _32, but ~40% slower on a 32-bit machine.
48355ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    if (sizeof(void*) == 4) {
48455ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org        return SkFastFourByteInterp256_32(src, dst, scale);
48555ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    } else {
48655ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org        return SkFastFourByteInterp256_64(src, dst, scale);
48755ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org    }
48855ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org}
48955ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org
49055ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org/**
49155ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org * Nearly the same as SkFourByteInterp, but faster and a touch more accurate, due to better
49255ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org * srcWeight scaling to [0, 256].
49355ca8244cc19c3067defa64f139521264d777eb0commit-bot@chromium.org */
494b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comstatic inline SkPMColor SkFastFourByteInterp(SkPMColor src,
495b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                                             SkPMColor dst,
496b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                                             U8CPU srcWeight) {
497b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    SkASSERT(srcWeight <= 255);
498b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    // scale = srcWeight + (srcWeight >> 7) is more accurate than
499b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    // scale = srcWeight + 1, but 7% slower
500b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    return SkFastFourByteInterp256(src, dst, srcWeight + (srcWeight >> 7));
501b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com}
502b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com
50313e812c69a9e2b2550871573786fc72b17bdd766tomhudson@google.com/**
504e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  Same as SkPackARGB32, but this version guarantees to not check that the
505e686322eba17fee0b5671393dc842e52f77109d9reed@google.com *  values are premultiplied in the debug version.
506e686322eba17fee0b5671393dc842e52f77109d9reed@google.com */
507e686322eba17fee0b5671393dc842e52f77109d9reed@google.comstatic inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
508e686322eba17fee0b5671393dc842e52f77109d9reed@google.com    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
509e686322eba17fee0b5671393dc842e52f77109d9reed@google.com           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
510e686322eba17fee0b5671393dc842e52f77109d9reed@google.com}
511e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
5120b8b3bb08330dd341acbd52c16e55455325e465areed@google.comstatic inline
5130b8b3bb08330dd341acbd52c16e55455325e465areed@google.comSkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
5140b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    SkA32Assert(a);
515c2050e3a3ecfb8738b36e2add15c526e8e0f21fecommit-bot@chromium.org    SkR32Assert(r);
516c2050e3a3ecfb8738b36e2add15c526e8e0f21fecommit-bot@chromium.org    SkG32Assert(g);
517c2050e3a3ecfb8738b36e2add15c526e8e0f21fecommit-bot@chromium.org    SkB32Assert(b);
5180b8b3bb08330dd341acbd52c16e55455325e465areed@google.com
5190b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    if (a != 255) {
5200b8b3bb08330dd341acbd52c16e55455325e465areed@google.com        r = SkMulDiv255Round(r, a);
5210b8b3bb08330dd341acbd52c16e55455325e465areed@google.com        g = SkMulDiv255Round(g, a);
5220b8b3bb08330dd341acbd52c16e55455325e465areed@google.com        b = SkMulDiv255Round(b, a);
5230b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    }
5240b8b3bb08330dd341acbd52c16e55455325e465areed@google.com    return SkPackARGB32(a, r, g, b);
5250b8b3bb08330dd341acbd52c16e55455325e465areed@google.com}
5260b8b3bb08330dd341acbd52c16e55455325e465areed@google.com
527f70e917df73ab776c8869e6f9caa381a03e5f595commit-bot@chromium.org// When Android is compiled optimizing for size, SkAlphaMulQ doesn't get
528f70e917df73ab776c8869e6f9caa381a03e5f595commit-bot@chromium.org// inlined; forcing inlining significantly improves performance.
529f70e917df73ab776c8869e6f9caa381a03e5f595commit-bot@chromium.orgstatic SK_ALWAYS_INLINE uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
530f31fa24914c683abcc2c860093b142725c43fbe6commit-bot@chromium.org    uint32_t mask = 0xFF00FF;
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t rb = ((c & mask) * scale) >> 8;
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t ag = ((c >> 8) & mask) * scale;
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (rb & mask) | (ag & ~mask);
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)aa <= 255);
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned src_scale = SkAlpha255To256(aa);
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale));
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale);
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////////
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Convert a 32bit pixel to a 16bit pixel (no dither)
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR32ToR16_MACRO(r)   ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG32ToG16_MACRO(g)   ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB32ToB16_MACRO(b)   ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
55834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline unsigned SkR32ToR16(unsigned r) {
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkR32Assert(r);
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkR32ToR16_MACRO(r);
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
56234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline unsigned SkG32ToG16(unsigned g) {
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkG32Assert(g);
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkG32ToG16_MACRO(g);
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
56634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline unsigned SkB32ToB16(unsigned b) {
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkB32Assert(b);
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkB32ToB16_MACRO(b);
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkR32ToR16(r)   SkR32ToR16_MACRO(r)
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkG32ToG16(g)   SkG32ToG16_MACRO(g)
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkB32ToB16(b)   SkB32ToB16_MACRO(b)
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked32ToR16(c)  (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked32ToG16(c)  (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked32ToB16(c)  (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58034245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkPixel32ToPixel16(SkPMColor c) {
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return r | g | b;
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (SkR32ToR16(r) << SK_R16_SHIFT) |
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (SkG32ToG16(g) << SK_G16_SHIFT) |
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (SkB32ToB16(b) << SK_B16_SHIFT);
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPixel32ToPixel16_ToU16(src)   SkToU16(SkPixel32ToPixel16(src))
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////////////////
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Fast dither from 32->16
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkShouldDitherXY(x, y)  (((x) ^ (y)) & 1)
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
60034245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
604e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(r, g, b);
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
60834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) {
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    It is now suitable for combining with a scaled expanded_rgb_16 color
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    as in SkSrcOver32To16().
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    We must do this 565 high-bit replication, in order for the subsequent add
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    to saturate properly (and not overflow). If we take the 8 bits as is, it is
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    possible to overflow.
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
61934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) {
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkPacked32ToR16(c);
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkPacked32ToG16(c);
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkPacked32ToB16(c);
623e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sr = (sr << 5) | sr;
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg = (sg << 5) | (sg >> 1);
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sb = (sb << 5) | sb;
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (sr << 11) | (sg << 21) | (sb << 0);
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (with dirt in the high 16bits, so caller beware).
6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkGetPackedR32(src);
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkGetPackedG32(src);
6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkGetPackedB32(src);
637e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dr = SkGetPackedR16(dst);
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dg = SkGetPackedG16(dst);
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned db = SkGetPackedB16(dst);
641e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned isa = 255 - SkGetPackedA32(src);
643e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
647e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(dr, dg, db);
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////////
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Convert a 16bit pixel to a 32bit pixel
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65434245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkR16ToR32(unsigned r) {
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
65734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com
65834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkG16ToG32(unsigned g) {
6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
66134245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com
66234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkB16ToB32(unsigned b) {
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked16ToR32(c)      SkR16ToR32(SkGetPackedR16(c))
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked16ToG32(c)      SkG16ToG32(SkGetPackedG16(c))
6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked16ToB32(c)      SkB16ToB32(SkGetPackedB16(c))
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
67034245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPixel16ToPixel32(U16CPU src) {
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(src == SkToU16(src));
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    r = SkPacked16ToR32(src);
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    g = SkPacked16ToG32(src);
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    b = SkPacked16ToB32(src);
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackARGB32(0xFF, r, g, b);
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
684c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com// similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor
685c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.comstatic inline SkColor SkPixel16ToColor(U16CPU src) {
686c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT(src == SkToU16(src));
687e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
688c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    unsigned    r = SkPacked16ToR32(src);
689c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    unsigned    g = SkPacked16ToG32(src);
690c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    unsigned    b = SkPacked16ToB32(src);
691e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
692c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
693c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
694c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
695e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
696c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com    return SkColorSetRGB(r, g, b);
697c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com}
698c64599649bab68aedf07959f86fa506fc46fa3c2reed@android.com
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef uint16_t SkPMColor16;
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Put in OpenGL order (r g b a)
7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_A4444_SHIFT    0
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_R4444_SHIFT    12
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_G4444_SHIFT    8
7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_B4444_SHIFT    4
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkA32To4444(a)  ((unsigned)(a) >> 4)
7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR32To4444(r)  ((unsigned)(r) >> 4)
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG32To4444(g)  ((unsigned)(g) >> 4)
7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB32To4444(b)  ((unsigned)(b) >> 4)
7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
71434245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U8CPU SkReplicateNibble(unsigned nib) {
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(nib <= 0xF);
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (nib << 4) | nib;
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkA4444ToA32(a)     SkReplicateNibble(a)
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkR4444ToR32(r)     SkReplicateNibble(r)
7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkG4444ToG32(g)     SkReplicateNibble(g)
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkB4444ToB32(b)     SkReplicateNibble(b)
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedA4444(c)     (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedR4444(c)     (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedG4444(c)     (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkGetPackedB4444(c)     (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToA32(c)    SkReplicateNibble(SkGetPackedA4444(c))
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToR32(c)    SkReplicateNibble(SkGetPackedR4444(c))
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToG32(c)    SkReplicateNibble(SkGetPackedG4444(c))
7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPacked4444ToB32(c)    SkReplicateNibble(SkGetPackedB4444(c))
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
73534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline void SkPMColor16Assert(U16CPU c) {
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned a = SkGetPackedA4444(c);
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = SkGetPackedR4444(c);
7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = SkGetPackedG4444(c);
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = SkGetPackedB4444(c);
740e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(a <= 0xF);
7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= a);
7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= a);
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= a);
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkPMColor16Assert(c)
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
75034245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkAlpha15To16(unsigned a) {
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(a <= 0xF);
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return a + (a >> 3);
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
75634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com    static inline int SkAlphaMul4(int value, int scale) {
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((unsigned)scale <= 0x10);
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return value * scale >> 4;
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkAlphaMul4(value, scale)   ((value) * (scale) >> 4)
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
76434245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkR4444ToR565(unsigned r) {
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= 0xF);
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
76934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkG4444ToG565(unsigned g) {
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= 0xF);
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
77434245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline unsigned SkB4444ToB565(unsigned b) {
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= 0xF);
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
78034245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com                                         unsigned g, unsigned b) {
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(a <= 0xF);
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(r <= a);
7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(g <= a);
7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(b <= a);
785e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                         (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
79034245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale) {
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(scale <= 16);
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned mask = 0xF0F;    //gMask_0F0F;
794e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned rb = ((c & mask) * scale) >> 4;
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned ag = ((c >> 4) & mask) * scale;
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (rb & mask) | (ag & ~mask);
7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    c = (c & mask) | ((c & (mask << 4)) << 12);
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    c = c * scale >> 4;
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (c & mask) | ((c >> 12) & (mask << 4));
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    once by a value up to 16. Used in conjunction with SkCompact_4444.
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
80934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkExpand_4444(U16CPU c) {
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(c == (uint16_t)c);
811e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned mask = 0xF0F;    //gMask_0F0F;
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (c & mask) | ((c & ~mask) << 12);
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16.
8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    NOTE: this explicitly does not clean the top 16 bits (which may be garbage).
8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    It does this for speed, since if it is being written directly to 16bits of
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    memory, the top 16bits will be ignored. Casting the result to uint16_t here
8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    would add 2 more instructions, slow us down. It is up to the caller to
8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    perform the cast if needed.
8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
82334245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline U16CPU SkCompact_4444(uint32_t c) {
8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const unsigned mask = 0xF0F;    //gMask_0F0F;
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (c & mask) | ((c >> 12) & ~mask);
8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
82834245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) {
8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sa = SkGetPackedA4444(s);
8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // To avoid overflow, we have to clear the low bit of the synthetic sg
8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // if the src alpha is <= 7.
8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // to see why, try blending 0x4444 on top of 565-white and watch green
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // overflow (sum == 64)
8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg &= ~(~(sa >> 3) & 1);
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned scale = SkAlpha15To16(15 - sa);
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
844e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0
8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (sg + dg > 63) {
8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(sr + dr, sg + dg, sb + db);
8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
85334245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) {
8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)scale16 <= 16);
855e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
85934245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16) {
8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)scale16 <= 16);
861e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t src32 = SkExpand_4444(src) * scale16;
8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // the scaled srcAlpha is the bottom byte
8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned srcA = SkGetPackedA4444(src) * scale16;
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(srcA == (src32 & 0xFF));
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4;
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t dst32 = SkExpand_4444(dst) * dstScale;
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkCompact_4444((src32 + dst32) >> 4);
8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
87534245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkPixel4444ToPixel32(U16CPU c) {
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 (SkGetPackedR4444(c) << SK_R32_SHIFT) |
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 (SkGetPackedG4444(c) << SK_G32_SHIFT) |
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                 (SkGetPackedB4444(c) << SK_B32_SHIFT);
8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return d | (d << 4);
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88334245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) {
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// cheap 2x2 dither
8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
89234245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.com                                               U8CPU g, U8CPU b) {
893735b790150096c3d5e817854b228945a9b869e86reed@android.com    // to ensure that we stay a legal premultiplied color, we take the max()
894735b790150096c3d5e817854b228945a9b869e86reed@android.com    // of the truncated and dithered alpha values. If we didn't, cases like
895735b790150096c3d5e817854b228945a9b869e86reed@android.com    // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...)
896735b790150096c3d5e817854b228945a9b869e86reed@android.com    // which is not legal premultiplied, since a < color
897735b790150096c3d5e817854b228945a9b869e86reed@android.com    unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
898735b790150096c3d5e817854b228945a9b869e86reed@android.com    a = SkMax32(a >> 4, dithered_a);
899735b790150096c3d5e817854b228945a9b869e86reed@android.com    // these we just dither in place
9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
903e686322eba17fee0b5671393dc842e52f77109d9reed@google.com
9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackARGB4444(a, r, g, b);
9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
90734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) {
9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                SkGetPackedG32(c), SkGetPackedB32(c));
9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Assumes 16bit is in standard RGBA order.
9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Transforms a normal ARGB_8888 into the same byte order as
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    expanded ARGB_4444, but keeps each component 8bits
9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
91634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkExpand_8888(SkPMColor c) {
9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> SK_G32_SHIFT) & 0xFF) <<  8) |
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> SK_A32_SHIFT) & 0xFF) <<  0);
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Undo the operation of SkExpand_8888, turning the argument back into
9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    a SkPMColor.
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
92634245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline SkPMColor SkCompact_8888(uint32_t c) {
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >>  8) & 0xFF) << SK_G32_SHIFT) |
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >>  0) & 0xFF) << SK_A32_SHIFT);
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    but this routine just keeps the high 4bits of each component in the low
9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    4bits of the result (just like a newly expanded PMColor16).
9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
93734245c7871f6339de8cc2be8fb1090ca3cba54efreed@android.comstatic inline uint32_t SkExpand32_4444(SkPMColor c) {
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> (SK_G32_SHIFT + 4)) & 0xF) <<  8) |
9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            (((c >> (SK_A32_SHIFT + 4)) & 0xF) <<  0);
9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// takes two values and alternamtes them as part of a memset16
9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// used for cheap 2x2 dithering when the colors are opaque
9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
948d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com///////////////////////////////////////////////////////////////////////////////
949d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com
950d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.comstatic inline int SkUpscale31To32(int value) {
951d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    SkASSERT((unsigned)value <= 31);
952d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    return value + (value >> 4);
953d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com}
954d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com
955d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.comstatic inline int SkBlend32(int src, int dst, int scale) {
956d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    SkASSERT((unsigned)src <= 0xFF);
957d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    SkASSERT((unsigned)dst <= 0xFF);
958d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    SkASSERT((unsigned)scale <= 32);
959d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    return dst + ((src - dst) * scale >> 5);
960d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com}
961d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com
962178964b6f6957762f00b0cfa12734f980fd97ca9bsalomon@google.comstatic inline SkPMColor SkBlendLCD16(int srcA, int srcR, int srcG, int srcB,
963fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                                     SkPMColor dst, uint16_t mask) {
964d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    if (mask == 0) {
965d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com        return dst;
966d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    }
967fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
968d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    /*  We want all of these in 5bits, hence the shifts in case one of them
969d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com     *  (green) is 6bits.
970d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com     */
971d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
972d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
973d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
974fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
975d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    // Now upscale them to 0..32, so we can use blend32
976d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    maskR = SkUpscale31To32(maskR);
977d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    maskG = SkUpscale31To32(maskG);
978d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    maskB = SkUpscale31To32(maskB);
979fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
980d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    // srcA has been upscaled to 256 before passed into this function
981d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    maskR = maskR * srcA >> 8;
982d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    maskG = maskG * srcA >> 8;
983d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    maskB = maskB * srcA >> 8;
984fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
985d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int dstR = SkGetPackedR32(dst);
986d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int dstG = SkGetPackedG32(dst);
987d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int dstB = SkGetPackedB32(dst);
988fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
989d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    // LCD blitting is only supported if the dst is known/required
990d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    // to be opaque
991d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    return SkPackARGB32(0xFF,
992d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com                        SkBlend32(srcR, dstR, maskR),
993d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com                        SkBlend32(srcG, dstG, maskG),
994d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com                        SkBlend32(srcB, dstB, maskB));
995d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com}
996d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com
997178964b6f6957762f00b0cfa12734f980fd97ca9bsalomon@google.comstatic inline SkPMColor SkBlendLCD16Opaque(int srcR, int srcG, int srcB,
998178964b6f6957762f00b0cfa12734f980fd97ca9bsalomon@google.com                                           SkPMColor dst, uint16_t mask,
999fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                                           SkPMColor opaqueDst) {
1000d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    if (mask == 0) {
1001d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com        return dst;
1002d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    }
1003d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com
1004d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    if (0xFFFF == mask) {
1005d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com        return opaqueDst;
1006d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    }
1007fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1008d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    /*  We want all of these in 5bits, hence the shifts in case one of them
1009d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com     *  (green) is 6bits.
1010d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com     */
1011d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
1012d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
1013d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
1014fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1015d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    // Now upscale them to 0..32, so we can use blend32
1016d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    maskR = SkUpscale31To32(maskR);
1017d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    maskG = SkUpscale31To32(maskG);
1018d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    maskB = SkUpscale31To32(maskB);
1019fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1020d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int dstR = SkGetPackedR32(dst);
1021d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int dstG = SkGetPackedG32(dst);
1022d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    int dstB = SkGetPackedB32(dst);
1023fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1024d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    // LCD blitting is only supported if the dst is known/required
1025d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    // to be opaque
1026d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    return SkPackARGB32(0xFF,
1027d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com                        SkBlend32(srcR, dstR, maskR),
1028d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com                        SkBlend32(srcG, dstG, maskG),
1029d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com                        SkBlend32(srcB, dstB, maskB));
1030d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com}
1031d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com
103276e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.orgstatic inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t mask[],
103376e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org                                  SkColor src, int width, SkPMColor) {
103476e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org    int srcA = SkColorGetA(src);
103576e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org    int srcR = SkColorGetR(src);
103676e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org    int srcG = SkColorGetG(src);
103776e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org    int srcB = SkColorGetB(src);
1038fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1039d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    srcA = SkAlpha255To256(srcA);
1040fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1041d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    for (int i = 0; i < width; i++) {
104276e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org        dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], mask[i]);
1043d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    }
1044d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com}
1045d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com
104676e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.orgstatic inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t mask[],
104776e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org                                        SkColor src, int width,
1048178964b6f6957762f00b0cfa12734f980fd97ca9bsalomon@google.com                                        SkPMColor opaqueDst) {
104976e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org    int srcR = SkColorGetR(src);
105076e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org    int srcG = SkColorGetG(src);
105176e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org    int srcB = SkColorGetB(src);
1052fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1053d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    for (int i = 0; i < width; i++) {
105476e0d137892f6a4f3bce278aceb99f9a0d37317ccommit-bot@chromium.org        dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], mask[i],
1055fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                                    opaqueDst);
1056d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com    }
1057d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com}
1058d6770e69e05c9dcc12f2a1a2d509c0b174372ee7tomhudson@google.com
10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1060