SkSetPoly3To3.cpp revision ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976e
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 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void computeOuterProduct(SkScalar op[4], 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pts0[3], const SkPoint& ave0, 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pts1[3], const SkPoint& ave1) { 134516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com sk_bzero(op, 4 * sizeof(op[0])); 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 3; i++) { 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x0 = pts0[i].fX - ave0.fX; 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar y0 = pts0[i].fY - ave0.fY; 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x1 = pts1[i].fX - ave1.fX; 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar y1 = pts1[i].fY - ave1.fY; 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op[0] += SkScalarMul(x0, x1); 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op[1] += SkScalarMul(x0, y1); 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op[2] += SkScalarMul(y0, x1); 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op[3] += SkScalarMul(y0, y1); 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkScalar dot(SkScalar ax, SkScalar ay, SkScalar bx, SkScalar by) { 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkScalarMul(ax, bx) + SkScalarMul(ay, by); 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkSetPoly3To3(SkMatrix* matrix, const SkPoint src[3], const SkPoint dst[3]) { 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint& srcAve = src[0]; 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint& dstAve = dst[0]; 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar srcOP[4], dstOP[4]; 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com computeOuterProduct(srcOP, src, srcAve, src, srcAve); 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com computeOuterProduct(dstOP, src, srcAve, dst, dstAve); 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar det = SkScalarMul(srcOP[0], srcOP[3]) - SkScalarMul(srcOP[1], srcOP[2]); 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need SkScalarNearlyZeroSquared for this (to match Chrome's fix) 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarNearlyZero(det)) { 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar invDet = SkScalarInvert(det); 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now compute invDet * [srcOP]T * [dstOP] 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // scale and transpose 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar srcOP0 = SkScalarMul( srcOP[3], invDet); 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar srcOP1 = SkScalarMul(-srcOP[1], invDet); 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar srcOP2 = SkScalarMul(-srcOP[2], invDet); 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar srcOP3 = SkScalarMul( srcOP[0], invDet); 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->reset(); 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setScaleX(dot(srcOP0, srcOP1, dstOP[0], dstOP[2])); 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setSkewX( dot(srcOP2, srcOP3, dstOP[0], dstOP[2])); 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setSkewY (dot(srcOP0, srcOP1, dstOP[1], dstOP[3])); 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setScaleY(dot(srcOP2, srcOP3, dstOP[1], dstOP[3])); 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setTranslateX(dstAve.fX - dot(srcAve.fX, srcAve.fY, 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->getScaleX(), matrix->getSkewX())); 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->setTranslateY(dstAve.fY - dot(srcAve.fX, srcAve.fY, 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->getSkewY(), matrix->getScaleY())); 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 68