1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMatrix.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 109da0cea3a32e274ad8b40174a25e5f8c532fbd9bcaryclark@google.com// FIXME: needs to be in a header 119da0cea3a32e274ad8b40174a25e5f8c532fbd9bcaryclark@google.combool SkSetPoly3To3(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]); 129da0cea3a32e274ad8b40174a25e5f8c532fbd9bcaryclark@google.com 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void computeOuterProduct(SkScalar op[4], 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pts0[3], const SkPoint& ave0, 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pts1[3], const SkPoint& ave1) { 164516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com sk_bzero(op, 4 * sizeof(op[0])); 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 3; i++) { 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x0 = pts0[i].fX - ave0.fX; 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar y0 = pts0[i].fY - ave0.fY; 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x1 = pts1[i].fX - ave1.fX; 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar y1 = pts1[i].fY - ave1.fY; 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op[0] += SkScalarMul(x0, x1); 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op[1] += SkScalarMul(x0, y1); 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op[2] += SkScalarMul(y0, x1); 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op[3] += SkScalarMul(y0, y1); 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkScalar dot(SkScalar ax, SkScalar ay, SkScalar bx, SkScalar by) { 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkScalarMul(ax, bx) + SkScalarMul(ay, by); 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkSetPoly3To3(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]) { 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint& srcAve = src[0]; 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint& dstAve = dst[0]; 36d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar srcOP[4], dstOP[4]; 38d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com computeOuterProduct(srcOP, src, srcAve, src, srcAve); 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com computeOuterProduct(dstOP, src, srcAve, dst, dstAve); 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar det = SkScalarMul(srcOP[0], srcOP[3]) - SkScalarMul(srcOP[1], srcOP[2]); 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need SkScalarNearlyZeroSquared for this (to match Chrome's fix) 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarNearlyZero(det)) { 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 48d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar invDet = SkScalarInvert(det); 50d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now compute invDet * [srcOP]T * [dstOP] 52d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // scale and transpose 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar srcOP0 = SkScalarMul( srcOP[3], invDet); 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar srcOP1 = SkScalarMul(-srcOP[1], invDet); 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar srcOP2 = SkScalarMul(-srcOP[2], invDet); 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar srcOP3 = SkScalarMul( srcOP[0], invDet); 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->reset(); 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setScaleX(dot(srcOP0, srcOP1, dstOP[0], dstOP[2])); 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setSkewX( dot(srcOP2, srcOP3, dstOP[0], dstOP[2])); 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setSkewY (dot(srcOP0, srcOP1, dstOP[1], dstOP[3])); 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setScaleY(dot(srcOP2, srcOP3, dstOP[1], dstOP[3])); 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setTranslateX(dstAve.fX - dot(srcAve.fX, srcAve.fY, 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->getScaleX(), matrix->getSkewX())); 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setTranslateY(dstAve.fY - dot(srcAve.fX, srcAve.fY, 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->getSkewY(), matrix->getScaleY())); 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 70