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 "SkTwoPointConicalGradient.h" | 8 #include "SkTwoPointConicalGradient.h" |
9 #include "SkTwoPointConicalGradient_gpu.h" | 9 #include "SkTwoPointConicalGradient_gpu.h" |
10 | 10 |
11 struct TwoPtRadialContext { | 11 struct TwoPtRadialContext { |
12 const TwoPtRadial& fRec; | 12 const TwoPtRadial& fRec; |
13 float fRelX, fRelY; | 13 float fRelX, fRelY; |
14 const float fIncX, fIncY; | 14 const float fIncX, fIncY; |
15 float fB; | 15 float fB; |
16 const float fDB; | 16 const float fDB; |
17 | 17 |
18 TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy, | 18 TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy, |
19 SkScalar dfx, SkScalar dfy); | 19 SkScalar dfx, SkScalar dfy); |
20 SkFixed nextT(); | 20 float nextT(); |
21 }; | 21 }; |
22 | 22 |
23 static int valid_divide(float numer, float denom, float* ratio) { | 23 static int valid_divide(float numer, float denom, float* ratio) { |
24 SkASSERT(ratio); | 24 SkASSERT(ratio); |
25 if (0 == denom) { | 25 if (0 == denom) { |
26 return 0; | 26 return 0; |
27 } | 27 } |
28 *ratio = numer / denom; | 28 *ratio = numer / denom; |
29 return 1; | 29 return 1; |
30 } | 30 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 } | 70 } |
71 return 2; | 71 return 2; |
72 } | 72 } |
73 | 73 |
74 static float lerp(float x, float dx, float t) { | 74 static float lerp(float x, float dx, float t) { |
75 return x + t * dx; | 75 return x + t * dx; |
76 } | 76 } |
77 | 77 |
78 static float sqr(float x) { return x * x; } | 78 static float sqr(float x) { return x * x; } |
79 | 79 |
| 80 const float TwoPtRadial::kDontDrawT = NAN; |
| 81 |
80 void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0, | 82 void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0, |
81 const SkPoint& center1, SkScalar rad1, | 83 const SkPoint& center1, SkScalar rad1, |
82 bool flipped) { | 84 bool flipped) { |
83 fCenterX = SkScalarToFloat(center0.fX); | 85 fCenterX = SkScalarToFloat(center0.fX); |
84 fCenterY = SkScalarToFloat(center0.fY); | 86 fCenterY = SkScalarToFloat(center0.fY); |
85 fDCenterX = SkScalarToFloat(center1.fX) - fCenterX; | 87 fDCenterX = SkScalarToFloat(center1.fX) - fCenterX; |
86 fDCenterY = SkScalarToFloat(center1.fY) - fCenterY; | 88 fDCenterY = SkScalarToFloat(center1.fY) - fCenterY; |
87 fRadius = SkScalarToFloat(rad0); | 89 fRadius = SkScalarToFloat(rad0); |
88 fDRadius = SkScalarToFloat(rad1) - fRadius; | 90 fDRadius = SkScalarToFloat(rad1) - fRadius; |
89 | 91 |
90 fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius); | 92 fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius); |
91 fRadius2 = sqr(fRadius); | 93 fRadius2 = sqr(fRadius); |
92 fRDR = fRadius * fDRadius; | 94 fRDR = fRadius * fDRadius; |
93 | 95 |
94 fFlipped = flipped; | 96 fFlipped = flipped; |
95 } | 97 } |
96 | 98 |
97 TwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkSc
alar fy, | 99 TwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkSc
alar fy, |
98 SkScalar dfx, SkScalar dfy) | 100 SkScalar dfx, SkScalar dfy) |
99 : fRec(rec) | 101 : fRec(rec) |
100 , fRelX(SkScalarToFloat(fx) - rec.fCenterX) | 102 , fRelX(SkScalarToFloat(fx) - rec.fCenterX) |
101 , fRelY(SkScalarToFloat(fy) - rec.fCenterY) | 103 , fRelY(SkScalarToFloat(fy) - rec.fCenterY) |
102 , fIncX(SkScalarToFloat(dfx)) | 104 , fIncX(SkScalarToFloat(dfx)) |
103 , fIncY(SkScalarToFloat(dfy)) | 105 , fIncY(SkScalarToFloat(dfy)) |
104 , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR)) | 106 , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR)) |
105 , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {} | 107 , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {} |
106 | 108 |
107 SkFixed TwoPtRadialContext::nextT() { | 109 float TwoPtRadialContext::nextT() { |
108 float roots[2]; | 110 float roots[2]; |
109 | 111 |
110 float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2; | 112 float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2; |
111 int countRoots = find_quad_roots(fRec.fA, fB, C, roots, fRec.fFlipped); | 113 int countRoots = find_quad_roots(fRec.fA, fB, C, roots, fRec.fFlipped); |
112 | 114 |
113 fRelX += fIncX; | 115 fRelX += fIncX; |
114 fRelY += fIncY; | 116 fRelY += fIncY; |
115 fB += fDB; | 117 fB += fDB; |
116 | 118 |
117 if (0 == countRoots) { | 119 if (0 == countRoots) { |
118 return TwoPtRadial::kDontDrawT; | 120 return TwoPtRadial::kDontDrawT; |
119 } | 121 } |
120 | 122 |
121 // Prefer the bigger t value if both give a radius(t) > 0 | 123 // Prefer the bigger t value if both give a radius(t) > 0 |
122 // find_quad_roots returns the values sorted, so we start with the last | 124 // find_quad_roots returns the values sorted, so we start with the last |
123 float t = roots[countRoots - 1]; | 125 float t = roots[countRoots - 1]; |
124 float r = lerp(fRec.fRadius, fRec.fDRadius, t); | 126 float r = lerp(fRec.fRadius, fRec.fDRadius, t); |
125 if (r < 0) { | 127 if (r < 0) { |
126 t = roots[0]; // might be the same as roots[countRoots-1] | 128 t = roots[0]; // might be the same as roots[countRoots-1] |
127 r = lerp(fRec.fRadius, fRec.fDRadius, t); | 129 r = lerp(fRec.fRadius, fRec.fDRadius, t); |
128 if (r < 0) { | 130 if (r < 0) { |
129 return TwoPtRadial::kDontDrawT; | 131 return TwoPtRadial::kDontDrawT; |
130 } | 132 } |
131 } | 133 } |
132 return SkFloatToFixed(t); | 134 return t; |
133 } | 135 } |
134 | 136 |
135 typedef void (*TwoPointConicalProc)(TwoPtRadialContext* rec, SkPMColor* dstC, | 137 typedef void (*TwoPointConicalProc)(TwoPtRadialContext* rec, SkPMColor* dstC, |
136 const SkPMColor* cache, int toggle, int coun
t); | 138 const SkPMColor* cache, int toggle, int coun
t); |
137 | 139 |
138 static void twopoint_clamp(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC, | 140 static void twopoint_clamp(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC, |
139 const SkPMColor* SK_RESTRICT cache, int toggle, | 141 const SkPMColor* SK_RESTRICT cache, int toggle, |
140 int count) { | 142 int count) { |
141 for (; count > 0; --count) { | 143 for (; count > 0; --count) { |
142 SkFixed t = rec->nextT(); | 144 float t = rec->nextT(); |
143 if (TwoPtRadial::DontDrawT(t)) { | 145 if (TwoPtRadial::DontDrawT(t)) { |
144 *dstC++ = 0; | 146 *dstC++ = 0; |
145 } else { | 147 } else { |
146 SkFixed index = SkClampMax(t, 0xFFFF); | 148 const unsigned index = clamp_tileproc(t); |
147 SkASSERT(index <= 0xFFFF); | 149 SkASSERT(index <= 0xFFFF); |
148 *dstC++ = cache[toggle + | 150 *dstC++ = cache[toggle + |
149 (index >> SkGradientShaderBase::kCache32Shift)]; | 151 (index >> SkGradientShaderBase::kCache32Shift)]; |
150 } | 152 } |
151 toggle = next_dither_toggle(toggle); | 153 toggle = next_dither_toggle(toggle); |
152 } | 154 } |
153 } | 155 } |
154 | 156 |
155 static void twopoint_repeat(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC
, | 157 static void twopoint_repeat(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC
, |
156 const SkPMColor* SK_RESTRICT cache, int toggle, | 158 const SkPMColor* SK_RESTRICT cache, int toggle, |
157 int count) { | 159 int count) { |
158 for (; count > 0; --count) { | 160 for (; count > 0; --count) { |
159 SkFixed t = rec->nextT(); | 161 float t = rec->nextT(); |
160 if (TwoPtRadial::DontDrawT(t)) { | 162 if (TwoPtRadial::DontDrawT(t)) { |
161 *dstC++ = 0; | 163 *dstC++ = 0; |
162 } else { | 164 } else { |
163 SkFixed index = repeat_tileproc(t); | 165 const unsigned index = repeat_tileproc(t); |
164 SkASSERT(index <= 0xFFFF); | 166 SkASSERT(index <= 0xFFFF); |
165 *dstC++ = cache[toggle + | 167 *dstC++ = cache[toggle + |
166 (index >> SkGradientShaderBase::kCache32Shift)]; | 168 (index >> SkGradientShaderBase::kCache32Shift)]; |
167 } | 169 } |
168 toggle = next_dither_toggle(toggle); | 170 toggle = next_dither_toggle(toggle); |
169 } | 171 } |
170 } | 172 } |
171 | 173 |
172 static void twopoint_mirror(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC
, | 174 static void twopoint_mirror(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC
, |
173 const SkPMColor* SK_RESTRICT cache, int toggle, | 175 const SkPMColor* SK_RESTRICT cache, int toggle, |
174 int count) { | 176 int count) { |
175 for (; count > 0; --count) { | 177 for (; count > 0; --count) { |
176 SkFixed t = rec->nextT(); | 178 float t = rec->nextT(); |
177 if (TwoPtRadial::DontDrawT(t)) { | 179 if (TwoPtRadial::DontDrawT(t)) { |
178 *dstC++ = 0; | 180 *dstC++ = 0; |
179 } else { | 181 } else { |
180 SkFixed index = mirror_tileproc(t); | 182 const unsigned index = mirror_tileproc(t); |
181 SkASSERT(index <= 0xFFFF); | 183 SkASSERT(index <= 0xFFFF); |
182 *dstC++ = cache[toggle + | 184 *dstC++ = cache[toggle + |
183 (index >> SkGradientShaderBase::kCache32Shift)]; | 185 (index >> SkGradientShaderBase::kCache32Shift)]; |
184 } | 186 } |
185 toggle = next_dither_toggle(toggle); | 187 toggle = next_dither_toggle(toggle); |
186 } | 188 } |
187 } | 189 } |
188 | 190 |
189 ///////////////////////////////////////////////////////////////////// | 191 ///////////////////////////////////////////////////////////////////// |
190 | 192 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 str->appendScalar(fCenter2.fY); | 390 str->appendScalar(fCenter2.fY); |
389 str->append(") radius2: "); | 391 str->append(") radius2: "); |
390 str->appendScalar(fRadius2); | 392 str->appendScalar(fRadius2); |
391 str->append(" "); | 393 str->append(" "); |
392 | 394 |
393 this->INHERITED::toString(str); | 395 this->INHERITED::toString(str); |
394 | 396 |
395 str->append(")"); | 397 str->append(")"); |
396 } | 398 } |
397 #endif | 399 #endif |
OLD | NEW |