OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "Sk4fLinearGradient.h" | 8 #include "Sk4fLinearGradient.h" |
9 #include "SkLinearGradient.h" | 9 #include "SkLinearGradient.h" |
10 #include "SkRefCnt.h" | 10 #include "SkRefCnt.h" |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
518 SkASSERT(rec[0].fPos <= rec[1].fPos); | 518 SkASSERT(rec[0].fPos <= rec[1].fPos); |
519 while (tiledX < rec->fPos || rec[1].fPosScale == 0) { | 519 while (tiledX < rec->fPos || rec[1].fPosScale == 0) { |
520 rec -= 1; | 520 rec -= 1; |
521 SkASSERT(rec[0].fPos >= 0 && rec[0].fPos <= 1); | 521 SkASSERT(rec[0].fPos >= 0 && rec[0].fPos <= 1); |
522 SkASSERT(rec[1].fPos >= 0 && rec[1].fPos <= 1); | 522 SkASSERT(rec[1].fPos >= 0 && rec[1].fPos <= 1); |
523 SkASSERT(rec[0].fPos <= rec[1].fPos); | 523 SkASSERT(rec[0].fPos <= rec[1].fPos); |
524 } | 524 } |
525 return rec; | 525 return rec; |
526 } | 526 } |
527 | 527 |
528 template <bool apply_alpha> SkPMColor trunc_from_255(const Sk4f& x) { | 528 template <bool apply_alpha> SkPMColor trunc_from_255(const Sk4f& x, const Sk4f& bias) { |
529 SkPMColor c; | 529 SkPMColor c; |
530 | |
531 #ifdef SK_SUPPORT_LEGACY_GRADIENT_PREMUL | |
530 SkNx_cast<uint8_t>(x).store(&c); | 532 SkNx_cast<uint8_t>(x).store(&c); |
531 if (apply_alpha) { | 533 if (apply_alpha) { |
532 c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c), | 534 c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c), |
533 SkGetPackedG32(c), SkGetPackedB32(c)); | 535 SkGetPackedG32(c), SkGetPackedB32(c)); |
534 } | 536 } |
537 #else | |
538 Sk4f c4f255; | |
539 if (!apply_alpha) { | |
540 // when apply_alpha is false, the bias is preapplied. | |
541 c4f255 = x; | |
542 } else { | |
543 const float scale = x[SkPM4f::A] * 1.f / 255; | |
reed1
2016/10/11 16:31:39
are we sure the 1 / 255 *always* gets resolved at
mtklein
2016/10/11 16:38:15
No, as written this will never be a single multipl
f(malita)
2016/10/11 19:19:06
Done.
| |
544 // apply the bias *after* premul | |
545 c4f255 = x * Sk4f(scale, scale, scale, 1) + bias; | |
546 } | |
547 SkNx_cast<uint8_t>(c4f255).store(&c); | |
548 #endif | |
535 return c; | 549 return c; |
536 } | 550 } |
537 | 551 |
538 template <bool apply_alpha> void fill(SkPMColor dst[], int count, | 552 template <bool apply_alpha> void fill(SkPMColor dst[], int count, |
539 const Sk4f& c4, const Sk4f& c4other) { | 553 const Sk4f& c4, const Sk4f& bias0, const S k4f& bias1) { |
540 sk_memset32_dither(dst, trunc_from_255<apply_alpha>(c4), | 554 #ifdef SK_SUPPORT_LEGACY_GRADIENT_PREMUL |
541 trunc_from_255<apply_alpha>(c4other), count); | 555 const SkPMColor c0 = trunc_from_255<apply_alpha>(c4 + bias0, 0); |
556 const SkPMColor c1 = trunc_from_255<apply_alpha>(c4 + bias1, 0); | |
557 #else | |
558 const SkPMColor c0 = apply_alpha | |
559 ? trunc_from_255<apply_alpha>(c4, bias0) | |
560 : trunc_from_255<apply_alpha>(c4 + bias0, 0); | |
561 const SkPMColor c1 = apply_alpha | |
562 ? trunc_from_255<apply_alpha>(c4, bias1) | |
563 : trunc_from_255<apply_alpha>(c4 + bias1, 0); | |
564 #endif | |
565 sk_memset32_dither(dst, c0, c1, count); | |
542 } | 566 } |
543 | 567 |
544 template <bool apply_alpha> void fill(SkPMColor dst[], int count, const Sk4f& c4 ) { | 568 template <bool apply_alpha> void fill(SkPMColor dst[], int count, const Sk4f& c4 ) { |
545 // Assumes that c4 does not need to be dithered. | 569 // Assumes that c4 does not need to be dithered. |
546 sk_memset32(dst, trunc_from_255<apply_alpha>(c4), count); | 570 sk_memset32(dst, trunc_from_255<apply_alpha>(c4, 0), count); |
547 } | 571 } |
548 | 572 |
549 /* | 573 /* |
550 * TODOs | 574 * TODOs |
551 * | 575 * |
552 * - tilemodes | 576 * - tilemodes |
553 * - interp before or after premul | 577 * - interp before or after premul |
554 * - perspective | 578 * - perspective |
555 * - optimizations | 579 * - optimizations |
556 * - use fixed (32bit or 16bit) instead of floats? | 580 * - use fixed (32bit or 16bit) instead of floats? |
557 */ | 581 */ |
558 | 582 |
559 static Sk4f lerp_color(float fx, const SkLinearGradient::LinearGradientContext:: Rec* rec) { | 583 static Sk4f lerp_color(float fx, const SkLinearGradient::LinearGradientContext:: Rec* rec) { |
560 SkASSERT(fx >= rec[0].fPos); | 584 SkASSERT(fx >= rec[0].fPos); |
561 SkASSERT(fx <= rec[1].fPos); | 585 SkASSERT(fx <= rec[1].fPos); |
562 | 586 |
563 const float p0 = rec[0].fPos; | 587 const float p0 = rec[0].fPos; |
564 const Sk4f c0 = rec[0].fColor; | 588 const Sk4f c0 = rec[0].fColor; |
565 const Sk4f c1 = rec[1].fColor; | 589 const Sk4f c1 = rec[1].fColor; |
566 const Sk4f diffc = c1 - c0; | 590 const Sk4f diffc = c1 - c0; |
567 const float scale = rec[1].fPosScale; | 591 const float scale = rec[1].fPosScale; |
568 const float t = (fx - p0) * scale; | 592 const float t = (fx - p0) * scale; |
569 return c0 + Sk4f(t) * diffc; | 593 return c0 + Sk4f(t) * diffc; |
570 } | 594 } |
571 | 595 |
572 template <bool apply_alpha> void ramp(SkPMColor dstC[], int n, const Sk4f& c, co nst Sk4f& dc, | 596 template <bool apply_alpha> void ramp(SkPMColor dstC[], int n, const Sk4f& c, co nst Sk4f& dc, |
573 const Sk4f& dither0, const Sk4f& dither1) { | 597 const Sk4f& dither0, const Sk4f& dither1) { |
574 Sk4f dc2 = dc + dc; | 598 Sk4f dc2 = dc + dc; |
575 Sk4f dc4 = dc2 + dc2; | 599 Sk4f dc4 = dc2 + dc2; |
576 Sk4f cd0 = c + dither0; | 600 Sk4f cd0 = c; |
577 Sk4f cd1 = c + dc + dither1; | 601 Sk4f cd1 = c + dc; |
602 #ifndef SK_SUPPORT_LEGACY_GRADIENT_PREMUL | |
603 // when apply_alpha is true, we defer dithering until after premul. | |
604 if (!apply_alpha) { | |
605 #endif | |
606 cd0 += dither0; | |
607 cd1 += dither1; | |
608 #ifndef SK_SUPPORT_LEGACY_GRADIENT_PREMUL | |
609 } | |
610 #endif | |
578 Sk4f cd2 = cd0 + dc2; | 611 Sk4f cd2 = cd0 + dc2; |
579 Sk4f cd3 = cd1 + dc2; | 612 Sk4f cd3 = cd1 + dc2; |
580 while (n >= 4) { | 613 while (n >= 4) { |
581 if (!apply_alpha) { | 614 if (!apply_alpha) { |
582 Sk4f_ToBytes((uint8_t*)dstC, cd0, cd1, cd2, cd3); | 615 Sk4f_ToBytes((uint8_t*)dstC, cd0, cd1, cd2, cd3); |
583 dstC += 4; | 616 dstC += 4; |
584 } else { | 617 } else { |
585 *dstC++ = trunc_from_255<apply_alpha>(cd0); | 618 *dstC++ = trunc_from_255<apply_alpha>(cd0, dither0); |
586 *dstC++ = trunc_from_255<apply_alpha>(cd1); | 619 *dstC++ = trunc_from_255<apply_alpha>(cd1, dither1); |
587 *dstC++ = trunc_from_255<apply_alpha>(cd2); | 620 *dstC++ = trunc_from_255<apply_alpha>(cd2, dither0); |
588 *dstC++ = trunc_from_255<apply_alpha>(cd3); | 621 *dstC++ = trunc_from_255<apply_alpha>(cd3, dither1); |
589 } | 622 } |
590 cd0 = cd0 + dc4; | 623 cd0 = cd0 + dc4; |
591 cd1 = cd1 + dc4; | 624 cd1 = cd1 + dc4; |
592 cd2 = cd2 + dc4; | 625 cd2 = cd2 + dc4; |
593 cd3 = cd3 + dc4; | 626 cd3 = cd3 + dc4; |
594 n -= 4; | 627 n -= 4; |
595 } | 628 } |
596 if (n & 2) { | 629 if (n & 2) { |
597 *dstC++ = trunc_from_255<apply_alpha>(cd0); | 630 *dstC++ = trunc_from_255<apply_alpha>(cd0, dither0); |
598 *dstC++ = trunc_from_255<apply_alpha>(cd1); | 631 *dstC++ = trunc_from_255<apply_alpha>(cd1, dither1); |
599 cd0 = cd0 + dc2; | 632 cd0 = cd0 + dc2; |
600 } | 633 } |
601 if (n & 1) { | 634 if (n & 1) { |
602 *dstC++ = trunc_from_255<apply_alpha>(cd0); | 635 *dstC++ = trunc_from_255<apply_alpha>(cd0, dither0); |
603 } | 636 } |
604 } | 637 } |
605 | 638 |
606 template <bool apply_alpha, bool dx_is_pos> | 639 template <bool apply_alpha, bool dx_is_pos> |
607 void SkLinearGradient::LinearGradientContext::shade4_dx_clamp(SkPMColor dstC[], int count, | 640 void SkLinearGradient::LinearGradientContext::shade4_dx_clamp(SkPMColor dstC[], int count, |
608 float fx, float dx , float invDx, | 641 float fx, float dx , float invDx, |
609 const float dither [2]) { | 642 const float dither [2]) { |
610 Sk4f dither0(dither[0]); | 643 Sk4f dither0(dither[0]); |
611 Sk4f dither1(dither[1]); | 644 Sk4f dither1(dither[1]); |
612 const Rec* rec = fRecs.begin(); | 645 const Rec* rec = fRecs.begin(); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
739 SkTSwap(dither0, dither1); | 772 SkTSwap(dither0, dither1); |
740 } | 773 } |
741 } | 774 } |
742 const float dither[2] = { dither0, dither1 }; | 775 const float dither[2] = { dither0, dither1 }; |
743 const float invDx = 1 / dx; | 776 const float invDx = 1 / dx; |
744 | 777 |
745 if (SkScalarNearlyZero(dx * count)) { // gradient is vertical | 778 if (SkScalarNearlyZero(dx * count)) { // gradient is vertical |
746 const float pinFx = SkTPin(fx, 0.0f, 1.0f); | 779 const float pinFx = SkTPin(fx, 0.0f, 1.0f); |
747 Sk4f c = lerp_color(pinFx, find_forward(fRecs.begin(), pinFx)); | 780 Sk4f c = lerp_color(pinFx, find_forward(fRecs.begin(), pinFx)); |
748 if (fApplyAlphaAfterInterp) { | 781 if (fApplyAlphaAfterInterp) { |
749 fill<true>(dstC, count, c + dither0, c + dither1); | 782 fill<true>(dstC, count, c, dither0, dither1); |
750 } else { | 783 } else { |
751 fill<false>(dstC, count, c + dither0, c + dither1); | 784 fill<false>(dstC, count, c, dither0, dither1); |
752 } | 785 } |
753 return; | 786 return; |
754 } | 787 } |
755 | 788 |
756 if (dx > 0) { | 789 if (dx > 0) { |
757 if (fApplyAlphaAfterInterp) { | 790 if (fApplyAlphaAfterInterp) { |
758 this->shade4_dx_clamp<true, true>(dstC, count, fx, dx, invDx, dither ); | 791 this->shade4_dx_clamp<true, true>(dstC, count, fx, dx, invDx, dither ); |
759 } else { | 792 } else { |
760 this->shade4_dx_clamp<false, true>(dstC, count, fx, dx, invDx, dithe r); | 793 this->shade4_dx_clamp<false, true>(dstC, count, fx, dx, invDx, dithe r); |
761 } | 794 } |
762 } else { | 795 } else { |
763 if (fApplyAlphaAfterInterp) { | 796 if (fApplyAlphaAfterInterp) { |
764 this->shade4_dx_clamp<true, false>(dstC, count, fx, dx, invDx, dithe r); | 797 this->shade4_dx_clamp<true, false>(dstC, count, fx, dx, invDx, dithe r); |
765 } else { | 798 } else { |
766 this->shade4_dx_clamp<false, false>(dstC, count, fx, dx, invDx, dith er); | 799 this->shade4_dx_clamp<false, false>(dstC, count, fx, dx, invDx, dith er); |
767 } | 800 } |
768 } | 801 } |
769 } | 802 } |
OLD | NEW |