SkColorFilters.cpp revision 40528743dbb9ce7f39f093e0cdc47849ac8887cf
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "SkBlitRow.h" 18#include "SkColorFilter.h" 19#include "SkColorPriv.h" 20#include "SkUtils.h" 21 22// common baseclass 23class Sk_XfermodeColorFilter : public SkColorFilter { 24protected: 25 Sk_XfermodeColorFilter(SkColor color) 26 : fPMColor(SkPreMultiplyColor(color)) {} 27 28 virtual void flatten(SkFlattenableWriteBuffer& buffer) { 29 buffer.write32(fPMColor); 30 } 31 32 Sk_XfermodeColorFilter(SkFlattenableReadBuffer& buffer) { 33 fPMColor = buffer.readU32(); 34 } 35 36 SkPMColor fPMColor; 37}; 38 39class SkSrc_XfermodeColorFilter : public Sk_XfermodeColorFilter { 40public: 41 SkSrc_XfermodeColorFilter(SkColor color) : INHERITED(color) {} 42 43 virtual uint32_t getFlags() { 44 if (SkGetPackedA32(fPMColor) == 0xFF) { 45 return kAlphaUnchanged_Flag | kHasFilter16_Flag; 46 } else { 47 return 0; 48 } 49 } 50 51 virtual void filterSpan(const SkPMColor shader[], int count, 52 SkPMColor result[]) { 53 sk_memset32(result, fPMColor, count); 54 } 55 56 virtual void filterSpan16(const uint16_t shader[], int count, 57 uint16_t result[]) { 58 SkASSERT(this->getFlags() & kHasFilter16_Flag); 59 sk_memset16(result, SkPixel32ToPixel16(fPMColor), count); 60 } 61 62protected: 63 virtual Factory getFactory() { return CreateProc; } 64 65 SkSrc_XfermodeColorFilter(SkFlattenableReadBuffer& buffer) 66 : INHERITED(buffer) {} 67 68private: 69 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 70 return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (buffer)); 71 } 72 73 typedef Sk_XfermodeColorFilter INHERITED; 74}; 75 76class SkSrcOver_XfermodeColorFilter : public Sk_XfermodeColorFilter { 77public: 78 SkSrcOver_XfermodeColorFilter(SkColor color) 79 : INHERITED(color), fColor32Proc(SkBlitRow::ColorProcFactory()) {} 80 81 virtual uint32_t getFlags() { 82 if (SkGetPackedA32(fPMColor) == 0xFF) { 83 return kAlphaUnchanged_Flag | kHasFilter16_Flag; 84 } else { 85 return 0; 86 } 87 } 88 89 virtual void filterSpan(const SkPMColor shader[], int count, 90 SkPMColor result[]) { 91 fColor32Proc(result, shader, count, fPMColor); 92 } 93 94 virtual void filterSpan16(const uint16_t shader[], int count, 95 uint16_t result[]) { 96 SkASSERT(this->getFlags() & kHasFilter16_Flag); 97 sk_memset16(result, SkPixel32ToPixel16(fPMColor), count); 98 } 99 100protected: 101 virtual Factory getFactory() { return CreateProc; } 102 103 SkSrcOver_XfermodeColorFilter(SkFlattenableReadBuffer& buffer) 104 : INHERITED(buffer), fColor32Proc(SkBlitRow::ColorProcFactory()) {} 105 106private: 107 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 108 return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (buffer)); 109 } 110 111 typedef Sk_XfermodeColorFilter INHERITED; 112 SkBlitRow::ColorProc fColor32Proc; 113}; 114 115////////////////////////////////////////////////////////////////////////////// 116 117class SkXfermodeColorFilter : public Sk_XfermodeColorFilter { 118public: 119 SkXfermodeColorFilter(SkColor color, SkXfermodeProc proc, 120 SkXfermodeProc16 proc16) : INHERITED(color) { 121 fProc = proc; 122 fProc16 = proc16; 123 } 124 125 virtual uint32_t getFlags() { 126 return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0; 127 } 128 129 virtual void filterSpan(const SkPMColor shader[], int count, 130 SkPMColor result[]) { 131 SkPMColor color = fPMColor; 132 SkXfermodeProc proc = fProc; 133 134 for (int i = 0; i < count; i++) { 135 result[i] = proc(color, shader[i]); 136 } 137 } 138 139 virtual void filterSpan16(const uint16_t shader[], int count, 140 uint16_t result[]) { 141 SkASSERT(this->getFlags() & kHasFilter16_Flag); 142 143 SkPMColor color = fPMColor; 144 SkXfermodeProc16 proc16 = fProc16; 145 146 for (int i = 0; i < count; i++) { 147 result[i] = proc16(color, shader[i]); 148 } 149 } 150 151protected: 152 virtual void flatten(SkFlattenableWriteBuffer& buffer) { 153 this->INHERITED::flatten(buffer); 154 buffer.writeFunctionPtr((void*)fProc); 155 buffer.writeFunctionPtr((void*)fProc16); 156 } 157 158 virtual Factory getFactory() { 159 return CreateProc; 160 } 161 162 SkXfermodeColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { 163 fProc = (SkXfermodeProc) buffer.readFunctionPtr(); 164 fProc16 = (SkXfermodeProc16) buffer.readFunctionPtr(); 165 } 166private: 167 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 168 return SkNEW_ARGS(SkXfermodeColorFilter, (buffer)); 169 } 170 171 SkXfermodeProc fProc; 172 SkXfermodeProc16 fProc16; 173 174 typedef Sk_XfermodeColorFilter INHERITED; 175}; 176 177SkColorFilter* SkColorFilter::CreateProcFilter(SkColor color, 178 SkXfermodeProc proc, 179 SkXfermodeProc16 proc16) { 180 return proc ? 181 SkNEW_ARGS(SkXfermodeColorFilter, (color, proc, proc16)) : 182 NULL; 183} 184 185/////////////////////////////////////////////////////////////////////////////// 186 187SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color, 188 SkXfermode::Mode mode) { 189 unsigned alpha = SkColorGetA(color); 190 191 // first collaps some modes if possible 192 193 if (SkXfermode::kClear_Mode == mode) { 194 color = 0; 195 mode = SkXfermode::kSrc_Mode; 196 } else if (SkXfermode::kSrcOver_Mode == mode) { 197 if (0 == alpha) { 198 mode = SkXfermode::kDst_Mode; 199 } else if (255 == alpha) { 200 mode = SkXfermode::kSrc_Mode; 201 } 202 // else just stay srcover 203 } 204 205 // weed out combinations that are noops, and just return null 206 if (SkXfermode::kDst_Mode == mode || 207 (0 == alpha && (SkXfermode::kSrcOver_Mode == mode || 208 SkXfermode::kDstOver_Mode == mode || 209 SkXfermode::kDstOut_Mode == mode || 210 SkXfermode::kSrcATop_Mode == mode || 211 SkXfermode::kXor_Mode == mode || 212 SkXfermode::kDarken_Mode == mode)) || 213 (0xFF == alpha && SkXfermode::kDstIn_Mode == mode)) { 214 return NULL; 215 } 216 217 switch (mode) { 218 case SkXfermode::kSrc_Mode: 219 return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (color)); 220 case SkXfermode::kSrcOver_Mode: 221 return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (color)); 222 default: 223 return SkColorFilter::CreateProcFilter(color, SkXfermode::GetProc(mode), 224 SkXfermode::GetProc16(mode, color)); 225 } 226} 227 228/////////////////////////////////////////////////////////////////////////////// 229 230static inline unsigned pin(unsigned value, unsigned max) { 231 if (value > max) { 232 value = max; 233 } 234 return value; 235} 236 237static inline unsigned SkUClampMax(unsigned value, unsigned max) { 238 SkASSERT((int32_t)value >= 0); 239 SkASSERT((int32_t)max >= 0); 240 241 int diff = max - value; 242 // clear diff if diff is positive 243 diff &= diff >> 31; 244 245 return value + diff; 246} 247 248class SkLightingColorFilter : public SkColorFilter { 249public: 250 SkLightingColorFilter(SkColor mul, SkColor add) : fMul(mul), fAdd(add) {} 251 252 virtual void filterSpan(const SkPMColor shader[], int count, 253 SkPMColor result[]) { 254 unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul)); 255 unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul)); 256 unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul)); 257 258 unsigned addR = SkColorGetR(fAdd); 259 unsigned addG = SkColorGetG(fAdd); 260 unsigned addB = SkColorGetB(fAdd); 261 262 for (int i = 0; i < count; i++) { 263 SkPMColor c = shader[i]; 264 if (c) { 265 unsigned a = SkGetPackedA32(c); 266 unsigned scaleA = SkAlpha255To256(a); 267 unsigned r = pin(SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA), a); 268 unsigned g = pin(SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA), a); 269 unsigned b = pin(SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA), a); 270 c = SkPackARGB32(a, r, g, b); 271 } 272 result[i] = c; 273 } 274 } 275 276protected: 277 virtual void flatten(SkFlattenableWriteBuffer& buffer) { 278 buffer.write32(fMul); 279 buffer.write32(fAdd); 280 } 281 282 virtual Factory getFactory() { 283 return CreateProc; 284 } 285 286 SkLightingColorFilter(SkFlattenableReadBuffer& buffer) { 287 fMul = buffer.readU32(); 288 fAdd = buffer.readU32(); 289 } 290 291 SkColor fMul, fAdd; 292 293private: 294 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 295 return SkNEW_ARGS(SkLightingColorFilter, (buffer)); 296 } 297}; 298 299class SkLightingColorFilter_JustAdd : public SkLightingColorFilter { 300public: 301 SkLightingColorFilter_JustAdd(SkColor mul, SkColor add) 302 : INHERITED(mul, add) {} 303 304 virtual void filterSpan(const SkPMColor shader[], int count, 305 SkPMColor result[]) { 306 unsigned addR = SkColorGetR(fAdd); 307 unsigned addG = SkColorGetG(fAdd); 308 unsigned addB = SkColorGetB(fAdd); 309 310 for (int i = 0; i < count; i++) { 311 SkPMColor c = shader[i]; 312 if (c) { 313 unsigned a = SkGetPackedA32(c); 314 unsigned scaleA = SkAlpha255To256(a); 315 unsigned r = pin(SkGetPackedR32(c) + SkAlphaMul(addR, scaleA), a); 316 unsigned g = pin(SkGetPackedG32(c) + SkAlphaMul(addG, scaleA), a); 317 unsigned b = pin(SkGetPackedB32(c) + SkAlphaMul(addB, scaleA), a); 318 c = SkPackARGB32(a, r, g, b); 319 } 320 result[i] = c; 321 } 322 } 323 324protected: 325 virtual Factory getFactory() { return CreateProc; } 326 327 SkLightingColorFilter_JustAdd(SkFlattenableReadBuffer& buffer) 328 : INHERITED(buffer) {} 329 330private: 331 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 332 return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (buffer)); 333 } 334 typedef SkLightingColorFilter INHERITED; 335}; 336 337class SkLightingColorFilter_JustMul : public SkLightingColorFilter { 338public: 339 SkLightingColorFilter_JustMul(SkColor mul, SkColor add) 340 : INHERITED(mul, add) {} 341 342 virtual void filterSpan(const SkPMColor shader[], int count, 343 SkPMColor result[]) { 344 unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul)); 345 unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul)); 346 unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul)); 347 348 for (int i = 0; i < count; i++) { 349 SkPMColor c = shader[i]; 350 if (c) { 351 unsigned a = SkGetPackedA32(c); 352 unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR); 353 unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG); 354 unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB); 355 c = SkPackARGB32(a, r, g, b); 356 } 357 result[i] = c; 358 } 359 } 360 361protected: 362 virtual Factory getFactory() { return CreateProc; } 363 364 SkLightingColorFilter_JustMul(SkFlattenableReadBuffer& buffer) 365 : INHERITED(buffer) {} 366 367private: 368 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 369 return SkNEW_ARGS(SkLightingColorFilter_JustMul, (buffer)); 370 } 371 372 typedef SkLightingColorFilter INHERITED; 373}; 374 375class SkLightingColorFilter_SingleMul : public SkLightingColorFilter { 376public: 377 SkLightingColorFilter_SingleMul(SkColor mul, SkColor add) 378 : INHERITED(mul, add) { 379 SkASSERT(SkColorGetR(add) == 0); 380 SkASSERT(SkColorGetG(add) == 0); 381 SkASSERT(SkColorGetB(add) == 0); 382 SkASSERT(SkColorGetR(mul) == SkColorGetG(mul)); 383 SkASSERT(SkColorGetR(mul) == SkColorGetB(mul)); 384 } 385 386 virtual uint32_t getFlags() { 387 return this->INHERITED::getFlags() | (kAlphaUnchanged_Flag | kHasFilter16_Flag); 388 } 389 390 virtual void filterSpan16(const uint16_t shader[], int count, 391 uint16_t result[]) { 392 // all mul components are the same 393 unsigned scale = SkAlpha255To256(SkColorGetR(fMul)); 394 395 if (count > 0) { 396 do { 397 *result++ = SkAlphaMulRGB16(*shader++, scale); 398 } while (--count > 0); 399 } 400 } 401 402protected: 403 virtual Factory getFactory() { return CreateProc; } 404 405 SkLightingColorFilter_SingleMul(SkFlattenableReadBuffer& buffer) 406 : INHERITED(buffer) {} 407 408private: 409 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 410 return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (buffer)); 411 } 412 413 typedef SkLightingColorFilter INHERITED; 414}; 415 416class SkLightingColorFilter_NoPin : public SkLightingColorFilter { 417public: 418 SkLightingColorFilter_NoPin(SkColor mul, SkColor add) 419 : INHERITED(mul, add) {} 420 421 virtual void filterSpan(const SkPMColor shader[], int count, 422 SkPMColor result[]) { 423 unsigned scaleR = SkAlpha255To256(SkColorGetR(fMul)); 424 unsigned scaleG = SkAlpha255To256(SkColorGetG(fMul)); 425 unsigned scaleB = SkAlpha255To256(SkColorGetB(fMul)); 426 427 unsigned addR = SkColorGetR(fAdd); 428 unsigned addG = SkColorGetG(fAdd); 429 unsigned addB = SkColorGetB(fAdd); 430 431 for (int i = 0; i < count; i++) { 432 SkPMColor c = shader[i]; 433 if (c) { 434 unsigned a = SkGetPackedA32(c); 435 unsigned scaleA = SkAlpha255To256(a); 436 unsigned r = SkAlphaMul(SkGetPackedR32(c), scaleR) + SkAlphaMul(addR, scaleA); 437 unsigned g = SkAlphaMul(SkGetPackedG32(c), scaleG) + SkAlphaMul(addG, scaleA); 438 unsigned b = SkAlphaMul(SkGetPackedB32(c), scaleB) + SkAlphaMul(addB, scaleA); 439 c = SkPackARGB32(a, r, g, b); 440 } 441 result[i] = c; 442 } 443 } 444 445protected: 446 virtual Factory getFactory() { return CreateProc; } 447 448 SkLightingColorFilter_NoPin(SkFlattenableReadBuffer& buffer) 449 : INHERITED(buffer) {} 450 451private: 452 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 453 return SkNEW_ARGS(SkLightingColorFilter_NoPin, (buffer)); 454 } 455 456 typedef SkLightingColorFilter INHERITED; 457}; 458 459/////////////////////////////////////////////////////////////////////////////// 460 461class SkSimpleColorFilter : public SkColorFilter { 462protected: 463 void filterSpan(const SkPMColor src[], int count, SkPMColor result[]) { 464 if (result != src) { 465 memcpy(result, src, count * sizeof(SkPMColor)); 466 } 467 } 468 469 virtual void flatten(SkFlattenableWriteBuffer& buffer) {} 470 471 virtual Factory getFactory() { 472 return CreateProc; 473 } 474 475 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 476 return SkNEW(SkSimpleColorFilter); 477 } 478}; 479 480SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) { 481 mul &= 0x00FFFFFF; 482 add &= 0x00FFFFFF; 483 484 if (0xFFFFFF == mul) { 485 if (0 == add) { 486 return SkNEW(SkSimpleColorFilter); // no change to the colors 487 } else { 488 return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add)); 489 } 490 } 491 492 if (0 == add) { 493 if (SkColorGetR(mul) == SkColorGetG(mul) && 494 SkColorGetR(mul) == SkColorGetB(mul)) { 495 return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add)); 496 } else { 497 return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add)); 498 } 499 } 500 501 if (SkColorGetR(mul) + SkColorGetR(add) <= 255 && 502 SkColorGetG(mul) + SkColorGetG(add) <= 255 && 503 SkColorGetB(mul) + SkColorGetB(add) <= 255) { 504 return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add)); 505 } 506 507 return SkNEW_ARGS(SkLightingColorFilter, (mul, add)); 508} 509 510