1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkAvoidXfermode.h" 11#include "SkColorPriv.h" 12 13SkAvoidXfermode::SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode) 14{ 15 if (tolerance > 255) { 16 tolerance = 255; 17 } 18 19 fOpColor = opColor; 20 fDistMul = (256 << 14) / (tolerance + 1); 21 fMode = mode; 22} 23 24SkAvoidXfermode::SkAvoidXfermode(SkFlattenableReadBuffer& buffer) 25 : INHERITED(buffer) 26{ 27 fOpColor = buffer.readU32(); 28 fDistMul = buffer.readU32(); 29 fMode = (Mode)buffer.readU8(); 30} 31 32void SkAvoidXfermode::flatten(SkFlattenableWriteBuffer& buffer) 33{ 34 this->INHERITED::flatten(buffer); 35 36 buffer.write32(fOpColor); 37 buffer.write32(fDistMul); 38 buffer.write8(fMode); 39} 40 41SkFlattenable* SkAvoidXfermode::Create(SkFlattenableReadBuffer& rb) 42{ 43 return SkNEW_ARGS(SkAvoidXfermode, (rb)); 44} 45 46SkFlattenable::Factory SkAvoidXfermode::getFactory() 47{ 48 return Create; 49} 50 51// returns 0..31 52static unsigned color_dist16(uint16_t c, unsigned r, unsigned g, unsigned b) 53{ 54 SkASSERT(r <= SK_R16_MASK); 55 SkASSERT(g <= SK_G16_MASK); 56 SkASSERT(b <= SK_B16_MASK); 57 58 unsigned dr = SkAbs32(SkGetPackedR16(c) - r); 59 unsigned dg = SkAbs32(SkGetPackedG16(c) - g) >> (SK_G16_BITS - SK_R16_BITS); 60 unsigned db = SkAbs32(SkGetPackedB16(c) - b); 61 62 return SkMax32(dr, SkMax32(dg, db)); 63} 64 65// returns 0..15 66static unsigned color_dist4444(uint16_t c, unsigned r, unsigned g, unsigned b) 67{ 68 SkASSERT(r <= 0xF); 69 SkASSERT(g <= 0xF); 70 SkASSERT(b <= 0xF); 71 72 unsigned dr = SkAbs32(SkGetPackedR4444(c) - r); 73 unsigned dg = SkAbs32(SkGetPackedG4444(c) - g); 74 unsigned db = SkAbs32(SkGetPackedB4444(c) - b); 75 76 return SkMax32(dr, SkMax32(dg, db)); 77} 78 79// returns 0..255 80static unsigned color_dist32(SkPMColor c, U8CPU r, U8CPU g, U8CPU b) 81{ 82 SkASSERT(r <= 0xFF); 83 SkASSERT(g <= 0xFF); 84 SkASSERT(b <= 0xFF); 85 86 unsigned dr = SkAbs32(SkGetPackedR32(c) - r); 87 unsigned dg = SkAbs32(SkGetPackedG32(c) - g); 88 unsigned db = SkAbs32(SkGetPackedB32(c) - b); 89 90 return SkMax32(dr, SkMax32(dg, db)); 91} 92 93static int scale_dist_14(int dist, uint32_t mul, uint32_t sub) 94{ 95 int tmp = dist * mul - sub; 96 int result = (tmp + (1 << 13)) >> 14; 97 98 return result; 99} 100 101static inline unsigned Accurate255To256(unsigned x) { 102 return x + (x >> 7); 103} 104 105void SkAvoidXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count, 106 const SkAlpha aa[]) 107{ 108 unsigned opR = SkColorGetR(fOpColor); 109 unsigned opG = SkColorGetG(fOpColor); 110 unsigned opB = SkColorGetB(fOpColor); 111 uint32_t mul = fDistMul; 112 uint32_t sub = (fDistMul - (1 << 14)) << 8; 113 114 int MAX, mask; 115 116 if (kTargetColor_Mode == fMode) { 117 mask = -1; 118 MAX = 255; 119 } else { 120 mask = 0; 121 MAX = 0; 122 } 123 124 for (int i = 0; i < count; i++) { 125 int d = color_dist32(dst[i], opR, opG, opB); 126 // now reverse d if we need to 127 d = MAX + (d ^ mask) - mask; 128 SkASSERT((unsigned)d <= 255); 129 d = Accurate255To256(d); 130 131 d = scale_dist_14(d, mul, sub); 132 SkASSERT(d <= 256); 133 134 if (d > 0) { 135 if (NULL != aa) { 136 d = SkAlphaMul(d, Accurate255To256(*aa++)); 137 if (0 == d) { 138 continue; 139 } 140 } 141 dst[i] = SkFourByteInterp(src[i], dst[i], d); 142 } 143 } 144} 145 146static inline U16CPU SkBlend3216(SkPMColor src, U16CPU dst, unsigned scale) 147{ 148 SkASSERT(scale <= 32); 149 scale <<= 3; 150 151 return SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(src), SkGetPackedR16(dst), scale), 152 SkAlphaBlend(SkPacked32ToG16(src), SkGetPackedG16(dst), scale), 153 SkAlphaBlend(SkPacked32ToB16(src), SkGetPackedB16(dst), scale)); 154} 155 156void SkAvoidXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count, 157 const SkAlpha aa[]) 158{ 159 unsigned opR = SkColorGetR(fOpColor) >> (8 - SK_R16_BITS); 160 unsigned opG = SkColorGetG(fOpColor) >> (8 - SK_G16_BITS); 161 unsigned opB = SkColorGetB(fOpColor) >> (8 - SK_R16_BITS); 162 uint32_t mul = fDistMul; 163 uint32_t sub = (fDistMul - (1 << 14)) << SK_R16_BITS; 164 165 int MAX, mask; 166 167 if (kTargetColor_Mode == fMode) { 168 mask = -1; 169 MAX = 31; 170 } else { 171 mask = 0; 172 MAX = 0; 173 } 174 175 for (int i = 0; i < count; i++) { 176 int d = color_dist16(dst[i], opR, opG, opB); 177 // now reverse d if we need to 178 d = MAX + (d ^ mask) - mask; 179 SkASSERT((unsigned)d <= 31); 180 // convert from 0..31 to 0..32 181 d += d >> 4; 182 d = scale_dist_14(d, mul, sub); 183 SkASSERT(d <= 32); 184 185 if (d > 0) { 186 if (NULL != aa) { 187 d = SkAlphaMul(d, Accurate255To256(*aa++)); 188 if (0 == d) { 189 continue; 190 } 191 } 192 dst[i] = SkBlend3216(src[i], dst[i], d); 193 } 194 } 195} 196 197void SkAvoidXfermode::xfer4444(uint16_t dst[], const SkPMColor src[], int count, 198 const SkAlpha aa[]) 199{ 200 unsigned opR = SkColorGetR(fOpColor) >> 4; 201 unsigned opG = SkColorGetG(fOpColor) >> 4; 202 unsigned opB = SkColorGetB(fOpColor) >> 4; 203 uint32_t mul = fDistMul; 204 uint32_t sub = (fDistMul - (1 << 14)) << 4; 205 206 int MAX, mask; 207 208 if (kTargetColor_Mode == fMode) { 209 mask = -1; 210 MAX = 15; 211 } else { 212 mask = 0; 213 MAX = 0; 214 } 215 216 for (int i = 0; i < count; i++) { 217 int d = color_dist4444(dst[i], opR, opG, opB); 218 // now reverse d if we need to 219 d = MAX + (d ^ mask) - mask; 220 SkASSERT((unsigned)d <= 15); 221 // convert from 0..15 to 0..16 222 d += d >> 3; 223 d = scale_dist_14(d, mul, sub); 224 SkASSERT(d <= 16); 225 226 if (d > 0) { 227 if (NULL != aa) { 228 d = SkAlphaMul(d, Accurate255To256(*aa++)); 229 if (0 == d) { 230 continue; 231 } 232 } 233 dst[i] = SkBlend4444(SkPixel32ToPixel4444(src[i]), dst[i], d); 234 } 235 } 236} 237 238void SkAvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count, const SkAlpha aa[]) 239{ 240 // override in subclass 241} 242 243SK_DEFINE_FLATTENABLE_REGISTRAR(SkAvoidXfermode) 244