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