OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
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 "SkGradientShaderPriv.h" | 8 #include "SkGradientShaderPriv.h" |
9 #include "SkLinearGradient.h" | 9 #include "SkLinearGradient.h" |
10 #include "SkRadialGradient.h" | 10 #include "SkRadialGradient.h" |
11 #include "SkTwoPointRadialGradient.h" | 11 #include "SkTwoPointRadialGradient.h" |
12 #include "SkTwoPointConicalGradient.h" | 12 #include "SkTwoPointConicalGradient.h" |
13 #include "SkSweepGradient.h" | 13 #include "SkSweepGradient.h" |
14 | 14 |
15 SkGradientShaderBase::SkGradientShaderBase(const SkColor colors[], const SkScala
r pos[], | 15 SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc) { |
16 int colorCount, SkShader::TileMode mode, SkUnitMapper* mapper) { | 16 SkASSERT(desc.fCount > 1); |
17 SkASSERT(colorCount > 1); | |
18 | 17 |
19 fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return | 18 fCacheAlpha = 256; // init to a value that paint.getAlpha() can't return |
20 | 19 |
21 fMapper = mapper; | 20 fMapper = desc.fMapper; |
22 SkSafeRef(mapper); | 21 SkSafeRef(fMapper); |
23 | 22 |
24 SkASSERT((unsigned)mode < SkShader::kTileModeCount); | 23 SkASSERT((unsigned)desc.fTileMode < SkShader::kTileModeCount); |
25 SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); | 24 SkASSERT(SkShader::kTileModeCount == SK_ARRAY_COUNT(gTileProcs)); |
26 fTileMode = mode; | 25 fTileMode = desc.fTileMode; |
27 fTileProc = gTileProcs[mode]; | 26 fTileProc = gTileProcs[desc.fTileMode]; |
28 | 27 |
29 fCache16 = fCache16Storage = NULL; | 28 fCache16 = fCache16Storage = NULL; |
30 fCache32 = NULL; | 29 fCache32 = NULL; |
31 fCache32PixelRef = NULL; | 30 fCache32PixelRef = NULL; |
32 | 31 |
33 /* Note: we let the caller skip the first and/or last position. | 32 /* Note: we let the caller skip the first and/or last position. |
34 i.e. pos[0] = 0.3, pos[1] = 0.7 | 33 i.e. pos[0] = 0.3, pos[1] = 0.7 |
35 In these cases, we insert dummy entries to ensure that the final data | 34 In these cases, we insert dummy entries to ensure that the final data |
36 will be bracketed by [0, 1]. | 35 will be bracketed by [0, 1]. |
37 i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1 | 36 i.e. our_pos[0] = 0, our_pos[1] = 0.3, our_pos[2] = 0.7, our_pos[3] = 1 |
38 | 37 |
39 Thus colorCount (the caller's value, and fColorCount (our value) may | 38 Thus colorCount (the caller's value, and fColorCount (our value) may |
40 differ by up to 2. In the above example: | 39 differ by up to 2. In the above example: |
41 colorCount = 2 | 40 colorCount = 2 |
42 fColorCount = 4 | 41 fColorCount = 4 |
43 */ | 42 */ |
44 fColorCount = colorCount; | 43 fColorCount = desc.fCount; |
45 // check if we need to add in dummy start and/or end position/colors | 44 // check if we need to add in dummy start and/or end position/colors |
46 bool dummyFirst = false; | 45 bool dummyFirst = false; |
47 bool dummyLast = false; | 46 bool dummyLast = false; |
48 if (pos) { | 47 if (desc.fPos) { |
49 dummyFirst = pos[0] != 0; | 48 dummyFirst = desc.fPos[0] != 0; |
50 dummyLast = pos[colorCount - 1] != SK_Scalar1; | 49 dummyLast = desc.fPos[desc.fCount - 1] != SK_Scalar1; |
51 fColorCount += dummyFirst + dummyLast; | 50 fColorCount += dummyFirst + dummyLast; |
52 } | 51 } |
53 | 52 |
54 if (fColorCount > kColorStorageCount) { | 53 if (fColorCount > kColorStorageCount) { |
55 size_t size = sizeof(SkColor) + sizeof(Rec); | 54 size_t size = sizeof(SkColor) + sizeof(Rec); |
56 fOrigColors = reinterpret_cast<SkColor*>( | 55 fOrigColors = reinterpret_cast<SkColor*>( |
57 sk_malloc_throw(size * fColorCount)); | 56 sk_malloc_throw(size * fColorCount)); |
58 } | 57 } |
59 else { | 58 else { |
60 fOrigColors = fStorage; | 59 fOrigColors = fStorage; |
61 } | 60 } |
62 | 61 |
63 // Now copy over the colors, adding the dummies as needed | 62 // Now copy over the colors, adding the dummies as needed |
64 { | 63 { |
65 SkColor* origColors = fOrigColors; | 64 SkColor* origColors = fOrigColors; |
66 if (dummyFirst) { | 65 if (dummyFirst) { |
67 *origColors++ = colors[0]; | 66 *origColors++ = desc.fColors[0]; |
68 } | 67 } |
69 memcpy(origColors, colors, colorCount * sizeof(SkColor)); | 68 memcpy(origColors, desc.fColors, desc.fCount * sizeof(SkColor)); |
70 if (dummyLast) { | 69 if (dummyLast) { |
71 origColors += colorCount; | 70 origColors += desc.fCount; |
72 *origColors = colors[colorCount - 1]; | 71 *origColors = desc.fColors[desc.fCount - 1]; |
73 } | 72 } |
74 } | 73 } |
75 | 74 |
76 fRecs = (Rec*)(fOrigColors + fColorCount); | 75 fRecs = (Rec*)(fOrigColors + fColorCount); |
77 if (fColorCount > 2) { | 76 if (fColorCount > 2) { |
78 Rec* recs = fRecs; | 77 Rec* recs = fRecs; |
79 recs->fPos = 0; | 78 recs->fPos = 0; |
80 // recs->fScale = 0; // unused; | 79 // recs->fScale = 0; // unused; |
81 recs += 1; | 80 recs += 1; |
82 if (pos) { | 81 if (desc.fPos) { |
83 /* We need to convert the user's array of relative positions into | 82 /* We need to convert the user's array of relative positions into |
84 fixed-point positions and scale factors. We need these results | 83 fixed-point positions and scale factors. We need these results |
85 to be strictly monotonic (no two values equal or out of order). | 84 to be strictly monotonic (no two values equal or out of order). |
86 Hence this complex loop that just jams a zero for the scale | 85 Hence this complex loop that just jams a zero for the scale |
87 value if it sees a segment out of order, and it assures that | 86 value if it sees a segment out of order, and it assures that |
88 we start at 0 and end at 1.0 | 87 we start at 0 and end at 1.0 |
89 */ | 88 */ |
90 SkFixed prev = 0; | 89 SkFixed prev = 0; |
91 int startIndex = dummyFirst ? 0 : 1; | 90 int startIndex = dummyFirst ? 0 : 1; |
92 int count = colorCount + dummyLast; | 91 int count = desc.fCount + dummyLast; |
93 for (int i = startIndex; i < count; i++) { | 92 for (int i = startIndex; i < count; i++) { |
94 // force the last value to be 1.0 | 93 // force the last value to be 1.0 |
95 SkFixed curr; | 94 SkFixed curr; |
96 if (i == colorCount) { // we're really at the dummyLast | 95 if (i == desc.fCount) { // we're really at the dummyLast |
97 curr = SK_Fixed1; | 96 curr = SK_Fixed1; |
98 } else { | 97 } else { |
99 curr = SkScalarToFixed(pos[i]); | 98 curr = SkScalarToFixed(desc.fPos[i]); |
100 } | 99 } |
101 // pin curr withing range | 100 // pin curr withing range |
102 if (curr < 0) { | 101 if (curr < 0) { |
103 curr = 0; | 102 curr = 0; |
104 } else if (curr > SK_Fixed1) { | 103 } else if (curr > SK_Fixed1) { |
105 curr = SK_Fixed1; | 104 curr = SK_Fixed1; |
106 } | 105 } |
107 recs->fPos = curr; | 106 recs->fPos = curr; |
108 if (curr > prev) { | 107 if (curr > prev) { |
109 recs->fScale = (1 << 24) / (curr - prev); | 108 recs->fScale = (1 << 24) / (curr - prev); |
110 } else { | 109 } else { |
111 recs->fScale = 0; // ignore this segment | 110 recs->fScale = 0; // ignore this segment |
112 } | 111 } |
113 // get ready for the next value | 112 // get ready for the next value |
114 prev = curr; | 113 prev = curr; |
115 recs += 1; | 114 recs += 1; |
116 } | 115 } |
117 } else { // assume even distribution | 116 } else { // assume even distribution |
118 SkFixed dp = SK_Fixed1 / (colorCount - 1); | 117 SkFixed dp = SK_Fixed1 / (desc.fCount - 1); |
119 SkFixed p = dp; | 118 SkFixed p = dp; |
120 SkFixed scale = (colorCount - 1) << 8; // (1 << 24) / dp | 119 SkFixed scale = (desc.fCount - 1) << 8; // (1 << 24) / dp |
121 for (int i = 1; i < colorCount; i++) { | 120 for (int i = 1; i < desc.fCount; i++) { |
122 recs->fPos = p; | 121 recs->fPos = p; |
123 recs->fScale = scale; | 122 recs->fScale = scale; |
124 recs += 1; | 123 recs += 1; |
125 p += dp; | 124 p += dp; |
126 } | 125 } |
127 } | 126 } |
128 } | 127 } |
129 this->initCommon(); | 128 this->initCommon(); |
130 } | 129 } |
131 | 130 |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 SkColor tmp[2]; \ | 632 SkColor tmp[2]; \ |
634 do { \ | 633 do { \ |
635 if (1 == count) { \ | 634 if (1 == count) { \ |
636 tmp[0] = tmp[1] = colors[0]; \ | 635 tmp[0] = tmp[1] = colors[0]; \ |
637 colors = tmp; \ | 636 colors = tmp; \ |
638 pos = NULL; \ | 637 pos = NULL; \ |
639 count = 2; \ | 638 count = 2; \ |
640 } \ | 639 } \ |
641 } while (0) | 640 } while (0) |
642 | 641 |
| 642 static void desc_init(SkGradientShaderBase::Descriptor* desc, |
| 643 const SkColor colors[], |
| 644 const SkScalar pos[], int colorCount, |
| 645 SkShader::TileMode mode, |
| 646 SkUnitMapper* mapper) { |
| 647 desc->fColors = colors; |
| 648 desc->fPos = pos; |
| 649 desc->fCount = colorCount; |
| 650 desc->fTileMode = mode; |
| 651 desc->fMapper = mapper; |
| 652 } |
| 653 |
643 SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2], | 654 SkShader* SkGradientShader::CreateLinear(const SkPoint pts[2], |
644 const SkColor colors[], | 655 const SkColor colors[], |
645 const SkScalar pos[], int colorCount, | 656 const SkScalar pos[], int colorCount, |
646 SkShader::TileMode mode, | 657 SkShader::TileMode mode, |
647 SkUnitMapper* mapper) { | 658 SkUnitMapper* mapper) { |
648 if (NULL == pts || NULL == colors || colorCount < 1) { | 659 if (NULL == pts || NULL == colors || colorCount < 1) { |
649 return NULL; | 660 return NULL; |
650 } | 661 } |
651 EXPAND_1_COLOR(colorCount); | 662 EXPAND_1_COLOR(colorCount); |
652 | 663 |
653 return SkNEW_ARGS(SkLinearGradient, | 664 SkGradientShaderBase::Descriptor desc; |
654 (pts, colors, pos, colorCount, mode, mapper)); | 665 desc_init(&desc, colors, pos, colorCount, mode, mapper); |
| 666 return SkNEW_ARGS(SkLinearGradient, (pts, desc)); |
655 } | 667 } |
656 | 668 |
657 SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius, | 669 SkShader* SkGradientShader::CreateRadial(const SkPoint& center, SkScalar radius, |
658 const SkColor colors[], | 670 const SkColor colors[], |
659 const SkScalar pos[], int colorCount, | 671 const SkScalar pos[], int colorCount, |
660 SkShader::TileMode mode, | 672 SkShader::TileMode mode, |
661 SkUnitMapper* mapper) { | 673 SkUnitMapper* mapper) { |
662 if (radius <= 0 || NULL == colors || colorCount < 1) { | 674 if (radius <= 0 || NULL == colors || colorCount < 1) { |
663 return NULL; | 675 return NULL; |
664 } | 676 } |
665 EXPAND_1_COLOR(colorCount); | 677 EXPAND_1_COLOR(colorCount); |
666 | 678 |
667 return SkNEW_ARGS(SkRadialGradient, | 679 SkGradientShaderBase::Descriptor desc; |
668 (center, radius, colors, pos, colorCount, mode, mapper)); | 680 desc_init(&desc, colors, pos, colorCount, mode, mapper); |
| 681 return SkNEW_ARGS(SkRadialGradient, (center, radius, desc)); |
669 } | 682 } |
670 | 683 |
671 SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start, | 684 SkShader* SkGradientShader::CreateTwoPointRadial(const SkPoint& start, |
672 SkScalar startRadius, | 685 SkScalar startRadius, |
673 const SkPoint& end, | 686 const SkPoint& end, |
674 SkScalar endRadius, | 687 SkScalar endRadius, |
675 const SkColor colors[], | 688 const SkColor colors[], |
676 const SkScalar pos[], | 689 const SkScalar pos[], |
677 int colorCount, | 690 int colorCount, |
678 SkShader::TileMode mode, | 691 SkShader::TileMode mode, |
679 SkUnitMapper* mapper) { | 692 SkUnitMapper* mapper) { |
680 if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { | 693 if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { |
681 return NULL; | 694 return NULL; |
682 } | 695 } |
683 EXPAND_1_COLOR(colorCount); | 696 EXPAND_1_COLOR(colorCount); |
684 | 697 |
| 698 SkGradientShaderBase::Descriptor desc; |
| 699 desc_init(&desc, colors, pos, colorCount, mode, mapper); |
685 return SkNEW_ARGS(SkTwoPointRadialGradient, | 700 return SkNEW_ARGS(SkTwoPointRadialGradient, |
686 (start, startRadius, end, endRadius, colors, pos, | 701 (start, startRadius, end, endRadius, desc)); |
687 colorCount, mode, mapper)); | |
688 } | 702 } |
689 | 703 |
690 SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start, | 704 SkShader* SkGradientShader::CreateTwoPointConical(const SkPoint& start, |
691 SkScalar startRadius, | 705 SkScalar startRadius, |
692 const SkPoint& end, | 706 const SkPoint& end, |
693 SkScalar endRadius, | 707 SkScalar endRadius, |
694 const SkColor colors[], | 708 const SkColor colors[], |
695 const SkScalar pos[], | 709 const SkScalar pos[], |
696 int colorCount, | 710 int colorCount, |
697 SkShader::TileMode mode, | 711 SkShader::TileMode mode, |
698 SkUnitMapper* mapper) { | 712 SkUnitMapper* mapper) { |
699 if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { | 713 if (startRadius < 0 || endRadius < 0 || NULL == colors || colorCount < 1) { |
700 return NULL; | 714 return NULL; |
701 } | 715 } |
702 if (start == end && startRadius == endRadius) { | 716 if (start == end && startRadius == endRadius) { |
703 return SkNEW(SkEmptyShader); | 717 return SkNEW(SkEmptyShader); |
704 } | 718 } |
705 EXPAND_1_COLOR(colorCount); | 719 EXPAND_1_COLOR(colorCount); |
706 | 720 |
| 721 SkGradientShaderBase::Descriptor desc; |
| 722 desc_init(&desc, colors, pos, colorCount, mode, mapper); |
707 return SkNEW_ARGS(SkTwoPointConicalGradient, | 723 return SkNEW_ARGS(SkTwoPointConicalGradient, |
708 (start, startRadius, end, endRadius, colors, pos, | 724 (start, startRadius, end, endRadius, desc)); |
709 colorCount, mode, mapper)); | |
710 } | 725 } |
711 | 726 |
712 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy, | 727 SkShader* SkGradientShader::CreateSweep(SkScalar cx, SkScalar cy, |
713 const SkColor colors[], | 728 const SkColor colors[], |
714 const SkScalar pos[], | 729 const SkScalar pos[], |
715 int count, SkUnitMapper* mapper) { | 730 int colorCount, SkUnitMapper* mapper) { |
716 if (NULL == colors || count < 1) { | 731 if (NULL == colors || colorCount < 1) { |
717 return NULL; | 732 return NULL; |
718 } | 733 } |
719 EXPAND_1_COLOR(count); | 734 EXPAND_1_COLOR(colorCount); |
720 | 735 |
721 return SkNEW_ARGS(SkSweepGradient, (cx, cy, colors, pos, count, mapper)); | 736 SkGradientShaderBase::Descriptor desc; |
| 737 desc_init(&desc, colors, pos, colorCount, SkShader::kClamp_TileMode, mapper)
; |
| 738 return SkNEW_ARGS(SkSweepGradient, (cx, cy, desc)); |
722 } | 739 } |
723 | 740 |
724 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader) | 741 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkGradientShader) |
725 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLinearGradient) | 742 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLinearGradient) |
726 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRadialGradient) | 743 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRadialGradient) |
727 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSweepGradient) | 744 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSweepGradient) |
728 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointRadialGradient) | 745 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointRadialGradient) |
729 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointConicalGradient) | 746 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTwoPointConicalGradient) |
730 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 747 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
731 | 748 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 (*stops)[i] = stop; | 908 (*stops)[i] = stop; |
892 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st
op) : 1.f; | 909 stop = i < outColors - 1 ? stop + random->nextUScalar1() * (1.f - st
op) : 1.f; |
893 } | 910 } |
894 } | 911 } |
895 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM
odeCount)); | 912 *tm = static_cast<SkShader::TileMode>(random->nextULessThan(SkShader::kTileM
odeCount)); |
896 | 913 |
897 return outColors; | 914 return outColors; |
898 } | 915 } |
899 | 916 |
900 #endif | 917 #endif |
OLD | NEW |