Home | History | Annotate | Download | only in utils
      1 #include "SkCubicInterval.h"
      2 
      3 static SkScalar eval_cubic(SkScalar c1, SkScalar c2, SkScalar c3,
      4                            SkScalar t) {
      5     return SkScalarMul(SkScalarMul(SkScalarMul(c3, t) + c2, t) + c1, t);
      6 }
      7 
      8 static SkScalar find_cubic_t(SkScalar c1, SkScalar c2, SkScalar c3,
      9                              SkScalar targetX) {
     10     SkScalar minT = 0;
     11     SkScalar maxT = SK_Scalar1;
     12     SkScalar t;
     13 
     14     for (;;) {
     15         t = SkScalarAve(minT, maxT);
     16         SkScalar x = eval_cubic(c1, c2, c3, t);
     17         if (SkScalarNearlyZero(x - targetX)) {
     18             break;
     19         }
     20         // subdivide the range and try again
     21         if (x < targetX) {
     22             minT = t;
     23         } else {
     24             maxT = t;
     25         }
     26     }
     27     return t;
     28 }
     29 
     30 /*
     31     a(1-t)^3 + 3bt(1-t)^2 + 3ct^2(1-t) + dt^3
     32     a: [0, 0]
     33     d: [1, 1]
     34 
     35     3bt - 6bt^2 + 3bt^3 + 3ct^2 - 3ct^3 + t^3
     36     C1 = t^1: 3b
     37     C2 = t^2: 3c - 6b
     38     C3 = t^3: 3b - 3c + 1
     39 
     40     ((C3*t + C2)*t + C1)*t
     41  */
     42 SkScalar SkEvalCubicInterval(SkScalar x1, SkScalar y1,
     43                              SkScalar x2, SkScalar y2,
     44                              SkScalar unitX) {
     45     x1 = SkScalarPin(x1, 0, SK_Scalar1);
     46     x2 = SkScalarPin(x2, 0, SK_Scalar1);
     47     unitX = SkScalarPin(unitX, 0, SK_Scalar1);
     48 
     49     // First compute our coefficients in X
     50     x1 *= 3;
     51     x2 *= 3;
     52 
     53     // now search for t given unitX
     54     SkScalar t = find_cubic_t(x1, x2 - 2*x1, x1 - x2 + SK_Scalar1, unitX);
     55 
     56     // now evaluate the cubic in Y
     57     y1 *= 3;
     58     y2 *= 3;
     59     return eval_cubic(y1, y2 - 2*y1, y1 - y2 + SK_Scalar1, t);
     60 }
     61 
     62