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