| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "GrPathUtils.h" | 8 #include "GrPathUtils.h" |
| 9 | 9 |
| 10 #include "GrTypes.h" | 10 #include "GrTypes.h" |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 540 | 540 |
| 541 for (int i = 0; i < count; ++i) { | 541 for (int i = 0; i < count; ++i) { |
| 542 SkPoint* cubic = chopped + 3*i; | 542 SkPoint* cubic = chopped + 3*i; |
| 543 convert_noninflect_cubic_to_quads(cubic, tolSqd, constrainWithinTangents
, dir, quads); | 543 convert_noninflect_cubic_to_quads(cubic, tolSqd, constrainWithinTangents
, dir, quads); |
| 544 } | 544 } |
| 545 | 545 |
| 546 } | 546 } |
| 547 | 547 |
| 548 //////////////////////////////////////////////////////////////////////////////// | 548 //////////////////////////////////////////////////////////////////////////////// |
| 549 | 549 |
| 550 enum CubicType { | |
| 551 kSerpentine_CubicType, | |
| 552 kCusp_CubicType, | |
| 553 kLoop_CubicType, | |
| 554 kQuadratic_CubicType, | |
| 555 kLine_CubicType, | |
| 556 kPoint_CubicType | |
| 557 }; | |
| 558 | |
| 559 // discr(I) = d0^2 * (3*d1^2 - 4*d0*d2) | |
| 560 // Classification: | |
| 561 // discr(I) > 0 Serpentine | |
| 562 // discr(I) = 0 Cusp | |
| 563 // discr(I) < 0 Loop | |
| 564 // d0 = d1 = 0 Quadratic | |
| 565 // d0 = d1 = d2 = 0 Line | |
| 566 // p0 = p1 = p2 = p3 Point | |
| 567 static CubicType classify_cubic(const SkPoint p[4], const SkScalar d[3]) { | |
| 568 if (p[0] == p[1] && p[0] == p[2] && p[0] == p[3]) { | |
| 569 return kPoint_CubicType; | |
| 570 } | |
| 571 const SkScalar discr = d[0] * d[0] * (3.f * d[1] * d[1] - 4.f * d[0] * d[2])
; | |
| 572 if (discr > SK_ScalarNearlyZero) { | |
| 573 return kSerpentine_CubicType; | |
| 574 } else if (discr < -SK_ScalarNearlyZero) { | |
| 575 return kLoop_CubicType; | |
| 576 } else { | |
| 577 if (0.f == d[0] && 0.f == d[1]) { | |
| 578 return (0.f == d[2] ? kLine_CubicType : kQuadratic_CubicType); | |
| 579 } else { | |
| 580 return kCusp_CubicType; | |
| 581 } | |
| 582 } | |
| 583 } | |
| 584 | |
| 585 // Assumes the third component of points is 1. | |
| 586 // Calcs p0 . (p1 x p2) | |
| 587 static SkScalar calc_dot_cross_cubic(const SkPoint& p0, const SkPoint& p1, const
SkPoint& p2) { | |
| 588 const SkScalar xComp = p0.fX * (p1.fY - p2.fY); | |
| 589 const SkScalar yComp = p0.fY * (p2.fX - p1.fX); | |
| 590 const SkScalar wComp = p1.fX * p2.fY - p1.fY * p2.fX; | |
| 591 return (xComp + yComp + wComp); | |
| 592 } | |
| 593 | |
| 594 // Solves linear system to extract klm | 550 // Solves linear system to extract klm |
| 595 // P.K = k (similarly for l, m) | 551 // P.K = k (similarly for l, m) |
| 596 // Where P is matrix of control points | 552 // Where P is matrix of control points |
| 597 // K is coefficients for the line K | 553 // K is coefficients for the line K |
| 598 // k is vector of values of K evaluated at the control points | 554 // k is vector of values of K evaluated at the control points |
| 599 // Solving for K, thus K = P^(-1) . k | 555 // Solving for K, thus K = P^(-1) . k |
| 600 static void calc_cubic_klm(const SkPoint p[4], const SkScalar controlK[4], | 556 static void calc_cubic_klm(const SkPoint p[4], const SkScalar controlK[4], |
| 601 const SkScalar controlL[4], const SkScalar controlM[4
], | 557 const SkScalar controlL[4], const SkScalar controlM[4
], |
| 602 SkScalar k[3], SkScalar l[3], SkScalar m[3]) { | 558 SkScalar k[3], SkScalar l[3], SkScalar m[3]) { |
| 603 SkMatrix matrix; | 559 SkMatrix matrix; |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 // If d2 < 0 we need to flip the orientation of our curve | 684 // If d2 < 0 we need to flip the orientation of our curve |
| 729 // This is done by negating the k and l values | 685 // This is done by negating the k and l values |
| 730 if ( d[2] > 0) { | 686 if ( d[2] > 0) { |
| 731 for (int i = 0; i < 4; ++i) { | 687 for (int i = 0; i < 4; ++i) { |
| 732 k[i] = -k[i]; | 688 k[i] = -k[i]; |
| 733 l[i] = -l[i]; | 689 l[i] = -l[i]; |
| 734 } | 690 } |
| 735 } | 691 } |
| 736 } | 692 } |
| 737 | 693 |
| 738 // Calc coefficients of I(s,t) where roots of I are inflection points of curve | |
| 739 // I(s,t) = t*(3*d0*s^2 - 3*d1*s*t + d2*t^2) | |
| 740 // d0 = a1 - 2*a2+3*a3 | |
| 741 // d1 = -a2 + 3*a3 | |
| 742 // d2 = 3*a3 | |
| 743 // a1 = p0 . (p3 x p2) | |
| 744 // a2 = p1 . (p0 x p3) | |
| 745 // a3 = p2 . (p1 x p0) | |
| 746 // Places the values of d1, d2, d3 in array d passed in | |
| 747 static void calc_cubic_inflection_func(const SkPoint p[4], SkScalar d[3]) { | |
| 748 SkScalar a1 = calc_dot_cross_cubic(p[0], p[3], p[2]); | |
| 749 SkScalar a2 = calc_dot_cross_cubic(p[1], p[0], p[3]); | |
| 750 SkScalar a3 = calc_dot_cross_cubic(p[2], p[1], p[0]); | |
| 751 | |
| 752 // need to scale a's or values in later calculations will grow to high | |
| 753 SkScalar max = SkScalarAbs(a1); | |
| 754 max = SkMaxScalar(max, SkScalarAbs(a2)); | |
| 755 max = SkMaxScalar(max, SkScalarAbs(a3)); | |
| 756 max = 1.f/max; | |
| 757 a1 = a1 * max; | |
| 758 a2 = a2 * max; | |
| 759 a3 = a3 * max; | |
| 760 | |
| 761 d[2] = 3.f * a3; | |
| 762 d[1] = d[2] - a2; | |
| 763 d[0] = d[1] - a2 + a1; | |
| 764 } | |
| 765 | |
| 766 int GrPathUtils::chopCubicAtLoopIntersection(const SkPoint src[4], SkPoint dst[1
0], SkScalar klm[9], | 694 int GrPathUtils::chopCubicAtLoopIntersection(const SkPoint src[4], SkPoint dst[1
0], SkScalar klm[9], |
| 767 SkScalar klm_rev[3]) { | 695 SkScalar klm_rev[3]) { |
| 768 // Variable to store the two parametric values at the loop double point | 696 // Variable to store the two parametric values at the loop double point |
| 769 SkScalar smallS = 0.f; | 697 SkScalar smallS = 0.f; |
| 770 SkScalar largeS = 0.f; | 698 SkScalar largeS = 0.f; |
| 771 | 699 |
| 772 SkScalar d[3]; | 700 SkScalar d[3]; |
| 773 calc_cubic_inflection_func(src, d); | 701 SkCubicType cType = SkClassifyCubic(src, d); |
| 774 | |
| 775 CubicType cType = classify_cubic(src, d); | |
| 776 | 702 |
| 777 int chop_count = 0; | 703 int chop_count = 0; |
| 778 if (kLoop_CubicType == cType) { | 704 if (kLoop_SkCubicType == cType) { |
| 779 SkScalar tempSqrt = SkScalarSqrt(4.f * d[0] * d[2] - 3.f * d[1] * d[1]); | 705 SkScalar tempSqrt = SkScalarSqrt(4.f * d[0] * d[2] - 3.f * d[1] * d[1]); |
| 780 SkScalar ls = d[1] - tempSqrt; | 706 SkScalar ls = d[1] - tempSqrt; |
| 781 SkScalar lt = 2.f * d[0]; | 707 SkScalar lt = 2.f * d[0]; |
| 782 SkScalar ms = d[1] + tempSqrt; | 708 SkScalar ms = d[1] + tempSqrt; |
| 783 SkScalar mt = 2.f * d[0]; | 709 SkScalar mt = 2.f * d[0]; |
| 784 ls = ls / lt; | 710 ls = ls / lt; |
| 785 ms = ms / mt; | 711 ms = ms / mt; |
| 786 // need to have t values sorted since this is what is expected by SkChop
CubicAt | 712 // need to have t values sorted since this is what is expected by SkChop
CubicAt |
| 787 if (ls <= ms) { | 713 if (ls <= ms) { |
| 788 smallS = ls; | 714 smallS = ls; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 if (smallS < 0.f && largeS > 1.f) { | 753 if (smallS < 0.f && largeS > 1.f) { |
| 828 klm_rev[0] = -1.f; | 754 klm_rev[0] = -1.f; |
| 829 } else { | 755 } else { |
| 830 klm_rev[0] = 1.f; | 756 klm_rev[0] = 1.f; |
| 831 } | 757 } |
| 832 } | 758 } |
| 833 SkScalar controlK[4]; | 759 SkScalar controlK[4]; |
| 834 SkScalar controlL[4]; | 760 SkScalar controlL[4]; |
| 835 SkScalar controlM[4]; | 761 SkScalar controlM[4]; |
| 836 | 762 |
| 837 if (kSerpentine_CubicType == cType || (kCusp_CubicType == cType && 0.f !
= d[0])) { | 763 if (kSerpentine_SkCubicType == cType || (kCusp_SkCubicType == cType && 0
.f != d[0])) { |
| 838 set_serp_klm(d, controlK, controlL, controlM); | 764 set_serp_klm(d, controlK, controlL, controlM); |
| 839 } else if (kLoop_CubicType == cType) { | 765 } else if (kLoop_SkCubicType == cType) { |
| 840 set_loop_klm(d, controlK, controlL, controlM); | 766 set_loop_klm(d, controlK, controlL, controlM); |
| 841 } else if (kCusp_CubicType == cType) { | 767 } else if (kCusp_SkCubicType == cType) { |
| 842 SkASSERT(0.f == d[0]); | 768 SkASSERT(0.f == d[0]); |
| 843 set_cusp_klm(d, controlK, controlL, controlM); | 769 set_cusp_klm(d, controlK, controlL, controlM); |
| 844 } else if (kQuadratic_CubicType == cType) { | 770 } else if (kQuadratic_SkCubicType == cType) { |
| 845 set_quadratic_klm(d, controlK, controlL, controlM); | 771 set_quadratic_klm(d, controlK, controlL, controlM); |
| 846 } | 772 } |
| 847 | 773 |
| 848 calc_cubic_klm(src, controlK, controlL, controlM, klm, &klm[3], &klm[6])
; | 774 calc_cubic_klm(src, controlK, controlL, controlM, klm, &klm[3], &klm[6])
; |
| 849 } | 775 } |
| 850 return chop_count + 1; | 776 return chop_count + 1; |
| 851 } | 777 } |
| 852 | 778 |
| 853 void GrPathUtils::getCubicKLM(const SkPoint p[4], SkScalar klm[9]) { | 779 void GrPathUtils::getCubicKLM(const SkPoint p[4], SkScalar klm[9]) { |
| 854 SkScalar d[3]; | 780 SkScalar d[3]; |
| 855 calc_cubic_inflection_func(p, d); | 781 SkCubicType cType = SkClassifyCubic(p, d); |
| 856 | |
| 857 CubicType cType = classify_cubic(p, d); | |
| 858 | 782 |
| 859 SkScalar controlK[4]; | 783 SkScalar controlK[4]; |
| 860 SkScalar controlL[4]; | 784 SkScalar controlL[4]; |
| 861 SkScalar controlM[4]; | 785 SkScalar controlM[4]; |
| 862 | 786 |
| 863 if (kSerpentine_CubicType == cType || (kCusp_CubicType == cType && 0.f != d[
0])) { | 787 if (kSerpentine_SkCubicType == cType || (kCusp_SkCubicType == cType && 0.f !
= d[0])) { |
| 864 set_serp_klm(d, controlK, controlL, controlM); | 788 set_serp_klm(d, controlK, controlL, controlM); |
| 865 } else if (kLoop_CubicType == cType) { | 789 } else if (kLoop_SkCubicType == cType) { |
| 866 set_loop_klm(d, controlK, controlL, controlM); | 790 set_loop_klm(d, controlK, controlL, controlM); |
| 867 } else if (kCusp_CubicType == cType) { | 791 } else if (kCusp_SkCubicType == cType) { |
| 868 SkASSERT(0.f == d[0]); | 792 SkASSERT(0.f == d[0]); |
| 869 set_cusp_klm(d, controlK, controlL, controlM); | 793 set_cusp_klm(d, controlK, controlL, controlM); |
| 870 } else if (kQuadratic_CubicType == cType) { | 794 } else if (kQuadratic_SkCubicType == cType) { |
| 871 set_quadratic_klm(d, controlK, controlL, controlM); | 795 set_quadratic_klm(d, controlK, controlL, controlM); |
| 872 } | 796 } |
| 873 | 797 |
| 874 calc_cubic_klm(p, controlK, controlL, controlM, klm, &klm[3], &klm[6]); | 798 calc_cubic_klm(p, controlK, controlL, controlM, klm, &klm[3], &klm[6]); |
| 875 } | 799 } |
| OLD | NEW |