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 // As an optimization, we can apply the dither bias before interpolation -- but
only when |
| 529 // operating in premul space (apply_alpha == false). When apply_alpha == true,
we must |
| 530 // defer the bias application until after premul. |
| 531 // |
| 532 // The following two helpers encapsulate this logic: pre_bias is called before i
nterpolation, |
| 533 // and effects the bias when apply_alpha == false, while post_bias is called aft
er premul and |
| 534 // effects the bias for the apply_alpha == true case. |
| 535 |
| 536 template <bool apply_alpha> |
| 537 Sk4f pre_bias(const Sk4f& x, const Sk4f& bias) { |
| 538 #ifdef SK_SUPPORT_LEGACY_GRADIENT_PREMUL |
| 539 return x + bias; |
| 540 #else |
| 541 return apply_alpha ? x : x + bias; |
| 542 #endif |
| 543 } |
| 544 |
| 545 template <bool apply_alpha> |
| 546 Sk4f post_bias(const Sk4f& x, const Sk4f& bias) { |
| 547 #ifdef SK_SUPPORT_LEGACY_GRADIENT_PREMUL |
| 548 return x; |
| 549 #else |
| 550 return apply_alpha ? x + bias : x; |
| 551 #endif |
| 552 } |
| 553 |
| 554 template <bool apply_alpha> SkPMColor trunc_from_255(const Sk4f& x, const Sk4f&
bias) { |
529 SkPMColor c; | 555 SkPMColor c; |
| 556 |
| 557 #ifdef SK_SUPPORT_LEGACY_GRADIENT_PREMUL |
530 SkNx_cast<uint8_t>(x).store(&c); | 558 SkNx_cast<uint8_t>(x).store(&c); |
531 if (apply_alpha) { | 559 if (apply_alpha) { |
532 c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c), | 560 c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c), |
533 SkGetPackedG32(c), SkGetPackedB32(c)); | 561 SkGetPackedG32(c), SkGetPackedB32(c)); |
534 } | 562 } |
| 563 #else |
| 564 Sk4f c4f255 = x; |
| 565 if (apply_alpha) { |
| 566 const float scale = x[SkPM4f::A] * (1 / 255.f); |
| 567 c4f255 *= Sk4f(scale, scale, scale, 1); |
| 568 } |
| 569 SkNx_cast<uint8_t>(post_bias<apply_alpha>(c4f255, bias)).store(&c); |
| 570 #endif |
535 return c; | 571 return c; |
536 } | 572 } |
537 | 573 |
538 template <bool apply_alpha> void fill(SkPMColor dst[], int count, | 574 template <bool apply_alpha> void fill(SkPMColor dst[], int count, |
539 const Sk4f& c4, const Sk4f& c4other) { | 575 const Sk4f& c4, const Sk4f& bias0, const S
k4f& bias1) { |
540 sk_memset32_dither(dst, trunc_from_255<apply_alpha>(c4), | 576 const SkPMColor c0 = trunc_from_255<apply_alpha>(pre_bias<apply_alpha>(c4, b
ias0), bias0); |
541 trunc_from_255<apply_alpha>(c4other), count); | 577 const SkPMColor c1 = trunc_from_255<apply_alpha>(pre_bias<apply_alpha>(c4, b
ias1), bias1); |
| 578 sk_memset32_dither(dst, c0, c1, count); |
542 } | 579 } |
543 | 580 |
544 template <bool apply_alpha> void fill(SkPMColor dst[], int count, const Sk4f& c4
) { | 581 template <bool apply_alpha> void fill(SkPMColor dst[], int count, const Sk4f& c4
) { |
545 // Assumes that c4 does not need to be dithered. | 582 // Assumes that c4 does not need to be dithered. |
546 sk_memset32(dst, trunc_from_255<apply_alpha>(c4), count); | 583 sk_memset32(dst, trunc_from_255<apply_alpha>(c4, 0), count); |
547 } | 584 } |
548 | 585 |
549 /* | 586 /* |
550 * TODOs | 587 * TODOs |
551 * | 588 * |
552 * - tilemodes | 589 * - tilemodes |
553 * - interp before or after premul | 590 * - interp before or after premul |
554 * - perspective | 591 * - perspective |
555 * - optimizations | 592 * - optimizations |
556 * - use fixed (32bit or 16bit) instead of floats? | 593 * - use fixed (32bit or 16bit) instead of floats? |
557 */ | 594 */ |
558 | 595 |
559 static Sk4f lerp_color(float fx, const SkLinearGradient::LinearGradientContext::
Rec* rec) { | 596 static Sk4f lerp_color(float fx, const SkLinearGradient::LinearGradientContext::
Rec* rec) { |
560 SkASSERT(fx >= rec[0].fPos); | 597 SkASSERT(fx >= rec[0].fPos); |
561 SkASSERT(fx <= rec[1].fPos); | 598 SkASSERT(fx <= rec[1].fPos); |
562 | 599 |
563 const float p0 = rec[0].fPos; | 600 const float p0 = rec[0].fPos; |
564 const Sk4f c0 = rec[0].fColor; | 601 const Sk4f c0 = rec[0].fColor; |
565 const Sk4f c1 = rec[1].fColor; | 602 const Sk4f c1 = rec[1].fColor; |
566 const Sk4f diffc = c1 - c0; | 603 const Sk4f diffc = c1 - c0; |
567 const float scale = rec[1].fPosScale; | 604 const float scale = rec[1].fPosScale; |
568 const float t = (fx - p0) * scale; | 605 const float t = (fx - p0) * scale; |
569 return c0 + Sk4f(t) * diffc; | 606 return c0 + Sk4f(t) * diffc; |
570 } | 607 } |
571 | 608 |
572 template <bool apply_alpha> void ramp(SkPMColor dstC[], int n, const Sk4f& c, co
nst Sk4f& dc, | 609 template <bool apply_alpha> void ramp(SkPMColor dstC[], int n, const Sk4f& c, co
nst Sk4f& dc, |
573 const Sk4f& dither0, const Sk4f& dither1)
{ | 610 const Sk4f& dither0, const Sk4f& dither1)
{ |
574 Sk4f dc2 = dc + dc; | 611 Sk4f dc2 = dc + dc; |
575 Sk4f dc4 = dc2 + dc2; | 612 Sk4f dc4 = dc2 + dc2; |
576 Sk4f cd0 = c + dither0; | 613 Sk4f cd0 = pre_bias<apply_alpha>(c , dither0); |
577 Sk4f cd1 = c + dc + dither1; | 614 Sk4f cd1 = pre_bias<apply_alpha>(c + dc, dither1); |
578 Sk4f cd2 = cd0 + dc2; | 615 Sk4f cd2 = cd0 + dc2; |
579 Sk4f cd3 = cd1 + dc2; | 616 Sk4f cd3 = cd1 + dc2; |
580 while (n >= 4) { | 617 while (n >= 4) { |
581 if (!apply_alpha) { | 618 if (!apply_alpha) { |
582 Sk4f_ToBytes((uint8_t*)dstC, cd0, cd1, cd2, cd3); | 619 Sk4f_ToBytes((uint8_t*)dstC, cd0, cd1, cd2, cd3); |
583 dstC += 4; | 620 dstC += 4; |
584 } else { | 621 } else { |
585 *dstC++ = trunc_from_255<apply_alpha>(cd0); | 622 *dstC++ = trunc_from_255<apply_alpha>(cd0, dither0); |
586 *dstC++ = trunc_from_255<apply_alpha>(cd1); | 623 *dstC++ = trunc_from_255<apply_alpha>(cd1, dither1); |
587 *dstC++ = trunc_from_255<apply_alpha>(cd2); | 624 *dstC++ = trunc_from_255<apply_alpha>(cd2, dither0); |
588 *dstC++ = trunc_from_255<apply_alpha>(cd3); | 625 *dstC++ = trunc_from_255<apply_alpha>(cd3, dither1); |
589 } | 626 } |
590 cd0 = cd0 + dc4; | 627 cd0 = cd0 + dc4; |
591 cd1 = cd1 + dc4; | 628 cd1 = cd1 + dc4; |
592 cd2 = cd2 + dc4; | 629 cd2 = cd2 + dc4; |
593 cd3 = cd3 + dc4; | 630 cd3 = cd3 + dc4; |
594 n -= 4; | 631 n -= 4; |
595 } | 632 } |
596 if (n & 2) { | 633 if (n & 2) { |
597 *dstC++ = trunc_from_255<apply_alpha>(cd0); | 634 *dstC++ = trunc_from_255<apply_alpha>(cd0, dither0); |
598 *dstC++ = trunc_from_255<apply_alpha>(cd1); | 635 *dstC++ = trunc_from_255<apply_alpha>(cd1, dither1); |
599 cd0 = cd0 + dc2; | 636 cd0 = cd0 + dc2; |
600 } | 637 } |
601 if (n & 1) { | 638 if (n & 1) { |
602 *dstC++ = trunc_from_255<apply_alpha>(cd0); | 639 *dstC++ = trunc_from_255<apply_alpha>(cd0, dither0); |
603 } | 640 } |
604 } | 641 } |
605 | 642 |
606 template <bool apply_alpha, bool dx_is_pos> | 643 template <bool apply_alpha, bool dx_is_pos> |
607 void SkLinearGradient::LinearGradientContext::shade4_dx_clamp(SkPMColor dstC[],
int count, | 644 void SkLinearGradient::LinearGradientContext::shade4_dx_clamp(SkPMColor dstC[],
int count, |
608 float fx, float dx
, float invDx, | 645 float fx, float dx
, float invDx, |
609 const float dither
[2]) { | 646 const float dither
[2]) { |
610 Sk4f dither0(dither[0]); | 647 Sk4f dither0(dither[0]); |
611 Sk4f dither1(dither[1]); | 648 Sk4f dither1(dither[1]); |
612 const Rec* rec = fRecs.begin(); | 649 const Rec* rec = fRecs.begin(); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 SkTSwap(dither0, dither1); | 776 SkTSwap(dither0, dither1); |
740 } | 777 } |
741 } | 778 } |
742 const float dither[2] = { dither0, dither1 }; | 779 const float dither[2] = { dither0, dither1 }; |
743 const float invDx = 1 / dx; | 780 const float invDx = 1 / dx; |
744 | 781 |
745 if (SkScalarNearlyZero(dx * count)) { // gradient is vertical | 782 if (SkScalarNearlyZero(dx * count)) { // gradient is vertical |
746 const float pinFx = SkTPin(fx, 0.0f, 1.0f); | 783 const float pinFx = SkTPin(fx, 0.0f, 1.0f); |
747 Sk4f c = lerp_color(pinFx, find_forward(fRecs.begin(), pinFx)); | 784 Sk4f c = lerp_color(pinFx, find_forward(fRecs.begin(), pinFx)); |
748 if (fApplyAlphaAfterInterp) { | 785 if (fApplyAlphaAfterInterp) { |
749 fill<true>(dstC, count, c + dither0, c + dither1); | 786 fill<true>(dstC, count, c, dither0, dither1); |
750 } else { | 787 } else { |
751 fill<false>(dstC, count, c + dither0, c + dither1); | 788 fill<false>(dstC, count, c, dither0, dither1); |
752 } | 789 } |
753 return; | 790 return; |
754 } | 791 } |
755 | 792 |
756 if (dx > 0) { | 793 if (dx > 0) { |
757 if (fApplyAlphaAfterInterp) { | 794 if (fApplyAlphaAfterInterp) { |
758 this->shade4_dx_clamp<true, true>(dstC, count, fx, dx, invDx, dither
); | 795 this->shade4_dx_clamp<true, true>(dstC, count, fx, dx, invDx, dither
); |
759 } else { | 796 } else { |
760 this->shade4_dx_clamp<false, true>(dstC, count, fx, dx, invDx, dithe
r); | 797 this->shade4_dx_clamp<false, true>(dstC, count, fx, dx, invDx, dithe
r); |
761 } | 798 } |
762 } else { | 799 } else { |
763 if (fApplyAlphaAfterInterp) { | 800 if (fApplyAlphaAfterInterp) { |
764 this->shade4_dx_clamp<true, false>(dstC, count, fx, dx, invDx, dithe
r); | 801 this->shade4_dx_clamp<true, false>(dstC, count, fx, dx, invDx, dithe
r); |
765 } else { | 802 } else { |
766 this->shade4_dx_clamp<false, false>(dstC, count, fx, dx, invDx, dith
er); | 803 this->shade4_dx_clamp<false, false>(dstC, count, fx, dx, invDx, dith
er); |
767 } | 804 } |
768 } | 805 } |
769 } | 806 } |
OLD | NEW |