Home | History | Annotate | Download | only in experimental
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "SkMatrix.h"
      9 #include "SkMalloc.h"
     10 
     11 // FIXME: needs to be in a header
     12 bool SkSetPoly3To3(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]);
     13 
     14 static void computeOuterProduct(SkScalar op[4],
     15                                 const SkPoint pts0[3], const SkPoint& ave0,
     16                                 const SkPoint pts1[3], const SkPoint& ave1) {
     17     sk_bzero(op, 4 * sizeof(op[0]));
     18     for (int i = 0; i < 3; i++) {
     19         SkScalar x0 = pts0[i].fX - ave0.fX;
     20         SkScalar y0 = pts0[i].fY - ave0.fY;
     21         SkScalar x1 = pts1[i].fX - ave1.fX;
     22         SkScalar y1 = pts1[i].fY - ave1.fY;
     23         op[0] += x0 * x1;
     24         op[1] += x0 * y1;
     25         op[2] += y0 * x1;
     26         op[3] += y0 * y1;
     27     }
     28 }
     29 
     30 static SkScalar dot(SkScalar ax, SkScalar ay, SkScalar bx, SkScalar by) {
     31     return ax * bx + ay * by;
     32 }
     33 
     34 bool SkSetPoly3To3(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]) {
     35     const SkPoint& srcAve = src[0];
     36     const SkPoint& dstAve = dst[0];
     37 
     38     SkScalar srcOP[4], dstOP[4];
     39 
     40     computeOuterProduct(srcOP, src, srcAve, src, srcAve);
     41     computeOuterProduct(dstOP, src, srcAve, dst, dstAve);
     42 
     43     SkScalar det = srcOP[0] * srcOP[3] - srcOP[1] * srcOP[2];
     44 
     45     // need SkScalarNearlyZeroSquared for this (to match Chrome's fix)
     46     if (SkScalarNearlyZero(det)) {
     47         return false;
     48     }
     49 
     50     SkScalar invDet = SkScalarInvert(det);
     51 
     52     // now compute invDet * [srcOP]T * [dstOP]
     53 
     54     // scale and transpose
     55     const SkScalar srcOP0 =  srcOP[3] * invDet;
     56     const SkScalar srcOP1 = -srcOP[1] * invDet;
     57     const SkScalar srcOP2 = -srcOP[2] * invDet;
     58     const SkScalar srcOP3 =  srcOP[0] * invDet;
     59 
     60     matrix->reset();
     61     matrix->setScaleX(dot(srcOP0, srcOP1, dstOP[0], dstOP[2]));
     62     matrix->setSkewX( dot(srcOP2, srcOP3, dstOP[0], dstOP[2]));
     63     matrix->setSkewY (dot(srcOP0, srcOP1, dstOP[1], dstOP[3]));
     64     matrix->setScaleY(dot(srcOP2, srcOP3, dstOP[1], dstOP[3]));
     65     matrix->setTranslateX(dstAve.fX - dot(srcAve.fX, srcAve.fY,
     66                                     matrix->getScaleX(), matrix->getSkewX()));
     67     matrix->setTranslateY(dstAve.fY - dot(srcAve.fX, srcAve.fY,
     68                                     matrix->getSkewY(), matrix->getScaleY()));
     69     return true;
     70 }
     71