blob: 4a6cf7d7367bf4b77ddb0e4f31d02500ed480933 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkMatrix.h"
9
10static void computeOuterProduct(SkScalar op[4],
11 const SkPoint pts0[3], const SkPoint& ave0,
12 const SkPoint pts1[3], const SkPoint& ave1) {
reed@android.com4516f472009-06-29 16:25:36 +000013 sk_bzero(op, 4 * sizeof(op[0]));
reed@android.com8a1c16f2008-12-17 15:59:43 +000014 for (int i = 0; i < 3; i++) {
15 SkScalar x0 = pts0[i].fX - ave0.fX;
16 SkScalar y0 = pts0[i].fY - ave0.fY;
17 SkScalar x1 = pts1[i].fX - ave1.fX;
18 SkScalar y1 = pts1[i].fY - ave1.fY;
19 op[0] += SkScalarMul(x0, x1);
20 op[1] += SkScalarMul(x0, y1);
21 op[2] += SkScalarMul(y0, x1);
22 op[3] += SkScalarMul(y0, y1);
23 }
24}
25
26static SkScalar dot(SkScalar ax, SkScalar ay, SkScalar bx, SkScalar by) {
27 return SkScalarMul(ax, bx) + SkScalarMul(ay, by);
28}
29
30bool SkSetPoly3To3(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]) {
31 const SkPoint& srcAve = src[0];
32 const SkPoint& dstAve = dst[0];
33
34 SkScalar srcOP[4], dstOP[4];
35
36 computeOuterProduct(srcOP, src, srcAve, src, srcAve);
37 computeOuterProduct(dstOP, src, srcAve, dst, dstAve);
38
39 SkScalar det = SkScalarMul(srcOP[0], srcOP[3]) - SkScalarMul(srcOP[1], srcOP[2]);
40
41 // need SkScalarNearlyZeroSquared for this (to match Chrome's fix)
42 if (SkScalarNearlyZero(det)) {
43 return false;
44 }
45
46 SkScalar invDet = SkScalarInvert(det);
47
48 // now compute invDet * [srcOP]T * [dstOP]
49
50 // scale and transpose
51 const SkScalar srcOP0 = SkScalarMul( srcOP[3], invDet);
52 const SkScalar srcOP1 = SkScalarMul(-srcOP[1], invDet);
53 const SkScalar srcOP2 = SkScalarMul(-srcOP[2], invDet);
54 const SkScalar srcOP3 = SkScalarMul( srcOP[0], invDet);
55
56 matrix->reset();
57 matrix->setScaleX(dot(srcOP0, srcOP1, dstOP[0], dstOP[2]));
58 matrix->setSkewX( dot(srcOP2, srcOP3, dstOP[0], dstOP[2]));
59 matrix->setSkewY (dot(srcOP0, srcOP1, dstOP[1], dstOP[3]));
60 matrix->setScaleY(dot(srcOP2, srcOP3, dstOP[1], dstOP[3]));
61 matrix->setTranslateX(dstAve.fX - dot(srcAve.fX, srcAve.fY,
62 matrix->getScaleX(), matrix->getSkewX()));
63 matrix->setTranslateY(dstAve.fY - dot(srcAve.fX, srcAve.fY,
64 matrix->getSkewY(), matrix->getScaleY()));
65 return true;
66}
67