SkAvoidXfermode.cpp revision 35e2e62b55598210f6999fc2ea26ff8f41446ffe
10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* libs/graphics/effects/SkAvoidXfermode.cpp
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Copyright 2006, The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger** Licensed under the Apache License, Version 2.0 (the "License");
635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger** you may not use this file except in compliance with the License.
735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger** You may obtain a copy of the License at
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger**     http://www.apache.org/licenses/LICENSE-2.0
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
1135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger** Unless required by applicable law or agreed to in writing, software
1235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger** distributed under the License is distributed on an "AS IS" BASIS,
1335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger** See the License for the specific language governing permissions and
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** limitations under the License.
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkAvoidXfermode.h"
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColorPriv.h"
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkAvoidXfermode::SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode)
2235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger{
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (tolerance > 255) {
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        tolerance = 255;
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fOpColor = opColor;
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fDistMul = (256 << 14) / (tolerance + 1);
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fMode = mode;
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkAvoidXfermode::SkAvoidXfermode(SkFlattenableReadBuffer& buffer)
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    : INHERITED(buffer)
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fOpColor = buffer.readU32();
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fDistMul = buffer.readU32();
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fMode = (Mode)buffer.readU8();
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkAvoidXfermode::flatten(SkFlattenableWriteBuffer& buffer)
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->INHERITED::flatten(buffer);
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write32(fOpColor);
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write32(fDistMul);
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    buffer.write8(fMode);
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkFlattenable* SkAvoidXfermode::Create(SkFlattenableReadBuffer& rb)
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkNEW_ARGS(SkAvoidXfermode, (rb));
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkFlattenable::Factory SkAvoidXfermode::getFactory()
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return Create;
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// returns 0..31
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic unsigned color_dist16(uint16_t c, unsigned r, unsigned g, unsigned b)
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(r <= SK_R16_MASK);
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(g <= SK_G16_MASK);
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(b <= SK_B16_MASK);
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned dr = SkAbs32(SkGetPackedR16(c) - r);
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned dg = SkAbs32(SkGetPackedG16(c) - g) >> (SK_G16_BITS - SK_R16_BITS);
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned db = SkAbs32(SkGetPackedB16(c) - b);
6935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkMax32(dr, SkMax32(dg, db));
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// returns 0..15
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic unsigned color_dist4444(uint16_t c, unsigned r, unsigned g, unsigned b)
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(r <= 0xF);
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(g <= 0xF);
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(b <= 0xF);
7935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned dr = SkAbs32(SkGetPackedR4444(c) - r);
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned dg = SkAbs32(SkGetPackedG4444(c) - g);
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned db = SkAbs32(SkGetPackedB4444(c) - b);
8335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkMax32(dr, SkMax32(dg, db));
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// returns 0..255
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic unsigned color_dist32(SkPMColor c, U8CPU r, U8CPU g, U8CPU b)
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(r <= 0xFF);
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(g <= 0xFF);
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(b <= 0xFF);
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned dr = SkAbs32(SkGetPackedR32(c) - r);
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned dg = SkAbs32(SkGetPackedG32(c) - g);
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned db = SkAbs32(SkGetPackedB32(c) - b);
9735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkMax32(dr, SkMax32(dg, db));
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic int scale_dist_14(int dist, uint32_t mul, uint32_t sub)
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int tmp = dist * mul - sub;
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int result = (tmp + (1 << 13)) >> 14;
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return result;
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst, unsigned scale)
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkPackARGB32(a, r, g, b);
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1194ffbc6172403ee38fc70608377ce78c9db00394aMike Reedstatic inline unsigned Accurate255To256(unsigned x) {
1204ffbc6172403ee38fc70608377ce78c9db00394aMike Reed    return x + (x >> 7);
1214ffbc6172403ee38fc70608377ce78c9db00394aMike Reed}
1224ffbc6172403ee38fc70608377ce78c9db00394aMike Reed
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkAvoidXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count,
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                             const SkAlpha aa[])
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned    opR = SkColorGetR(fOpColor);
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned    opG = SkColorGetG(fOpColor);
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned    opB = SkColorGetB(fOpColor);
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t    mul = fDistMul;
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t    sub = (fDistMul - (1 << 14)) << 8;
13135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int MAX, mask;
13335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (kTargetColor_Mode == fMode) {
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        mask = -1;
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        MAX = 255;
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        mask = 0;
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        MAX = 0;
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
14135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (int i = 0; i < count; i++) {
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int d = color_dist32(dst[i], opR, opG, opB);
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now reverse d if we need to
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        d = MAX + (d ^ mask) - mask;
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT((unsigned)d <= 255);
1474ffbc6172403ee38fc70608377ce78c9db00394aMike Reed        d = Accurate255To256(d);
14835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        d = scale_dist_14(d, mul, sub);
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(d <= 256);
15135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (d > 0) {
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (NULL != aa) {
1544ffbc6172403ee38fc70608377ce78c9db00394aMike Reed                d = SkAlphaMul(d, Accurate255To256(*aa++));
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (0 == d) {
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    continue;
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            dst[i] = SkFourByteInterp(src[i], dst[i], d);
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline U16CPU SkBlend3216(SkPMColor src, U16CPU dst, unsigned scale)
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(scale <= 32);
1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    scale <<= 3;
1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(src), SkGetPackedR16(dst), scale),
1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        SkAlphaBlend(SkPacked32ToG16(src), SkGetPackedG16(dst), scale),
1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        SkAlphaBlend(SkPacked32ToB16(src), SkGetPackedB16(dst), scale));
1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkAvoidXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count,
1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                             const SkAlpha aa[])
1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned    opR = SkColorGetR(fOpColor) >> (8 - SK_R16_BITS);
1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned    opG = SkColorGetG(fOpColor) >> (8 - SK_G16_BITS);
1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned    opB = SkColorGetB(fOpColor) >> (8 - SK_R16_BITS);
1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t    mul = fDistMul;
18124fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed    uint32_t    sub = (fDistMul - (1 << 14)) << SK_R16_BITS;
1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int MAX, mask;
18435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (kTargetColor_Mode == fMode) {
1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        mask = -1;
1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        MAX = 31;
1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        mask = 0;
1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        MAX = 0;
1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (int i = 0; i < count; i++) {
1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int d = color_dist16(dst[i], opR, opG, opB);
1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now reverse d if we need to
1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        d = MAX + (d ^ mask) - mask;
1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT((unsigned)d <= 31);
1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // convert from 0..31 to 0..32
1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        d += d >> 4;
2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        d = scale_dist_14(d, mul, sub);
2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(d <= 32);
2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (d > 0) {
2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (NULL != aa) {
2054ffbc6172403ee38fc70608377ce78c9db00394aMike Reed                d = SkAlphaMul(d, Accurate255To256(*aa++));
2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (0 == d) {
2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    continue;
2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            dst[i] = SkBlend3216(src[i], dst[i], d);
2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkAvoidXfermode::xfer4444(uint16_t dst[], const SkPMColor src[], int count,
2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                               const SkAlpha aa[])
2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned    opR = SkColorGetR(fOpColor) >> 4;
2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned    opG = SkColorGetG(fOpColor) >> 4;
2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned    opB = SkColorGetB(fOpColor) >> 4;
2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint32_t    mul = fDistMul;
22224fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed    uint32_t    sub = (fDistMul - (1 << 14)) << 4;
22335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int MAX, mask;
22535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (kTargetColor_Mode == fMode) {
2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        mask = -1;
2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        MAX = 15;
2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        mask = 0;
2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        MAX = 0;
2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
23335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (int i = 0; i < count; i++) {
2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int d = color_dist4444(dst[i], opR, opG, opB);
2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now reverse d if we need to
2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        d = MAX + (d ^ mask) - mask;
2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT((unsigned)d <= 15);
23924fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed        // convert from 0..15 to 0..16
24024fb8c7cc7b76134a25914d8f6346c89c359c621Mike Reed        d += d >> 3;
2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        d = scale_dist_14(d, mul, sub);
2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(d <= 16);
24335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (d > 0) {
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (NULL != aa) {
2464ffbc6172403ee38fc70608377ce78c9db00394aMike Reed                d = SkAlphaMul(d, Accurate255To256(*aa++));
2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (0 == d) {
2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    continue;
2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            dst[i] = SkBlend4444(SkPixel32ToPixel4444(src[i]), dst[i], d);
2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkAvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count, const SkAlpha aa[])
2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // override in subclass
2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
26135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic SkFlattenable::Registrar
26235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    gSkAvoidXfermodeReg("SkAvoidXfermode", SkAvoidXfermode::CreateProc);
263