add (untested) tangent calc for conics
git-svn-id: http://skia.googlecode.com/svn/trunk@9048 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkGeometry.cpp b/src/core/SkGeometry.cpp
index b6b23bc..cb961b0 100644
--- a/src/core/SkGeometry.cpp
+++ b/src/core/SkGeometry.cpp
@@ -1483,13 +1483,53 @@
dst[2].set(src[2].fX * 1, src[2].fY * 1, 1);
}
-void SkConic::evalAt(SkScalar t, SkPoint* pt) const {
+/* Derivative of conic : just the numerator, as the denom has no P values
+ and can be ignored if we want to return a "normalized" tangent vector.
+
+ 2 (P2 t (1 + t (-1 + w)) - P0 (-1 + t) (t (-1 + w) - w) + P1 (1 - 2 t) w)
+
+ -- grouping by powers of t yields --
+
+ t^2 : (2 P0 - 2 P2 - 2 P0 w + 2 P2 w)
+ t^1 : (-2 P0 + 2 P2 + 4 P0 w - 4 P1 w)
+ t^0 : -2 P0 w + 2 P1 w
+
+ We can trivially divide everything by 2 to simplify
+*/
+static SkScalar conic_eval_tan(const SkScalar coord[], SkScalar w, SkScalar t) {
+ // At^2 + Bt + C == t * (t * A + B) + C
+
+ const SkScalar P0 = coord[0];
+ const SkScalar P1 = coord[2];
+ const SkScalar P2 = coord[4];
+ const SkScalar P20 = P2 - P0;
+ const SkScalar P10 = P1 - P0;
+ const SkScalar wP10 = w * P10;
+ // 2 P0 - 2 P2 - 2 P0 w + 2 P2 w
+ // 2 * (P0 - P2 - P0w + P2w)
+ // 2 * (invW * P0 - invW * P2
+ SkScalar A = P20 - w * P20;
+ // -2 P0 + 2 P2 + 4 P0 w - 4 P1 w
+ // 2 * (P2 - P0 + P0w - P1w)
+ // 2 * (w * (P0 - P1) + P2 - P0)
+ SkScalar B = P20 - wP10;
+ // -2 P0 w + 2 P1 w
+ SkScalar C = wP10;
+
+ return t * (t * A + B) + C;
+}
+
+void SkConic::evalAt(SkScalar t, SkPoint* pt, SkVector* tangent) const {
SkASSERT(t >= 0 && t <= SK_Scalar1);
if (pt) {
pt->set(rat_eval_pos(&fPts[0].fX, fW, t),
rat_eval_pos(&fPts[0].fY, fW, t));
}
+ if (tangent) {
+ tangent->set(conic_eval_tan(&fPts[0].fX, fW, t),
+ conic_eval_tan(&fPts[0].fY, fW, t));
+ }
}
void SkConic::chopAt(SkScalar t, SkConic dst[2]) const {
@@ -1654,3 +1694,4 @@
void SkConic::computeFastBounds(SkRect* bounds) const {
bounds->set(fPts, 3);
}
+