15bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com 2f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/* 35bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * Copyright 2006 The Android Open Source Project 4f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * 55bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * Use of this source code is governed by a BSD-style license that can be 65bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * found in the LICENSE file. 7f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 8f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 95bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com 10f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#ifndef SkMatrix_DEFINED 11f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#define SkMatrix_DEFINED 12f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 13f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#include "SkRect.h" 14f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 15f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comclass SkString; 16f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 1733b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com#ifdef SK_SCALAR_IS_FLOAT 1833b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com typedef SkScalar SkPersp; 1933b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com #define SkScalarToPersp(x) (x) 2033b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com #define SkPerspToScalar(x) (x) 2133b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com#else 2233b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com typedef SkFract SkPersp; 2333b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com #define SkScalarToPersp(x) SkFixedToFract(x) 2433b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com #define SkPerspToScalar(x) SkFractToFixed(x) 2533b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com#endif 2633b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com 27f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** \class SkMatrix 28f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 29f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com The SkMatrix class holds a 3x3 matrix for transforming coordinates. 30f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkMatrix does not have a constructor, so it must be explicitly initialized 31f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com using either reset() - to construct an identity matrix, or one of the set 32f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com functions (e.g. setTranslate, setRotate, etc.). 33f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/ 342083387d719b933797044ad07efd3bb67f99a5c5ctguil@chromium.orgclass SK_API SkMatrix { 35f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.compublic: 36f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Enum of bit fields for the mask return by getType(). 37f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com Use this to identify the complexity of the matrix. 38f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 39f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com enum TypeMask { 40f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kIdentity_Mask = 0, 41f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kTranslate_Mask = 0x01, //!< set if the matrix has translation 42f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kScale_Mask = 0x02, //!< set if the matrix has X or Y scale 43f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kAffine_Mask = 0x04, //!< set if the matrix skews or rotates 44f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kPerspective_Mask = 0x08 //!< set if the matrix is in perspective 45f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com }; 46f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 471fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com /** Returns a bitfield describing the transformations the matrix may 481de8c88f781c346b3dd92b3a882d1eb3ae1f7e70bsalomon@google.com perform. The bitfield is computed conservatively, so it may include 491fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com false positives. For example, when kPerspective_Mask is true, all 501de8c88f781c346b3dd92b3a882d1eb3ae1f7e70bsalomon@google.com other bits may be set to true even in the case of a pure perspective 511de8c88f781c346b3dd92b3a882d1eb3ae1f7e70bsalomon@google.com transform. 521ebef13e8530b48413b9439f1595075d04ab1dcdjunov@chromium.org */ 53f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com TypeMask getType() const { 54f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com if (fTypeMask & kUnknown_Mask) { 55f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTypeMask = this->computeTypeMask(); 56f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 57f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com // only return the public masks 58f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return (TypeMask)(fTypeMask & 0xF); 59f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 60f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 61f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Returns true if the matrix is identity. 62f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 63f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool isIdentity() const { 64f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return this->getType() == 0; 65f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 66f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 67f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Returns true if will map a rectangle to another rectangle. This can be 68f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com true if the matrix is identity, scale-only, or rotates a multiple of 69f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 90 degrees. 70f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 71f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool rectStaysRect() const { 72f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com if (fTypeMask & kUnknown_Mask) { 73f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTypeMask = this->computeTypeMask(); 74f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 75f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return (fTypeMask & kRectStaysRect_Mask) != 0; 76f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 77104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com // alias for rectStaysRect() 78104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com bool preservesAxisAlignment() const { return this->rectStaysRect(); } 79104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com 80104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com /** 81b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com * Returns true if the matrix contains perspective elements. 82104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com */ 83104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com bool hasPerspective() const { 84b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com return SkToBool(this->getPerspectiveTypeMaskOnly() & 85b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com kPerspective_Mask); 86104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com } 87f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 889f4434e38b0718796d97d6746265f076546dd19cjvanverth@google.com /** Returns true if the matrix contains only translation, rotation or uniform scale 899f4434e38b0718796d97d6746265f076546dd19cjvanverth@google.com Returns false if other transformation types are included or is degenerate 909f4434e38b0718796d97d6746265f076546dd19cjvanverth@google.com */ 919f4434e38b0718796d97d6746265f076546dd19cjvanverth@google.com bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const; 929f4434e38b0718796d97d6746265f076546dd19cjvanverth@google.com 93d23e4f39124243f8624e83ef9777f88154427e63robertphillips@google.com /** Returns true if the matrix contains only translation, rotation or scale 94d23e4f39124243f8624e83ef9777f88154427e63robertphillips@google.com (non-uniform scale is allowed). 95d23e4f39124243f8624e83ef9777f88154427e63robertphillips@google.com Returns false if other transformation types are included or is degenerate 96d23e4f39124243f8624e83ef9777f88154427e63robertphillips@google.com */ 97d23e4f39124243f8624e83ef9777f88154427e63robertphillips@google.com bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const; 98d23e4f39124243f8624e83ef9777f88154427e63robertphillips@google.com 99f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com enum { 100f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kMScaleX, 101f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kMSkewX, 102f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kMTransX, 103f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kMSkewY, 104f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kMScaleY, 105f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kMTransY, 106f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kMPersp0, 107f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kMPersp1, 108f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kMPersp2 109f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com }; 1101fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 111f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com /** Affine arrays are in column major order 112f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com because that's how PDF and XPS like it. 113f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com */ 114f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com enum { 115f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com kAScaleX, 116f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com kASkewY, 117f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com kASkewX, 118f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com kAScaleY, 119f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com kATransX, 120f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com kATransY 121f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com }; 122f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com 123f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar operator[](int index) const { 124f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT((unsigned)index < 9); 125f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return fMat[index]; 126f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 1271fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 128f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar get(int index) const { 129f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT((unsigned)index < 9); 130f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return fMat[index]; 131f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 1321fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 133f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar getScaleX() const { return fMat[kMScaleX]; } 134f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar getScaleY() const { return fMat[kMScaleY]; } 135f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar getSkewY() const { return fMat[kMSkewY]; } 136f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar getSkewX() const { return fMat[kMSkewX]; } 137f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar getTranslateX() const { return fMat[kMTransX]; } 138f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar getTranslateY() const { return fMat[kMTransY]; } 13933b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com SkPersp getPerspX() const { return fMat[kMPersp0]; } 14033b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com SkPersp getPerspY() const { return fMat[kMPersp1]; } 141f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 14252f5479f914697415df3e7cc6a04f2e751bc564creed@android.com SkScalar& operator[](int index) { 14352f5479f914697415df3e7cc6a04f2e751bc564creed@android.com SkASSERT((unsigned)index < 9); 14452f5479f914697415df3e7cc6a04f2e751bc564creed@android.com this->setTypeMask(kUnknown_Mask); 14552f5479f914697415df3e7cc6a04f2e751bc564creed@android.com return fMat[index]; 14652f5479f914697415df3e7cc6a04f2e751bc564creed@android.com } 14752f5479f914697415df3e7cc6a04f2e751bc564creed@android.com 148f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void set(int index, SkScalar value) { 149f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT((unsigned)index < 9); 150f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fMat[index] = value; 151f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com this->setTypeMask(kUnknown_Mask); 152f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 153f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 154f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setScaleX(SkScalar v) { this->set(kMScaleX, v); } 155f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setScaleY(SkScalar v) { this->set(kMScaleY, v); } 156f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setSkewY(SkScalar v) { this->set(kMSkewY, v); } 157f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setSkewX(SkScalar v) { this->set(kMSkewX, v); } 158f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setTranslateX(SkScalar v) { this->set(kMTransX, v); } 159f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setTranslateY(SkScalar v) { this->set(kMTransY, v); } 16033b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com void setPerspX(SkPersp v) { this->set(kMPersp0, v); } 16133b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com void setPerspY(SkPersp v) { this->set(kMPersp1, v); } 162f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 163104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com void setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, 164104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com SkScalar skewY, SkScalar scaleY, SkScalar transY, 16533b76b59d1840fc7731985460404de45fbe26e2bbungeman@google.com SkPersp persp0, SkPersp persp1, SkPersp persp2) { 166104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com fMat[kMScaleX] = scaleX; 167104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com fMat[kMSkewX] = skewX; 168104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com fMat[kMTransX] = transX; 169104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com fMat[kMSkewY] = skewY; 170104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com fMat[kMScaleY] = scaleY; 171104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com fMat[kMTransY] = transY; 172104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com fMat[kMPersp0] = persp0; 173104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com fMat[kMPersp1] = persp1; 174104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com fMat[kMPersp2] = persp2; 175104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com this->setTypeMask(kUnknown_Mask); 176104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com } 1771fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 178f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to identity 179f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 180f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void reset(); 181104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com // alias for reset() 182104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com void setIdentity() { this->reset(); } 183104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com 184f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to translate by (dx, dy). 185f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 186f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setTranslate(SkScalar dx, SkScalar dy); 1879613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com void setTranslate(const SkVector& v) { this->setTranslate(v.fX, v.fY); } 1889613767e1f1d08ce627c665e8c0098cb59b10931bsalomon@google.com 189f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to scale by sx and sy, with a pivot point at (px, py). 190f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com The pivot point is the coordinate that should remain unchanged by the 191f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com specified transformation. 192f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 193f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); 194f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to scale by sx and sy. 195f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 196f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setScale(SkScalar sx, SkScalar sy); 19790b26fa6e1082ee8d22aac0702012e7502daecbfbsalomon@google.com /** Set the matrix to scale by 1/divx and 1/divy. Returns false and doesn't 19890b26fa6e1082ee8d22aac0702012e7502daecbfbsalomon@google.com touch the matrix if either divx or divy is zero. 19990b26fa6e1082ee8d22aac0702012e7502daecbfbsalomon@google.com */ 20090b26fa6e1082ee8d22aac0702012e7502daecbfbsalomon@google.com bool setIDiv(int divx, int divy); 201f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to rotate by the specified number of degrees, with a 202f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com pivot point at (px, py). The pivot point is the coordinate that should 203f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com remain unchanged by the specified transformation. 204f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 205f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setRotate(SkScalar degrees, SkScalar px, SkScalar py); 206f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to rotate about (0,0) by the specified number of degrees. 207f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 208f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setRotate(SkScalar degrees); 209f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to rotate by the specified sine and cosine values, with 210f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com a pivot point at (px, py). The pivot point is the coordinate that 211f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com should remain unchanged by the specified transformation. 212f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 213f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setSinCos(SkScalar sinValue, SkScalar cosValue, 214f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar px, SkScalar py); 215f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to rotate by the specified sine and cosine values. 216f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 217f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setSinCos(SkScalar sinValue, SkScalar cosValue); 218f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to skew by sx and sy, with a pivot point at (px, py). 219f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com The pivot point is the coordinate that should remain unchanged by the 220f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com specified transformation. 221f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 222f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); 223f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to skew by sx and sy. 224f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 225f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setSkew(SkScalar kx, SkScalar ky); 226f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to the concatenation of the two specified matrices, 227f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com returning true if the the result can be represented. Either of the 228f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com two matrices may also be the target matrix. *this = a * b; 229f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 230f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool setConcat(const SkMatrix& a, const SkMatrix& b); 231f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 232f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Preconcats the matrix with the specified translation. 233f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = M * T(dx, dy) 234f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 235f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool preTranslate(SkScalar dx, SkScalar dy); 236f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Preconcats the matrix with the specified scale. 237f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = M * S(sx, sy, px, py) 238f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 239f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); 240f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Preconcats the matrix with the specified scale. 241f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = M * S(sx, sy) 242f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 243f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool preScale(SkScalar sx, SkScalar sy); 244f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Preconcats the matrix with the specified rotation. 245f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = M * R(degrees, px, py) 246f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 247f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool preRotate(SkScalar degrees, SkScalar px, SkScalar py); 248f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Preconcats the matrix with the specified rotation. 249f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = M * R(degrees) 250f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 251f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool preRotate(SkScalar degrees); 252f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Preconcats the matrix with the specified skew. 253f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = M * K(kx, ky, px, py) 254f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 255f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); 256f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Preconcats the matrix with the specified skew. 257f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = M * K(kx, ky) 258f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 259f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool preSkew(SkScalar kx, SkScalar ky); 260f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Preconcats the matrix with the specified matrix. 261f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = M * other 262f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 263f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool preConcat(const SkMatrix& other); 264f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 265f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Postconcats the matrix with the specified translation. 266f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = T(dx, dy) * M 267f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 268f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool postTranslate(SkScalar dx, SkScalar dy); 269f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Postconcats the matrix with the specified scale. 270f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = S(sx, sy, px, py) * M 271f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 272f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); 273f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Postconcats the matrix with the specified scale. 274f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = S(sx, sy) * M 275f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 276f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool postScale(SkScalar sx, SkScalar sy); 277f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Postconcats the matrix by dividing it by the specified integers. 278f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = S(1/divx, 1/divy, 0, 0) * M 279f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 280f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool postIDiv(int divx, int divy); 281f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Postconcats the matrix with the specified rotation. 282f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = R(degrees, px, py) * M 283f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 284f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool postRotate(SkScalar degrees, SkScalar px, SkScalar py); 285f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Postconcats the matrix with the specified rotation. 286f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = R(degrees) * M 287f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 288f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool postRotate(SkScalar degrees); 289f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Postconcats the matrix with the specified skew. 290f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = K(kx, ky, px, py) * M 291f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 292f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); 293f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Postconcats the matrix with the specified skew. 294f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = K(kx, ky) * M 295f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 296f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool postSkew(SkScalar kx, SkScalar ky); 297f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Postconcats the matrix with the specified matrix. 298f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com M' = other * M 299f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 300f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool postConcat(const SkMatrix& other); 301f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 302f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com enum ScaleToFit { 303f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** 304f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * Scale in X and Y independently, so that src matches dst exactly. 305f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * This may change the aspect ratio of the src. 306f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 307f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kFill_ScaleToFit, 308f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** 309f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * Compute a scale that will maintain the original src aspect ratio, 310f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * but will also ensure that src fits entirely inside dst. At least one 311f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * axis (X or Y) will fit exactly. kStart aligns the result to the 312f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * left and top edges of dst. 313f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 314f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kStart_ScaleToFit, 315f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** 316f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * Compute a scale that will maintain the original src aspect ratio, 317f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * but will also ensure that src fits entirely inside dst. At least one 318f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * axis (X or Y) will fit exactly. The result is centered inside dst. 319f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 320f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kCenter_ScaleToFit, 321f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** 322f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * Compute a scale that will maintain the original src aspect ratio, 323f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * but will also ensure that src fits entirely inside dst. At least one 324f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * axis (X or Y) will fit exactly. kEnd aligns the result to the 325f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com * right and bottom edges of dst. 326f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 327f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kEnd_ScaleToFit 328f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com }; 329f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 330f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix to the scale and translate values that map the source 331f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com rectangle to the destination rectangle, returning true if the the result 332f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com can be represented. 333f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param src the source rectangle to map from. 334f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param dst the destination rectangle to map to. 335f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param stf the ScaleToFit option 336f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @return true if the matrix can be represented by the rectangle mapping. 337f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 338f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf); 3391fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 340f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set the matrix such that the specified src points would map to the 341f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com specified dst points. count must be within [0..4]. 342f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param src The array of src points 343f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param dst The array of dst points 344f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param count The number of points to use for the transformation 345f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @return true if the matrix was set to the specified transformation 346f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 347f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count); 348f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 349f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** If this matrix can be inverted, return true and if inverse is not null, 350f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com set inverse to be the inverse of this matrix. If this matrix cannot be 351f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com inverted, ignore inverse and return false 352f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 353f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const { 354f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com // Allow the trivial case to be inlined. 355f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com if (this->isIdentity()) { 356f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com if (NULL != inverse) { 357f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com inverse->reset(); 358f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com } 359f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com return true; 360f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com } 361f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com return this->invertNonIdentity(inverse); 362f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com } 363f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 364f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com /** Fills the passed array with affine identity values 365f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com in column major order. 366f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com @param affine The array to fill with affine identity values. 367f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com Must not be NULL. 368f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com */ 369f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com static void SetAffineIdentity(SkScalar affine[6]); 370f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com 371f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com /** Fills the passed array with the affine values in column major order. 372f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com If the matrix is a perspective transform, returns false 373f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com and does not change the passed array. 374f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com @param affine The array to fill with affine values. Ignored if NULL. 375b5c881444329c8c4b6bfda0d8babd33b6927a9advandebo@chromium.org */ 376f5fdad15a20383dafce6acb4024261be76b90988bungeman@google.com bool asAffine(SkScalar affine[6]) const; 377b5c881444329c8c4b6bfda0d8babd33b6927a9advandebo@chromium.org 378f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Apply this matrix to the array of points specified by src, and write 379f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com the transformed points into the array of points specified by dst. 380f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com dst[] = M * src[] 381f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param dst Where the transformed coordinates are written. It must 382f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com contain at least count entries 383f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param src The original coordinates that are to be transformed. It 384f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com must contain at least count entries 385f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param count The number of points in src to read, and then transform 386f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com into dst. 387f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 388f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void mapPoints(SkPoint dst[], const SkPoint src[], int count) const; 389f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 390f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Apply this matrix to the array of points, overwriting it with the 391f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com transformed values. 392f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com dst[] = M * pts[] 393f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param pts The points to be transformed. It must contain at least 394f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com count entries 395f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param count The number of points in pts. 396f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 397f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void mapPoints(SkPoint pts[], int count) const { 398f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com this->mapPoints(pts, pts, count); 399f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 4001fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 401a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com /** Like mapPoints but with custom byte stride between the points. Stride 402a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com * should be a multiple of sizeof(SkScalar). 403a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com */ 404a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const { 405a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com SkASSERT(stride >= sizeof(SkPoint)); 406a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com SkASSERT(0 == stride % sizeof(SkScalar)); 407a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com for (int i = 0; i < count; ++i) { 408a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com this->mapPoints(pts, pts, 1); 409a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com pts = (SkPoint*)((intptr_t)pts + stride); 410a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com } 411a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com } 412a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com 413a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com /** Like mapPoints but with custom byte stride between the points. 414a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com */ 415a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com void mapPointsWithStride(SkPoint dst[], SkPoint src[], 416a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com size_t stride, int count) const { 417a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com SkASSERT(stride >= sizeof(SkPoint)); 418a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com SkASSERT(0 == stride % sizeof(SkScalar)); 419a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com for (int i = 0; i < count; ++i) { 420a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com this->mapPoints(dst, src, 1); 421a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com src = (SkPoint*)((intptr_t)src + stride); 422a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com dst = (SkPoint*)((intptr_t)dst + stride); 423a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com } 424a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com } 425a244157250c91c9cb57a3e6ca7b64e0d35daebcbbsalomon@google.com 4267d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com /** Apply this matrix to the array of homogeneous points, specified by src, 4277d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com where a homogeneous point is defined by 3 contiguous scalar values, 4287d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com and write the transformed points into the array of scalars specified by dst. 4297d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com dst[] = M * src[] 4307d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com @param dst Where the transformed coordinates are written. It must 4317d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com contain at least 3 * count entries 4327d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com @param src The original coordinates that are to be transformed. It 4337d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com must contain at least 3 * count entries 4347d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com @param count The number of triples (homogeneous points) in src to read, 4357d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com and then transform into dst. 4367d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com */ 4377d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com void mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const; 4387d3f2c3e843e51740e5d8551f2673997c849fb20egdaniel@google.com 439f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void mapXY(SkScalar x, SkScalar y, SkPoint* result) const { 440f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT(result); 441f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com this->getMapXYProc()(*this, x, y, result); 442f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 443f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 444f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Apply this matrix to the array of vectors specified by src, and write 445f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com the transformed vectors into the array of vectors specified by dst. 446f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com This is similar to mapPoints, but ignores any translation in the matrix. 447f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param dst Where the transformed coordinates are written. It must 448f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com contain at least count entries 449f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param src The original coordinates that are to be transformed. It 450f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com must contain at least count entries 451f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param count The number of vectors in src to read, and then transform 452f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com into dst. 453f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 454f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void mapVectors(SkVector dst[], const SkVector src[], int count) const; 455f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 456f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Apply this matrix to the array of vectors specified by src, and write 457f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com the transformed vectors into the array of vectors specified by dst. 458f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com This is similar to mapPoints, but ignores any translation in the matrix. 459f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param vecs The vectors to be transformed. It must contain at least 460f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com count entries 461f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param count The number of vectors in vecs. 462f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 463f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void mapVectors(SkVector vecs[], int count) const { 464f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com this->mapVectors(vecs, vecs, count); 465f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 466f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 467f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Apply this matrix to the src rectangle, and write the transformed 468f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com rectangle into dst. This is accomplished by transforming the 4 corners 469f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com of src, and then setting dst to the bounds of those points. 470f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param dst Where the transformed rectangle is written. 471f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param src The original rectangle to be transformed. 472f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @return the result of calling rectStaysRect() 473f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 474f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool mapRect(SkRect* dst, const SkRect& src) const; 475f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 476f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Apply this matrix to the rectangle, and write the transformed rectangle 477f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com back into it. This is accomplished by transforming the 4 corners of 478f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com rect, and then setting it to the bounds of those points 479f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @param rect The rectangle to transform. 480f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com @return the result of calling rectStaysRect() 481f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 482f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool mapRect(SkRect* rect) const { 483f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return this->mapRect(rect, *rect); 484f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 485f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 4863069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org /** Apply this matrix to the src rectangle, and write the four transformed 4873069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org points into dst. The points written to dst will be the original top-left, top-right, 4883069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org bottom-right, and bottom-left points transformed by the matrix. 4893069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org @param dst Where the transformed quad is written. 4903069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org @param rect The original rectangle to be transformed. 4913069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org */ 4923069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const { 4933069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org // This could potentially be faster if we only transformed each x and y of the rect once. 4943069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org rect.toQuad(dst); 4953069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org this->mapPoints(dst, 4); 4963069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org } 4973069ef5a55b98779152b939822dd609849273fb6commit-bot@chromium.org 498f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Return the mean radius of a circle after it has been mapped by 499f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com this matrix. NOTE: in perspective this value assumes the circle 500f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com has its center at the origin. 501f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 502f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkScalar mapRadius(SkScalar radius) const; 503f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 504f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y, 505f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkPoint* result); 506f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 507f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static MapXYProc GetMapXYProc(TypeMask mask) { 508f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT((mask & ~kAllMasks) == 0); 509f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return gMapXYProcs[mask & kAllMasks]; 510f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 5111fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 512f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com MapXYProc getMapXYProc() const { 513f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return GetMapXYProc(this->getType()); 514f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 515f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 516f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[], 517f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com const SkPoint src[], int count); 518f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 519f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static MapPtsProc GetMapPtsProc(TypeMask mask) { 520f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT((mask & ~kAllMasks) == 0); 521f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return gMapPtsProcs[mask & kAllMasks]; 522f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 5231fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 524f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com MapPtsProc getMapPtsProc() const { 525f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com return GetMapPtsProc(this->getType()); 526f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 527f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 528f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** If the matrix can be stepped in X (not complex perspective) 529f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com then return true and if step[XY] is not null, return the step[XY] value. 530f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com If it cannot, return false and ignore step. 531f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 532f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const; 533f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 5341b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com /** Efficient comparison of two matrices. It distinguishes between zero and 5351b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com * negative zero. It will return false when the sign of zero values is the 5361b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com * only difference between the two matrices. It considers NaN values to be 5371b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com * equal to themselves. So a matrix full of NaNs is "cheap equal" to 5381b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com * another matrix full of NaNs iff the NaN values are bitwise identical 5391b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com * while according to strict the strict == test a matrix with a NaN value 5401b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com * is equal to nothing, including itself. 5411b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com */ 5421b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com bool cheapEqualTo(const SkMatrix& m) const { 5431b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com return 0 == memcmp(fMat, m.fMat, sizeof(fMat)); 544f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 545f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 5461b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com#ifdef SK_SCALAR_IS_FIXED 5471b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com friend bool operator==(const SkMatrix& a, const SkMatrix& b) { 548afcde3a5a6d66f0f269f0a537ffd9f5684aa2bcabsalomon@google.com return a.cheapEqualTo(b); 549f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 550d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com#else 5511b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com friend bool operator==(const SkMatrix& a, const SkMatrix& b); 5521b0d6300fe68e2a9cae4fbc3b5b6ad47aaab2f0ebsalomon@google.com#endif 553d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com friend bool operator!=(const SkMatrix& a, const SkMatrix& b) { 554d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com return !(a == b); 555d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com } 5568bd93bf4de826b5a2343e5b88338d4d636c98bb2reed@android.com 557e48af74e37973fb2b70d00fa74bd774c2662f353reed@android.com enum { 558e8a47507732bffb3ee045727ea9477a067f224d7djsollen@google.com // writeTo/readFromMemory will never return a value larger than this 559e48af74e37973fb2b70d00fa74bd774c2662f353reed@android.com kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t) 560e48af74e37973fb2b70d00fa74bd774c2662f353reed@android.com }; 5618bd93bf4de826b5a2343e5b88338d4d636c98bb2reed@android.com // return the number of bytes written, whether or not buffer is null 5623a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org size_t writeToMemory(void* buffer) const; 5633a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org /** 5643a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org * Reads data from the buffer parameter 5653a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org * 5663a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org * @param buffer Memory to read from 5673a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org * @param length Amount of memory available in the buffer 5683a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org * @return number of bytes read (must be a multiple of 4) or 5693a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org * 0 if there was not enough memory available 5703a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org */ 5713a7d93ce0ea5bbd43a8c998681bebfe3615b3480commit-bot@chromium.org size_t readFromMemory(const void* buffer, size_t length); 5721fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 5736b10a0e65b4e9b82605b6236a2cec9e7c2404898robertphillips@google.com SkDEVCODE(void dump() const;) 5746b10a0e65b4e9b82605b6236a2cec9e7c2404898robertphillips@google.com SkDEVCODE(void toString(SkString*) const;) 575f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 576104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com /** 577b4ca22eb0c93165edae74ae2544ffc56b98eb0dfcommit-bot@chromium.org * Calculates the minimum stretching factor of the matrix. If the matrix has 578b4ca22eb0c93165edae74ae2544ffc56b98eb0dfcommit-bot@chromium.org * perspective -1 is returned. 579b4ca22eb0c93165edae74ae2544ffc56b98eb0dfcommit-bot@chromium.org * 580b4ca22eb0c93165edae74ae2544ffc56b98eb0dfcommit-bot@chromium.org * @return minumum strecthing factor 581b4ca22eb0c93165edae74ae2544ffc56b98eb0dfcommit-bot@chromium.org */ 582b4ca22eb0c93165edae74ae2544ffc56b98eb0dfcommit-bot@chromium.org SkScalar getMinStretch() const; 583b4ca22eb0c93165edae74ae2544ffc56b98eb0dfcommit-bot@chromium.org 584b4ca22eb0c93165edae74ae2544ffc56b98eb0dfcommit-bot@chromium.org /** 585da882f21588ddc33be0617b8c1afe8cac04b6237bsalomon@google.com * Calculates the maximum stretching factor of the matrix. If the matrix has 586862b2f7eef0eac4925188aa0f98d1f15124c41b8bsalomon@google.com * perspective -1 is returned. 587104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com * 588862b2f7eef0eac4925188aa0f98d1f15124c41b8bsalomon@google.com * @return maximum strecthing factor 589104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com */ 590104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com SkScalar getMaxStretch() const; 591104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com 592104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com /** 593104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com * Return a reference to a const identity matrix 594104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com */ 595104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com static const SkMatrix& I(); 596104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com 597104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com /** 598104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com * Return a reference to a const matrix that is "invalid", one that could 599104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com * never be used. 600104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com */ 601104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com static const SkMatrix& InvalidMatrix(); 602104de7640deeaf4453fed3830ea31b63c29e425ebsalomon@google.com 603b2f432c2cffc82221b2138db05b1663a27fce69dtomhudson@google.com /** 604b2f432c2cffc82221b2138db05b1663a27fce69dtomhudson@google.com * Testing routine; the matrix's type cache should never need to be 605b2f432c2cffc82221b2138db05b1663a27fce69dtomhudson@google.com * manually invalidated during normal use. 606b2f432c2cffc82221b2138db05b1663a27fce69dtomhudson@google.com */ 607b2f432c2cffc82221b2138db05b1663a27fce69dtomhudson@google.com void dirtyMatrixTypeCache() { 608b2f432c2cffc82221b2138db05b1663a27fce69dtomhudson@google.com this->setTypeMask(kUnknown_Mask); 609b2f432c2cffc82221b2138db05b1663a27fce69dtomhudson@google.com } 610b2f432c2cffc82221b2138db05b1663a27fce69dtomhudson@google.com 611f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comprivate: 612f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com enum { 613f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com /** Set if the matrix will map a rectangle to another rectangle. This 614f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com can be true if the matrix is scale-only, or rotates a multiple of 6154f4d33c778d64e8b641d5374d00051c6b7946bcbbsalomon@google.com 90 degrees. 6161fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 617f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com This bit will be set on identity matrices 618f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */ 619f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kRectStaysRect_Mask = 0x10, 620f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 621b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com /** Set if the perspective bit is valid even though the rest of 622b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com the matrix is Unknown. 623b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com */ 624b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com kOnlyPerspectiveValid_Mask = 0x40, 625b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com 626f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kUnknown_Mask = 0x80, 627d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com 628d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com kORableMasks = kTranslate_Mask | 629d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com kScale_Mask | 630d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com kAffine_Mask | 631d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com kPerspective_Mask, 632d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com 633f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kAllMasks = kTranslate_Mask | 634f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kScale_Mask | 635f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kAffine_Mask | 636f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kPerspective_Mask | 637f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com kRectStaysRect_Mask 638f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com }; 639f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 640f12f2b4331d3c04cedd94a430a09bdcd266ffe98tomhudson@google.com SkScalar fMat[9]; 641f12f2b4331d3c04cedd94a430a09bdcd266ffe98tomhudson@google.com mutable uint32_t fTypeMask; 642f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 643f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com uint8_t computeTypeMask() const; 644b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com uint8_t computePerspectiveTypeMask() const; 645f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 646f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void setTypeMask(int mask) { 647f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com // allow kUnknown or a valid mask 648b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask || 649478c604fea898131572621fc3825b56481adfd96junov@chromium.org ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask) 650478c604fea898131572621fc3825b56481adfd96junov@chromium.org == (kUnknown_Mask | kOnlyPerspectiveValid_Mask)); 651f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTypeMask = SkToU8(mask); 652f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 653d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com 654d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com void orTypeMask(int mask) { 655d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com SkASSERT((mask & kORableMasks) == mask); 656d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com fTypeMask = SkToU8(fTypeMask | mask); 657d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com } 658d5ef4a9f01459c372b8841816a9b1662ea51fef6reed@google.com 659f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com void clearTypeMask(int mask) { 660f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com // only allow a valid mask 661f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com SkASSERT((mask & kAllMasks) == mask); 662f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com fTypeMask &= ~mask; 663f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com } 664b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com 665b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com TypeMask getPerspectiveTypeMaskOnly() const { 666b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com if ((fTypeMask & kUnknown_Mask) && 667b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com !(fTypeMask & kOnlyPerspectiveValid_Mask)) { 668b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com fTypeMask = this->computePerspectiveTypeMask(); 669b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com } 670b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com return (TypeMask)(fTypeMask & 0xF); 671b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com } 672b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com 673b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com /** Returns true if we already know that the matrix is identity; 674b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com false otherwise. 675b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com */ 676b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com bool isTriviallyIdentity() const { 677b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com if (fTypeMask & kUnknown_Mask) { 678b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com return false; 679b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com } 680b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com return ((fTypeMask & 0xF) == 0); 681b4ca308fe54ba1285a5be3869e595908fbd76e7dtomhudson@google.com } 6821fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 683f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const; 684f60feb19198cf47e7497f62af197538d018fdf3dbsalomon@google.com 685f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale); 686f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale); 687f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale); 688f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 689f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 690f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 691f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 692f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 693f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 694f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 695f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*); 6961fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 697f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static const MapXYProc gMapXYProcs[]; 6981fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 699f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int); 700f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 701f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 702f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], 703f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com int count); 704f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void Rot_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 705f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void RotTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], 706f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com int count); 707f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int); 7081fde19f3b72345b473a1a9bd64729237a388813frmistry@google.com 709f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com static const MapPtsProc gMapPtsProcs[]; 710f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 711f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com friend class SkPerspIter; 712f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com}; 713f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com 714f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#endif 715