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 | 9 |
10 #include "SkTwoPointConicalGradient_gpu.h" | 10 #include "SkTwoPointConicalGradient_gpu.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 SkASSERT(ratio); | 25 SkASSERT(ratio); |
26 if (0 == denom) { | 26 if (0 == denom) { |
27 return 0; | 27 return 0; |
28 } | 28 } |
29 *ratio = numer / denom; | 29 *ratio = numer / denom; |
30 return 1; | 30 return 1; |
31 } | 31 } |
32 | 32 |
33 // 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 |
34 // ascending order | 34 // ascending order |
35 static int find_quad_roots(float A, float B, float C, float roots[2]) { | 35 static int find_quad_roots(float A, float B, float C, float roots[2], bool desce
ndingOrder = false) { |
36 SkASSERT(roots); | 36 SkASSERT(roots); |
37 | 37 |
38 if (A == 0) { | 38 if (A == 0) { |
39 return valid_divide(-C, B, roots); | 39 return valid_divide(-C, B, roots); |
40 } | 40 } |
41 | 41 |
42 float R = B*B - 4*A*C; | 42 float R = B*B - 4*A*C; |
43 if (R < 0) { | 43 if (R < 0) { |
44 return 0; | 44 return 0; |
45 } | 45 } |
(...skipping 13 matching lines...) Expand all Loading... |
59 Q *= -0.5f; | 59 Q *= -0.5f; |
60 if (0 == Q) { | 60 if (0 == Q) { |
61 roots[0] = 0; | 61 roots[0] = 0; |
62 return 1; | 62 return 1; |
63 } | 63 } |
64 | 64 |
65 float r0 = Q / A; | 65 float r0 = Q / A; |
66 float r1 = C / Q; | 66 float r1 = C / Q; |
67 roots[0] = r0 < r1 ? r0 : r1; | 67 roots[0] = r0 < r1 ? r0 : r1; |
68 roots[1] = r0 > r1 ? r0 : r1; | 68 roots[1] = r0 > r1 ? r0 : r1; |
| 69 if (descendingOrder) { |
| 70 SkTSwap(roots[0], roots[1]); |
| 71 } |
69 return 2; | 72 return 2; |
70 } | 73 } |
71 | 74 |
72 static float lerp(float x, float dx, float t) { | 75 static float lerp(float x, float dx, float t) { |
73 return x + t * dx; | 76 return x + t * dx; |
74 } | 77 } |
75 | 78 |
76 static float sqr(float x) { return x * x; } | 79 static float sqr(float x) { return x * x; } |
77 | 80 |
78 void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0, | 81 void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0, |
79 const SkPoint& center1, SkScalar rad1) { | 82 const SkPoint& center1, SkScalar rad1, |
| 83 bool flipped) { |
80 fCenterX = SkScalarToFloat(center0.fX); | 84 fCenterX = SkScalarToFloat(center0.fX); |
81 fCenterY = SkScalarToFloat(center0.fY); | 85 fCenterY = SkScalarToFloat(center0.fY); |
82 fDCenterX = SkScalarToFloat(center1.fX) - fCenterX; | 86 fDCenterX = SkScalarToFloat(center1.fX) - fCenterX; |
83 fDCenterY = SkScalarToFloat(center1.fY) - fCenterY; | 87 fDCenterY = SkScalarToFloat(center1.fY) - fCenterY; |
84 fRadius = SkScalarToFloat(rad0); | 88 fRadius = SkScalarToFloat(rad0); |
85 fDRadius = SkScalarToFloat(rad1) - fRadius; | 89 fDRadius = SkScalarToFloat(rad1) - fRadius; |
86 | 90 |
87 fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius); | 91 fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius); |
88 fRadius2 = sqr(fRadius); | 92 fRadius2 = sqr(fRadius); |
89 fRDR = fRadius * fDRadius; | 93 fRDR = fRadius * fDRadius; |
| 94 |
| 95 fFlipped = flipped; |
90 } | 96 } |
91 | 97 |
92 TwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkSc
alar fy, | 98 TwoPtRadialContext::TwoPtRadialContext(const TwoPtRadial& rec, SkScalar fx, SkSc
alar fy, |
93 SkScalar dfx, SkScalar dfy) | 99 SkScalar dfx, SkScalar dfy) |
94 : fRec(rec) | 100 : fRec(rec) |
95 , fRelX(SkScalarToFloat(fx) - rec.fCenterX) | 101 , fRelX(SkScalarToFloat(fx) - rec.fCenterX) |
96 , fRelY(SkScalarToFloat(fy) - rec.fCenterY) | 102 , fRelY(SkScalarToFloat(fy) - rec.fCenterY) |
97 , fIncX(SkScalarToFloat(dfx)) | 103 , fIncX(SkScalarToFloat(dfx)) |
98 , fIncY(SkScalarToFloat(dfy)) | 104 , fIncY(SkScalarToFloat(dfy)) |
99 , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR)) | 105 , fB(-2 * (rec.fDCenterX * fRelX + rec.fDCenterY * fRelY + rec.fRDR)) |
100 , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {} | 106 , fDB(-2 * (rec.fDCenterX * fIncX + rec.fDCenterY * fIncY)) {} |
101 | 107 |
102 SkFixed TwoPtRadialContext::nextT() { | 108 SkFixed TwoPtRadialContext::nextT() { |
103 float roots[2]; | 109 float roots[2]; |
104 | 110 |
105 float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2; | 111 float C = sqr(fRelX) + sqr(fRelY) - fRec.fRadius2; |
106 int countRoots = find_quad_roots(fRec.fA, fB, C, roots); | 112 int countRoots = find_quad_roots(fRec.fA, fB, C, roots, fRec.fFlipped); |
107 | 113 |
108 fRelX += fIncX; | 114 fRelX += fIncX; |
109 fRelY += fIncY; | 115 fRelY += fIncY; |
110 fB += fDB; | 116 fB += fDB; |
111 | 117 |
112 if (0 == countRoots) { | 118 if (0 == countRoots) { |
113 return TwoPtRadial::kDontDrawT; | 119 return TwoPtRadial::kDontDrawT; |
114 } | 120 } |
115 | 121 |
116 // 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 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 SkFixed index = mirror_tileproc(t); | 181 SkFixed index = mirror_tileproc(t); |
176 SkASSERT(index <= 0xFFFF); | 182 SkASSERT(index <= 0xFFFF); |
177 *dstC++ = cache[toggle + | 183 *dstC++ = cache[toggle + |
178 (index >> SkGradientShaderBase::kCache32Shift)]; | 184 (index >> SkGradientShaderBase::kCache32Shift)]; |
179 } | 185 } |
180 toggle = next_dither_toggle(toggle); | 186 toggle = next_dither_toggle(toggle); |
181 } | 187 } |
182 } | 188 } |
183 | 189 |
184 void SkTwoPointConicalGradient::init() { | 190 void SkTwoPointConicalGradient::init() { |
185 fRec.init(fCenter1, fRadius1, fCenter2, fRadius2); | 191 fRec.init(fCenter1, fRadius1, fCenter2, fRadius2, fFlippedGrad); |
186 fPtsToUnit.reset(); | 192 fPtsToUnit.reset(); |
187 } | 193 } |
188 | 194 |
189 ///////////////////////////////////////////////////////////////////// | 195 ///////////////////////////////////////////////////////////////////// |
190 | 196 |
191 SkTwoPointConicalGradient::SkTwoPointConicalGradient( | 197 SkTwoPointConicalGradient::SkTwoPointConicalGradient( |
192 const SkPoint& start, SkScalar startRadius, | 198 const SkPoint& start, SkScalar startRadius, |
193 const SkPoint& end, SkScalar endRadius, | 199 const SkPoint& end, SkScalar endRadius, |
194 const Descriptor& desc) | 200 bool flippedGrad, const Descriptor& desc) |
195 : SkGradientShaderBase(desc), | 201 : SkGradientShaderBase(desc), |
196 fCenter1(start), | 202 fCenter1(start), |
197 fCenter2(end), | 203 fCenter2(end), |
198 fRadius1(startRadius), | 204 fRadius1(startRadius), |
199 fRadius2(endRadius) { | 205 fRadius2(endRadius), |
| 206 fFlippedGrad(flippedGrad) { |
200 // this is degenerate, and should be caught by our caller | 207 // this is degenerate, and should be caught by our caller |
201 SkASSERT(fCenter1 != fCenter2 || fRadius1 != fRadius2); | 208 SkASSERT(fCenter1 != fCenter2 || fRadius1 != fRadius2); |
202 this->init(); | 209 this->init(); |
203 } | 210 } |
204 | 211 |
205 bool SkTwoPointConicalGradient::isOpaque() const { | 212 bool SkTwoPointConicalGradient::isOpaque() const { |
206 // 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 |
207 // shader as opaque even if the gradient itself is opaque. | 214 // shader as opaque even if the gradient itself is opaque. |
208 // 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 |
209 return false; | 216 return false; |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 return kConical_GradientType; | 345 return kConical_GradientType; |
339 } | 346 } |
340 | 347 |
341 SkTwoPointConicalGradient::SkTwoPointConicalGradient( | 348 SkTwoPointConicalGradient::SkTwoPointConicalGradient( |
342 SkReadBuffer& buffer) | 349 SkReadBuffer& buffer) |
343 : INHERITED(buffer), | 350 : INHERITED(buffer), |
344 fCenter1(buffer.readPoint()), | 351 fCenter1(buffer.readPoint()), |
345 fCenter2(buffer.readPoint()), | 352 fCenter2(buffer.readPoint()), |
346 fRadius1(buffer.readScalar()), | 353 fRadius1(buffer.readScalar()), |
347 fRadius2(buffer.readScalar()) { | 354 fRadius2(buffer.readScalar()) { |
| 355 if (buffer.pictureVersion() >= 24 || 0 == buffer.pictureVersion()) { |
| 356 fFlippedGrad = buffer.readBool(); |
| 357 } else { |
| 358 // V23_COMPATIBILITY_CODE |
| 359 // Sort gradient by radius size for old pictures |
| 360 if (fRadius2 < fRadius1) { |
| 361 SkTSwap(fCenter1, fCenter2); |
| 362 SkTSwap(fRadius1, fRadius2); |
| 363 this->flipGradientColors(); |
| 364 fFlippedGrad = true; |
| 365 } else { |
| 366 fFlippedGrad = false; |
| 367 } |
| 368 } |
348 this->init(); | 369 this->init(); |
349 }; | 370 }; |
350 | 371 |
351 void SkTwoPointConicalGradient::flatten( | 372 void SkTwoPointConicalGradient::flatten( |
352 SkWriteBuffer& buffer) const { | 373 SkWriteBuffer& buffer) const { |
353 this->INHERITED::flatten(buffer); | 374 this->INHERITED::flatten(buffer); |
354 buffer.writePoint(fCenter1); | 375 buffer.writePoint(fCenter1); |
355 buffer.writePoint(fCenter2); | 376 buffer.writePoint(fCenter2); |
356 buffer.writeScalar(fRadius1); | 377 buffer.writeScalar(fRadius1); |
357 buffer.writeScalar(fRadius2); | 378 buffer.writeScalar(fRadius2); |
| 379 buffer.writeBool(fFlippedGrad); |
358 } | 380 } |
359 | 381 |
360 #if SK_SUPPORT_GPU | 382 #if SK_SUPPORT_GPU |
361 | 383 |
362 GrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext* context, const Sk
Paint&) const { | 384 GrEffectRef* SkTwoPointConicalGradient::asNewEffect(GrContext* context, const Sk
Paint&) const { |
363 SkASSERT(NULL != context); | 385 SkASSERT(NULL != context); |
364 SkASSERT(fPtsToUnit.isIdentity()); | 386 SkASSERT(fPtsToUnit.isIdentity()); |
365 | 387 |
366 return Gr2PtConicalGradientEffect::Create(context, *this, fTileMode); | 388 return Gr2PtConicalGradientEffect::Create(context, *this, fTileMode); |
367 } | 389 } |
(...skipping 25 matching lines...) Expand all Loading... |
393 str->appendScalar(fCenter2.fY); | 415 str->appendScalar(fCenter2.fY); |
394 str->append(") radius2: "); | 416 str->append(") radius2: "); |
395 str->appendScalar(fRadius2); | 417 str->appendScalar(fRadius2); |
396 str->append(" "); | 418 str->append(" "); |
397 | 419 |
398 this->INHERITED::toString(str); | 420 this->INHERITED::toString(str); |
399 | 421 |
400 str->append(")"); | 422 str->append(")"); |
401 } | 423 } |
402 #endif | 424 #endif |
OLD | NEW |