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