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

Side by Side Diff: src/effects/gradients/SkTwoPointConicalGradient.cpp

Issue 207683004: Extract most of the mutable state of SkShader into a separate Context object. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: rebase Created 6 years, 8 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
OLDNEW
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 9
10 #include "SkTwoPointConicalGradient_gpu.h" 10 #include "SkTwoPointConicalGradient_gpu.h"
11 11
12 struct TwoPtRadialContext {
13 const TwoPtRadial& fRec;
14 float fRelX, fRelY;
15 const float fIncX, fIncY;
16 float fB;
17 const float fDB;
18
19 TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkScalar fy,
20 SkScalar dfx, SkScalar dfy);
21 SkFixed nextT();
22 };
23
12 static int valid_divide(float numer, float denom, float* ratio) { 24 static int valid_divide(float numer, float denom, float* ratio) {
13 SkASSERT(ratio); 25 SkASSERT(ratio);
14 if (0 == denom) { 26 if (0 == denom) {
15 return 0; 27 return 0;
16 } 28 }
17 *ratio = numer / denom; 29 *ratio = numer / denom;
18 return 1; 30 return 1;
19 } 31 }
20 32
21 // Return the number of distinct real roots, and write them into roots[] in 33 // Return the number of distinct real roots, and write them into roots[] in
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 fRadius = SkScalarToFloat(rad0); 88 fRadius = SkScalarToFloat(rad0);
77 fDRadius = SkScalarToFloat(rad1) - fRadius; 89 fDRadius = SkScalarToFloat(rad1) - fRadius;
78 90
79 fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius); 91 fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius);
80 fRadius2 = sqr(fRadius); 92 fRadius2 = sqr(fRadius);
81 fRDR = fRadius * fDRadius; 93 fRDR = fRadius * fDRadius;
82 94
83 fFlipped = flipped; 95 fFlipped = flipped;
84 } 96 }
85 97
86 void TwoPtRadial::setup(SkScalar fx, SkScalar fy, SkScalar dfx, SkScalar dfy) { 98 TwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkSc alar fy,
87 fRelX = SkScalarToFloat(fx) - fCenterX; 99 SkScalar dfx, SkScalar dfy)
88 fRelY = SkScalarToFloat(fy) - fCenterY; 100 : fRec(rec)
89 fIncX = SkScalarToFloat(dfx); 101 , fRelX(SkScalarToFloat(fx) - rec.fCenterX)
90 fIncY = SkScalarToFloat(dfy); 102 , fRelY(SkScalarToFloat(fy) - rec.fCenterY)
91 fB = -2 * (fDCenterX * fRelX + fDCenterY * fRelY + fRDR); 103 , fIncX(SkScalarToFloat(dfx))
92 fDB = -2 * (fDCenterX * fIncX + fDCenterY * fIncY); 104 , fIncY(SkScalarToFloat(dfy))
93 } 105 , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR))
106 , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {}
94 107
95 SkFixed TwoPtRadial::nextT() { 108 SkFixed TwoPtRadialContext::nextT() {
96 float roots[2]; 109 float roots[2];
97 110
98 float C = sqr(fRelX) + sqr(fRelY) - fRadius2; 111 float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2;
99 int countRoots = find_quad_roots(fA, fB, C, roots, fFlipped); 112 int countRoots = find_quad_roots(fRec.fA, fB, C, roots, fRec.fFlipped);
100 113
101 fRelX += fIncX; 114 fRelX += fIncX;
102 fRelY += fIncY; 115 fRelY += fIncY;
103 fB += fDB; 116 fB += fDB;
104 117
105 if (0 == countRoots) { 118 if (0 == countRoots) {
106 return kDontDrawT; 119 return TwoPtRadial::kDontDrawT;
107 } 120 }
108 121
109 // Prefer the bigger t value if both give a radius(t) > 0 122 // Prefer the bigger t value if both give a radius(t) > 0
110 // find_quad_roots returns the values sorted, so we start with the last 123 // find_quad_roots returns the values sorted, so we start with the last
111 float t = roots[countRoots - 1]; 124 float t = roots[countRoots - 1];
112 float r = lerp(fRadius, fDRadius, t); 125 float r = lerp(fRec.fRadius, fRec.fDRadius, t);
113 if (r <= 0) { 126 if (r <= 0) {
114 t = roots[0]; // might be the same as roots[countRoots-1] 127 t = roots[0]; // might be the same as roots[countRoots-1]
115 r = lerp(fRadius, fDRadius, t); 128 r = lerp(fRec.fRadius, fRec.fDRadius, t);
116 if (r <= 0) { 129 if (r <= 0) {
117 return kDontDrawT; 130 return TwoPtRadial::kDontDrawT;
118 } 131 }
119 } 132 }
120 return SkFloatToFixed(t); 133 return SkFloatToFixed(t);
121 } 134 }
122 135
123 typedef void (*TwoPointConicalProc)(TwoPtRadial* rec, SkPMColor* dstC, 136 typedef void (*TwoPointConicalProc)(TwoPtRadialContext* rec, SkPMColor* dstC,
124 const SkPMColor* cache, int toggle, int coun t); 137 const SkPMColor* cache, int toggle, int coun t);
125 138
126 static void twopoint_clamp(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 139 static void twopoint_clamp(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC,
127 const SkPMColor* SK_RESTRICT cache, int toggle, 140 const SkPMColor* SK_RESTRICT cache, int toggle,
128 int count) { 141 int count) {
129 for (; count > 0; --count) { 142 for (; count > 0; --count) {
130 SkFixed t = rec->nextT(); 143 SkFixed t = rec->nextT();
131 if (TwoPtRadial::DontDrawT(t)) { 144 if (TwoPtRadial::DontDrawT(t)) {
132 *dstC++ = 0; 145 *dstC++ = 0;
133 } else { 146 } else {
134 SkFixed index = SkClampMax(t, 0xFFFF); 147 SkFixed index = SkClampMax(t, 0xFFFF);
135 SkASSERT(index <= 0xFFFF); 148 SkASSERT(index <= 0xFFFF);
136 *dstC++ = cache[toggle + 149 *dstC++ = cache[toggle +
137 (index >> SkGradientShaderBase::kCache32Shift)]; 150 (index >> SkGradientShaderBase::kCache32Shift)];
138 } 151 }
139 toggle = next_dither_toggle(toggle); 152 toggle = next_dither_toggle(toggle);
140 } 153 }
141 } 154 }
142 155
143 static void twopoint_repeat(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 156 static void twopoint_repeat(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC ,
144 const SkPMColor* SK_RESTRICT cache, int toggle, 157 const SkPMColor* SK_RESTRICT cache, int toggle,
145 int count) { 158 int count) {
146 for (; count > 0; --count) { 159 for (; count > 0; --count) {
147 SkFixed t = rec->nextT(); 160 SkFixed t = rec->nextT();
148 if (TwoPtRadial::DontDrawT(t)) { 161 if (TwoPtRadial::DontDrawT(t)) {
149 *dstC++ = 0; 162 *dstC++ = 0;
150 } else { 163 } else {
151 SkFixed index = repeat_tileproc(t); 164 SkFixed index = repeat_tileproc(t);
152 SkASSERT(index <= 0xFFFF); 165 SkASSERT(index <= 0xFFFF);
153 *dstC++ = cache[toggle + 166 *dstC++ = cache[toggle +
154 (index >> SkGradientShaderBase::kCache32Shift)]; 167 (index >> SkGradientShaderBase::kCache32Shift)];
155 } 168 }
156 toggle = next_dither_toggle(toggle); 169 toggle = next_dither_toggle(toggle);
157 } 170 }
158 } 171 }
159 172
160 static void twopoint_mirror(TwoPtRadial* rec, SkPMColor* SK_RESTRICT dstC, 173 static void twopoint_mirror(TwoPtRadialContext* rec, SkPMColor* SK_RESTRICT dstC ,
161 const SkPMColor* SK_RESTRICT cache, int toggle, 174 const SkPMColor* SK_RESTRICT cache, int toggle,
162 int count) { 175 int count) {
163 for (; count > 0; --count) { 176 for (; count > 0; --count) {
164 SkFixed t = rec->nextT(); 177 SkFixed t = rec->nextT();
165 if (TwoPtRadial::DontDrawT(t)) { 178 if (TwoPtRadial::DontDrawT(t)) {
166 *dstC++ = 0; 179 *dstC++ = 0;
167 } else { 180 } else {
168 SkFixed index = mirror_tileproc(t); 181 SkFixed index = mirror_tileproc(t);
169 SkASSERT(index <= 0xFFFF); 182 SkASSERT(index <= 0xFFFF);
170 *dstC++ = cache[toggle + 183 *dstC++ = cache[toggle +
(...skipping 25 matching lines...) Expand all
196 this->init(); 209 this->init();
197 } 210 }
198 211
199 bool SkTwoPointConicalGradient::isOpaque() const { 212 bool SkTwoPointConicalGradient::isOpaque() const {
200 // Because areas outside the cone are left untouched, we cannot treat the 213 // Because areas outside the cone are left untouched, we cannot treat the
201 // shader as opaque even if the gradient itself is opaque. 214 // shader as opaque even if the gradient itself is opaque.
202 // TODO(junov): Compute whether the cone fills the plane crbug.com/222380 215 // TODO(junov): Compute whether the cone fills the plane crbug.com/222380
203 return false; 216 return false;
204 } 217 }
205 218
206 void SkTwoPointConicalGradient::shadeSpan(int x, int y, SkPMColor* dstCParam, 219 size_t SkTwoPointConicalGradient::contextSize() const {
207 int count) { 220 return sizeof(TwoPointConicalGradientContext);
221 }
222
223 SkShader::Context* SkTwoPointConicalGradient::createContext(
224 const SkBitmap& device, const SkPaint& paint,
225 const SkMatrix& matrix, void* storage) const {
226 if (!this->validContext(device, paint, matrix)) {
227 return NULL;
228 }
229
230 return SkNEW_PLACEMENT_ARGS(storage, TwoPointConicalGradientContext,
231 (*this, device, paint, matrix));
232 }
233
234 SkTwoPointConicalGradient::TwoPointConicalGradientContext::TwoPointConicalGradie ntContext(
235 const SkTwoPointConicalGradient& shader, const SkBitmap& device,
236 const SkPaint& paint, const SkMatrix& matrix)
237 : INHERITED(shader, device, paint, matrix)
238 {
239 // we don't have a span16 proc
240 fFlags &= ~kHasSpan16_Flag;
241
242 // in general, we might discard based on computed-radius, so clear
243 // this flag (todo: sometimes we can detect that we never discard...)
244 fFlags &= ~kOpaqueAlpha_Flag;
245 }
246
247 void SkTwoPointConicalGradient::TwoPointConicalGradientContext::shadeSpan(
248 int x, int y, SkPMColor* dstCParam, int count) {
249 const SkTwoPointConicalGradient& twoPointConicalGradient =
250 static_cast<const SkTwoPointConicalGradient&>(fShader);
251
208 int toggle = init_dither_toggle(x, y); 252 int toggle = init_dither_toggle(x, y);
209 253
210 SkASSERT(count > 0); 254 SkASSERT(count > 0);
211 255
212 SkPMColor* SK_RESTRICT dstC = dstCParam; 256 SkPMColor* SK_RESTRICT dstC = dstCParam;
213 257
214 SkMatrix::MapXYProc dstProc = fDstToIndexProc; 258 SkMatrix::MapXYProc dstProc = fDstToIndexProc;
215 259
216 const SkPMColor* SK_RESTRICT cache = this->getCache32(); 260 const SkPMColor* SK_RESTRICT cache = fCache->getCache32();
217 261
218 TwoPointConicalProc shadeProc = twopoint_repeat; 262 TwoPointConicalProc shadeProc = twopoint_repeat;
219 if (SkShader::kClamp_TileMode == fTileMode) { 263 if (SkShader::kClamp_TileMode == twoPointConicalGradient.fTileMode) {
220 shadeProc = twopoint_clamp; 264 shadeProc = twopoint_clamp;
221 } else if (SkShader::kMirror_TileMode == fTileMode) { 265 } else if (SkShader::kMirror_TileMode == twoPointConicalGradient.fTileMode) {
222 shadeProc = twopoint_mirror; 266 shadeProc = twopoint_mirror;
223 } else { 267 } else {
224 SkASSERT(SkShader::kRepeat_TileMode == fTileMode); 268 SkASSERT(SkShader::kRepeat_TileMode == twoPointConicalGradient.fTileMode );
225 } 269 }
226 270
227 if (fDstToIndexClass != kPerspective_MatrixClass) { 271 if (fDstToIndexClass != kPerspective_MatrixClass) {
228 SkPoint srcPt; 272 SkPoint srcPt;
229 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf, 273 dstProc(fDstToIndex, SkIntToScalar(x) + SK_ScalarHalf,
230 SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 274 SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
231 SkScalar dx, fx = srcPt.fX; 275 SkScalar dx, fx = srcPt.fX;
232 SkScalar dy, fy = srcPt.fY; 276 SkScalar dy, fy = srcPt.fY;
233 277
234 if (fDstToIndexClass == kFixedStepInX_MatrixClass) { 278 if (fDstToIndexClass == kFixedStepInX_MatrixClass) {
235 SkFixed fixedX, fixedY; 279 SkFixed fixedX, fixedY;
236 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY); 280 (void)fDstToIndex.fixedStepInX(SkIntToScalar(y), &fixedX, &fixedY);
237 dx = SkFixedToScalar(fixedX); 281 dx = SkFixedToScalar(fixedX);
238 dy = SkFixedToScalar(fixedY); 282 dy = SkFixedToScalar(fixedY);
239 } else { 283 } else {
240 SkASSERT(fDstToIndexClass == kLinear_MatrixClass); 284 SkASSERT(fDstToIndexClass == kLinear_MatrixClass);
241 dx = fDstToIndex.getScaleX(); 285 dx = fDstToIndex.getScaleX();
242 dy = fDstToIndex.getSkewY(); 286 dy = fDstToIndex.getSkewY();
243 } 287 }
244 288
245 fRec.setup(fx, fy, dx, dy); 289 TwoPtRadialContext rec(twoPointConicalGradient.fRec, fx, fy, dx, dy);
246 (*shadeProc)(&fRec, dstC, cache, toggle, count); 290 (*shadeProc)(&rec, dstC, cache, toggle, count);
247 } else { // perspective case 291 } else { // perspective case
248 SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf; 292 SkScalar dstX = SkIntToScalar(x) + SK_ScalarHalf;
249 SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf; 293 SkScalar dstY = SkIntToScalar(y) + SK_ScalarHalf;
250 for (; count > 0; --count) { 294 for (; count > 0; --count) {
251 SkPoint srcPt; 295 SkPoint srcPt;
252 dstProc(fDstToIndex, dstX, dstY, &srcPt); 296 dstProc(fDstToIndex, dstX, dstY, &srcPt);
253 fRec.setup(srcPt.fX, srcPt.fY, 0, 0); 297 TwoPtRadialContext rec(twoPointConicalGradient.fRec, srcPt.fX, srcPt .fY, 0, 0);
254 (*shadeProc)(&fRec, dstC, cache, toggle, 1); 298 (*shadeProc)(&rec, dstC, cache, toggle, 1);
255 299
256 dstX += SK_Scalar1; 300 dstX += SK_Scalar1;
257 toggle = next_dither_toggle(toggle); 301 toggle = next_dither_toggle(toggle);
258 dstC += 1; 302 dstC += 1;
259 } 303 }
260 } 304 }
261 } 305 }
262 306
263 bool SkTwoPointConicalGradient::setContext(const SkBitmap& device,
264 const SkPaint& paint,
265 const SkMatrix& matrix) {
266 if (!this->INHERITED::setContext(device, paint, matrix)) {
267 return false;
268 }
269
270 // we don't have a span16 proc
271 fFlags &= ~kHasSpan16_Flag;
272
273 // in general, we might discard based on computed-radius, so clear
274 // this flag (todo: sometimes we can detect that we never discard...)
275 fFlags &= ~kOpaqueAlpha_Flag;
276
277 return true;
278 }
279
280 SkShader::BitmapType SkTwoPointConicalGradient::asABitmap( 307 SkShader::BitmapType SkTwoPointConicalGradient::asABitmap(
281 SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const { 308 SkBitmap* bitmap, SkMatrix* matrix, SkShader::TileMode* xy) const {
282 SkPoint diff = fCenter2 - fCenter1; 309 SkPoint diff = fCenter2 - fCenter1;
283 SkScalar diffLen = 0; 310 SkScalar diffLen = 0;
284 311
285 if (bitmap) { 312 if (bitmap) {
286 this->getGradientTableBitmap(bitmap); 313 this->getGradientTableBitmap(bitmap);
287 } 314 }
288 if (matrix) { 315 if (matrix) {
289 diffLen = diff.length(); 316 diffLen = diff.length();
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 str->appendScalar(fCenter2.fY); 420 str->appendScalar(fCenter2.fY);
394 str->append(") radius2: "); 421 str->append(") radius2: ");
395 str->appendScalar(fRadius2); 422 str->appendScalar(fRadius2);
396 str->append(" "); 423 str->append(" ");
397 424
398 this->INHERITED::toString(str); 425 this->INHERITED::toString(str);
399 426
400 str->append(")"); 427 str->append(")");
401 } 428 }
402 #endif 429 #endif
OLDNEW
« no previous file with comments | « src/effects/gradients/SkTwoPointConicalGradient.h ('k') | src/effects/gradients/SkTwoPointRadialGradient.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698