1 /* 2 * Copyright 2006 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkAvoidXfermode.h" 9 #include "SkColorPriv.h" 10 #include "SkFlattenableBuffers.h" 11 #include "SkString.h" 12 13 SkAvoidXfermode::SkAvoidXfermode(SkColor opColor, U8CPU tolerance, Mode mode) { 14 if (tolerance > 255) { 15 tolerance = 255; 16 } 17 18 fOpColor = opColor; 19 fDistMul = (256 << 14) / (tolerance + 1); 20 fMode = mode; 21 } 22 23 SkAvoidXfermode::SkAvoidXfermode(SkFlattenableReadBuffer& buffer) 24 : INHERITED(buffer) { 25 fOpColor = buffer.readColor(); 26 fDistMul = buffer.readUInt(); 27 fMode = (Mode)buffer.readUInt(); 28 } 29 30 void SkAvoidXfermode::flatten(SkFlattenableWriteBuffer& buffer) const { 31 this->INHERITED::flatten(buffer); 32 33 buffer.writeColor(fOpColor); 34 buffer.writeUInt(fDistMul); 35 buffer.writeUInt(fMode); 36 } 37 38 // returns 0..31 39 static unsigned color_dist16(uint16_t c, unsigned r, unsigned g, unsigned b) { 40 SkASSERT(r <= SK_R16_MASK); 41 SkASSERT(g <= SK_G16_MASK); 42 SkASSERT(b <= SK_B16_MASK); 43 44 unsigned dr = SkAbs32(SkGetPackedR16(c) - r); 45 unsigned dg = SkAbs32(SkGetPackedG16(c) - g) >> (SK_G16_BITS - SK_R16_BITS); 46 unsigned db = SkAbs32(SkGetPackedB16(c) - b); 47 48 return SkMax32(dr, SkMax32(dg, db)); 49 } 50 51 // returns 0..255 52 static unsigned color_dist32(SkPMColor c, U8CPU r, U8CPU g, U8CPU b) { 53 SkASSERT(r <= 0xFF); 54 SkASSERT(g <= 0xFF); 55 SkASSERT(b <= 0xFF); 56 57 unsigned dr = SkAbs32(SkGetPackedR32(c) - r); 58 unsigned dg = SkAbs32(SkGetPackedG32(c) - g); 59 unsigned db = SkAbs32(SkGetPackedB32(c) - b); 60 61 return SkMax32(dr, SkMax32(dg, db)); 62 } 63 64 static int scale_dist_14(int dist, uint32_t mul, uint32_t sub) { 65 int tmp = dist * mul - sub; 66 int result = (tmp + (1 << 13)) >> 14; 67 68 return result; 69 } 70 71 static inline unsigned Accurate255To256(unsigned x) { 72 return x + (x >> 7); 73 } 74 75 void SkAvoidXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count, 76 const SkAlpha aa[]) const { 77 unsigned opR = SkColorGetR(fOpColor); 78 unsigned opG = SkColorGetG(fOpColor); 79 unsigned opB = SkColorGetB(fOpColor); 80 uint32_t mul = fDistMul; 81 uint32_t sub = (fDistMul - (1 << 14)) << 8; 82 83 int MAX, mask; 84 85 if (kTargetColor_Mode == fMode) { 86 mask = -1; 87 MAX = 255; 88 } else { 89 mask = 0; 90 MAX = 0; 91 } 92 93 for (int i = 0; i < count; i++) { 94 int d = color_dist32(dst[i], opR, opG, opB); 95 // now reverse d if we need to 96 d = MAX + (d ^ mask) - mask; 97 SkASSERT((unsigned)d <= 255); 98 d = Accurate255To256(d); 99 100 d = scale_dist_14(d, mul, sub); 101 SkASSERT(d <= 256); 102 103 if (d > 0) { 104 if (NULL != aa) { 105 d = SkAlphaMul(d, Accurate255To256(*aa++)); 106 if (0 == d) { 107 continue; 108 } 109 } 110 dst[i] = SkFourByteInterp256(src[i], dst[i], d); 111 } 112 } 113 } 114 115 static inline U16CPU SkBlend3216(SkPMColor src, U16CPU dst, unsigned scale) { 116 SkASSERT(scale <= 32); 117 scale <<= 3; 118 119 return SkPackRGB16( SkAlphaBlend(SkPacked32ToR16(src), SkGetPackedR16(dst), scale), 120 SkAlphaBlend(SkPacked32ToG16(src), SkGetPackedG16(dst), scale), 121 SkAlphaBlend(SkPacked32ToB16(src), SkGetPackedB16(dst), scale)); 122 } 123 124 void SkAvoidXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count, 125 const SkAlpha aa[]) const { 126 unsigned opR = SkColorGetR(fOpColor) >> (8 - SK_R16_BITS); 127 unsigned opG = SkColorGetG(fOpColor) >> (8 - SK_G16_BITS); 128 unsigned opB = SkColorGetB(fOpColor) >> (8 - SK_R16_BITS); 129 uint32_t mul = fDistMul; 130 uint32_t sub = (fDistMul - (1 << 14)) << SK_R16_BITS; 131 132 int MAX, mask; 133 134 if (kTargetColor_Mode == fMode) { 135 mask = -1; 136 MAX = 31; 137 } else { 138 mask = 0; 139 MAX = 0; 140 } 141 142 for (int i = 0; i < count; i++) { 143 int d = color_dist16(dst[i], opR, opG, opB); 144 // now reverse d if we need to 145 d = MAX + (d ^ mask) - mask; 146 SkASSERT((unsigned)d <= 31); 147 // convert from 0..31 to 0..32 148 d += d >> 4; 149 d = scale_dist_14(d, mul, sub); 150 SkASSERT(d <= 32); 151 152 if (d > 0) { 153 if (NULL != aa) { 154 d = SkAlphaMul(d, Accurate255To256(*aa++)); 155 if (0 == d) { 156 continue; 157 } 158 } 159 dst[i] = SkBlend3216(src[i], dst[i], d); 160 } 161 } 162 } 163 164 void SkAvoidXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count, 165 const SkAlpha aa[]) const { 166 // override in subclass 167 } 168 169 #ifdef SK_DEVELOPER 170 void SkAvoidXfermode::toString(SkString* str) const { 171 str->append("SkAvoidXfermode: opColor: "); 172 str->appendHex(fOpColor); 173 str->appendf("distMul: %d ", fDistMul); 174 175 static const char* gModeStrings[] = { "Avoid", "Target" }; 176 177 str->appendf("mode: %s", gModeStrings[fMode]); 178 } 179 #endif 180