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 |