OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkXfermode.h" | 10 #include "SkXfermode.h" |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) { | 424 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) { |
425 int sa = SkGetPackedA32(src); | 425 int sa = SkGetPackedA32(src); |
426 int da = SkGetPackedA32(dst); | 426 int da = SkGetPackedA32(dst); |
427 int a = srcover_byte(sa, da); | 427 int a = srcover_byte(sa, da); |
428 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); | 428 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); |
429 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); | 429 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); |
430 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); | 430 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); |
431 return SkPackARGB32(a, r, g, b); | 431 return SkPackARGB32(a, r, g, b); |
432 } | 432 } |
433 | 433 |
| 434 // The CSS compositing spec introduces the following formulas: |
| 435 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingn
onseparable) |
| 436 // SkComputeLuminance is similar to this formula but it uses the new definition
from Rec. 709 |
| 437 // while PDF and CG uses the one from Rec. Rec. 601 |
| 438 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-
versus-sd-color-space.htm |
| 439 static inline int Lum(int r, int g, int b) |
| 440 { |
| 441 return (r * 77 + g * 151 + b * 28) >> 8; |
| 442 } |
| 443 |
| 444 static inline int min2(int a, int b) { return a < b ? a : b; } |
| 445 static inline int max2(int a, int b) { return a > b ? a : b; } |
| 446 #define minimum(a, b, c) min2(min2(a, b), c) |
| 447 #define maximum(a, b, c) max2(max2(a, b), c) |
| 448 |
| 449 static inline int Sat(int r, int g, int b) { |
| 450 return maximum(r, g, b) - minimum(r, g, b); |
| 451 } |
| 452 |
| 453 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int
s) { |
| 454 if(Cmax > Cmin) { |
| 455 *Cmid = (((*Cmid - *Cmin) * s ) / (*Cmax - *Cmin)); |
| 456 *Cmax = s; |
| 457 } else { |
| 458 *Cmax = 0; |
| 459 *Cmid = 0; |
| 460 } |
| 461 |
| 462 *Cmin = 0; |
| 463 } |
| 464 |
| 465 static inline void SetSat(int* r, int* g, int* b, int s) { |
| 466 if(*r <= *g) { |
| 467 if(*g <= *b) { |
| 468 setSaturationComponents(r, g, b, s); |
| 469 } else if(*r <= *b) { |
| 470 setSaturationComponents(r, b, g, s); |
| 471 } else { |
| 472 setSaturationComponents(b, r, g, s); |
| 473 } |
| 474 } else if(*r <= *b) { |
| 475 setSaturationComponents(g, r, b, s); |
| 476 } else if(*g <= *b) { |
| 477 setSaturationComponents(g, b, r, s); |
| 478 } else { |
| 479 setSaturationComponents(b, g, r, s); |
| 480 } |
| 481 } |
| 482 |
| 483 static inline void clipColor(int* r, int* g, int* b) { |
| 484 int L = Lum(*r, *g, *b); |
| 485 int n = minimum(*r, *g, *b); |
| 486 int x = maximum(*r, *g, *b); |
| 487 if(n < 0) { |
| 488 *r = L + (((*r - L) * L) / (L - n)); |
| 489 *g = L + (((*g - L) * L) / (L - n)); |
| 490 *b = L + (((*b - L) * L) / (L - n)); |
| 491 } |
| 492 |
| 493 if(x > 255) { |
| 494 *r = L + (((*r - L) * (255 - L)) / (x - L)); |
| 495 *g = L + (((*g - L) * (255 - L)) / (x - L)); |
| 496 *b = L + (((*b - L) * (255 - L)) / (x - L)); |
| 497 } |
| 498 } |
| 499 |
| 500 static inline void SetLum(int* r, int* g, int* b, int l) { |
| 501 int d = l - Lum(*r, *g, *b); |
| 502 *r += d; |
| 503 *g += d; |
| 504 *b += d; |
| 505 |
| 506 clipColor(r, g, b); |
| 507 } |
| 508 |
| 509 // non-separable blend modes are done in non-premultiplied alpha |
| 510 #define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \ |
| 511 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + clamp_div255round(sa
* da) * blendval) |
| 512 |
| 513 // kHue_Mode |
| 514 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb)) |
| 515 // Create a color with the hue of the source color and the saturation and lumino
sity of the backdrop color. |
| 516 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) { |
| 517 int sr = SkGetPackedR32(src); |
| 518 int sg = SkGetPackedG32(src); |
| 519 int sb = SkGetPackedB32(src); |
| 520 int sa = SkGetPackedA32(src); |
| 521 |
| 522 int dr = SkGetPackedR32(dst); |
| 523 int dg = SkGetPackedG32(dst); |
| 524 int db = SkGetPackedB32(dst); |
| 525 int da = SkGetPackedA32(dst); |
| 526 int Sr, Sg, Sb; |
| 527 |
| 528 if(sa && da) { |
| 529 Sr = SkMulDiv255Round(sr, sa); |
| 530 Sg = SkMulDiv255Round(sg, sa); |
| 531 Sb = SkMulDiv255Round(sb, sa); |
| 532 int Dr = SkMulDiv255Round(dr, da); |
| 533 int Dg = SkMulDiv255Round(dg, da); |
| 534 int Db = SkMulDiv255Round(db, da); |
| 535 SetSat(&Sr, &Sg, &Sb, Sat(Dr, Dg, Db)); |
| 536 SetLum(&Sr, &Sg, &Sb, Lum(Dr, Dg, Db)); |
| 537 } else { |
| 538 Sr = 0; |
| 539 Sg = 0; |
| 540 Sb = 0; |
| 541 } |
| 542 |
| 543 int a = srcover_byte(sa, da); |
| 544 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr); |
| 545 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg); |
| 546 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb); |
| 547 return SkPackARGB32(a, r, g, b); |
| 548 } |
| 549 |
| 550 // kSaturation_Mode |
| 551 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb)) |
| 552 // Create a color with the saturation of the source color and the hue and lumino
sity of the backdrop color. |
| 553 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) { |
| 554 int sr = SkGetPackedR32(src); |
| 555 int sg = SkGetPackedG32(src); |
| 556 int sb = SkGetPackedB32(src); |
| 557 int sa = SkGetPackedA32(src); |
| 558 |
| 559 int dr = SkGetPackedR32(dst); |
| 560 int dg = SkGetPackedG32(dst); |
| 561 int db = SkGetPackedB32(dst); |
| 562 int da = SkGetPackedA32(dst); |
| 563 int Dr, Dg, Db; |
| 564 |
| 565 if(sa && da) { |
| 566 int Sr = SkMulDiv255Round(sr, sa); |
| 567 int Sg = SkMulDiv255Round(sg, sa); |
| 568 int Sb = SkMulDiv255Round(sb, sa); |
| 569 Dr = SkMulDiv255Round(dr, da); |
| 570 Dg = SkMulDiv255Round(dg, da); |
| 571 Db = SkMulDiv255Round(db, da); |
| 572 int LumD = Lum(Dr, Dg, Db); |
| 573 SetSat(&Dr, &Dg, &Db, Sat(Sr, Sg, Sb)); |
| 574 SetLum(&Dr, &Dg, &Db, LumD); |
| 575 } else { |
| 576 Dr = 0; |
| 577 Dg = 0; |
| 578 Db = 0; |
| 579 } |
| 580 |
| 581 int a = srcover_byte(sa, da); |
| 582 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); |
| 583 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); |
| 584 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); |
| 585 return SkPackARGB32(a, r, g, b); |
| 586 } |
| 587 |
| 588 // kColor_Mode |
| 589 // B(Cb, Cs) = SetLum(Cs, Lum(Cb)) |
| 590 // Create a color with the hue and saturation of the source color and the lumino
sity of the backdrop color. |
| 591 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) { |
| 592 int sr = SkGetPackedR32(src); |
| 593 int sg = SkGetPackedG32(src); |
| 594 int sb = SkGetPackedB32(src); |
| 595 int sa = SkGetPackedA32(src); |
| 596 |
| 597 int dr = SkGetPackedR32(dst); |
| 598 int dg = SkGetPackedG32(dst); |
| 599 int db = SkGetPackedB32(dst); |
| 600 int da = SkGetPackedA32(dst); |
| 601 int Sr, Sg, Sb; |
| 602 |
| 603 if(sa && da) { |
| 604 Sr = SkMulDiv255Round(sr, sa); |
| 605 Sg = SkMulDiv255Round(sg, sa); |
| 606 Sb = SkMulDiv255Round(sb, sa); |
| 607 int Dr = SkMulDiv255Round(dr, da); |
| 608 int Dg = SkMulDiv255Round(dg, da); |
| 609 int Db = SkMulDiv255Round(db, da); |
| 610 SetLum(&Sr, &Sg, &Sb, Lum(Dr, Dg, Db)); |
| 611 } else { |
| 612 Sr = 0; |
| 613 Sg = 0; |
| 614 Sb = 0; |
| 615 } |
| 616 |
| 617 int a = srcover_byte(sa, da); |
| 618 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr); |
| 619 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg); |
| 620 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb); |
| 621 return SkPackARGB32(a, r, g, b); |
| 622 } |
| 623 |
| 624 // kLuminosity_Mode |
| 625 // B(Cb, Cs) = SetLum(Cb, Lum(Cs)) |
| 626 // Create a color with the luminosity of the source color and the hue and satura
tion of the backdrop color. |
| 627 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) { |
| 628 int sr = SkGetPackedR32(src); |
| 629 int sg = SkGetPackedG32(src); |
| 630 int sb = SkGetPackedB32(src); |
| 631 int sa = SkGetPackedA32(src); |
| 632 |
| 633 int dr = SkGetPackedR32(dst); |
| 634 int dg = SkGetPackedG32(dst); |
| 635 int db = SkGetPackedB32(dst); |
| 636 int da = SkGetPackedA32(dst); |
| 637 int Dr, Dg, Db; |
| 638 |
| 639 if(sa && da) { |
| 640 int Sr = SkMulDiv255Round(sr, sa); |
| 641 int Sg = SkMulDiv255Round(sg, sa); |
| 642 int Sb = SkMulDiv255Round(sb, sa); |
| 643 Dr = SkMulDiv255Round(dr, da); |
| 644 Dg = SkMulDiv255Round(dg, da); |
| 645 Db = SkMulDiv255Round(db, da); |
| 646 SetLum(&Dr, &Dg, &Db, Lum(Sr, Sg, Sb)); |
| 647 } else { |
| 648 Dr = 0; |
| 649 Dg = 0; |
| 650 Db = 0; |
| 651 } |
| 652 |
| 653 int a = srcover_byte(sa, da); |
| 654 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); |
| 655 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); |
| 656 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); |
| 657 return SkPackARGB32(a, r, g, b); |
| 658 } |
| 659 |
| 660 |
434 struct ProcCoeff { | 661 struct ProcCoeff { |
435 SkXfermodeProc fProc; | 662 SkXfermodeProc fProc; |
436 SkXfermode::Coeff fSC; | 663 SkXfermode::Coeff fSC; |
437 SkXfermode::Coeff fDC; | 664 SkXfermode::Coeff fDC; |
438 }; | 665 }; |
439 | 666 |
440 #define CANNOT_USE_COEFF SkXfermode::Coeff(-1) | 667 #define CANNOT_USE_COEFF SkXfermode::Coeff(-1) |
441 | 668 |
442 static const ProcCoeff gProcCoeffs[] = { | 669 static const ProcCoeff gProcCoeffs[] = { |
443 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, | 670 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, |
(...skipping 15 matching lines...) Expand all Loading... |
459 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, | 686 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
460 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, | 687 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
461 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, | 688 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
462 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, | 689 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
463 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, | 690 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
464 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, | 691 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
465 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, | 692 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
466 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, | 693 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
467 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, | 694 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
468 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, | 695 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| 696 { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| 697 { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| 698 { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
| 699 { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, |
469 }; | 700 }; |
470 | 701 |
471 /////////////////////////////////////////////////////////////////////////////// | 702 /////////////////////////////////////////////////////////////////////////////// |
472 | 703 |
473 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const { | 704 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const { |
474 return false; | 705 return false; |
475 } | 706 } |
476 | 707 |
477 bool SkXfermode::asMode(Mode* mode) const { | 708 bool SkXfermode::asMode(Mode* mode) const { |
478 return false; | 709 return false; |
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1257 { NULL, NULL, NULL }, // screen | 1488 { NULL, NULL, NULL }, // screen |
1258 { NULL, NULL, NULL }, // overla
y | 1489 { NULL, NULL, NULL }, // overla
y |
1259 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken | 1490 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken |
1260 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighte
n | 1491 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighte
n |
1261 { NULL, NULL, NULL }, // colord
odge | 1492 { NULL, NULL, NULL }, // colord
odge |
1262 { NULL, NULL, NULL }, // colorb
urn | 1493 { NULL, NULL, NULL }, // colorb
urn |
1263 { NULL, NULL, NULL }, // hardli
ght | 1494 { NULL, NULL, NULL }, // hardli
ght |
1264 { NULL, NULL, NULL }, // softli
ght | 1495 { NULL, NULL, NULL }, // softli
ght |
1265 { NULL, NULL, NULL }, // differ
ence | 1496 { NULL, NULL, NULL }, // differ
ence |
1266 { NULL, NULL, NULL }, // exclus
ion | 1497 { NULL, NULL, NULL }, // exclus
ion |
| 1498 { NULL, NULL, NULL }, // multip
ly |
| 1499 { NULL, NULL, NULL }, // hue |
| 1500 { NULL, NULL, NULL }, // satura
tion |
| 1501 { NULL, NULL, NULL }, // color |
| 1502 { NULL, NULL, NULL }, // lumino
sity |
1267 }; | 1503 }; |
1268 | 1504 |
1269 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { | 1505 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { |
1270 SkXfermodeProc16 proc16 = NULL; | 1506 SkXfermodeProc16 proc16 = NULL; |
1271 if ((unsigned)mode < kModeCount) { | 1507 if ((unsigned)mode < kModeCount) { |
1272 const Proc16Rec& rec = gModeProcs16[mode]; | 1508 const Proc16Rec& rec = gModeProcs16[mode]; |
1273 unsigned a = SkColorGetA(srcColor); | 1509 unsigned a = SkColorGetA(srcColor); |
1274 | 1510 |
1275 if (0 == a) { | 1511 if (0 == a) { |
1276 proc16 = rec.fProc16_0; | 1512 proc16 = rec.fProc16_0; |
1277 } else if (255 == a) { | 1513 } else if (255 == a) { |
1278 proc16 = rec.fProc16_255; | 1514 proc16 = rec.fProc16_255; |
1279 } else { | 1515 } else { |
1280 proc16 = rec.fProc16_General; | 1516 proc16 = rec.fProc16_General; |
1281 } | 1517 } |
1282 } | 1518 } |
1283 return proc16; | 1519 return proc16; |
1284 } | 1520 } |
1285 | 1521 |
1286 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) | 1522 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) |
1287 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) | 1523 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) |
1288 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) | 1524 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) |
1289 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) | 1525 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) |
1290 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) | 1526 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) |
1291 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) | 1527 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) |
1292 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 1528 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
OLD | NEW |