1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/effects/SkAvoidXfermode.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,180 @@ 1.4 +/* 1.5 + * Copyright 2006 The Android Open Source Project 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkAvoidXfermode.h" 1.12 +#include "SkColorPriv.h" 1.13 +#include "SkReadBuffer.h" 1.14 +#include "SkWriteBuffer.h" 1.15 +#include "SkString.h" 1.16 + 1.17 +SkAvoidXfermode::SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode) { 1.18 + if (tolerance > 255) { 1.19 + tolerance = 255; 1.20 + } 1.21 + 1.22 + fOpColor = opColor; 1.23 + fDistMul = (256 << 14) / (tolerance + 1); 1.24 + fMode = mode; 1.25 +} 1.26 + 1.27 +SkAvoidXfermode::SkAvoidXfermode(SkReadBuffer& buffer) 1.28 + : INHERITED(buffer) { 1.29 + fOpColor = buffer.readColor(); 1.30 + fDistMul = buffer.readUInt(); 1.31 + fMode = (Mode)buffer.readUInt(); 1.32 +} 1.33 + 1.34 +void SkAvoidXfermode::flatten(SkWriteBuffer& buffer) const { 1.35 + this->INHERITED::flatten(buffer); 1.36 + 1.37 + buffer.writeColor(fOpColor); 1.38 + buffer.writeUInt(fDistMul); 1.39 + buffer.writeUInt(fMode); 1.40 +} 1.41 + 1.42 +// returns 0..31 1.43 +static unsigned color_dist16(uint16_t c, unsigned r, unsigned g, unsigned b) { 1.44 + SkASSERT(r <= SK_R16_MASK); 1.45 + SkASSERT(g <= SK_G16_MASK); 1.46 + SkASSERT(b <= SK_B16_MASK); 1.47 + 1.48 + unsigned dr = SkAbs32(SkGetPackedR16(c) - r); 1.49 + unsigned dg = SkAbs32(SkGetPackedG16(c) - g) >> (SK_G16_BITS - SK_R16_BITS); 1.50 + unsigned db = SkAbs32(SkGetPackedB16(c) - b); 1.51 + 1.52 + return SkMax32(dr, SkMax32(dg, db)); 1.53 +} 1.54 + 1.55 +// returns 0..255 1.56 +static unsigned color_dist32(SkPMColor c, U8CPU r, U8CPU g, U8CPU b) { 1.57 + SkASSERT(r <= 0xFF); 1.58 + SkASSERT(g <= 0xFF); 1.59 + SkASSERT(b <= 0xFF); 1.60 + 1.61 + unsigned dr = SkAbs32(SkGetPackedR32(c) - r); 1.62 + unsigned dg = SkAbs32(SkGetPackedG32(c) - g); 1.63 + unsigned db = SkAbs32(SkGetPackedB32(c) - b); 1.64 + 1.65 + return SkMax32(dr, SkMax32(dg, db)); 1.66 +} 1.67 + 1.68 +static int scale_dist_14(int dist, uint32_t mul, uint32_t sub) { 1.69 + int tmp = dist * mul - sub; 1.70 + int result = (tmp + (1 << 13)) >> 14; 1.71 + 1.72 + return result; 1.73 +} 1.74 + 1.75 +static inline unsigned Accurate255To256(unsigned x) { 1.76 + return x + (x >> 7); 1.77 +} 1.78 + 1.79 +void SkAvoidXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count, 1.80 + const SkAlpha aa[]) const { 1.81 + unsigned opR = SkColorGetR(fOpColor); 1.82 + unsigned opG = SkColorGetG(fOpColor); 1.83 + unsigned opB = SkColorGetB(fOpColor); 1.84 + uint32_t mul = fDistMul; 1.85 + uint32_t sub = (fDistMul - (1 << 14)) << 8; 1.86 + 1.87 + int MAX, mask; 1.88 + 1.89 + if (kTargetColor_Mode == fMode) { 1.90 + mask = -1; 1.91 + MAX = 255; 1.92 + } else { 1.93 + mask = 0; 1.94 + MAX = 0; 1.95 + } 1.96 + 1.97 + for (int i = 0; i < count; i++) { 1.98 + int d = color_dist32(dst[i], opR, opG, opB); 1.99 + // now reverse d if we need to 1.100 + d = MAX + (d ^ mask) - mask; 1.101 + SkASSERT((unsigned)d <= 255); 1.102 + d = Accurate255To256(d); 1.103 + 1.104 + d = scale_dist_14(d, mul, sub); 1.105 + SkASSERT(d <= 256); 1.106 + 1.107 + if (d > 0) { 1.108 + if (NULL != aa) { 1.109 + d = SkAlphaMul(d, Accurate255To256(*aa++)); 1.110 + if (0 == d) { 1.111 + continue; 1.112 + } 1.113 + } 1.114 + dst[i] = SkFourByteInterp256(src[i], dst[i], d); 1.115 + } 1.116 + } 1.117 +} 1.118 + 1.119 +static inline U16CPU SkBlend3216(SkPMColor src, U16CPU dst, unsigned scale) { 1.120 + SkASSERT(scale <= 32); 1.121 + scale <<= 3; 1.122 + 1.123 + return SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(src), SkGetPackedR16(dst), scale), 1.124 + SkAlphaBlend(SkPacked32ToG16(src), SkGetPackedG16(dst), scale), 1.125 + SkAlphaBlend(SkPacked32ToB16(src), SkGetPackedB16(dst), scale)); 1.126 +} 1.127 + 1.128 +void SkAvoidXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count, 1.129 + const SkAlpha aa[]) const { 1.130 + unsigned opR = SkColorGetR(fOpColor) >> (8 - SK_R16_BITS); 1.131 + unsigned opG = SkColorGetG(fOpColor) >> (8 - SK_G16_BITS); 1.132 + unsigned opB = SkColorGetB(fOpColor) >> (8 - SK_R16_BITS); 1.133 + uint32_t mul = fDistMul; 1.134 + uint32_t sub = (fDistMul - (1 << 14)) << SK_R16_BITS; 1.135 + 1.136 + int MAX, mask; 1.137 + 1.138 + if (kTargetColor_Mode == fMode) { 1.139 + mask = -1; 1.140 + MAX = 31; 1.141 + } else { 1.142 + mask = 0; 1.143 + MAX = 0; 1.144 + } 1.145 + 1.146 + for (int i = 0; i < count; i++) { 1.147 + int d = color_dist16(dst[i], opR, opG, opB); 1.148 + // now reverse d if we need to 1.149 + d = MAX + (d ^ mask) - mask; 1.150 + SkASSERT((unsigned)d <= 31); 1.151 + // convert from 0..31 to 0..32 1.152 + d += d >> 4; 1.153 + d = scale_dist_14(d, mul, sub); 1.154 + SkASSERT(d <= 32); 1.155 + 1.156 + if (d > 0) { 1.157 + if (NULL != aa) { 1.158 + d = SkAlphaMul(d, Accurate255To256(*aa++)); 1.159 + if (0 == d) { 1.160 + continue; 1.161 + } 1.162 + } 1.163 + dst[i] = SkBlend3216(src[i], dst[i], d); 1.164 + } 1.165 + } 1.166 +} 1.167 + 1.168 +void SkAvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count, 1.169 + const SkAlpha aa[]) const { 1.170 + // override in subclass 1.171 +} 1.172 + 1.173 +#ifndef SK_IGNORE_TO_STRING 1.174 +void SkAvoidXfermode::toString(SkString* str) const { 1.175 + str->append("SkAvoidXfermode: opColor: "); 1.176 + str->appendHex(fOpColor); 1.177 + str->appendf("distMul: %d ", fDistMul); 1.178 + 1.179 + static const char* gModeStrings[] = { "Avoid", "Target" }; 1.180 + 1.181 + str->appendf("mode: %s", gModeStrings[fMode]); 1.182 +} 1.183 +#endif