1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMatrix.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFloatBits.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkString.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12ada3635c8e83739f45cd52459d3e052783d1a40emtklein#include <stddef.h> 13ada3635c8e83739f45cd52459d3e052783d1a40emtklein 140b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// In a few places, we performed the following 150b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// a * b + c * d + e 160b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// as 170b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// a * b + (c * d + e) 180b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// 190b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// sdot and scross are indended to capture these compound operations into a 200b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// function, with an eye toward considering upscaling the intermediates to 210b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// doubles for more precision (as we do in concat and invert). 220b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// 230b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// However, these few lines that performed the last add before the "dot", cause 240b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// tiny image differences, so we guard that change until we see the impact on 250b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// chrome's layouttests. 260b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org// 270b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#define SK_LEGACY_MATRIX_MATH_ORDER 28ab7ac026d25fcb6e10c042e933f03e5f806c9097reed@android.com 298f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.comstatic inline float SkDoubleToFloat(double x) { 308f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com return static_cast<float>(x); 318f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com} 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* [scale-x skew-x trans-x] [X] [X'] 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com [skew-y scale-y trans-y] * [Y] = [Y'] 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com [persp-0 persp-1 persp-2] [1] [1 ] 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::reset() { 390b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1; 40fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com fMat[kMSkewX] = fMat[kMSkewY] = 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransX] = fMat[kMTransY] = 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMPersp0] = fMat[kMPersp1] = 0; 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask); 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this guy aligns with the masks, so we can compute a mask from a varaible 0/1 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comenum { 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kTranslate_Shift, 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kScale_Shift, 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kAffine_Shift, 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kPerspective_Shift, 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kRectStaysRect_Shift 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 568f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.comstatic const int32_t kScalar1Int = 0x3f800000; 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 58dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.comuint8_t SkMatrix::computePerspectiveTypeMask() const { 596fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // Benchmarking suggests that replacing this set of SkScalarAs2sCompliment 606fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // is a win, but replacing those below is not. We don't yet understand 616fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // that result. 620b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) { 63fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // If this is a perspective transform, we return true for all other 6419263b1e67b31590f9ecb50a1c5bcb6b331c8ef7bsalomon@google.com // transform flags - this does not disable any optimizations, respects 65fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // the rule that the type mask must be conservative, and speeds up 666fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // type mask computation. 676fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org return SkToU8(kORableMasks); 68dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com } 69dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com 706fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org return SkToU8(kOnlyPerspectiveValid_Mask | kUnknown_Mask); 71dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com} 72dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comuint8_t SkMatrix::computeTypeMask() const { 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned mask = 0; 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 760b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) { 776fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // Once it is determined that that this is a perspective transform, 786fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // all other flags are moot as far as optimizations are concerned. 796fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org return SkToU8(kORableMasks); 80ac3852571e4079e7dee8fb576e31048d596c8c17tomhudson@google.com } 81ac3852571e4079e7dee8fb576e31048d596c8c17tomhudson@google.com 82ac3852571e4079e7dee8fb576e31048d596c8c17tomhudson@google.com if (fMat[kMTransX] != 0 || fMat[kMTransY] != 0) { 83ac3852571e4079e7dee8fb576e31048d596c8c17tomhudson@google.com mask |= kTranslate_Mask; 84ac3852571e4079e7dee8fb576e31048d596c8c17tomhudson@google.com } 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int m00 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleX]); 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int m01 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewX]); 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int m10 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewY]); 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int m11 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleY]); 90ac3852571e4079e7dee8fb576e31048d596c8c17tomhudson@google.com 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (m01 | m10) { 926fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // The skew components may be scale-inducing, unless we are dealing 936fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // with a pure rotation. Testing for a pure rotation is expensive, 946fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // so we opt for being conservative by always setting the scale bit. 956fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // along with affine. 966fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // By doing this, we are also ensuring that matrices have the same 976fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // type masks as their inverses. 986fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org mask |= kAffine_Mask | kScale_Mask; 996fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org 1006fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // For rectStaysRect, in the affine case, we only need check that 1016fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // the primary diagonal is all zeros and that the secondary diagonal 1026fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // is all non-zero. 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // map non-zero to 1 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m01 = m01 != 0; 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m10 = m10 != 0; 107ac3852571e4079e7dee8fb576e31048d596c8c17tomhudson@google.com 1086fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org int dp0 = 0 == (m00 | m11) ; // true if both are 0 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ds1 = m01 & m10; // true if both are 1 110ac3852571e4079e7dee8fb576e31048d596c8c17tomhudson@google.com 1116fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org mask |= (dp0 & ds1) << kRectStaysRect_Shift; 1126fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org } else { 1136fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // Only test for scale explicitly if not affine, since affine sets the 1146fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // scale bit. 1156fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org if ((m00 - kScalar1Int) | (m11 - kScalar1Int)) { 1166fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org mask |= kScale_Mask; 1176fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org } 1186fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org 119fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com // Not affine, therefore we already know secondary diagonal is 1206fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // all zeros, so we just need to check that primary diagonal is 1216fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // all non-zero. 1226fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org 1236fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // map non-zero to 1 1246fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org m00 = m00 != 0; 1256fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org m11 = m11 != 0; 1266fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org 1276fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org // record if the (p)rimary diagonal is all non-zero 1286fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org mask |= (m00 & m11) << kRectStaysRect_Shift; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkToU8(mask); 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1363fb5187647397e056843c1f41a508992be22175dreed@google.combool operator==(const SkMatrix& a, const SkMatrix& b) { 1373fb5187647397e056843c1f41a508992be22175dreed@google.com const SkScalar* SK_RESTRICT ma = a.fMat; 1383fb5187647397e056843c1f41a508992be22175dreed@google.com const SkScalar* SK_RESTRICT mb = b.fMat; 1393fb5187647397e056843c1f41a508992be22175dreed@google.com 1403fb5187647397e056843c1f41a508992be22175dreed@google.com return ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] && 1413fb5187647397e056843c1f41a508992be22175dreed@google.com ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] && 1423fb5187647397e056843c1f41a508992be22175dreed@google.com ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8]; 1433fb5187647397e056843c1f41a508992be22175dreed@google.com} 1443fb5187647397e056843c1f41a508992be22175dreed@google.com 1453fb5187647397e056843c1f41a508992be22175dreed@google.com/////////////////////////////////////////////////////////////////////////////// 1463fb5187647397e056843c1f41a508992be22175dreed@google.com 1474dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org// helper function to determine if upper-left 2x2 of matrix is degenerate 14816d53aac9c78635b25d930f1c20d677e8fdd29c3skia.committer@gmail.comstatic inline bool is_degenerate_2x2(SkScalar scaleX, SkScalar skewX, 1494dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org SkScalar skewY, SkScalar scaleY) { 1504dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org SkScalar perp_dot = scaleX*scaleY - skewX*skewY; 1514dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org return SkScalarNearlyZero(perp_dot, SK_ScalarNearlyZero*SK_ScalarNearlyZero); 1524dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org} 1534dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org 1544dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org/////////////////////////////////////////////////////////////////////////////// 1554dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org 15646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.combool SkMatrix::isSimilarity(SkScalar tol) const { 15746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com // if identity or translate matrix 15846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com TypeMask mask = this->getType(); 15946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com if (mask <= kTranslate_Mask) { 16046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com return true; 16146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com } 16246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com if (mask & kPerspective_Mask) { 16346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com return false; 16446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com } 16546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 16646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com SkScalar mx = fMat[kMScaleX]; 16746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com SkScalar my = fMat[kMScaleY]; 16846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com // if no skew, can just compare scale factors 16946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com if (!(mask & kAffine_Mask)) { 17046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com return !SkScalarNearlyZero(mx) && SkScalarNearlyEqual(SkScalarAbs(mx), SkScalarAbs(my)); 17146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com } 17246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com SkScalar sx = fMat[kMSkewX]; 17346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com SkScalar sy = fMat[kMSkewY]; 17446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 1754dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org if (is_degenerate_2x2(mx, sx, sy, my)) { 17646d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com return false; 17746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com } 17846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 17946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com // it has scales and skews, but it could also be rotation, check it out. 18046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com SkVector vec[2]; 18146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com vec[0].set(mx, sx); 18246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com vec[1].set(sy, my); 18346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 18446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)) && 18546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com SkScalarNearlyEqual(vec[0].lengthSqd(), vec[1].lengthSqd(), 186df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com SkScalarSquare(tol)); 187df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com} 188df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com 189df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.combool SkMatrix::preservesRightAngles(SkScalar tol) const { 190df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com TypeMask mask = this->getType(); 19107d3a6575b86845ded0d4bd785aec8f4c2cc99dcskia.committer@gmail.com 192df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com if (mask <= (SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)) { 193df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com // identity, translate and/or scale 194df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com return true; 195df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com } 196df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com if (mask & kPerspective_Mask) { 197df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com return false; 198df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com } 199df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com 200df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com SkASSERT(mask & kAffine_Mask); 201df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com 202df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com SkScalar mx = fMat[kMScaleX]; 203df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com SkScalar my = fMat[kMScaleY]; 204df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com SkScalar sx = fMat[kMSkewX]; 205df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com SkScalar sy = fMat[kMSkewY]; 206df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com 2074dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org if (is_degenerate_2x2(mx, sx, sy, my)) { 208df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com return false; 209df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com } 210df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com 211df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com // it has scales and skews, but it could also be rotation, check it out. 212df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com SkVector vec[2]; 213df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com vec[0].set(mx, sx); 214df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com vec[1].set(sy, my); 215df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com 216df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)) && 217df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com SkScalarNearlyEqual(vec[0].lengthSqd(), vec[1].lengthSqd(), 218df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com SkScalarSquare(tol)); 21946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com} 22046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 22146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com/////////////////////////////////////////////////////////////////////////////// 22246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 2230b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.orgstatic inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d) { 2240b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org return a * b + c * d; 2250b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org} 2260b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org 2270b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.orgstatic inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d, 2280b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar e, SkScalar f) { 2290b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org return a * b + c * d + e * f; 2300b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org} 2310b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org 2320b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.orgstatic inline SkScalar scross(SkScalar a, SkScalar b, SkScalar c, SkScalar d) { 2330b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org return a * b - c * d; 2340b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org} 2350b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::setTranslate(SkScalar dx, SkScalar dy) { 237c0784dbd408596aff13a5d97448f7a9e5d3cf7d9reed@google.com if (dx || dy) { 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransX] = dx; 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransY] = dy; 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2410b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMScaleX] = fMat[kMScaleY] = fMat[kMPersp2] = 1; 242fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com fMat[kMSkewX] = fMat[kMSkewY] = 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMPersp0] = fMat[kMPersp1] = 0; 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask); 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->reset(); 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 25192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::preTranslate(SkScalar dx, SkScalar dy) { 25292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org if (!dx && !dy) { 25392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return; 25492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org } 25592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org 2568d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (this->hasPerspective()) { 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setTranslate(dx, dy); 25992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->preConcat(m); 26092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org } else { 2610b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy); 2620b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy); 263dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::postTranslate(SkScalar dx, SkScalar dy) { 26892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org if (!dx && !dy) { 26992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return; 27092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org } 27192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org 2728d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (this->hasPerspective()) { 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setTranslate(dx, dy); 27592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->postConcat(m); 27692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org } else { 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransX] += dx; 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransY] += dy; 279dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 2860b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org if (1 == sx && 1 == sy) { 287f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com this->reset(); 288f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com } else { 289f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com fMat[kMScaleX] = sx; 290f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com fMat[kMScaleY] = sy; 2910b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMTransX] = px - sx * px; 2920b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMTransY] = py - sy * py; 2930b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMPersp2] = 1; 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 295fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com fMat[kMSkewX] = fMat[kMSkewY] = 296f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com fMat[kMPersp0] = fMat[kMPersp1] = 0; 297fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 298f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com this->setTypeMask(kScale_Mask | kTranslate_Mask | kRectStaysRect_Mask); 299f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com } 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::setScale(SkScalar sx, SkScalar sy) { 3030b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org if (1 == sx && 1 == sy) { 304f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com this->reset(); 305f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com } else { 306f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com fMat[kMScaleX] = sx; 307f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com fMat[kMScaleY] = sy; 3080b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMPersp2] = 1; 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 310f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com fMat[kMTransX] = fMat[kMTransY] = 311fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com fMat[kMSkewX] = fMat[kMSkewY] = 312f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com fMat[kMPersp0] = fMat[kMPersp1] = 0; 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 314f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com this->setTypeMask(kScale_Mask | kRectStaysRect_Mask); 315f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com } 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3185c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.combool SkMatrix::setIDiv(int divx, int divy) { 3195c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com if (!divx || !divy) { 3205c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com return false; 3215c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com } 3220b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org this->setScale(SkScalarInvert(divx), SkScalarInvert(divy)); 3235c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com return true; 3245c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com} 3255c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com 32692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 32792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org if (1 == sx && 1 == sy) { 32892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return; 32992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org } 33092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setScale(sx, sy, px, py); 33392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->preConcat(m); 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 33692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::preScale(SkScalar sx, SkScalar sy) { 3370b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org if (1 == sx && 1 == sy) { 33892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return; 339f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com } 340f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com 3413fb5187647397e056843c1f41a508992be22175dreed@google.com // the assumption is that these multiplies are very cheap, and that 3423fb5187647397e056843c1f41a508992be22175dreed@google.com // a full concat and/or just computing the matrix type is more expensive. 3433fb5187647397e056843c1f41a508992be22175dreed@google.com // Also, the fixed-point case checks for overflow, but the float doesn't, 3443fb5187647397e056843c1f41a508992be22175dreed@google.com // so we can get away with these blind multiplies. 3453fb5187647397e056843c1f41a508992be22175dreed@google.com 3460b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMScaleX] *= sx; 3470b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMSkewY] *= sx; 3480b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMPersp0] *= sx; 3493fb5187647397e056843c1f41a508992be22175dreed@google.com 3500b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMSkewX] *= sy; 3510b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMScaleY] *= sy; 3520b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMPersp1] *= sy; 3533fb5187647397e056843c1f41a508992be22175dreed@google.com 3543fb5187647397e056843c1f41a508992be22175dreed@google.com this->orTypeMask(kScale_Mask); 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 35792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 3580b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org if (1 == sx && 1 == sy) { 35992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return; 360f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com } 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setScale(sx, sy, px, py); 36392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->postConcat(m); 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 36692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::postScale(SkScalar sx, SkScalar sy) { 3670b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org if (1 == sx && 1 == sy) { 36892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return; 369f244f901a9b76b75447e74cefd077ccf16eb8f40reed@google.com } 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setScale(sx, sy); 37292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->postConcat(m); 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this guy perhaps can go away, if we have a fract/high-precision way to 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// scale matrices 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkMatrix::postIDiv(int divx, int divy) { 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (divx == 0 || divy == 0) { 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const float invX = 1.f / divx; 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const float invY = 1.f / divy; 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMScaleX] *= invX; 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMSkewX] *= invX; 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransX] *= invX; 388fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMScaleY] *= invY; 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMSkewY] *= invY; 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransY] *= invY; 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setTypeMask(kUnknown_Mask); 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////// 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV, 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar px, SkScalar py) { 4010b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org const SkScalar oneMinusCosV = 1 - cosV; 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMScaleX] = cosV; 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMSkewX] = -sinV; 4050b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMTransX] = sdot(sinV, py, oneMinusCosV, px); 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMSkewY] = sinV; 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMScaleY] = cosV; 4090b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMTransY] = sdot(-sinV, px, oneMinusCosV, py); 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMPersp0] = fMat[kMPersp1] = 0; 4120b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMPersp2] = 1; 413fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 414dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) { 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMScaleX] = cosV; 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMSkewX] = -sinV; 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransX] = 0; 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMSkewY] = sinV; 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMScaleY] = cosV; 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransY] = 0; 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMPersp0] = fMat[kMPersp1] = 0; 4270b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMPersp2] = 1; 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 429dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) { 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sinV, cosV; 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV); 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setSinCos(sinV, cosV, px, py); 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::setRotate(SkScalar degrees) { 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sinV, cosV; 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV); 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setSinCos(sinV, cosV); 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 44492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) { 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setRotate(degrees, px, py); 44792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->preConcat(m); 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 45092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::preRotate(SkScalar degrees) { 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setRotate(degrees); 45392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->preConcat(m); 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 45692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) { 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setRotate(degrees, px, py); 45992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->postConcat(m); 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 46292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::postRotate(SkScalar degrees) { 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setRotate(degrees); 46592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->postConcat(m); 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////// 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 4710b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMScaleX] = 1; 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMSkewX] = sx; 4730b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMTransX] = -sx * py; 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMSkewY] = sy; 4760b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMScaleY] = 1; 4770b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMTransY] = -sy * px; 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMPersp0] = fMat[kMPersp1] = 0; 4800b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMPersp2] = 1; 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 482dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::setSkew(SkScalar sx, SkScalar sy) { 4860b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMScaleX] = 1; 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMSkewX] = sx; 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransX] = 0; 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMSkewY] = sy; 4910b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMScaleY] = 1; 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransY] = 0; 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMPersp0] = fMat[kMPersp1] = 0; 4950b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMPersp2] = 1; 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 497dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 50092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setSkew(sx, sy, px, py); 50392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->preConcat(m); 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 50692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::preSkew(SkScalar sx, SkScalar sy) { 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setSkew(sx, sy); 50992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->preConcat(m); 5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 51292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setSkew(sx, sy, px, py); 51592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->postConcat(m); 5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 51892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::postSkew(SkScalar sx, SkScalar sy) { 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m; 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.setSkew(sx, sy); 52192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->postConcat(m); 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst, 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ScaleToFit align) 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (src.isEmpty()) { 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->reset(); 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (dst.isEmpty()) { 5354516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com sk_bzero(fMat, 8 * sizeof(SkScalar)); 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setTypeMask(kScale_Mask | kRectStaysRect_Mask); 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5380b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar tx, sx = dst.width() / src.width(); 5390b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar ty, sy = dst.height() / src.height(); 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool xLarger = false; 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (align != kFill_ScaleToFit) { 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (sx > sy) { 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com xLarger = true; 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sx = sy; 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sy = sx; 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5510b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org tx = dst.fLeft - src.fLeft * sx; 5520b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org ty = dst.fTop - src.fTop * sy; 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) { 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar diff; 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (xLarger) { 5570b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org diff = dst.width() - src.width() * sy; 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5590b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org diff = dst.height() - src.height() * sy; 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 561fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (align == kCenter_ScaleToFit) { 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com diff = SkScalarHalf(diff); 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (xLarger) { 5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tx += diff; 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ty += diff; 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMScaleX] = sx; 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMScaleY] = sy; 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransX] = tx; 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMTransY] = ty; 577fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com fMat[kMSkewX] = fMat[kMSkewY] = 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[kMPersp0] = fMat[kMPersp1] = 0; 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 58097cd69ca23b27d88e08727366c29c1147eb564dereed@google.com unsigned mask = kRectStaysRect_Mask; 5810b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org if (sx != 1 || sy != 1) { 58297cd69ca23b27d88e08727366c29c1147eb564dereed@google.com mask |= kScale_Mask; 58397cd69ca23b27d88e08727366c29c1147eb564dereed@google.com } 58497cd69ca23b27d88e08727366c29c1147eb564dereed@google.com if (tx || ty) { 58597cd69ca23b27d88e08727366c29c1147eb564dereed@google.com mask |= kTranslate_Mask; 58697cd69ca23b27d88e08727366c29c1147eb564dereed@google.com } 58797cd69ca23b27d88e08727366c29c1147eb564dereed@google.com this->setTypeMask(mask); 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // shared cleanup 5900b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org fMat[kMPersp2] = 1; 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 59692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgstatic inline float muladdmul(float a, float b, float c, float d) { 59792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return SkDoubleToFloat((double)a * b + (double)c * d); 5988f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com} 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 60092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgstatic inline float rowcol3(const float row[], const float col[]) { 60192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return row[0] * col[0] + row[1] * col[3] + row[2] * col[6]; 6028f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com} 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void normalize_perspective(SkScalar mat[9]) { 6050b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > 1) { 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < 9; i++) 6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mat[i] = SkScalarHalf(mat[i]); 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 61192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) { 612dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com TypeMask aType = a.getPerspectiveTypeMaskOnly(); 613dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com TypeMask bType = b.getPerspectiveTypeMaskOnly(); 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 615dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com if (a.isTriviallyIdentity()) { 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *this = b; 617dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com } else if (b.isTriviallyIdentity()) { 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *this = a; 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix tmp; 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((aType | bType) & kPerspective_Mask) { 62392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMScaleX] = rowcol3(&a.fMat[0], &b.fMat[0]); 62492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMSkewX] = rowcol3(&a.fMat[0], &b.fMat[1]); 62592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMTransX] = rowcol3(&a.fMat[0], &b.fMat[2]); 62692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMSkewY] = rowcol3(&a.fMat[3], &b.fMat[0]); 62792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMScaleY] = rowcol3(&a.fMat[3], &b.fMat[1]); 62892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMTransY] = rowcol3(&a.fMat[3], &b.fMat[2]); 62992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMPersp0] = rowcol3(&a.fMat[6], &b.fMat[0]); 63092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMPersp1] = rowcol3(&a.fMat[6], &b.fMat[1]); 63192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMPersp2] = rowcol3(&a.fMat[6], &b.fMat[2]); 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com normalize_perspective(tmp.fMat); 634dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com tmp.setTypeMask(kUnknown_Mask); 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // not perspective 63692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMScaleX] = muladdmul(a.fMat[kMScaleX], 63792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMScaleX], 63892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org a.fMat[kMSkewX], 63992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMSkewY]); 64092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org 64192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMSkewX] = muladdmul(a.fMat[kMScaleX], 64292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMSkewX], 64392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org a.fMat[kMSkewX], 64492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMScaleY]); 64592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org 64692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMTransX] = muladdmul(a.fMat[kMScaleX], 64792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMTransX], 64892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org a.fMat[kMSkewX], 64992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMTransY]); 65092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org 65192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMTransX] += a.fMat[kMTransX]; 65292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org 65392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMSkewY] = muladdmul(a.fMat[kMSkewY], 65492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMScaleX], 65592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org a.fMat[kMScaleY], 65692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMSkewY]); 65792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org 65892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMScaleY] = muladdmul(a.fMat[kMSkewY], 65992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMSkewX], 66092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org a.fMat[kMScaleY], 66192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMScaleY]); 66292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org 66392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMTransY] = muladdmul(a.fMat[kMSkewY], 66492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMTransX], 66592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org a.fMat[kMScaleY], 66692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org b.fMat[kMTransY]); 66792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org 66892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmp.fMat[kMTransY] += a.fMat[kMTransY]; 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0; 6700b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org tmp.fMat[kMPersp2] = 1; 671dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType()); 672dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com //SkASSERT(!(tmp.getType() & kPerspective_Mask)); 673dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *this = tmp; 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 67992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::preConcat(const SkMatrix& mat) { 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for identity first, so we don't do a needless copy of ourselves 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // to ourselves inside setConcat() 68292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org if(!mat.isIdentity()) { 68392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->setConcat(*this, mat); 68492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org } 6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 68792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.orgvoid SkMatrix::postConcat(const SkMatrix& mat) { 6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for identity first, so we don't do a needless copy of ourselves 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // to ourselves inside setConcat() 69092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org if (!mat.isIdentity()) { 69192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->setConcat(mat, *this); 69292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org } 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6970b9e2dbf2f51ac41439db2052cf80704d60932f4reed@android.com/* Matrix inversion is very expensive, but also the place where keeping 6980b9e2dbf2f51ac41439db2052cf80704d60932f4reed@android.com precision may be most important (here and matrix concat). Hence to avoid 6990b9e2dbf2f51ac41439db2052cf80704d60932f4reed@android.com bitmap blitting artifacts when walking the inverse, we use doubles for 7000b9e2dbf2f51ac41439db2052cf80704d60932f4reed@android.com the intermediate math, even though we know that is more expensive. 7010b9e2dbf2f51ac41439db2052cf80704d60932f4reed@android.com */ 7020b9e2dbf2f51ac41439db2052cf80704d60932f4reed@android.com 7030b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.orgstatic inline SkScalar scross_dscale(SkScalar a, SkScalar b, 7040b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar c, SkScalar d, double scale) { 7050b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org return SkDoubleToScalar(scross(a, b, c, d) * scale); 7060b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org} 7070b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org 7080b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.orgstatic inline double dcross(double a, double b, double c, double d) { 7090b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org return a * b - c * d; 7100b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org} 7110b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org 7120b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.orgstatic inline SkScalar dcross_dscale(double a, double b, 7130b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org double c, double d, double scale) { 7140b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org return SkDoubleToScalar(dcross(a, b, c, d) * scale); 7150b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org} 7160b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org 7170b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.orgstatic double sk_inv_determinant(const float mat[9], int isPerspective) { 7188f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com double det; 7198f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com 7208f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com if (isPerspective) { 7210b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org det = mat[SkMatrix::kMScaleX] * 7220b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dcross(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2], 7230b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1]) 7240b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org + 7250b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org mat[SkMatrix::kMSkewX] * 7260b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dcross(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0], 7270b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2]) 7280b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org + 7290b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org mat[SkMatrix::kMTransX] * 7300b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dcross(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1], 7310b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]); 7328f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com } else { 7330b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org det = dcross(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY], 7340b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]); 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7378f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com // Since the determinant is on the order of the cube of the matrix members, 7388f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com // compare to the cube of the default nearly-zero constant (although an 7398f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com // estimate of the condition number would be better if it wasn't so expensive). 7408f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) { 7418f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com return 0; 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7438f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com return 1.0 / det; 7448f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com} 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7461ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.comvoid SkMatrix::SetAffineIdentity(SkScalar affine[6]) { 7470b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org affine[kAScaleX] = 1; 7481ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com affine[kASkewY] = 0; 7491ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com affine[kASkewX] = 0; 7500b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org affine[kAScaleY] = 1; 7511ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com affine[kATransX] = 0; 7521ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com affine[kATransY] = 0; 7531ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com} 7541ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com 7551ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.combool SkMatrix::asAffine(SkScalar affine[6]) const { 7568d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (this->hasPerspective()) { 7571ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com return false; 7581ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com } 7591ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com if (affine) { 7601ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com affine[kAScaleX] = this->fMat[kMScaleX]; 7611ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com affine[kASkewY] = this->fMat[kMSkewY]; 7621ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com affine[kASkewX] = this->fMat[kMSkewX]; 7631ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com affine[kAScaleY] = this->fMat[kMScaleY]; 7641ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com affine[kATransX] = this->fMat[kMTransX]; 7651ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com affine[kATransY] = this->fMat[kMTransY]; 7661ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com } 767ddbbd805b5b453e12cda0b3300e5655d8fb2bc19vandebo@chromium.org return true; 768ddbbd805b5b453e12cda0b3300e5655d8fb2bc19vandebo@chromium.org} 769ddbbd805b5b453e12cda0b3300e5655d8fb2bc19vandebo@chromium.org 770683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.combool SkMatrix::invertNonIdentity(SkMatrix* inv) const { 771683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com SkASSERT(!this->isIdentity()); 7722fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com 7732fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com TypeMask mask = this->getType(); 7742fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com 7752fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com if (0 == (mask & ~(kScale_Mask | kTranslate_Mask))) { 776e40591d5484762067f976d979c506f126c7779e1reed@google.com bool invertible = true; 7772fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com if (inv) { 7782fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com if (mask & kScale_Mask) { 7792fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com SkScalar invX = fMat[kMScaleX]; 7802fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com SkScalar invY = fMat[kMScaleY]; 7812fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com if (0 == invX || 0 == invY) { 7822fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com return false; 7832fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com } 7842fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com invX = SkScalarInvert(invX); 7852fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com invY = SkScalarInvert(invY); 7862fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com 7872fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com // Must be careful when writing to inv, since it may be the 7882fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com // same memory as this. 7892fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com 7902fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com inv->fMat[kMSkewX] = inv->fMat[kMSkewY] = 7912fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com inv->fMat[kMPersp0] = inv->fMat[kMPersp1] = 0; 7922fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com 7932fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com inv->fMat[kMScaleX] = invX; 7942fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com inv->fMat[kMScaleY] = invY; 7950b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMPersp2] = 1; 7960b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMTransX] = -fMat[kMTransX] * invX; 7970b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMTransY] = -fMat[kMTransY] * invY; 7982fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com 7992fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com inv->setTypeMask(mask | kRectStaysRect_Mask); 8002fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com } else { 8012fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com // translate only 8022fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com inv->setTranslate(-fMat[kMTransX], -fMat[kMTransY]); 8032fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com } 804e40591d5484762067f976d979c506f126c7779e1reed@google.com } else { // inv is NULL, just check if we're invertible 805e40591d5484762067f976d979c506f126c7779e1reed@google.com if (!fMat[kMScaleX] || !fMat[kMScaleY]) { 806e40591d5484762067f976d979c506f126c7779e1reed@google.com invertible = false; 807e40591d5484762067f976d979c506f126c7779e1reed@google.com } 8082fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com } 809e40591d5484762067f976d979c506f126c7779e1reed@google.com return invertible; 8102fb96cc5d713451216bd63d5dc8d19abc8550730reed@google.com } 8114a1362a3c91ae9461a54bf1b04c250b0aa145db4reed@google.com 8120b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org int isPersp = mask & kPerspective_Mask; 8130b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org double scale = sk_inv_determinant(fMat, isPersp); 8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale == 0) { // underflow 8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (inv) { 8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix tmp; 821cf9b7505f22aedde30612655e16f330f19ba2470bsalomon@google.com if (inv == this) { 8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inv = &tmp; 823cf9b7505f22aedde30612655e16f330f19ba2470bsalomon@google.com } 8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (isPersp) { 8260b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMScaleX] = scross_dscale(fMat[kMScaleY], fMat[kMPersp2], fMat[kMTransY], fMat[kMPersp1], scale); 8270b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMSkewX] = scross_dscale(fMat[kMTransX], fMat[kMPersp1], fMat[kMSkewX], fMat[kMPersp2], scale); 8280b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMTransX] = scross_dscale(fMat[kMSkewX], fMat[kMTransY], fMat[kMTransX], fMat[kMScaleY], scale); 8290b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org 8300b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMSkewY] = scross_dscale(fMat[kMTransY], fMat[kMPersp0], fMat[kMSkewY], fMat[kMPersp2], scale); 8310b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMScaleY] = scross_dscale(fMat[kMScaleX], fMat[kMPersp2], fMat[kMTransX], fMat[kMPersp0], scale); 8320b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMTransY] = scross_dscale(fMat[kMTransX], fMat[kMSkewY], fMat[kMScaleX], fMat[kMTransY], scale); 8330b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org 8340b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMPersp0] = scross_dscale(fMat[kMSkewY], fMat[kMPersp1], fMat[kMScaleY], fMat[kMPersp0], scale); 8350b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMPersp1] = scross_dscale(fMat[kMSkewX], fMat[kMPersp0], fMat[kMScaleX], fMat[kMPersp1], scale); 8360b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMPersp2] = scross_dscale(fMat[kMScaleX], fMat[kMScaleY], fMat[kMSkewX], fMat[kMSkewY], scale); 8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // not perspective 8380b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMScaleX] = SkDoubleToScalar(fMat[kMScaleY] * scale); 8390b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMSkewX] = SkDoubleToScalar(-fMat[kMSkewX] * scale); 8400b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMTransX] = dcross_dscale(fMat[kMSkewX], fMat[kMTransY], fMat[kMScaleY], fMat[kMTransX], scale); 841fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 8420b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMSkewY] = SkDoubleToScalar(-fMat[kMSkewY] * scale); 8430b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMScaleY] = SkDoubleToScalar(fMat[kMScaleX] * scale); 8440b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMTransY] = dcross_dscale(fMat[kMSkewY], fMat[kMTransX], fMat[kMScaleX], fMat[kMTransY], scale); 84583c6a2252555a974be4054aaca3a294e76efc32areed@google.com 8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inv->fMat[kMPersp0] = 0; 8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inv->fMat[kMPersp1] = 0; 8480b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org inv->fMat[kMPersp2] = 1; 8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8516fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org inv->setTypeMask(fTypeMask); 8526fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org 8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (inv == &tmp) { 8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *(SkMatrix*)this = tmp; 8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], 8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint src[], int count) { 8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(m.getType() == 0); 8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (dst != src && count > 0) 8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(dst, src, count * sizeof(SkPoint)); 8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[], 8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint src[], int count) { 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(m.getType() == kTranslate_Mask); 8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar tx = m.fMat[kMTransX]; 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar ty = m.fMat[kMTransY]; 8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fY = src->fY + ty; 8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fX = src->fX + tx; 8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--count); 8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[], 8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint src[], int count) { 8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(m.getType() == kScale_Mask); 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar mx = m.fMat[kMScaleX]; 8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar my = m.fMat[kMScaleY]; 8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 8940b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fY = src->fY * my; 8950b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fX = src->fX * mx; 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--count); 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::ScaleTrans_pts(const SkMatrix& m, SkPoint dst[], 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint src[], int count) { 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(m.getType() == (kScale_Mask | kTranslate_Mask)); 9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar mx = m.fMat[kMScaleX]; 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar my = m.fMat[kMScaleY]; 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar tx = m.fMat[kMTransX]; 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar ty = m.fMat[kMTransY]; 9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 9120b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fY = src->fY * my + ty; 9130b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fX = src->fX * mx + tx; 9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--count); 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::Rot_pts(const SkMatrix& m, SkPoint dst[], 9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint src[], int count) { 9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((m.getType() & (kPerspective_Mask | kTranslate_Mask)) == 0); 9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar mx = m.fMat[kMScaleX]; 9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar my = m.fMat[kMScaleY]; 9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar kx = m.fMat[kMSkewX]; 9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar ky = m.fMat[kMSkewY]; 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sy = src->fY; 9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sx = src->fX; 9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 9330b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fY = sdot(sx, ky, sy, my); 9340b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fX = sdot(sx, mx, sy, kx); 9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--count); 9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::RotTrans_pts(const SkMatrix& m, SkPoint dst[], 9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint src[], int count) { 9428d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com SkASSERT(!m.hasPerspective()); 9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar mx = m.fMat[kMScaleX]; 9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar my = m.fMat[kMScaleY]; 9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar kx = m.fMat[kMSkewX]; 9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar ky = m.fMat[kMSkewY]; 9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar tx = m.fMat[kMTransX]; 9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar ty = m.fMat[kMTransY]; 9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sy = src->fY; 9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sx = src->fX; 9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 9550b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#ifdef SK_LEGACY_MATRIX_MATH_ORDER 9560b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fY = sx * ky + (sy * my + ty); 9570b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fX = sx * mx + (sy * kx + tx); 9580b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#else 9590b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fY = sdot(sx, ky, sy, my) + ty; 9600b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fX = sdot(sx, mx, sy, kx) + tx; 9610b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#endif 9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--count); 9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[], 9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint src[], int count) { 9698d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com SkASSERT(m.hasPerspective()); 9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sy = src->fY; 9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sx = src->fX; 9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src += 1; 9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9770b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 9780b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar y = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 9790b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#ifdef SK_LEGACY_MATRIX_MATH_ORDER 9800b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar z = sx * m.fMat[kMPersp0] + (sy * m.fMat[kMPersp1] + m.fMat[kMPersp2]); 9810b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#else 9820b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2]; 9830b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#endif 9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (z) { 9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com z = SkScalarFastInvert(z); 9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9880b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fY = y * z; 9890b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fX = x * z; 9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst += 1; 9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--count); 9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = { 9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Identity_pts, SkMatrix::Trans_pts, 9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Scale_pts, SkMatrix::ScaleTrans_pts, 9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Rot_pts, SkMatrix::RotTrans_pts, 9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Rot_pts, SkMatrix::RotTrans_pts, 10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // repeat the persp proc 8 times 10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_pts, SkMatrix::Persp_pts, 10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_pts, SkMatrix::Persp_pts, 10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_pts, SkMatrix::Persp_pts, 10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_pts, SkMatrix::Persp_pts 10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const { 1008259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com SkASSERT((dst && src && count > 0) || 0 == count); 10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // no partial overlap 10103dc82c44706b017877880160ad6af284ec3997e3bungeman@google.com SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]); 10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->getMapPtsProc()(*this, dst, src, count); 10138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1017259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.comvoid SkMatrix::mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const { 1018259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com SkASSERT((dst && src && count > 0) || 0 == count); 1019259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com // no partial overlap 1020259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= 3*count); 1021259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com 1022259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com if (count > 0) { 1023259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com if (this->isIdentity()) { 1024259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com memcpy(dst, src, 3*count*sizeof(SkScalar)); 1025259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com return; 1026259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com } 1027259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com do { 1028259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com SkScalar sx = src[0]; 1029259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com SkScalar sy = src[1]; 1030259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com SkScalar sw = src[2]; 1031259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com src += 3; 1032259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com 10330b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar x = sdot(sx, fMat[kMScaleX], sy, fMat[kMSkewX], sw, fMat[kMTransX]); 10340b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar y = sdot(sx, fMat[kMSkewY], sy, fMat[kMScaleY], sw, fMat[kMTransY]); 10350b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar w = sdot(sx, fMat[kMPersp0], sy, fMat[kMPersp1], sw, fMat[kMPersp2]); 1036259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com 1037259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com dst[0] = x; 1038259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com dst[1] = y; 1039259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com dst[2] = w; 1040259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com dst += 3; 1041259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com } while (--count); 1042259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com } 1043259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com} 1044259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com 1045259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com/////////////////////////////////////////////////////////////////////////////// 1046259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const { 10488d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (this->hasPerspective()) { 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint origin; 10508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MapXYProc proc = this->getMapXYProc(); 10528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(*this, 0, 0, &origin); 10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = count - 1; i >= 0; --i) { 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint tmp; 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(*this, src[i].fX, src[i].fY, &tmp); 10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY); 10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix tmp = *this; 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0; 10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.clearTypeMask(kTranslate_Mask); 10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.mapPoints(dst, src, count); 10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const { 10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(dst && &src); 10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->rectStaysRect()) { 10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2); 10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->sort(); 10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint quad[4]; 10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src.toQuad(quad); 10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->mapPoints(quad, quad, 4); 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->set(quad, 4); 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScalar SkMatrix::mapRadius(SkScalar radius) const { 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkVector vec[2]; 10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com vec[0].set(radius, 0); 10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com vec[1].set(0, radius); 10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->mapVectors(vec, 2); 10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar d0 = vec[0].length(); 10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar d1 = vec[1].length(); 10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10966e252d49c9bb6b805478560dd99b83ff1d1411dereed@google.com // return geometric mean 10976e252d49c9bb6b805478560dd99b83ff1d1411dereed@google.com return SkScalarSqrt(d0 * d1); 10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* pt) { 11048d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com SkASSERT(m.hasPerspective()); 11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11060b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 11070b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar y = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 11080b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2]; 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (z) { 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com z = SkScalarFastInvert(z); 11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11120b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fX = x * z; 11130b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fY = y * z; 11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* pt) { 11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask); 1119fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 11200b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#ifdef SK_LEGACY_MATRIX_MATH_ORDER 11210b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX] + m.fMat[kMTransX]); 11220b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fY = sx * m.fMat[kMSkewY] + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]); 11230b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#else 11240b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 11250b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fY = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 11260b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#endif 11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* pt) { 11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask); 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == m.fMat[kMTransX]); 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == m.fMat[kMTransY]); 11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11350b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#ifdef SK_LEGACY_MATRIX_MATH_ORDER 11360b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX] + m.fMat[kMTransX]); 11370b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fY = sx * m.fMat[kMSkewY] + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]); 11380b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#else 11390b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 11400b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fY = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 11410b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org#endif 11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* pt) { 11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) 11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com == kScale_Mask); 1148fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 11490b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fX = sx * m.fMat[kMScaleX] + m.fMat[kMTransX]; 11500b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fY = sy * m.fMat[kMScaleY] + m.fMat[kMTransY]; 11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* pt) { 11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) 11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com == kScale_Mask); 11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == m.fMat[kMTransX]); 11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == m.fMat[kMTransY]); 11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11600b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fX = sx * m.fMat[kMScaleX]; 11610b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org pt->fY = sy * m.fMat[kMScaleY]; 11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* pt) { 11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(m.getType() == kTranslate_Mask); 11678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt->fX = sx + m.fMat[kMTransX]; 11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt->fY = sy + m.fMat[kMTransY]; 11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* pt) { 11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == m.getType()); 11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt->fX = sx; 11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt->fY = sy; 11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = { 11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Identity_xy, SkMatrix::Trans_xy, 11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Scale_xy, SkMatrix::ScaleTrans_xy, 11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Rot_xy, SkMatrix::RotTrans_xy, 11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Rot_xy, SkMatrix::RotTrans_xy, 11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // repeat the persp proc 8 times 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_xy, SkMatrix::Persp_xy, 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_xy, SkMatrix::Persp_xy, 11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_xy, SkMatrix::Persp_xy, 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_xy, SkMatrix::Persp_xy 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// if its nearly zero (just made up 26, perhaps it should be bigger or smaller) 119583c6a2252555a974be4054aaca3a294e76efc32areed@google.com#define PerspNearlyZero(x) SkScalarNearlyZero(x, (1.0f / (1 << 26))) 11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const { 11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (PerspNearlyZero(fMat[kMPersp0])) { 11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (stepX || stepY) { 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (PerspNearlyZero(fMat[kMPersp1]) && 12010b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org PerspNearlyZero(fMat[kMPersp2] - 1)) { 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (stepX) { 12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *stepX = SkScalarToFixed(fMat[kMScaleX]); 12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (stepY) { 12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *stepY = SkScalarToFixed(fMat[kMSkewY]); 12078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 120983c6a2252555a974be4054aaca3a294e76efc32areed@google.com SkScalar z = y * fMat[kMPersp1] + fMat[kMPersp2]; 12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (stepX) { 12110b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org *stepX = SkScalarToFixed(fMat[kMScaleX] / z); 12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (stepY) { 12140b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org *stepY = SkScalarToFixed(fMat[kMSkewY] / z); 12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPerspIter.h" 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count) 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fMatrix(m), fSX(x0), fSY(y0), fCount(count) { 12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_xy(m, x0, y0, &pt); 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fX = SkScalarToFixed(pt.fX); 12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fY = SkScalarToFixed(pt.fY); 12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkPerspIter::next() { 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int n = fCount; 1238fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == n) { 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = fX; 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = fY; 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed dx, dy; 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (n >= kCount) { 12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = kCount; 12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fSX += SkIntToScalar(kCount); 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt); 12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fX = SkScalarToFixed(pt.fX); 12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fY = SkScalarToFixed(pt.fY); 12538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dx = (fX - x) >> kShift; 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dy = (fY - y) >> kShift; 12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fSX += SkIntToScalar(n); 12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt); 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fX = SkScalarToFixed(pt.fX); 12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fY = SkScalarToFixed(pt.fY); 12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dx = (fX - x) / n; 12618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dy = (fY - y) / n; 12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed* p = fStorage; 12658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < n; i++) { 12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *p++ = x; x += dx; 12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *p++ = y; y += dy; 12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1269fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCount -= n; 12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return n; 12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline bool checkForZero(float x) { 12778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return x*x == 0; 12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) { 12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float x = 1, y = 1; 12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt1, pt2; 12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 1) { 12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt1.fX = poly[1].fX - poly[0].fX; 12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt1.fY = poly[1].fY - poly[0].fY; 12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y = SkPoint::Length(pt1.fX, pt1.fY); 12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (checkForZero(y)) { 12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (count) { 12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case 2: 12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case 3: 12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt2.fX = poly[0].fY - poly[2].fY; 12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt2.fY = poly[2].fX - poly[0].fX; 12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto CALC_X; 12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt2.fX = poly[0].fY - poly[3].fY; 13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt2.fY = poly[3].fX - poly[0].fX; 13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CALC_X: 13020b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org x = sdot(pt1.fX, pt2.fX, pt1.fY, pt2.fY) / y; 13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt->set(x, y); 13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst, 13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint& scale) { 13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float invScale = 1 / scale.fY; 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale; 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale; 13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMPersp0] = 0; 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; 13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMPersp1] = 0; 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMTransX] = srcPt[0].fX; 13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMTransY] = srcPt[0].fY; 13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMPersp2] = 1; 13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->setTypeMask(kUnknown_Mask); 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst, 13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint& scale) { 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float invScale = 1 / scale.fX; 13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale; 13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale; 13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMPersp0] = 0; 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com invScale = 1 / scale.fY; 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; 13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; 13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMPersp1] = 0; 13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMTransX] = srcPt[0].fX; 13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMTransY] = srcPt[0].fY; 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMPersp2] = 1; 13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->setTypeMask(kUnknown_Mask); 13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst, 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint& scale) { 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float a1, a2; 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float x0, y0, x1, y1, x2, y2; 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x0 = srcPt[2].fX - srcPt[0].fX; 13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y0 = srcPt[2].fY - srcPt[0].fY; 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x1 = srcPt[2].fX - srcPt[1].fX; 13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y1 = srcPt[2].fY - srcPt[1].fY; 13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x2 = srcPt[2].fX - srcPt[3].fX; 13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y2 = srcPt[2].fY - srcPt[3].fY; 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* check if abs(x2) > abs(y2) */ 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) { 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float denom = SkScalarMulDiv(x1, y2, x2) - y1; 13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (checkForZero(denom)) { 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13640b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org a1 = (SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1) / denom; 13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float denom = x1 - SkScalarMulDiv(y1, x2, y2); 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (checkForZero(denom)) { 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13700b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org a1 = (x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2)) / denom; 13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* check if abs(x1) > abs(y1) */ 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) { 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float denom = y2 - SkScalarMulDiv(x2, y1, x1); 13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (checkForZero(denom)) { 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13790b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org a2 = (y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1)) / denom; 13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com float denom = SkScalarMulDiv(y2, x1, y1) - x2; 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (checkForZero(denom)) { 13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13850b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org a2 = (SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2) / denom; 13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13880b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org float invScale = SkScalarInvert(scale.fX); 13890b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fMat[kMScaleX] = (a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX) * invScale; 13900b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fMat[kMSkewY] = (a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY) * invScale; 13910b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fMat[kMPersp0] = a2 * invScale; 13920b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org 13930b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org invScale = SkScalarInvert(scale.fY); 13940b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fMat[kMSkewX] = (a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX) * invScale; 13950b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fMat[kMScaleY] = (a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY) * invScale; 13960b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org dst->fMat[kMPersp1] = a1 * invScale; 13970b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org 13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMTransX] = srcPt[0].fX; 13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMTransY] = srcPt[0].fY; 14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fMat[kMPersp2] = 1; 14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->setTypeMask(kUnknown_Mask); 14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&); 14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* Taken from Rob Johnson's original sample code in QuickDraw GX 14088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[], 14108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count) { 14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((unsigned)count > 4) { 14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count); 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == count) { 14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->reset(); 14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (1 == count) { 14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY); 14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 14238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint scale; 14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!poly_to_point(&scale, src, count) || 14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalarNearlyZero(scale.fX) || 14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalarNearlyZero(scale.fY)) { 14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const PolyMapProc gPolyMapProcs[] = { 14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc 14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PolyMapProc proc = gPolyMapProcs[count - 2]; 14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix tempMap, result; 14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tempMap.setTypeMask(kUnknown_Mask); 14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!proc(src, &tempMap, scale)) { 14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!tempMap.invert(&result)) { 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!proc(dst, &tempMap, scale)) { 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 144992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org this->setConcat(tempMap, result); 14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1455311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.orgenum MinMaxOrBoth { 1456311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org kMin_MinMaxOrBoth, 1457311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org kMax_MinMaxOrBoth, 1458311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org kBoth_MinMaxOrBoth 1459cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org}; 1460cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com 1461311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.orgtemplate <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask, 1462311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org const SkScalar m[9], 1463311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org SkScalar results[/*1 or 2*/]) { 1464cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org if (typeMask & SkMatrix::kPerspective_Mask) { 1465311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org return false; 1466383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com } 1467cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org if (SkMatrix::kIdentity_Mask == typeMask) { 1468311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = SK_Scalar1; 1469311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1470311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[1] = SK_Scalar1; 1471311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } 1472311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org return true; 1473383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com } 1474cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org if (!(typeMask & SkMatrix::kAffine_Mask)) { 1475311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1476311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), 1477311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org SkScalarAbs(m[SkMatrix::kMScaleY])); 1478311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1479311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), 1480311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org SkScalarAbs(m[SkMatrix::kMScaleY])); 1481cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org } else { 1482311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]); 1483311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]); 1484311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org if (results[0] > results[1]) { 1485311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org SkTSwap(results[0], results[1]); 1486311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } 1487cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org } 1488311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org return true; 1489383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com } 1490383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com // ignore the translation part of the matrix, just look at 2x2 portion. 1491cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org // compute singular values, take largest or smallest abs value. 1492383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com // [a b; b c] = A^T*A 14930b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX], 14940b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]); 14950b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX], 14960b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]); 14970b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar c = sdot(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX], 14980b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]); 1499383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com // eigenvalues of A^T*A are the squared singular values of A. 1500383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com // characteristic equation is det((A^T*A) - l*I) = 0 1501383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com // l^2 - (a + c)l + (ac-b^2) 1502383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff 1503cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org // and roots are guaranteed to be pos and real). 15040b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar bSqd = b * b; 1505383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com // if upper left 2x2 is orthogonal save some math 1506c490f801b063a0837501feab3d12b73d71f46312jvanverth@google.com if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { 1507311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1508311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = SkMinScalar(a, c); 1509311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1510311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = SkMaxScalar(a, c); 1511cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org } else { 1512311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = a; 1513311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[1] = c; 1514311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org if (results[0] > results[1]) { 1515311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org SkTSwap(results[0], results[1]); 1516311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } 1517cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org } 1518cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com } else { 1519383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com SkScalar aminusc = a - c; 1520383963280ddd13030331765fe88d2aefa3e32130bsalomon@google.com SkScalar apluscdiv2 = SkScalarHalf(a + c); 15210b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd)); 1522311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1523311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = apluscdiv2 - x; 1524311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1525311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = apluscdiv2 + x; 1526cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org } else { 1527311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = apluscdiv2 - x; 1528311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[1] = apluscdiv2 + x; 1529cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org } 1530cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com } 1531311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org SkASSERT(results[0] >= 0); 1532311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[0] = SkScalarSqrt(results[0]); 1533311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1534311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org SkASSERT(results[1] >= 0); 1535311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org results[1] = SkScalarSqrt(results[1]); 1536311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } 1537311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org return true; 1538cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org} 1539cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org 15401878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.orgSkScalar SkMatrix::getMinScale() const { 1541311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org SkScalar factor; 1542311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) { 1543311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org return factor; 1544311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } else { 1545311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org return -1; 1546311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } 1547cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org} 1548cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org 15491878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.orgSkScalar SkMatrix::getMaxScale() const { 1550311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org SkScalar factor; 1551311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) { 1552311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org return factor; 1553311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } else { 1554311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org return -1; 1555311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org } 1556311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org} 1557311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org 1558311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.orgbool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const { 1559311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors); 1560cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com} 1561cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com 156278358bf624c7e7c09ffccf638c50870808d884d6mtkleinnamespace { 156378358bf624c7e7c09ffccf638c50870808d884d6mtklein 1564ada3635c8e83739f45cd52459d3e052783d1a40emtkleinstruct PODMatrix { 1565ada3635c8e83739f45cd52459d3e052783d1a40emtklein SkScalar matrix[9]; 1566ada3635c8e83739f45cd52459d3e052783d1a40emtklein uint32_t typemask; 156778358bf624c7e7c09ffccf638c50870808d884d6mtklein 1568ada3635c8e83739f45cd52459d3e052783d1a40emtklein const SkMatrix& asSkMatrix() const { return *reinterpret_cast<const SkMatrix*>(this); } 1569ada3635c8e83739f45cd52459d3e052783d1a40emtklein}; 1570ada3635c8e83739f45cd52459d3e052783d1a40emtkleinSK_COMPILE_ASSERT(sizeof(PODMatrix) == sizeof(SkMatrix), PODMatrixSizeMismatch); 157121a705d2ebdf0319d45970784950886f62a77141commit-bot@chromium.org 157278358bf624c7e7c09ffccf638c50870808d884d6mtklein} // namespace 157378358bf624c7e7c09ffccf638c50870808d884d6mtklein 1574cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.comconst SkMatrix& SkMatrix::I() { 1575ada3635c8e83739f45cd52459d3e052783d1a40emtklein SK_COMPILE_ASSERT(offsetof(SkMatrix, fMat) == offsetof(PODMatrix, matrix), BadfMat); 1576ada3635c8e83739f45cd52459d3e052783d1a40emtklein SK_COMPILE_ASSERT(offsetof(SkMatrix, fTypeMask) == offsetof(PODMatrix, typemask), BadfTypeMask); 1577ada3635c8e83739f45cd52459d3e052783d1a40emtklein 1578ada3635c8e83739f45cd52459d3e052783d1a40emtklein static const PODMatrix identity = { {SK_Scalar1, 0, 0, 1579ada3635c8e83739f45cd52459d3e052783d1a40emtklein 0, SK_Scalar1, 0, 1580ada3635c8e83739f45cd52459d3e052783d1a40emtklein 0, 0, SK_Scalar1 }, 1581ada3635c8e83739f45cd52459d3e052783d1a40emtklein kIdentity_Mask | kRectStaysRect_Mask}; 1582ada3635c8e83739f45cd52459d3e052783d1a40emtklein SkASSERT(identity.asSkMatrix().isIdentity()); 1583ada3635c8e83739f45cd52459d3e052783d1a40emtklein return identity.asSkMatrix(); 15841f90287df3129cb267422e482c52ebeca6a8990ftomhudson@google.com} 1585cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com 1586cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.comconst SkMatrix& SkMatrix::InvalidMatrix() { 1587ada3635c8e83739f45cd52459d3e052783d1a40emtklein SK_COMPILE_ASSERT(offsetof(SkMatrix, fMat) == offsetof(PODMatrix, matrix), BadfMat); 1588ada3635c8e83739f45cd52459d3e052783d1a40emtklein SK_COMPILE_ASSERT(offsetof(SkMatrix, fTypeMask) == offsetof(PODMatrix, typemask), BadfTypeMask); 1589ada3635c8e83739f45cd52459d3e052783d1a40emtklein 1590ada3635c8e83739f45cd52459d3e052783d1a40emtklein static const PODMatrix invalid = 1591ada3635c8e83739f45cd52459d3e052783d1a40emtklein { {SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1592ada3635c8e83739f45cd52459d3e052783d1a40emtklein SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1593ada3635c8e83739f45cd52459d3e052783d1a40emtklein SK_ScalarMax, SK_ScalarMax, SK_ScalarMax }, 1594ada3635c8e83739f45cd52459d3e052783d1a40emtklein kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask }; 1595ada3635c8e83739f45cd52459d3e052783d1a40emtklein return invalid.asSkMatrix(); 1596cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com} 1597cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com 1598cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com/////////////////////////////////////////////////////////////////////////////// 1599cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com 16004faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgsize_t SkMatrix::writeToMemory(void* buffer) const { 16010ad336f8c6f6f0325eee309c9cd501ea432cc33ereed@android.com // TODO write less for simple matrices 16024faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org static const size_t sizeInMemory = 9 * sizeof(SkScalar); 16030ad336f8c6f6f0325eee309c9cd501ea432cc33ereed@android.com if (buffer) { 16044faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org memcpy(buffer, fMat, sizeInMemory); 16050ad336f8c6f6f0325eee309c9cd501ea432cc33ereed@android.com } 16064faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org return sizeInMemory; 16070ad336f8c6f6f0325eee309c9cd501ea432cc33ereed@android.com} 16080ad336f8c6f6f0325eee309c9cd501ea432cc33ereed@android.com 16094faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgsize_t SkMatrix::readFromMemory(const void* buffer, size_t length) { 16104faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org static const size_t sizeInMemory = 9 * sizeof(SkScalar); 16114faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org if (length < sizeInMemory) { 16124faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org return 0; 16134faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org } 1614f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (buffer) { 16154faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org memcpy(fMat, buffer, sizeInMemory); 1616f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->setTypeMask(kUnknown_Mask); 1617f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 16184faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org return sizeInMemory; 16190ad336f8c6f6f0325eee309c9cd501ea432cc33ereed@android.com} 16200ad336f8c6f6f0325eee309c9cd501ea432cc33ereed@android.com 162176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#ifdef SK_DEVELOPER 16228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkMatrix::dump() const { 16238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString str; 162476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->toString(&str); 16258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("%s\n", str.c_str()); 16268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16270f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#endif 16288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16290f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 163076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkMatrix::toString(SkString* str) const { 163176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]", 16328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5], 16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[6], fMat[7], fMat[8]); 16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 163576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 1636ad514302158887002e83625a837f9ecbe540d1d3reed@google.com 1637ad514302158887002e83625a837f9ecbe540d1d3reed@google.com/////////////////////////////////////////////////////////////////////////////// 1638ad514302158887002e83625a837f9ecbe540d1d3reed@google.com 1639ad514302158887002e83625a837f9ecbe540d1d3reed@google.com#include "SkMatrixUtils.h" 1640ad514302158887002e83625a837f9ecbe540d1d3reed@google.com 1641ae57358447bac678e3fc458fa2857a349a6a7081reed@google.combool SkTreatAsSprite(const SkMatrix& mat, int width, int height, 1642ad514302158887002e83625a837f9ecbe540d1d3reed@google.com unsigned subpixelBits) { 1643ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com // quick reject on affine or perspective 1644ad514302158887002e83625a837f9ecbe540d1d3reed@google.com if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) { 1645ad514302158887002e83625a837f9ecbe540d1d3reed@google.com return false; 1646ad514302158887002e83625a837f9ecbe540d1d3reed@google.com } 1647422188f3c6286d2991a029027958387b070e4dc6skia.committer@gmail.com 1648ad514302158887002e83625a837f9ecbe540d1d3reed@google.com // quick success check 1649ad514302158887002e83625a837f9ecbe540d1d3reed@google.com if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) { 1650ad514302158887002e83625a837f9ecbe540d1d3reed@google.com return true; 1651ad514302158887002e83625a837f9ecbe540d1d3reed@google.com } 1652422188f3c6286d2991a029027958387b070e4dc6skia.committer@gmail.com 1653ad514302158887002e83625a837f9ecbe540d1d3reed@google.com // mapRect supports negative scales, so we eliminate those first 1654ad514302158887002e83625a837f9ecbe540d1d3reed@google.com if (mat.getScaleX() < 0 || mat.getScaleY() < 0) { 1655ad514302158887002e83625a837f9ecbe540d1d3reed@google.com return false; 1656ad514302158887002e83625a837f9ecbe540d1d3reed@google.com } 1657422188f3c6286d2991a029027958387b070e4dc6skia.committer@gmail.com 1658ad514302158887002e83625a837f9ecbe540d1d3reed@google.com SkRect dst; 1659ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com SkIRect isrc = { 0, 0, width, height }; 1660d9f65e3df45c9b4994c70f6bf13d29985afd2f65skia.committer@gmail.com 1661ad514302158887002e83625a837f9ecbe540d1d3reed@google.com { 1662ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com SkRect src; 1663ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com src.set(isrc); 1664ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com mat.mapRect(&dst, src); 1665ad514302158887002e83625a837f9ecbe540d1d3reed@google.com } 1666422188f3c6286d2991a029027958387b070e4dc6skia.committer@gmail.com 1667ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com // just apply the translate to isrc 1668ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com isrc.offset(SkScalarRoundToInt(mat.getTranslateX()), 1669ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com SkScalarRoundToInt(mat.getTranslateY())); 1670ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com 1671ad514302158887002e83625a837f9ecbe540d1d3reed@google.com if (subpixelBits) { 1672ad514302158887002e83625a837f9ecbe540d1d3reed@google.com isrc.fLeft <<= subpixelBits; 1673ad514302158887002e83625a837f9ecbe540d1d3reed@google.com isrc.fTop <<= subpixelBits; 1674ad514302158887002e83625a837f9ecbe540d1d3reed@google.com isrc.fRight <<= subpixelBits; 1675ad514302158887002e83625a837f9ecbe540d1d3reed@google.com isrc.fBottom <<= subpixelBits; 1676422188f3c6286d2991a029027958387b070e4dc6skia.committer@gmail.com 1677ad514302158887002e83625a837f9ecbe540d1d3reed@google.com const float scale = 1 << subpixelBits; 1678ad514302158887002e83625a837f9ecbe540d1d3reed@google.com dst.fLeft *= scale; 1679ad514302158887002e83625a837f9ecbe540d1d3reed@google.com dst.fTop *= scale; 1680ad514302158887002e83625a837f9ecbe540d1d3reed@google.com dst.fRight *= scale; 1681ad514302158887002e83625a837f9ecbe540d1d3reed@google.com dst.fBottom *= scale; 1682ad514302158887002e83625a837f9ecbe540d1d3reed@google.com } 1683422188f3c6286d2991a029027958387b070e4dc6skia.committer@gmail.com 1684ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com SkIRect idst; 1685ad514302158887002e83625a837f9ecbe540d1d3reed@google.com dst.round(&idst); 1686ad514302158887002e83625a837f9ecbe540d1d3reed@google.com return isrc == idst; 1687ad514302158887002e83625a837f9ecbe540d1d3reed@google.com} 168808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org 16895b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org// A square matrix M can be decomposed (via polar decomposition) into two matrices -- 16905b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org// an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T, 16915b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org// where U is another orthogonal matrix and W is a scale matrix. These can be recombined 16925b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org// to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix. 16935b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org// 16945b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org// The one wrinkle is that traditionally Q may contain a reflection -- the 16955b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org// calculation has been rejiggered to put that reflection into W. 169608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.orgbool SkDecomposeUpper2x2(const SkMatrix& matrix, 16975b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org SkPoint* rotation1, 16985b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org SkPoint* scale, 16995b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org SkPoint* rotation2) { 170008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org 170108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org SkScalar A = matrix[SkMatrix::kMScaleX]; 170208284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org SkScalar B = matrix[SkMatrix::kMSkewX]; 170308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org SkScalar C = matrix[SkMatrix::kMSkewY]; 170408284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org SkScalar D = matrix[SkMatrix::kMScaleY]; 170508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org 17064dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org if (is_degenerate_2x2(A, B, C, D)) { 17074dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org return false; 17084dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org } 17094dcd062803fef457899add1df56e9defb667ce8dcommit-bot@chromium.org 17105b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org double w1, w2; 17115b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org SkScalar cos1, sin1; 17125b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org SkScalar cos2, sin2; 171308284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org 17145b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org // do polar decomposition (M = Q*S) 17155b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org SkScalar cosQ, sinQ; 17165b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org double Sa, Sb, Sd; 17175b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org // if M is already symmetric (i.e., M = I*S) 17185b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org if (SkScalarNearlyEqual(B, C)) { 17190b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org cosQ = 1; 17205b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org sinQ = 0; 172108284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org 17225b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org Sa = A; 17235b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org Sb = B; 17245b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org Sd = D; 172508284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org } else { 17265b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org cosQ = A + D; 17275b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org sinQ = C - B; 17280b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ)); 17295b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org cosQ *= reciplen; 17305b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org sinQ *= reciplen; 17315b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org 17325b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org // S = Q^-1*M 17335b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org // we don't calc Sc since it's symmetric 17345b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org Sa = A*cosQ + C*sinQ; 17355b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org Sb = B*cosQ + D*sinQ; 17365b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org Sd = -B*sinQ + D*cosQ; 17375b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org } 17385b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org 17395b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org // Now we need to compute eigenvalues of S (our scale factors) 17405b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org // and eigenvectors (bases for our rotation) 17415b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org // From this, should be able to reconstruct S as U*W*U^T 174225f72ed03485f58998846d80858d64b5a3c40c7fjvanverth@google.com if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) { 17435b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org // already diagonalized 17440b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org cos1 = 1; 17455b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org sin1 = 0; 17465b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org w1 = Sa; 17475b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org w2 = Sd; 17485b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org cos2 = cosQ; 17495b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org sin2 = sinQ; 175085092f05c406ed5a0c65ff576816924c1a6b903bskia.committer@gmail.com } else { 17515b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org double diff = Sa - Sd; 17525b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org double discriminant = sqrt(diff*diff + 4.0*Sb*Sb); 17535b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org double trace = Sa + Sd; 17545b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org if (diff > 0) { 17555b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org w1 = 0.5*(trace + discriminant); 17565b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org w2 = 0.5*(trace - discriminant); 17575b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org } else { 17585b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org w1 = 0.5*(trace - discriminant); 17595b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org w2 = 0.5*(trace + discriminant); 176008284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org } 176185092f05c406ed5a0c65ff576816924c1a6b903bskia.committer@gmail.com 176225f72ed03485f58998846d80858d64b5a3c40c7fjvanverth@google.com cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa); 17630b9ada1318acf7d5fe90c57331c2a4548aad8b98commit-bot@chromium.org SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1)); 17645b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org cos1 *= reciplen; 17655b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org sin1 *= reciplen; 176685092f05c406ed5a0c65ff576816924c1a6b903bskia.committer@gmail.com 17675b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org // rotation 2 is composition of Q and U 17685b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org cos2 = cos1*cosQ - sin1*sinQ; 17695b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org sin2 = sin1*cosQ + cos1*sinQ; 177085092f05c406ed5a0c65ff576816924c1a6b903bskia.committer@gmail.com 17715b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org // rotation 1 is U^T 17725b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org sin1 = -sin1; 17735b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org } 17745b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org 17755b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org if (NULL != scale) { 177625f72ed03485f58998846d80858d64b5a3c40c7fjvanverth@google.com scale->fX = SkDoubleToScalar(w1); 177725f72ed03485f58998846d80858d64b5a3c40c7fjvanverth@google.com scale->fY = SkDoubleToScalar(w2); 177808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org } 177908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org if (NULL != rotation1) { 17805b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org rotation1->fX = cos1; 17815b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org rotation1->fY = sin1; 17825b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org } 17835b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org if (NULL != rotation2) { 17845b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org rotation2->fX = cos2; 17855b2e2640ed345c4670b99b349f62eb6f9446ec1ecommit-bot@chromium.org rotation2->fY = sin2; 178608284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org } 178708284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org 178808284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org return true; 178908284e4d2421fb6c1978e68038a3568711cd9877commit-bot@chromium.org} 1790