Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(403)

Side by Side Diff: src/core/SkXfermode.cpp

Issue 12393049: Added support for non-separable blending modes and fixed scalar issue (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « include/core/SkXfermode.h ('k') | src/pdf/SkPDFGraphicState.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « include/core/SkXfermode.h ('k') | src/pdf/SkPDFGraphicState.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698