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