1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkMatrix_DEFINED 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkMatrix_DEFINED 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 130b544ae222aab1c5d9122a8dfe2800451b31d979mtklein#include "SkDynamicAnnotations.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRect.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkString; 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 188f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com// TODO: can we remove these 3 (need to check chrome/android) 198f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.comtypedef SkScalar SkPersp; 208f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com#define SkScalarToPersp(x) (x) 218f4d2306fa866a26f9448048ff63f692b2ba43aareed@google.com#define SkPerspToScalar(x) (x) 2207faed110275048c83a55ae39042da2c9d916108bungeman@google.com 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkMatrix 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The SkMatrix class holds a 3x3 matrix for transforming coordinates. 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix does not have a constructor, so it must be explicitly initialized 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com using either reset() - to construct an identity matrix, or one of the set 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com functions (e.g. setTranslate, setRotate, etc.). 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 307ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgclass SK_API SkMatrix { 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Enum of bit fields for the mask return by getType(). 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Use this to identify the complexity of the matrix. 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com enum TypeMask { 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kIdentity_Mask = 0, 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kTranslate_Mask = 0x01, //!< set if the matrix has translation 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kScale_Mask = 0x02, //!< set if the matrix has X or Y scale 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kAffine_Mask = 0x04, //!< set if the matrix skews or rotates 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kPerspective_Mask = 0x08 //!< set if the matrix is in perspective 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 43fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com /** Returns a bitfield describing the transformations the matrix may 44fd4c00eb36c9164487bf9e1cea39eaca64a9be91bsalomon@google.com perform. The bitfield is computed conservatively, so it may include 45fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com false positives. For example, when kPerspective_Mask is true, all 46fd4c00eb36c9164487bf9e1cea39eaca64a9be91bsalomon@google.com other bits may be set to true even in the case of a pure perspective 47fd4c00eb36c9164487bf9e1cea39eaca64a9be91bsalomon@google.com transform. 486fc5699e777c27c4eea9587a131aecf6e92a677ajunov@chromium.org */ 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TypeMask getType() const { 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fTypeMask & kUnknown_Mask) { 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTypeMask = this->computeTypeMask(); 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // only return the public masks 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (TypeMask)(fTypeMask & 0xF); 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Returns true if the matrix is identity. 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isIdentity() const { 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->getType() == 0; 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 63e12770148a7d170e4845ebfae75ac38ae9cf4f32Robert Phillips bool isScaleTranslate() const { 64e12770148a7d170e4845ebfae75ac38ae9cf4f32Robert Phillips return !(this->getType() & ~(kScale_Mask | kTranslate_Mask)); 65e12770148a7d170e4845ebfae75ac38ae9cf4f32Robert Phillips } 66e12770148a7d170e4845ebfae75ac38ae9cf4f32Robert Phillips 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Returns true if will map a rectangle to another rectangle. This can be 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com true if the matrix is identity, scale-only, or rotates a multiple of 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 90 degrees. 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool rectStaysRect() const { 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fTypeMask & kUnknown_Mask) { 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTypeMask = this->computeTypeMask(); 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (fTypeMask & kRectStaysRect_Mask) != 0; 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 77cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com // alias for rectStaysRect() 78cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com bool preservesAxisAlignment() const { return this->rectStaysRect(); } 79cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com 80cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com /** 81dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com * Returns true if the matrix contains perspective elements. 82cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com */ 83cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com bool hasPerspective() const { 84dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com return SkToBool(this->getPerspectiveTypeMaskOnly() & 85dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com kPerspective_Mask); 86cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com } 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8817a845f76094eb3b5ac464556fced2a60dd0f088jvanverth /** Returns true if the matrix contains only translation, rotation/reflection or uniform scale 8946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com Returns false if other transformation types are included or is degenerate 9046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com */ 9146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const; 9246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com 9317a845f76094eb3b5ac464556fced2a60dd0f088jvanverth /** Returns true if the matrix contains only translation, rotation/reflection or scale 94df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com (non-uniform scale is allowed). 95df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com Returns false if other transformation types are included or is degenerate 96df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com */ 97df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const; 98df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com enum { 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMScaleX, 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMSkewX, 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMTransX, 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMSkewY, 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMScaleY, 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMTransY, 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMPersp0, 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMPersp1, 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMPersp2 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 110fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1111ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com /** Affine arrays are in column major order 1121ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com because that's how PDF and XPS like it. 1131ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com */ 1141ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com enum { 1151ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com kAScaleX, 1161ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com kASkewY, 1171ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com kASkewX, 1181ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com kAScaleY, 1191ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com kATransX, 1201ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com kATransY 1211ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com }; 1221ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar operator[](int index) const { 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)index < 9); 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMat[index]; 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 127fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar get(int index) const { 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)index < 9); 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fMat[index]; 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 132fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar getScaleX() const { return fMat[kMScaleX]; } 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar getScaleY() const { return fMat[kMScaleY]; } 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar getSkewY() const { return fMat[kMSkewY]; } 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar getSkewX() const { return fMat[kMSkewX]; } 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar getTranslateX() const { return fMat[kMTransX]; } 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar getTranslateY() const { return fMat[kMTransY]; } 13907faed110275048c83a55ae39042da2c9d916108bungeman@google.com SkPersp getPerspX() const { return fMat[kMPersp0]; } 14007faed110275048c83a55ae39042da2c9d916108bungeman@google.com SkPersp getPerspY() const { return fMat[kMPersp1]; } 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 142d055c1fde2128514167b315f4d104b177e04a3dereed@android.com SkScalar& operator[](int index) { 143d055c1fde2128514167b315f4d104b177e04a3dereed@android.com SkASSERT((unsigned)index < 9); 144d055c1fde2128514167b315f4d104b177e04a3dereed@android.com this->setTypeMask(kUnknown_Mask); 145d055c1fde2128514167b315f4d104b177e04a3dereed@android.com return fMat[index]; 146d055c1fde2128514167b315f4d104b177e04a3dereed@android.com } 147d055c1fde2128514167b315f4d104b177e04a3dereed@android.com 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void set(int index, SkScalar value) { 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)index < 9); 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMat[index] = value; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setTypeMask(kUnknown_Mask); 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setScaleX(SkScalar v) { this->set(kMScaleX, v); } 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setScaleY(SkScalar v) { this->set(kMScaleY, v); } 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setSkewY(SkScalar v) { this->set(kMSkewY, v); } 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setSkewX(SkScalar v) { this->set(kMSkewX, v); } 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setTranslateX(SkScalar v) { this->set(kMTransX, v); } 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setTranslateY(SkScalar v) { this->set(kMTransY, v); } 16007faed110275048c83a55ae39042da2c9d916108bungeman@google.com void setPerspX(SkPersp v) { this->set(kMPersp0, v); } 16107faed110275048c83a55ae39042da2c9d916108bungeman@google.com void setPerspY(SkPersp v) { this->set(kMPersp1, v); } 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 163cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com void setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, 164cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com SkScalar skewY, SkScalar scaleY, SkScalar transY, 16507faed110275048c83a55ae39042da2c9d916108bungeman@google.com SkPersp persp0, SkPersp persp1, SkPersp persp2) { 166cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com fMat[kMScaleX] = scaleX; 167cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com fMat[kMSkewX] = skewX; 168cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com fMat[kMTransX] = transX; 169cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com fMat[kMSkewY] = skewY; 170cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com fMat[kMScaleY] = scaleY; 171cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com fMat[kMTransY] = transY; 172cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com fMat[kMPersp0] = persp0; 173cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com fMat[kMPersp1] = persp1; 174cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com fMat[kMPersp2] = persp2; 175cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com this->setTypeMask(kUnknown_Mask); 176cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com } 177fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to identity 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void reset(); 181cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com // alias for reset() 182cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com void setIdentity() { this->reset(); } 183cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to translate by (dx, dy). 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setTranslate(SkScalar dx, SkScalar dy); 1877b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com void setTranslate(const SkVector& v) { this->setTranslate(v.fX, v.fY); } 1887b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to scale by sx and sy, with a pivot point at (px, py). 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The pivot point is the coordinate that should remain unchanged by the 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com specified transformation. 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to scale by sx and sy. 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setScale(SkScalar sx, SkScalar sy); 1975c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com /** Set the matrix to scale by 1/divx and 1/divy. Returns false and doesn't 1985c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com touch the matrix if either divx or divy is zero. 1995c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com */ 2005c63865b529eb5714e41419dfa23c70d26ff6e4ebsalomon@google.com bool setIDiv(int divx, int divy); 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to rotate by the specified number of degrees, with a 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pivot point at (px, py). The pivot point is the coordinate that should 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com remain unchanged by the specified transformation. 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setRotate(SkScalar degrees, SkScalar px, SkScalar py); 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to rotate about (0,0) by the specified number of degrees. 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setRotate(SkScalar degrees); 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to rotate by the specified sine and cosine values, with 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a pivot point at (px, py). The pivot point is the coordinate that 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com should remain unchanged by the specified transformation. 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setSinCos(SkScalar sinValue, SkScalar cosValue, 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar px, SkScalar py); 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to rotate by the specified sine and cosine values. 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setSinCos(SkScalar sinValue, SkScalar cosValue); 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to skew by sx and sy, with a pivot point at (px, py). 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com The pivot point is the coordinate that should remain unchanged by the 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com specified transformation. 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to skew by sx and sy. 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setSkew(SkScalar kx, SkScalar ky); 22692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org /** Set the matrix to the concatenation of the two specified matrices. 22792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org Either of the two matrices may also be the target matrix. 22892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org *this = a * b; 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 23092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void setConcat(const SkMatrix& a, const SkMatrix& b); 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Preconcats the matrix with the specified translation. 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = M * T(dx, dy) 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 23592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void preTranslate(SkScalar dx, SkScalar dy); 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Preconcats the matrix with the specified scale. 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = M * S(sx, sy, px, py) 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 23992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Preconcats the matrix with the specified scale. 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = M * S(sx, sy) 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 24392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void preScale(SkScalar sx, SkScalar sy); 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Preconcats the matrix with the specified rotation. 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = M * R(degrees, px, py) 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 24792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void preRotate(SkScalar degrees, SkScalar px, SkScalar py); 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Preconcats the matrix with the specified rotation. 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = M * R(degrees) 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 25192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void preRotate(SkScalar degrees); 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Preconcats the matrix with the specified skew. 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = M * K(kx, ky, px, py) 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 25592362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Preconcats the matrix with the specified skew. 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = M * K(kx, ky) 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 25992362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void preSkew(SkScalar kx, SkScalar ky); 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Preconcats the matrix with the specified matrix. 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = M * other 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 26392362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void preConcat(const SkMatrix& other); 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Postconcats the matrix with the specified translation. 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = T(dx, dy) * M 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 26892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void postTranslate(SkScalar dx, SkScalar dy); 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Postconcats the matrix with the specified scale. 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = S(sx, sy, px, py) * M 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 27292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Postconcats the matrix with the specified scale. 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = S(sx, sy) * M 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 27692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void postScale(SkScalar sx, SkScalar sy); 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Postconcats the matrix by dividing it by the specified integers. 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = S(1/divx, 1/divy, 0, 0) * M 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool postIDiv(int divx, int divy); 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Postconcats the matrix with the specified rotation. 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = R(degrees, px, py) * M 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 28492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void postRotate(SkScalar degrees, SkScalar px, SkScalar py); 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Postconcats the matrix with the specified rotation. 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = R(degrees) * M 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 28892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void postRotate(SkScalar degrees); 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Postconcats the matrix with the specified skew. 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = K(kx, ky, px, py) * M 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 29292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Postconcats the matrix with the specified skew. 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = K(kx, ky) * M 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 29692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void postSkew(SkScalar kx, SkScalar ky); 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Postconcats the matrix with the specified matrix. 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com M' = other * M 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 30092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org void postConcat(const SkMatrix& other); 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com enum ScaleToFit { 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Scale in X and Y independently, so that src matches dst exactly. 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * This may change the aspect ratio of the src. 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kFill_ScaleToFit, 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Compute a scale that will maintain the original src aspect ratio, 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * but will also ensure that src fits entirely inside dst. At least one 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * axis (X or Y) will fit exactly. kStart aligns the result to the 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * left and top edges of dst. 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kStart_ScaleToFit, 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Compute a scale that will maintain the original src aspect ratio, 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * but will also ensure that src fits entirely inside dst. At least one 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * axis (X or Y) will fit exactly. The result is centered inside dst. 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kCenter_ScaleToFit, 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * Compute a scale that will maintain the original src aspect ratio, 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * but will also ensure that src fits entirely inside dst. At least one 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * axis (X or Y) will fit exactly. kEnd aligns the result to the 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * right and bottom edges of dst. 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kEnd_ScaleToFit 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix to the scale and translate values that map the source 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rectangle to the destination rectangle, returning true if the the result 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com can be represented. 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param src the source rectangle to map from. 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param dst the destination rectangle to map to. 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param stf the ScaleToFit option 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @return true if the matrix can be represented by the rectangle mapping. 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf); 339fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set the matrix such that the specified src points would map to the 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com specified dst points. count must be within [0..4]. 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param src The array of src points 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param dst The array of dst points 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param count The number of points to use for the transformation 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @return true if the matrix was set to the specified transformation 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count); 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** If this matrix can be inverted, return true and if inverse is not null, 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com set inverse to be the inverse of this matrix. If this matrix cannot be 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inverted, ignore inverse and return false 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 353683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const { 354683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com // Allow the trivial case to be inlined. 355683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com if (this->isIdentity()) { 35649f085dddff10473b6ebf832a974288300224e60bsalomon if (inverse) { 357683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com inverse->reset(); 358683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com } 359683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com return true; 360683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com } 361683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com return this->invertNonIdentity(inverse); 362683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com } 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3641ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com /** Fills the passed array with affine identity values 3651ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com in column major order. 3661ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com @param affine The array to fill with affine identity values. 3671ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com Must not be NULL. 3681ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com */ 3691ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com static void SetAffineIdentity(SkScalar affine[6]); 3701ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com 3711ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com /** Fills the passed array with the affine values in column major order. 3721ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com If the matrix is a perspective transform, returns false 3731ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com and does not change the passed array. 3741ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com @param affine The array to fill with affine values. Ignored if NULL. 375ddbbd805b5b453e12cda0b3300e5655d8fb2bc19vandebo@chromium.org */ 3761ddd7c39289b7dd18537fdac4b630e378cd78842bungeman@google.com bool asAffine(SkScalar affine[6]) const; 377ddbbd805b5b453e12cda0b3300e5655d8fb2bc19vandebo@chromium.org 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Apply this matrix to the array of points specified by src, and write 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com the transformed points into the array of points specified by dst. 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[] = M * src[] 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param dst Where the transformed coordinates are written. It must 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com contain at least count entries 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param src The original coordinates that are to be transformed. It 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com must contain at least count entries 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param count The number of points in src to read, and then transform 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com into dst. 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void mapPoints(SkPoint dst[], const SkPoint src[], int count) const; 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Apply this matrix to the array of points, overwriting it with the 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com transformed values. 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[] = M * pts[] 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param pts The points to be transformed. It must contain at least 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count entries 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param count The number of points in pts. 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void mapPoints(SkPoint pts[], int count) const { 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->mapPoints(pts, pts, count); 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 400fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 401647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com /** Like mapPoints but with custom byte stride between the points. Stride 402647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com * should be a multiple of sizeof(SkScalar). 403647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com */ 404647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const { 405647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com SkASSERT(stride >= sizeof(SkPoint)); 406647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com SkASSERT(0 == stride % sizeof(SkScalar)); 407647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com for (int i = 0; i < count; ++i) { 408647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com this->mapPoints(pts, pts, 1); 409647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com pts = (SkPoint*)((intptr_t)pts + stride); 410647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com } 411647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com } 412647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com 413647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com /** Like mapPoints but with custom byte stride between the points. 414647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com */ 415647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com void mapPointsWithStride(SkPoint dst[], SkPoint src[], 416647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com size_t stride, int count) const { 417647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com SkASSERT(stride >= sizeof(SkPoint)); 418647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com SkASSERT(0 == stride % sizeof(SkScalar)); 419647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com for (int i = 0; i < count; ++i) { 420647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com this->mapPoints(dst, src, 1); 421647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com src = (SkPoint*)((intptr_t)src + stride); 422647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com dst = (SkPoint*)((intptr_t)dst + stride); 423647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com } 424647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com } 425647a804c3dd53b6743091ec97dd12111f90efec3bsalomon@google.com 426259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com /** Apply this matrix to the array of homogeneous points, specified by src, 427259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com where a homogeneous point is defined by 3 contiguous scalar values, 428259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com and write the transformed points into the array of scalars specified by dst. 429259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com dst[] = M * src[] 430259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com @param dst Where the transformed coordinates are written. It must 431259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com contain at least 3 * count entries 432259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com @param src The original coordinates that are to be transformed. It 433259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com must contain at least 3 * count entries 434259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com @param count The number of triples (homogeneous points) in src to read, 435259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com and then transform into dst. 436259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com */ 437259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com void mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const; 438259fbaf7a464827bc560517988daeb5836e11e98egdaniel@google.com 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void mapXY(SkScalar x, SkScalar y, SkPoint* result) const { 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(result); 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->getMapXYProc()(*this, x, y, result); 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Apply this matrix to the array of vectors specified by src, and write 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com the transformed vectors into the array of vectors specified by dst. 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com This is similar to mapPoints, but ignores any translation in the matrix. 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param dst Where the transformed coordinates are written. It must 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com contain at least count entries 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param src The original coordinates that are to be transformed. It 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com must contain at least count entries 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param count The number of vectors in src to read, and then transform 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com into dst. 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void mapVectors(SkVector dst[], const SkVector src[], int count) const; 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Apply this matrix to the array of vectors specified by src, and write 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com the transformed vectors into the array of vectors specified by dst. 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com This is similar to mapPoints, but ignores any translation in the matrix. 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param vecs The vectors to be transformed. It must contain at least 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count entries 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param count The number of vectors in vecs. 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void mapVectors(SkVector vecs[], int count) const { 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->mapVectors(vecs, vecs, count); 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Apply this matrix to the src rectangle, and write the transformed 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rectangle into dst. This is accomplished by transforming the 4 corners 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com of src, and then setting dst to the bounds of those points. 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param dst Where the transformed rectangle is written. 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param src The original rectangle to be transformed. 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @return the result of calling rectStaysRect() 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool mapRect(SkRect* dst, const SkRect& src) const; 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Apply this matrix to the rectangle, and write the transformed rectangle 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com back into it. This is accomplished by transforming the 4 corners of 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rect, and then setting it to the bounds of those points 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @param rect The rectangle to transform. 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com @return the result of calling rectStaysRect() 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool mapRect(SkRect* rect) const { 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->mapRect(rect, *rect); 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 48624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /** Apply this matrix to the src rectangle, and write the four transformed 48724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org points into dst. The points written to dst will be the original top-left, top-right, 48824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org bottom-right, and bottom-left points transformed by the matrix. 48924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org @param dst Where the transformed quad is written. 49024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org @param rect The original rectangle to be transformed. 49124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org */ 49224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const { 49324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org // This could potentially be faster if we only transformed each x and y of the rect once. 49424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org rect.toQuad(dst); 49524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org this->mapPoints(dst, 4); 49624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org } 49724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Return the mean radius of a circle after it has been mapped by 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this matrix. NOTE: in perspective this value assumes the circle 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com has its center at the origin. 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar mapRadius(SkScalar radius) const; 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y, 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* result); 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static MapXYProc GetMapXYProc(TypeMask mask) { 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((mask & ~kAllMasks) == 0); 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return gMapXYProcs[mask & kAllMasks]; 5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 511fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MapXYProc getMapXYProc() const { 5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return GetMapXYProc(this->getType()); 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[], 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint src[], int count); 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static MapPtsProc GetMapPtsProc(TypeMask mask) { 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((mask & ~kAllMasks) == 0); 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return gMapPtsProcs[mask & kAllMasks]; 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 523fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MapPtsProc getMapPtsProc() const { 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return GetMapPtsProc(this->getType()); 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** If the matrix can be stepped in X (not complex perspective) 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com then return true and if step[XY] is not null, return the step[XY] value. 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com If it cannot, return false and ignore step. 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const; 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5348fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com /** Efficient comparison of two matrices. It distinguishes between zero and 5358fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com * negative zero. It will return false when the sign of zero values is the 5368fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com * only difference between the two matrices. It considers NaN values to be 5378fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com * equal to themselves. So a matrix full of NaNs is "cheap equal" to 5388fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com * another matrix full of NaNs iff the NaN values are bitwise identical 5398fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com * while according to strict the strict == test a matrix with a NaN value 5408fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com * is equal to nothing, including itself. 5418fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com */ 5428fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com bool cheapEqualTo(const SkMatrix& m) const { 5438fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com return 0 == memcmp(fMat, m.fMat, sizeof(fMat)); 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5468fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com friend bool operator==(const SkMatrix& a, const SkMatrix& b); 5473fb5187647397e056843c1f41a508992be22175dreed@google.com friend bool operator!=(const SkMatrix& a, const SkMatrix& b) { 5483fb5187647397e056843c1f41a508992be22175dreed@google.com return !(a == b); 5493fb5187647397e056843c1f41a508992be22175dreed@google.com } 5500ad336f8c6f6f0325eee309c9cd501ea432cc33ereed@android.com 5514b7577b042966657c776fd95c67f9363af57945freed@android.com enum { 55294e75ee46a569cbcdf61fb7f04ee3a69d3ca0896djsollen@google.com // writeTo/readFromMemory will never return a value larger than this 5534b7577b042966657c776fd95c67f9363af57945freed@android.com kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t) 5544b7577b042966657c776fd95c67f9363af57945freed@android.com }; 5550ad336f8c6f6f0325eee309c9cd501ea432cc33ereed@android.com // return the number of bytes written, whether or not buffer is null 5564faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org size_t writeToMemory(void* buffer) const; 5574faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org /** 5584faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * Reads data from the buffer parameter 5594faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * 5604faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * @param buffer Memory to read from 5614faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * @param length Amount of memory available in the buffer 5624faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * @return number of bytes read (must be a multiple of 4) or 5634faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org * 0 if there was not enough memory available 5644faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org */ 5654faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org size_t readFromMemory(const void* buffer, size_t length); 566fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 56776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com SkDEVCODE(void dump() const;) 5680f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SK_TO_STRING_NONVIRT() 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 570cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com /** 571311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org * Calculates the minimum scaling factor of the matrix as computed from the SVD of the upper 572311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org * left 2x2. If the matrix has perspective -1 is returned. 573cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org * 5741878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org * @return minumum scale factor 575cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org */ 5761878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org SkScalar getMinScale() const; 577cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org 578cea9abb001b07eaf4340a78db708bfac9e8c68c2commit-bot@chromium.org /** 579311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org * Calculates the maximum scaling factor of the matrix as computed from the SVD of the upper 580311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org * left 2x2. If the matrix has perspective -1 is returned. 581cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com * 5821878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org * @return maximum scale factor 583cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com */ 5841878651990d7c9da72cf43481432232bbef3550dcommit-bot@chromium.org SkScalar getMaxScale() const; 585cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com 586cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com /** 587311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org * Gets both the min and max scale factors. The min scale factor is scaleFactors[0] and the max 588311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org * is scaleFactors[1]. If the matrix has perspective false will be returned and scaleFactors 589311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org * will be unchanged. 590311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org */ 591311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org bool getMinMaxScales(SkScalar scaleFactors[2]) const; 59229de433b06aa4886d75508c1aa28ee7911737760skia.committer@gmail.com 593311a3cda9457d50cc7c2a0fc9f153a9ce2c8cb8ecommit-bot@chromium.org /** 594cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com * Return a reference to a const identity matrix 595cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com */ 596cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com static const SkMatrix& I(); 597cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com 598cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com /** 599cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com * Return a reference to a const matrix that is "invalid", one that could 600cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com * never be used. 601cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com */ 602cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com static const SkMatrix& InvalidMatrix(); 603cc4dac3dac215dc0dd56f7b30d07cc304671b033bsalomon@google.com 604317d540409bc1d246a272b7f61ffba0097c4bd29tomhudson@google.com /** 60599bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org * Return the concatenation of two matrices, a * b. 60699bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org */ 60799bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) { 60899bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org SkMatrix result; 60999bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org result.setConcat(a, b); 61099bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org return result; 61199bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org } 61299bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org 61399bd7d817471ec903a7fe364b4e1d4477b1372b5commit-bot@chromium.org /** 614317d540409bc1d246a272b7f61ffba0097c4bd29tomhudson@google.com * Testing routine; the matrix's type cache should never need to be 615317d540409bc1d246a272b7f61ffba0097c4bd29tomhudson@google.com * manually invalidated during normal use. 616317d540409bc1d246a272b7f61ffba0097c4bd29tomhudson@google.com */ 617317d540409bc1d246a272b7f61ffba0097c4bd29tomhudson@google.com void dirtyMatrixTypeCache() { 618317d540409bc1d246a272b7f61ffba0097c4bd29tomhudson@google.com this->setTypeMask(kUnknown_Mask); 619317d540409bc1d246a272b7f61ffba0097c4bd29tomhudson@google.com } 620317d540409bc1d246a272b7f61ffba0097c4bd29tomhudson@google.com 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com enum { 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Set if the matrix will map a rectangle to another rectangle. This 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com can be true if the matrix is scale-only, or rotates a multiple of 6250e5104c1570de4709e04720e62d80a0ca8970260bsalomon@google.com 90 degrees. 626fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com This bit will be set on identity matrices 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kRectStaysRect_Mask = 0x10, 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 631dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com /** Set if the perspective bit is valid even though the rest of 632dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com the matrix is Unknown. 633dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com */ 634dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com kOnlyPerspectiveValid_Mask = 0x40, 635dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com 6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kUnknown_Mask = 0x80, 6373fb5187647397e056843c1f41a508992be22175dreed@google.com 6383fb5187647397e056843c1f41a508992be22175dreed@google.com kORableMasks = kTranslate_Mask | 6393fb5187647397e056843c1f41a508992be22175dreed@google.com kScale_Mask | 6403fb5187647397e056843c1f41a508992be22175dreed@google.com kAffine_Mask | 6413fb5187647397e056843c1f41a508992be22175dreed@google.com kPerspective_Mask, 6423fb5187647397e056843c1f41a508992be22175dreed@google.com 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kAllMasks = kTranslate_Mask | 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kScale_Mask | 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kAffine_Mask | 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kPerspective_Mask | 6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kRectStaysRect_Mask 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 650601d312bd4a894cb6e981a9dfdc644288f3a4d47tomhudson@google.com SkScalar fMat[9]; 6510b544ae222aab1c5d9122a8dfe2800451b31d979mtklein mutable SkTRacy<uint32_t> fTypeMask; 6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t computeTypeMask() const; 654dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com uint8_t computePerspectiveTypeMask() const; 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setTypeMask(int mask) { 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // allow kUnknown or a valid mask 658dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask || 65902662b7febb826752a1c55cda243ad48b2b85adbjunov@chromium.org ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask) 66002662b7febb826752a1c55cda243ad48b2b85adbjunov@chromium.org == (kUnknown_Mask | kOnlyPerspectiveValid_Mask)); 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTypeMask = SkToU8(mask); 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6633fb5187647397e056843c1f41a508992be22175dreed@google.com 6643fb5187647397e056843c1f41a508992be22175dreed@google.com void orTypeMask(int mask) { 6653fb5187647397e056843c1f41a508992be22175dreed@google.com SkASSERT((mask & kORableMasks) == mask); 6663fb5187647397e056843c1f41a508992be22175dreed@google.com fTypeMask = SkToU8(fTypeMask | mask); 6673fb5187647397e056843c1f41a508992be22175dreed@google.com } 6683fb5187647397e056843c1f41a508992be22175dreed@google.com 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void clearTypeMask(int mask) { 6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // only allow a valid mask 6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((mask & kAllMasks) == mask); 6720b544ae222aab1c5d9122a8dfe2800451b31d979mtklein fTypeMask = fTypeMask & ~mask; 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 674dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com 675dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com TypeMask getPerspectiveTypeMaskOnly() const { 676dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com if ((fTypeMask & kUnknown_Mask) && 677dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com !(fTypeMask & kOnlyPerspectiveValid_Mask)) { 678dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com fTypeMask = this->computePerspectiveTypeMask(); 679dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com } 680dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com return (TypeMask)(fTypeMask & 0xF); 681dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com } 682dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com 683dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com /** Returns true if we already know that the matrix is identity; 684dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com false otherwise. 685dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com */ 686dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com bool isTriviallyIdentity() const { 687dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com if (fTypeMask & kUnknown_Mask) { 688dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com return false; 689dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com } 690dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com return ((fTypeMask & 0xF) == 0); 691dd5f7442f65813c1023a59c3380f4446583ccd5dtomhudson@google.com } 692fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 693683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const; 694683c3c76cfd2cc71621e570889a16548f8cc88c6bsalomon@google.com 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale); 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale); 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale); 6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 706fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const MapXYProc gMapXYProcs[]; 708fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int); 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count); 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void Rot_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void RotTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count); 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 718fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const MapPtsProc gMapPtsProcs[]; 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com friend class SkPerspIter; 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 725