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

Side by Side Diff: src/core/SkGeometry.cpp

Issue 117053002: remove SK_SCALAR_IS_[FLOAT,FIXED] and assume floats (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years 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 | Annotate | Revision Log
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #include "SkGeometry.h" 10 #include "SkGeometry.h"
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 SkScalar b = pts[0].fY - SkScalarMul(slope, pts[0].fX); 61 SkScalar b = pts[0].fY - SkScalarMul(slope, pts[0].fX);
62 // Solve for x coordinate at y = pt.fY 62 // Solve for x coordinate at y = pt.fY
63 SkScalar x = SkScalarDiv(pt.fY - b, slope); 63 SkScalar x = SkScalarDiv(pt.fY - b, slope);
64 return pt.fX <= x; 64 return pt.fX <= x;
65 } 65 }
66 66
67 /** If defined, this makes eval_quad and eval_cubic do more setup (sometimes 67 /** If defined, this makes eval_quad and eval_cubic do more setup (sometimes
68 involving integer multiplies by 2 or 3, but fewer calls to SkScalarMul. 68 involving integer multiplies by 2 or 3, but fewer calls to SkScalarMul.
69 May also introduce overflow of fixed when we compute our setup. 69 May also introduce overflow of fixed when we compute our setup.
70 */ 70 */
71 #ifdef SK_SCALAR_IS_FIXED 71 // #define DIRECT_EVAL_OF_POLYNOMIALS
72 #define DIRECT_EVAL_OF_POLYNOMIALS
73 #endif
74 72
75 //////////////////////////////////////////////////////////////////////// 73 ////////////////////////////////////////////////////////////////////////
76 74
77 #ifdef SK_SCALAR_IS_FIXED 75 static int is_not_monotonic(float a, float b, float c) {
78 static int is_not_monotonic(int a, int b, int c, int d) 76 float ab = a - b;
79 { 77 float bc = b - c;
80 return (((a - b) | (b - c) | (c - d)) & ((b - a) | (c - b) | (d - c))) > > 31; 78 if (ab < 0) {
79 bc = -bc;
81 } 80 }
82 81 return ab == 0 || bc < 0;
83 static int is_not_monotonic(int a, int b, int c) 82 }
84 {
85 return (((a - b) | (b - c)) & ((b - a) | (c - b))) >> 31;
86 }
87 #else
88 static int is_not_monotonic(float a, float b, float c)
89 {
90 float ab = a - b;
91 float bc = b - c;
92 if (ab < 0)
93 bc = -bc;
94 return ab == 0 || bc < 0;
95 }
96 #endif
97 83
98 //////////////////////////////////////////////////////////////////////// 84 ////////////////////////////////////////////////////////////////////////
99 85
100 static bool is_unit_interval(SkScalar x) 86 static bool is_unit_interval(SkScalar x)
101 { 87 {
102 return x > 0 && x < SK_Scalar1; 88 return x > 0 && x < SK_Scalar1;
103 } 89 }
104 90
105 static int valid_unit_divide(SkScalar numer, SkScalar denom, SkScalar* ratio) 91 static int valid_unit_divide(SkScalar numer, SkScalar denom, SkScalar* ratio)
106 { 92 {
(...skipping 27 matching lines...) Expand all
134 */ 120 */
135 int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]) 121 int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2])
136 { 122 {
137 SkASSERT(roots); 123 SkASSERT(roots);
138 124
139 if (A == 0) 125 if (A == 0)
140 return valid_unit_divide(-C, B, roots); 126 return valid_unit_divide(-C, B, roots);
141 127
142 SkScalar* r = roots; 128 SkScalar* r = roots;
143 129
144 #ifdef SK_SCALAR_IS_FLOAT
145 float R = B*B - 4*A*C; 130 float R = B*B - 4*A*C;
146 if (R < 0 || SkScalarIsNaN(R)) { // complex roots 131 if (R < 0 || SkScalarIsNaN(R)) { // complex roots
147 return 0; 132 return 0;
148 } 133 }
149 R = sk_float_sqrt(R); 134 R = sk_float_sqrt(R);
150 #else
151 Sk64 RR, tmp;
152
153 RR.setMul(B,B);
154 tmp.setMul(A,C);
155 tmp.shiftLeft(2);
156 RR.sub(tmp);
157 if (RR.isNeg())
158 return 0;
159 SkFixed R = RR.getSqrt();
160 #endif
161 135
162 SkScalar Q = (B < 0) ? -(B-R)/2 : -(B+R)/2; 136 SkScalar Q = (B < 0) ? -(B-R)/2 : -(B+R)/2;
163 r += valid_unit_divide(Q, A, r); 137 r += valid_unit_divide(Q, A, r);
164 r += valid_unit_divide(C, Q, r); 138 r += valid_unit_divide(C, Q, r);
165 if (r - roots == 2) 139 if (r - roots == 2)
166 { 140 {
167 if (roots[0] > roots[1]) 141 if (roots[0] > roots[1])
168 SkTSwap<SkScalar>(roots[0], roots[1]); 142 SkTSwap<SkScalar>(roots[0], roots[1]);
169 else if (roots[0] == roots[1]) // nearly-equal? 143 else if (roots[0] == roots[1]) // nearly-equal?
170 r -= 1; // skip the double root 144 r -= 1; // skip the double root
171 } 145 }
172 return (int)(r - roots); 146 return (int)(r - roots);
173 } 147 }
174 148
175 #ifdef SK_SCALAR_IS_FIXED 149 ///////////////////////////////////////////////////////////////////////////////
176 /** Trim A/B/C down so that they are all <= 32bits 150 ///////////////////////////////////////////////////////////////////////////////
177 and then call SkFindUnitQuadRoots()
178 */
179 static int Sk64FindFixedQuadRoots(const Sk64& A, const Sk64& B, const Sk64& C, S kFixed roots[2])
180 {
181 int na = A.shiftToMake32();
182 int nb = B.shiftToMake32();
183 int nc = C.shiftToMake32();
184
185 int shift = SkMax32(na, SkMax32(nb, nc));
186 SkASSERT(shift >= 0);
187
188 return SkFindUnitQuadRoots(A.getShiftRight(shift), B.getShiftRight(shift), C .getShiftRight(shift), roots);
189 }
190 #endif
191
192 //////////////////////////////////////////////////////////////////////////////// /////
193 //////////////////////////////////////////////////////////////////////////////// /////
194 151
195 static SkScalar eval_quad(const SkScalar src[], SkScalar t) 152 static SkScalar eval_quad(const SkScalar src[], SkScalar t)
196 { 153 {
197 SkASSERT(src); 154 SkASSERT(src);
198 SkASSERT(t >= 0 && t <= SK_Scalar1); 155 SkASSERT(t >= 0 && t <= SK_Scalar1);
199 156
200 #ifdef DIRECT_EVAL_OF_POLYNOMIALS 157 #ifdef DIRECT_EVAL_OF_POLYNOMIALS
201 SkScalar C = src[0]; 158 SkScalar C = src[0];
202 SkScalar A = src[4] - 2 * src[2] + C; 159 SkScalar A = src[4] - 2 * src[2] + C;
203 SkScalar B = 2 * (src[2] - C); 160 SkScalar B = 2 * (src[2] - C);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 /** Quad'(t) = At + B, where 247 /** Quad'(t) = At + B, where
291 A = 2(a - 2b + c) 248 A = 2(a - 2b + c)
292 B = 2(b - a) 249 B = 2(b - a)
293 Solve for t, only if it fits between 0 < t < 1 250 Solve for t, only if it fits between 0 < t < 1
294 */ 251 */
295 int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValue[1]) 252 int SkFindQuadExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar tValue[1])
296 { 253 {
297 /* At + B == 0 254 /* At + B == 0
298 t = -B / A 255 t = -B / A
299 */ 256 */
300 #ifdef SK_SCALAR_IS_FIXED
301 return is_not_monotonic(a, b, c) && valid_unit_divide(a - b, a - b - b + c, tValue);
302 #else
303 return valid_unit_divide(a - b, a - b - b + c, tValue); 257 return valid_unit_divide(a - b, a - b - b + c, tValue);
304 #endif
305 } 258 }
306 259
307 static inline void flatten_double_quad_extrema(SkScalar coords[14]) 260 static inline void flatten_double_quad_extrema(SkScalar coords[14])
308 { 261 {
309 coords[2] = coords[6] = coords[4]; 262 coords[2] = coords[6] = coords[4];
310 } 263 }
311 264
312 /* Returns 0 for 1 quad, and 1 for two quads, either way the answer is 265 /* Returns 0 for 1 quad, and 1 for two quads, either way the answer is
313 stored in dst[]. Guarantees that the 1/2 quads will be monotonic. 266 stored in dst[]. Guarantees that the 1/2 quads will be monotonic.
314 */ 267 */
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 // 347 //
395 // t = - (Ax Bx + Ay By) / (Bx ^ 2 + By ^ 2) 348 // t = - (Ax Bx + Ay By) / (Bx ^ 2 + By ^ 2)
396 // 349 //
397 float SkFindQuadMaxCurvature(const SkPoint src[3]) { 350 float SkFindQuadMaxCurvature(const SkPoint src[3]) {
398 SkScalar Ax = src[1].fX - src[0].fX; 351 SkScalar Ax = src[1].fX - src[0].fX;
399 SkScalar Ay = src[1].fY - src[0].fY; 352 SkScalar Ay = src[1].fY - src[0].fY;
400 SkScalar Bx = src[0].fX - src[1].fX - src[1].fX + src[2].fX; 353 SkScalar Bx = src[0].fX - src[1].fX - src[1].fX + src[2].fX;
401 SkScalar By = src[0].fY - src[1].fY - src[1].fY + src[2].fY; 354 SkScalar By = src[0].fY - src[1].fY - src[1].fY + src[2].fY;
402 SkScalar t = 0; // 0 means don't chop 355 SkScalar t = 0; // 0 means don't chop
403 356
404 #ifdef SK_SCALAR_IS_FLOAT
405 (void)valid_unit_divide(-(Ax * Bx + Ay * By), Bx * Bx + By * By, &t); 357 (void)valid_unit_divide(-(Ax * Bx + Ay * By), Bx * Bx + By * By, &t);
406 #else
407 // !!! should I use SkFloat here? seems like it
408 Sk64 numer, denom, tmp;
409
410 numer.setMul(Ax, -Bx);
411 tmp.setMul(Ay, -By);
412 numer.add(tmp);
413
414 if (numer.isPos()) // do nothing if numer <= 0
415 {
416 denom.setMul(Bx, Bx);
417 tmp.setMul(By, By);
418 denom.add(tmp);
419 SkASSERT(!denom.isNeg());
420 if (numer < denom)
421 {
422 t = numer.getFixedDiv(denom);
423 SkASSERT(t >= 0 && t <= SK_Fixed1); // assert that we're numeric ally stable (ha!)
424 if ((unsigned)t >= SK_Fixed1) // runtime check for numeric al stability
425 t = 0; // ignore the chop
426 }
427 }
428 #endif
429 return t; 358 return t;
430 } 359 }
431 360
432 int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5]) 361 int SkChopQuadAtMaxCurvature(const SkPoint src[3], SkPoint dst[5])
433 { 362 {
434 SkScalar t = SkFindQuadMaxCurvature(src); 363 SkScalar t = SkFindQuadMaxCurvature(src);
435 if (t == 0) { 364 if (t == 0) {
436 memcpy(dst, src, 3 * sizeof(SkPoint)); 365 memcpy(dst, src, 3 * sizeof(SkPoint));
437 return 1; 366 return 1;
438 } else { 367 } else {
439 SkChopQuadAt(src, dst, t); 368 SkChopQuadAt(src, dst, t);
440 return 2; 369 return 2;
441 } 370 }
442 } 371 }
443 372
444 #ifdef SK_SCALAR_IS_FLOAT 373 #define SK_ScalarTwoThirds (0.666666666f)
445 #define SK_ScalarTwoThirds (0.666666666f)
446 #else
447 #define SK_ScalarTwoThirds ((SkFixed)(43691))
448 #endif
449 374
450 void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]) { 375 void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]) {
451 const SkScalar scale = SK_ScalarTwoThirds; 376 const SkScalar scale = SK_ScalarTwoThirds;
452 dst[0] = src[0]; 377 dst[0] = src[0];
453 dst[1].set(src[0].fX + SkScalarMul(src[1].fX - src[0].fX, scale), 378 dst[1].set(src[0].fX + SkScalarMul(src[1].fX - src[0].fX, scale),
454 src[0].fY + SkScalarMul(src[1].fY - src[0].fY, scale)); 379 src[0].fY + SkScalarMul(src[1].fY - src[0].fY, scale));
455 dst[2].set(src[2].fX + SkScalarMul(src[1].fX - src[2].fX, scale), 380 dst[2].set(src[2].fX + SkScalarMul(src[1].fX - src[2].fX, scale),
456 src[2].fY + SkScalarMul(src[1].fY - src[2].fY, scale)); 381 src[2].fY + SkScalarMul(src[1].fY - src[2].fY, scale));
457 dst[3] = src[2]; 382 dst[3] = src[2];
458 } 383 }
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 } 471 }
547 472
548 /** Cubic'(t) = At^2 + Bt + C, where 473 /** Cubic'(t) = At^2 + Bt + C, where
549 A = 3(-a + 3(b - c) + d) 474 A = 3(-a + 3(b - c) + d)
550 B = 6(a - 2b + c) 475 B = 6(a - 2b + c)
551 C = 3(b - a) 476 C = 3(b - a)
552 Solve for t, keeping only those that fit betwee 0 < t < 1 477 Solve for t, keeping only those that fit betwee 0 < t < 1
553 */ 478 */
554 int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar tValues[2]) 479 int SkFindCubicExtrema(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar tValues[2])
555 { 480 {
556 #ifdef SK_SCALAR_IS_FIXED
557 if (!is_not_monotonic(a, b, c, d))
558 return 0;
559 #endif
560
561 // we divide A,B,C by 3 to simplify 481 // we divide A,B,C by 3 to simplify
562 SkScalar A = d - a + 3*(b - c); 482 SkScalar A = d - a + 3*(b - c);
563 SkScalar B = 2*(a - b - b + c); 483 SkScalar B = 2*(a - b - b + c);
564 SkScalar C = b - a; 484 SkScalar C = b - a;
565 485
566 return SkFindUnitQuadRoots(A, B, C, tValues); 486 return SkFindUnitQuadRoots(A, B, C, tValues);
567 } 487 }
568 488
569 static void interp_cubic_coords(const SkScalar* src, SkScalar* dst, SkScalar t) 489 static void interp_cubic_coords(const SkScalar* src, SkScalar* dst, SkScalar t)
570 { 490 {
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 (BxCy - ByCx)t^2 + (AxCy - AyCx)t + AxBy - AyBx == 0 660 (BxCy - ByCx)t^2 + (AxCy - AyCx)t + AxBy - AyBx == 0
741 */ 661 */
742 int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[]) 662 int SkFindCubicInflections(const SkPoint src[4], SkScalar tValues[])
743 { 663 {
744 SkScalar Ax = src[1].fX - src[0].fX; 664 SkScalar Ax = src[1].fX - src[0].fX;
745 SkScalar Ay = src[1].fY - src[0].fY; 665 SkScalar Ay = src[1].fY - src[0].fY;
746 SkScalar Bx = src[2].fX - 2 * src[1].fX + src[0].fX; 666 SkScalar Bx = src[2].fX - 2 * src[1].fX + src[0].fX;
747 SkScalar By = src[2].fY - 2 * src[1].fY + src[0].fY; 667 SkScalar By = src[2].fY - 2 * src[1].fY + src[0].fY;
748 SkScalar Cx = src[3].fX + 3 * (src[1].fX - src[2].fX) - src[0].fX; 668 SkScalar Cx = src[3].fX + 3 * (src[1].fX - src[2].fX) - src[0].fX;
749 SkScalar Cy = src[3].fY + 3 * (src[1].fY - src[2].fY) - src[0].fY; 669 SkScalar Cy = src[3].fY + 3 * (src[1].fY - src[2].fY) - src[0].fY;
750 int count;
751 670
752 #ifdef SK_SCALAR_IS_FLOAT 671 return SkFindUnitQuadRoots(Bx*Cy - By*Cx, Ax*Cy - Ay*Cx, Ax*By - Ay*Bx, tVal ues);
753 count = SkFindUnitQuadRoots(Bx*Cy - By*Cx, Ax*Cy - Ay*Cx, Ax*By - Ay*Bx, tVa lues);
754 #else
755 Sk64 A, B, C, tmp;
756
757 A.setMul(Bx, Cy);
758 tmp.setMul(By, Cx);
759 A.sub(tmp);
760
761 B.setMul(Ax, Cy);
762 tmp.setMul(Ay, Cx);
763 B.sub(tmp);
764
765 C.setMul(Ax, By);
766 tmp.setMul(Ay, Bx);
767 C.sub(tmp);
768
769 count = Sk64FindFixedQuadRoots(A, B, C, tValues);
770 #endif
771
772 return count;
773 } 672 }
774 673
775 int SkChopCubicAtInflections(const SkPoint src[], SkPoint dst[10]) 674 int SkChopCubicAtInflections(const SkPoint src[], SkPoint dst[10])
776 { 675 {
777 SkScalar tValues[2]; 676 SkScalar tValues[2];
778 int count = SkFindCubicInflections(src, tValues); 677 int count = SkFindCubicInflections(src, tValues);
779 678
780 if (dst) 679 if (dst)
781 { 680 {
782 if (count == 0) 681 if (count == 0)
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 memcpy(dst, data[i].fData, data[i].fCount * sizeof(dst[0])); 783 memcpy(dst, data[i].fData, data[i].fCount * sizeof(dst[0]));
885 int count = collaps_duplicates(dst, data[i].fCount); 784 int count = collaps_duplicates(dst, data[i].fCount);
886 SkASSERT(data[i].fCollapsedCount == count); 785 SkASSERT(data[i].fCollapsedCount == count);
887 for (int j = 1; j < count; ++j) { 786 for (int j = 1; j < count; ++j) {
888 SkASSERT(dst[j-1] < dst[j]); 787 SkASSERT(dst[j-1] < dst[j]);
889 } 788 }
890 } 789 }
891 } 790 }
892 #endif 791 #endif
893 792
894 #if defined _WIN32 && _MSC_VER >= 1300 && defined SK_SCALAR_IS_FIXED // disable warning : unreachable code if building fixed point for windows desktop
895 #pragma warning ( disable : 4702 )
896 #endif
897
898 static SkScalar SkScalarCubeRoot(SkScalar x) { 793 static SkScalar SkScalarCubeRoot(SkScalar x) {
899 return sk_float_pow(x, 0.3333333f); 794 return sk_float_pow(x, 0.3333333f);
900 } 795 }
901 796
902 /* Solve coeff(t) == 0, returning the number of roots that 797 /* Solve coeff(t) == 0, returning the number of roots that
903 lie withing 0 < t < 1. 798 lie withing 0 < t < 1.
904 coeff[0]t^3 + coeff[1]t^2 + coeff[2]t + coeff[3] 799 coeff[0]t^3 + coeff[1]t^2 + coeff[2]t + coeff[3]
905 800
906 Eliminates repeated roots (so that all tValues are distinct, and are always 801 Eliminates repeated roots (so that all tValues are distinct, and are always
907 in increasing order. 802 in increasing order.
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 } 1523 }
1629 if (this->findYExtrema(&t)) { 1524 if (this->findYExtrema(&t)) {
1630 this->evalAt(t, &pts[count++]); 1525 this->evalAt(t, &pts[count++]);
1631 } 1526 }
1632 bounds->set(pts, count); 1527 bounds->set(pts, count);
1633 } 1528 }
1634 1529
1635 void SkConic::computeFastBounds(SkRect* bounds) const { 1530 void SkConic::computeFastBounds(SkRect* bounds) const {
1636 bounds->set(fPts, 3); 1531 bounds->set(fPts, 3);
1637 } 1532 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698