1f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 2f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/* 3f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Copyright 2006 The Android Open Source Project 4f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * 5f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 6f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * found in the LICENSE file. 7f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger */ 8f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 9f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 10f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkMatrix.h" 11f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "Sk64.h" 12f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkFloatBits.h" 13f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkScalarCompare.h" 14f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkString.h" 15f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 16f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT 17f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger #define kMatrix22Elem SK_Scalar1 18f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 19f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static inline float SkDoubleToFloat(double x) { 20f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return static_cast<float>(x); 21f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 22f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 23f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger #define kMatrix22Elem SK_Fract1 24f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 25f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 26f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/* [scale-x skew-x trans-x] [X] [X'] 27f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger [skew-y scale-y trans-y] * [Y] = [Y'] 28f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger [persp-0 persp-1 persp-2] [1] [1 ] 29f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger*/ 30f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 31f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::reset() { 32f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; 33f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = fMat[kMSkewY] = 34f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] = fMat[kMTransY] = 35f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp0] = fMat[kMPersp1] = 0; 36f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp2] = kMatrix22Elem; 37f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 38f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask); 39f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 40f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 41f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// this guy aligns with the masks, so we can compute a mask from a varaible 0/1 42f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerenum { 43f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger kTranslate_Shift, 44f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger kScale_Shift, 45f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger kAffine_Shift, 46f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger kPerspective_Shift, 47f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger kRectStaysRect_Shift 48f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}; 49f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 50f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT 51f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static const int32_t kScalar1Int = 0x3f800000; 52f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static const int32_t kPersp1Int = 0x3f800000; 53f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 54f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger #define scalarAsInt(x) (x) 55f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static const int32_t kScalar1Int = (1 << 16); 56f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static const int32_t kPersp1Int = (1 << 30); 57f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 58f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 59f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergeruint8_t SkMatrix::computePerspectiveTypeMask() const { 60f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger unsigned mask = kOnlyPerspectiveValid_Mask | kUnknown_Mask; 61f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 62f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SkScalarAs2sCompliment(fMat[kMPersp0]) | 63f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarAs2sCompliment(fMat[kMPersp1]) | 64f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) { 65f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mask |= kPerspective_Mask; 66f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 67f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 68f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return SkToU8(mask); 69f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 70f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 71f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergeruint8_t SkMatrix::computeTypeMask() const { 72f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger unsigned mask = 0; 73f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 74f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_SLOW_COMPARES 75f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SkScalarAs2sCompliment(fMat[kMPersp0]) | 76f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarAs2sCompliment(fMat[kMPersp1]) | 77f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) { 78f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mask |= kPerspective_Mask; 79f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 80f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 81f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SkScalarAs2sCompliment(fMat[kMTransX]) | 82f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarAs2sCompliment(fMat[kMTransY])) { 83f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mask |= kTranslate_Mask; 84f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 85f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 86f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // Benchmarking suggests that replacing this set of SkScalarAs2sCompliment 87f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // is a win, but replacing those below is not. We don't yet understand 88f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // that result. 89f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || 90f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp2] != kMatrix22Elem) { 91f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mask |= kPerspective_Mask; 92f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 93f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 94f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (fMat[kMTransX] != 0 || fMat[kMTransY] != 0) { 95f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mask |= kTranslate_Mask; 96f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 97f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 98f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 99f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int m00 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleX]); 100f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int m01 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewX]); 101f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int m10 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewY]); 102f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int m11 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleY]); 103f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 104f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (m01 | m10) { 105f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mask |= kAffine_Mask; 106f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 107f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 108f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if ((m00 - kScalar1Int) | (m11 - kScalar1Int)) { 109f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mask |= kScale_Mask; 110f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 111f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 112f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if ((mask & kPerspective_Mask) == 0) { 113f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // map non-zero to 1 114f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m00 = m00 != 0; 115f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m01 = m01 != 0; 116f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m10 = m10 != 0; 117f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m11 = m11 != 0; 118f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 119f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // record if the (p)rimary and (s)econdary diagonals are all 0 or 120f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // all non-zero (answer is 0 or 1) 121f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int dp0 = (m00 | m11) ^ 1; // true if both are 0 122f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int dp1 = m00 & m11; // true if both are 1 123f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int ds0 = (m01 | m10) ^ 1; // true if both are 0 124f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int ds1 = m01 & m10; // true if both are 1 125f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 126f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // return 1 if primary is 1 and secondary is 0 or 127f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // primary is 0 and secondary is 1 128f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift; 129f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 130f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 131f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return SkToU8(mask); 132f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 133f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 134f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 135f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 136f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT 137f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 138f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool operator==(const SkMatrix& a, const SkMatrix& b) { 139f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkScalar* SK_RESTRICT ma = a.fMat; 140f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkScalar* SK_RESTRICT mb = b.fMat; 141f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 142f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] && 143f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] && 144f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8]; 145f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 146f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 147f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 148f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 149f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 150f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 151f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::setTranslate(SkScalar dx, SkScalar dy) { 152f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) { 153f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] = dx; 154f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] = dy; 155f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 156f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; 157f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = fMat[kMSkewY] = 158f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp0] = fMat[kMPersp1] = 0; 159f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp2] = kMatrix22Elem; 160f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 161f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask); 162f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 163f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->reset(); 164f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 165f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 166f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 167f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) { 168f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (this->hasPerspective()) { 169f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 170f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setTranslate(dx, dy); 171f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->preConcat(m); 172f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 173f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 174f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) { 175f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) + 176f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(fMat[kMSkewX], dy); 177f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) + 178f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(fMat[kMScaleY], dy); 179f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 180f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 181f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 182f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 183f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 184f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 185f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) { 186f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (this->hasPerspective()) { 187f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 188f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setTranslate(dx, dy); 189f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->postConcat(m); 190f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 191f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 192f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) { 193f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] += dx; 194f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] += dy; 195f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 196f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 197f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 198f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 199f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 200f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 201f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 202f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 203f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SK_Scalar1 == sx && SK_Scalar1 == sy) { 204f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->reset(); 205f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 206f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = sx; 207f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY] = sy; 208f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] = px - SkScalarMul(sx, px); 209f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] = py - SkScalarMul(sy, py); 210f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp2] = kMatrix22Elem; 211f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 212f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = fMat[kMSkewY] = 213f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp0] = fMat[kMPersp1] = 0; 214f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 215f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kScale_Mask | kTranslate_Mask | kRectStaysRect_Mask); 216f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 217f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 218f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 219f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::setScale(SkScalar sx, SkScalar sy) { 220f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SK_Scalar1 == sx && SK_Scalar1 == sy) { 221f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->reset(); 222f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 223f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = sx; 224f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY] = sy; 225f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp2] = kMatrix22Elem; 226f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 227f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] = fMat[kMTransY] = 228f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = fMat[kMSkewY] = 229f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp0] = fMat[kMPersp1] = 0; 230f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 231f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kScale_Mask | kRectStaysRect_Mask); 232f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 233f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 234f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 235f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::setIDiv(int divx, int divy) { 236f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!divx || !divy) { 237f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 238f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 239f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setScale(SK_Scalar1 / divx, SK_Scalar1 / divy); 240f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 241f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 242f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 243f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 244f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 245f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setScale(sx, sy, px, py); 246f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->preConcat(m); 247f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 248f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 249f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::preScale(SkScalar sx, SkScalar sy) { 250f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SK_Scalar1 == sx && SK_Scalar1 == sy) { 251f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 252f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 253f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 254f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 255f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 256f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setScale(sx, sy); 257f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->preConcat(m); 258f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 259f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // the assumption is that these multiplies are very cheap, and that 260f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // a full concat and/or just computing the matrix type is more expensive. 261f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // Also, the fixed-point case checks for overflow, but the float doesn't, 262f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // so we can get away with these blind multiplies. 263f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 264f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = SkScalarMul(fMat[kMScaleX], sx); 265f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewY] = SkScalarMul(fMat[kMSkewY], sx); 266f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp0] = SkScalarMul(fMat[kMPersp0], sx); 267f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 268f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = SkScalarMul(fMat[kMSkewX], sy); 269f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY] = SkScalarMul(fMat[kMScaleY], sy); 270f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp1] = SkScalarMul(fMat[kMPersp1], sy); 271f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 272f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->orTypeMask(kScale_Mask); 273f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 274f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 275f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 276f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 277f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 278f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SK_Scalar1 == sx && SK_Scalar1 == sy) { 279f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 280f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 281f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 282f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setScale(sx, sy, px, py); 283f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->postConcat(m); 284f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 285f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 286f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::postScale(SkScalar sx, SkScalar sy) { 287f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SK_Scalar1 == sx && SK_Scalar1 == sy) { 288f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 289f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 290f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 291f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setScale(sx, sy); 292f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->postConcat(m); 293f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 294f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 295f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 296f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static inline SkFixed roundidiv(SkFixed numer, int denom) { 297f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int ns = numer >> 31; 298f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int ds = denom >> 31; 299f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger numer = (numer ^ ns) - ns; 300f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger denom = (denom ^ ds) - ds; 301f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 302f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed answer = (numer + (denom >> 1)) / denom; 303f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int as = ns ^ ds; 304f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return (answer ^ as) - as; 305f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 306f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 307f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 308f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// this guy perhaps can go away, if we have a fract/high-precision way to 309f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// scale matrices 310f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::postIDiv(int divx, int divy) { 311f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (divx == 0 || divy == 0) { 312f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 313f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 314f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 315f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 316f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = roundidiv(fMat[kMScaleX], divx); 317f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = roundidiv(fMat[kMSkewX], divx); 318f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] = roundidiv(fMat[kMTransX], divx); 319f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 320f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY] = roundidiv(fMat[kMScaleY], divy); 321f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewY] = roundidiv(fMat[kMSkewY], divy); 322f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] = roundidiv(fMat[kMTransY], divy); 323f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 324f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const float invX = 1.f / divx; 325f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const float invY = 1.f / divy; 326f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 327f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] *= invX; 328f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] *= invX; 329f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] *= invX; 330f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 331f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY] *= invY; 332f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewY] *= invY; 333f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] *= invY; 334f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 335f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 336f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kUnknown_Mask); 337f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 338f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 339f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 340f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//////////////////////////////////////////////////////////////////////////////////// 341f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 342f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV, 343f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar px, SkScalar py) { 344f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkScalar oneMinusCosV = SK_Scalar1 - cosV; 345f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 346f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = cosV; 347f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = -sinV; 348f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] = SkScalarMul(sinV, py) + SkScalarMul(oneMinusCosV, px); 349f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 350f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewY] = sinV; 351f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY] = cosV; 352f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] = SkScalarMul(-sinV, px) + SkScalarMul(oneMinusCosV, py); 353f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 354f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp0] = fMat[kMPersp1] = 0; 355f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp2] = kMatrix22Elem; 356f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 357f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 358f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 359f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 360f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) { 361f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = cosV; 362f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = -sinV; 363f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] = 0; 364f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 365f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewY] = sinV; 366f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY] = cosV; 367f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] = 0; 368f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 369f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp0] = fMat[kMPersp1] = 0; 370f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp2] = kMatrix22Elem; 371f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 372f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 373f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 374f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 375f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) { 376f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar sinV, cosV; 377f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV); 378f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setSinCos(sinV, cosV, px, py); 379f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 380f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 381f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::setRotate(SkScalar degrees) { 382f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar sinV, cosV; 383f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV); 384f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setSinCos(sinV, cosV); 385f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 386f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 387f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) { 388f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 389f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setRotate(degrees, px, py); 390f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->preConcat(m); 391f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 392f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 393f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::preRotate(SkScalar degrees) { 394f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 395f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setRotate(degrees); 396f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->preConcat(m); 397f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 398f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 399f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) { 400f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 401f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setRotate(degrees, px, py); 402f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->postConcat(m); 403f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 404f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 405f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::postRotate(SkScalar degrees) { 406f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 407f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setRotate(degrees); 408f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->postConcat(m); 409f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 410f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 411f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger//////////////////////////////////////////////////////////////////////////////////// 412f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 413f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 414f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = SK_Scalar1; 415f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = sx; 416f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] = SkScalarMul(-sx, py); 417f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 418f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewY] = sy; 419f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY] = SK_Scalar1; 420f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] = SkScalarMul(-sy, px); 421f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 422f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp0] = fMat[kMPersp1] = 0; 423f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp2] = kMatrix22Elem; 424f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 425f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 426f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 427f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 428f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::setSkew(SkScalar sx, SkScalar sy) { 429f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = SK_Scalar1; 430f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = sx; 431f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] = 0; 432f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 433f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewY] = sy; 434f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY] = SK_Scalar1; 435f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] = 0; 436f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 437f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp0] = fMat[kMPersp1] = 0; 438f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp2] = kMatrix22Elem; 439f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 440f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 441f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 442f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 443f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 444f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 445f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setSkew(sx, sy, px, py); 446f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->preConcat(m); 447f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 448f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 449f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::preSkew(SkScalar sx, SkScalar sy) { 450f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 451f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setSkew(sx, sy); 452f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->preConcat(m); 453f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 454f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 455f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 456f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 457f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setSkew(sx, sy, px, py); 458f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->postConcat(m); 459f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 460f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 461f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::postSkew(SkScalar sx, SkScalar sy) { 462f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix m; 463f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.setSkew(sx, sy); 464f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return this->postConcat(m); 465f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 466f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 467f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 468f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 469f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst, 470f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger ScaleToFit align) 471f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger{ 472f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (src.isEmpty()) { 473f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->reset(); 474f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 475f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 476f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 477f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (dst.isEmpty()) { 478f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger sk_bzero(fMat, 8 * sizeof(SkScalar)); 479f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kScale_Mask | kRectStaysRect_Mask); 480f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 481f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar tx, sx = SkScalarDiv(dst.width(), src.width()); 482f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar ty, sy = SkScalarDiv(dst.height(), src.height()); 483f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger bool xLarger = false; 484f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 485f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (align != kFill_ScaleToFit) { 486f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (sx > sy) { 487f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger xLarger = true; 488f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger sx = sy; 489f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 490f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger sy = sx; 491f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 492f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 493f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 494f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tx = dst.fLeft - SkScalarMul(src.fLeft, sx); 495f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger ty = dst.fTop - SkScalarMul(src.fTop, sy); 496f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) { 497f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar diff; 498f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 499f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (xLarger) { 500f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger diff = dst.width() - SkScalarMul(src.width(), sy); 501f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 502f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger diff = dst.height() - SkScalarMul(src.height(), sy); 503f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 504f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 505f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (align == kCenter_ScaleToFit) { 506f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger diff = SkScalarHalf(diff); 507f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 508f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 509f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (xLarger) { 510f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tx += diff; 511f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 512f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger ty += diff; 513f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 514f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 515f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 516f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX] = sx; 517f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY] = sy; 518f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransX] = tx; 519f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMTransY] = ty; 520f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMSkewX] = fMat[kMSkewY] = 521f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp0] = fMat[kMPersp1] = 0; 522f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 523f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kScale_Mask | kTranslate_Mask | kRectStaysRect_Mask); 524f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 525f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // shared cleanup 526f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMPersp2] = kMatrix22Elem; 527f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 528f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 529f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 530f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 531f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 532f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT 533f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static inline int fixmuladdmul(float a, float b, float c, float d, 534f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float* result) { 535f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *result = SkDoubleToFloat((double)a * b + (double)c * d); 536f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 537f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 538f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 539f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static inline bool rowcol3(const float row[], const float col[], 540f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float* result) { 541f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *result = row[0] * col[0] + row[1] * col[3] + row[2] * col[6]; 542f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 543f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 544f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 545f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static inline int negifaddoverflows(float& result, float a, float b) { 546f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger result = a + b; 547f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return 0; 548f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 549f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 550f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static inline bool fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d, 551f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed* result) { 552f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger Sk64 tmp1, tmp2; 553f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.setMul(a, b); 554f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp2.setMul(c, d); 555f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.add(tmp2); 556f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (tmp1.isFixed()) { 557f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *result = tmp1.getFixed(); 558f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 559f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 560f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 561f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 562f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 563f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static inline SkFixed fracmuladdmul(SkFixed a, SkFract b, SkFixed c, 564f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFract d) { 565f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger Sk64 tmp1, tmp2; 566f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.setMul(a, b); 567f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp2.setMul(c, d); 568f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.add(tmp2); 569f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return tmp1.getFract(); 570f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 571f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 572f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static inline bool rowcol3(const SkFixed row[], const SkFixed col[], 573f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed* result) { 574f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger Sk64 tmp1, tmp2; 575f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 576f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.setMul(row[0], col[0]); // N * fixed 577f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp2.setMul(row[1], col[3]); // N * fixed 578f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.add(tmp2); 579f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 580f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp2.setMul(row[2], col[6]); // N * fract 581f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp2.roundRight(14); // make it fixed 582f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.add(tmp2); 583f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 584f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (tmp1.isFixed()) { 585f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *result = tmp1.getFixed(); 586f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 587f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 588f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 589f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 590f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 591f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static inline int negifaddoverflows(SkFixed& result, SkFixed a, SkFixed b) { 592f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed c = a + b; 593f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger result = c; 594f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return (c ^ a) & (c ^ b); 595f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 596f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 597f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 598f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic void normalize_perspective(SkScalar mat[9]) { 599f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > kMatrix22Elem) { 600f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger for (int i = 0; i < 9; i++) 601f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mat[i] = SkScalarHalf(mat[i]); 602f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 603f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 604f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 605f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) { 606f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger TypeMask aType = a.getPerspectiveTypeMaskOnly(); 607f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger TypeMask bType = b.getPerspectiveTypeMaskOnly(); 608f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 609f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (a.isTriviallyIdentity()) { 610f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *this = b; 611f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else if (b.isTriviallyIdentity()) { 612f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *this = a; 613f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 614f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix tmp; 615f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 616f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if ((aType | bType) & kPerspective_Mask) { 617f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!rowcol3(&a.fMat[0], &b.fMat[0], &tmp.fMat[kMScaleX])) { 618f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 619f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 620f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!rowcol3(&a.fMat[0], &b.fMat[1], &tmp.fMat[kMSkewX])) { 621f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 622f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 623f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!rowcol3(&a.fMat[0], &b.fMat[2], &tmp.fMat[kMTransX])) { 624f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 625f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 626f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 627f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!rowcol3(&a.fMat[3], &b.fMat[0], &tmp.fMat[kMSkewY])) { 628f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 629f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 630f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!rowcol3(&a.fMat[3], &b.fMat[1], &tmp.fMat[kMScaleY])) { 631f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 632f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 633f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!rowcol3(&a.fMat[3], &b.fMat[2], &tmp.fMat[kMTransY])) { 634f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 635f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 636f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 637f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!rowcol3(&a.fMat[6], &b.fMat[0], &tmp.fMat[kMPersp0])) { 638f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 639f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 640f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!rowcol3(&a.fMat[6], &b.fMat[1], &tmp.fMat[kMPersp1])) { 641f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 642f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 643f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!rowcol3(&a.fMat[6], &b.fMat[2], &tmp.fMat[kMPersp2])) { 644f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 645f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 646f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 647f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger normalize_perspective(tmp.fMat); 648f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.setTypeMask(kUnknown_Mask); 649f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { // not perspective 650f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMScaleX], 651f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a.fMat[kMSkewX], b.fMat[kMSkewY], &tmp.fMat[kMScaleX])) { 652f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 653f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 654f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMSkewX], 655f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a.fMat[kMSkewX], b.fMat[kMScaleY], &tmp.fMat[kMSkewX])) { 656f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 657f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 658f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMTransX], 659f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a.fMat[kMSkewX], b.fMat[kMTransY], &tmp.fMat[kMTransX])) { 660f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 661f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 662f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (negifaddoverflows(tmp.fMat[kMTransX], tmp.fMat[kMTransX], 663f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a.fMat[kMTransX]) < 0) { 664f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 665f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 666f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 667f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMScaleX], 668f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a.fMat[kMScaleY], b.fMat[kMSkewY], &tmp.fMat[kMSkewY])) { 669f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 670f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 671f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMSkewX], 672f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a.fMat[kMScaleY], b.fMat[kMScaleY], &tmp.fMat[kMScaleY])) { 673f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 674f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 675f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMTransX], 676f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a.fMat[kMScaleY], b.fMat[kMTransY], &tmp.fMat[kMTransY])) { 677f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 678f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 679f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (negifaddoverflows(tmp.fMat[kMTransY], tmp.fMat[kMTransY], 680f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a.fMat[kMTransY]) < 0) { 681f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 682f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 683f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 684f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0; 685f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.fMat[kMPersp2] = kMatrix22Elem; 686f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType()); 687f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger //SkASSERT(!(tmp.getType() & kPerspective_Mask)); 688f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 689f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 690f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *this = tmp; 691f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 692f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 693f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 694f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 695f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::preConcat(const SkMatrix& mat) { 696f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // check for identity first, so we don't do a needless copy of ourselves 697f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // to ourselves inside setConcat() 698f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return mat.isIdentity() || this->setConcat(*this, mat); 699f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 700f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 701f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::postConcat(const SkMatrix& mat) { 702f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // check for identity first, so we don't do a needless copy of ourselves 703f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // to ourselves inside setConcat() 704f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return mat.isIdentity() || this->setConcat(mat, *this); 705f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 706f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 707f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 708f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 709f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/* Matrix inversion is very expensive, but also the place where keeping 710f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger precision may be most important (here and matrix concat). Hence to avoid 711f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger bitmap blitting artifacts when walking the inverse, we use doubles for 712f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger the intermediate math, even though we know that is more expensive. 713f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger The fixed counter part is us using Sk64 for temp calculations. 714f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger */ 715f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 716f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT 717f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger typedef double SkDetScalar; 718f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger #define SkPerspMul(a, b) SkScalarMul(a, b) 719f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger #define SkScalarMulShift(a, b, s) SkDoubleToFloat((a) * (b)) 720f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static double sk_inv_determinant(const float mat[9], int isPerspective, 721f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int* /* (only used in Fixed case) */) { 722f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger double det; 723f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 724f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (isPerspective) { 725f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger det = mat[SkMatrix::kMScaleX] * ((double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp2] - (double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp1]) + 726f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mat[SkMatrix::kMSkewX] * ((double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp0] - (double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp2]) + 727f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger mat[SkMatrix::kMTransX] * ((double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp1] - (double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp0]); 728f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 729f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger det = (double)mat[SkMatrix::kMScaleX] * mat[SkMatrix::kMScaleY] - (double)mat[SkMatrix::kMSkewX] * mat[SkMatrix::kMSkewY]; 730f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 731f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 732f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // Since the determinant is on the order of the cube of the matrix members, 733f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // compare to the cube of the default nearly-zero constant (although an 734f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // estimate of the condition number would be better if it wasn't so expensive). 735f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) { 736f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return 0; 737f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 738f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return 1.0 / det; 739f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 740f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // we declar a,b,c,d to all be doubles, because we want to perform 741f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // double-precision muls and subtract, even though the original values are 742f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // from the matrix, which are floats. 743f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static float inline mul_diff_scale(double a, double b, double c, double d, 744f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger double scale) { 745f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return SkDoubleToFloat((a * b - c * d) * scale); 746f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 747f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 748f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger typedef SkFixed SkDetScalar; 749f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger #define SkPerspMul(a, b) SkFractMul(a, b) 750f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger #define SkScalarMulShift(a, b, s) SkMulShift(a, b, s) 751f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static void set_muladdmul(Sk64* dst, int32_t a, int32_t b, int32_t c, 752f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int32_t d) { 753f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger Sk64 tmp; 754f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->setMul(a, b); 755f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.setMul(c, d); 756f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->add(tmp); 757f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 758f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 759f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static SkFixed sk_inv_determinant(const SkFixed mat[9], int isPerspective, 760f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int* shift) { 761f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger Sk64 tmp1, tmp2; 762f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 763f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (isPerspective) { 764f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.setMul(mat[SkMatrix::kMScaleX], fracmuladdmul(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2], -mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1])); 765f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp2.setMul(mat[SkMatrix::kMSkewX], fracmuladdmul(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0], -mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2])); 766f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.add(tmp2); 767f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp2.setMul(mat[SkMatrix::kMTransX], fracmuladdmul(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1], -mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0])); 768f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.add(tmp2); 769f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 770f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.setMul(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY]); 771f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp2.setMul(mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]); 772f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.sub(tmp2); 773f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 774f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 775f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int s = tmp1.getClzAbs(); 776f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *shift = s; 777f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 778f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed denom; 779f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (s <= 32) { 780f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger denom = tmp1.getShiftRight(33 - s); 781f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 782f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger denom = (int32_t)tmp1.fLo << (s - 33); 783f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 784f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 785f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (denom == 0) { 786f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return 0; 787f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 788f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger /** This could perhaps be a special fractdiv function, since both of its 789f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger arguments are known to have bit 31 clear and bit 30 set (when they 790f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger are made positive), thus eliminating the need for calling clz() 791f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger */ 792f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return SkFractDiv(SK_Fract1, denom); 793f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 794f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 795f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 796f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::SetAffineIdentity(SkScalar affine[6]) { 797f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kAScaleX] = SK_Scalar1; 798f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kASkewY] = 0; 799f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kASkewX] = 0; 800f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kAScaleY] = SK_Scalar1; 801f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kATransX] = 0; 802f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kATransY] = 0; 803f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 804f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 805f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::asAffine(SkScalar affine[6]) const { 806f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (this->hasPerspective()) { 807f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 808f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 809f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (affine) { 810f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kAScaleX] = this->fMat[kMScaleX]; 811f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kASkewY] = this->fMat[kMSkewY]; 812f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kASkewX] = this->fMat[kMSkewX]; 813f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kAScaleY] = this->fMat[kMScaleY]; 814f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kATransX] = this->fMat[kMTransX]; 815f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger affine[kATransY] = this->fMat[kMTransY]; 816f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 817f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 818f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 819f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 820f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::invert(SkMatrix* inv) const { 821f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int isPersp = this->hasPerspective(); 822f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int shift; 823f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkDetScalar scale = sk_inv_determinant(fMat, isPersp, &shift); 824f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 825f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (scale == 0) { // underflow 826f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 827f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 828f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 829f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (inv) { 830f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix tmp; 831f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (inv == this) { 832f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv = &tmp; 833f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 834f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->setTypeMask(kUnknown_Mask); 835f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 836f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (isPersp) { 837f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger shift = 61 - shift; 838f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMScaleX] = SkScalarMulShift(SkPerspMul(fMat[kMScaleY], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransY], fMat[kMPersp1]), scale, shift); 839f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMSkewX] = SkScalarMulShift(SkPerspMul(fMat[kMTransX], fMat[kMPersp1]) - SkPerspMul(fMat[kMSkewX], fMat[kMPersp2]), scale, shift); 840f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMTransX] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMTransY]) - SkScalarMul(fMat[kMTransX], fMat[kMScaleY]), scale, shift); 841f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 842f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMSkewY] = SkScalarMulShift(SkPerspMul(fMat[kMTransY], fMat[kMPersp0]) - SkPerspMul(fMat[kMSkewY], fMat[kMPersp2]), scale, shift); 843f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMScaleY] = SkScalarMulShift(SkPerspMul(fMat[kMScaleX], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransX], fMat[kMPersp0]), scale, shift); 844f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMTransY] = SkScalarMulShift(SkScalarMul(fMat[kMTransX], fMat[kMSkewY]) - SkScalarMul(fMat[kMScaleX], fMat[kMTransY]), scale, shift); 845f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 846f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMPersp0] = SkScalarMulShift(SkScalarMul(fMat[kMSkewY], fMat[kMPersp1]) - SkScalarMul(fMat[kMScaleY], fMat[kMPersp0]), scale, shift); 847f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMPersp1] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMPersp0]) - SkScalarMul(fMat[kMScaleX], fMat[kMPersp1]), scale, shift); 848f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMPersp2] = SkScalarMulShift(SkScalarMul(fMat[kMScaleX], fMat[kMScaleY]) - SkScalarMul(fMat[kMSkewX], fMat[kMSkewY]), scale, shift); 849f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 850f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (SkAbs32(inv->fMat[kMPersp2]) > SK_Fixed1) { 851f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger Sk64 tmp; 852f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 853f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.set(SK_Fract1); 854f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.shiftLeft(16); 855f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.div(inv->fMat[kMPersp2], Sk64::kRound_DivOption); 856f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 857f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFract scale = tmp.get32(); 858f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 859f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger for (int i = 0; i < 9; i++) { 860f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[i] = SkFractMul(inv->fMat[i], scale); 861f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 862f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 863f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMPersp2] = SkFixedToFract(inv->fMat[kMPersp2]); 864f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 865f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->setTypeMask(kUnknown_Mask); 866f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { // not perspective 867f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 868f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger Sk64 tx, ty; 869f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int clzNumer; 870f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 871f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // check the 2x2 for overflow 872f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger { 873f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int32_t value = SkAbs32(fMat[kMScaleY]); 874f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger value |= SkAbs32(fMat[kMSkewX]); 875f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger value |= SkAbs32(fMat[kMScaleX]); 876f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger value |= SkAbs32(fMat[kMSkewY]); 877f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger clzNumer = SkCLZ(value); 878f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (shift - clzNumer > 31) 879f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; // overflow 880f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 881f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 882f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger set_muladdmul(&tx, fMat[kMSkewX], fMat[kMTransY], -fMat[kMScaleY], fMat[kMTransX]); 883f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger set_muladdmul(&ty, fMat[kMSkewY], fMat[kMTransX], -fMat[kMScaleX], fMat[kMTransY]); 884f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // check tx,ty for overflow 885f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger clzNumer = SkCLZ(SkAbs32(tx.fHi) | SkAbs32(ty.fHi)); 886f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (shift - clzNumer > 14) { 887f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; // overflow 888f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 889f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 890f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int fixedShift = 61 - shift; 891f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int sk64shift = 44 - shift + clzNumer; 892f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 893f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMScaleX] = SkMulShift(fMat[kMScaleY], scale, fixedShift); 894f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMSkewX] = SkMulShift(-fMat[kMSkewX], scale, fixedShift); 895f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMTransX] = SkMulShift(tx.getShiftRight(33 - clzNumer), scale, sk64shift); 896f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 897f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMSkewY] = SkMulShift(-fMat[kMSkewY], scale, fixedShift); 898f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMScaleY] = SkMulShift(fMat[kMScaleX], scale, fixedShift); 899f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMTransY] = SkMulShift(ty.getShiftRight(33 - clzNumer), scale, sk64shift); 900f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 901f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMScaleX] = SkDoubleToFloat(fMat[kMScaleY] * scale); 902f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMSkewX] = SkDoubleToFloat(-fMat[kMSkewX] * scale); 903f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMTransX] = mul_diff_scale(fMat[kMSkewX], fMat[kMTransY], 904f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleY], fMat[kMTransX], scale); 905f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 906f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMSkewY] = SkDoubleToFloat(-fMat[kMSkewY] * scale); 907f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMScaleY] = SkDoubleToFloat(fMat[kMScaleX] * scale); 908f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMTransY] = mul_diff_scale(fMat[kMSkewY], fMat[kMTransX], 909f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[kMScaleX], fMat[kMTransY], scale); 910f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 911f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMPersp0] = 0; 912f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMPersp1] = 0; 913f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->fMat[kMPersp2] = kMatrix22Elem; 914f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger inv->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 915f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 916f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 917f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (inv == &tmp) { 918f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *(SkMatrix*)this = tmp; 919f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 920f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 921f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 922f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 923f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 924f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 925f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 926f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], 927f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint src[], int count) { 928f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(m.getType() == 0); 929f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 930f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (dst != src && count > 0) 931f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger memcpy(dst, src, count * sizeof(SkPoint)); 932f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 933f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 934f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[], 935f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint src[], int count) { 936f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(m.getType() == kTranslate_Mask); 937f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 938f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (count > 0) { 939f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar tx = m.fMat[kMTransX]; 940f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar ty = m.fMat[kMTransY]; 941f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger do { 942f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fY = src->fY + ty; 943f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fX = src->fX + tx; 944f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger src += 1; 945f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst += 1; 946f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } while (--count); 947f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 948f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 949f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 950f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[], 951f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint src[], int count) { 952f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(m.getType() == kScale_Mask); 953f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 954f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (count > 0) { 955f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar mx = m.fMat[kMScaleX]; 956f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar my = m.fMat[kMScaleY]; 957f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger do { 958f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fY = SkScalarMul(src->fY, my); 959f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fX = SkScalarMul(src->fX, mx); 960f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger src += 1; 961f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst += 1; 962f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } while (--count); 963f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 964f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 965f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 966f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::ScaleTrans_pts(const SkMatrix& m, SkPoint dst[], 967f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint src[], int count) { 968f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(m.getType() == (kScale_Mask | kTranslate_Mask)); 969f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 970f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (count > 0) { 971f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar mx = m.fMat[kMScaleX]; 972f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar my = m.fMat[kMScaleY]; 973f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar tx = m.fMat[kMTransX]; 974f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar ty = m.fMat[kMTransY]; 975f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger do { 976f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fY = SkScalarMulAdd(src->fY, my, ty); 977f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fX = SkScalarMulAdd(src->fX, mx, tx); 978f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger src += 1; 979f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst += 1; 980f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } while (--count); 981f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 982f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 983f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 984f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::Rot_pts(const SkMatrix& m, SkPoint dst[], 985f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint src[], int count) { 986f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT((m.getType() & (kPerspective_Mask | kTranslate_Mask)) == 0); 987f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 988f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (count > 0) { 989f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar mx = m.fMat[kMScaleX]; 990f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar my = m.fMat[kMScaleY]; 991f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar kx = m.fMat[kMSkewX]; 992f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar ky = m.fMat[kMSkewY]; 993f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger do { 994f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar sy = src->fY; 995f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar sx = src->fX; 996f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger src += 1; 997f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fY = SkScalarMul(sx, ky) + SkScalarMul(sy, my); 998f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fX = SkScalarMul(sx, mx) + SkScalarMul(sy, kx); 999f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst += 1; 1000f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } while (--count); 1001f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1002f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1003f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1004f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::RotTrans_pts(const SkMatrix& m, SkPoint dst[], 1005f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint src[], int count) { 1006f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(!m.hasPerspective()); 1007f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1008f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (count > 0) { 1009f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar mx = m.fMat[kMScaleX]; 1010f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar my = m.fMat[kMScaleY]; 1011f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar kx = m.fMat[kMSkewX]; 1012f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar ky = m.fMat[kMSkewY]; 1013f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar tx = m.fMat[kMTransX]; 1014f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar ty = m.fMat[kMTransY]; 1015f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger do { 1016f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar sy = src->fY; 1017f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar sx = src->fX; 1018f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger src += 1; 1019f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fY = SkScalarMul(sx, ky) + SkScalarMulAdd(sy, my, ty); 1020f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fX = SkScalarMul(sx, mx) + SkScalarMulAdd(sy, kx, tx); 1021f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst += 1; 1022f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } while (--count); 1023f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1024f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1025f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1026f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[], 1027f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint src[], int count) { 1028f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(m.hasPerspective()); 1029f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1030f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 1031f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed persp2 = SkFractToFixed(m.fMat[kMPersp2]); 1032f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1033f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1034f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (count > 0) { 1035f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger do { 1036f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar sy = src->fY; 1037f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar sx = src->fX; 1038f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger src += 1; 1039f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1040f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) + 1041f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 1042f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) + 1043f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 1044f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 1045f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) + 1046f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFractMul(sy, m.fMat[kMPersp1]) + persp2; 1047f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 1048f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float z = SkScalarMul(sx, m.fMat[kMPersp0]) + 1049f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMulAdd(sy, m.fMat[kMPersp1], m.fMat[kMPersp2]); 1050f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1051f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (z) { 1052f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger z = SkScalarFastInvert(z); 1053f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1054f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1055f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fY = SkScalarMul(y, z); 1056f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fX = SkScalarMul(x, z); 1057f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst += 1; 1058f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } while (--count); 1059f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1060f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1061f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1062f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = { 1063f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Identity_pts, SkMatrix::Trans_pts, 1064f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Scale_pts, SkMatrix::ScaleTrans_pts, 1065f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Rot_pts, SkMatrix::RotTrans_pts, 1066f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Rot_pts, SkMatrix::RotTrans_pts, 1067f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // repeat the persp proc 8 times 1068f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_pts, SkMatrix::Persp_pts, 1069f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_pts, SkMatrix::Persp_pts, 1070f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_pts, SkMatrix::Persp_pts, 1071f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_pts, SkMatrix::Persp_pts 1072f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}; 1073f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1074f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const { 1075f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT((dst && src && count > 0) || count == 0); 1076f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // no partial overlap 1077f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= count); 1078f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1079f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->getMapPtsProc()(*this, dst, src, count); 1080f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1081f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1082f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1083f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1084f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const { 1085f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (this->hasPerspective()) { 1086f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint origin; 1087f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1088f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger MapXYProc proc = this->getMapXYProc(); 1089f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger proc(*this, 0, 0, &origin); 1090f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1091f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger for (int i = count - 1; i >= 0; --i) { 1092f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint tmp; 1093f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1094f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger proc(*this, src[i].fX, src[i].fY, &tmp); 1095f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY); 1096f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1097f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 1098f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix tmp = *this; 1099f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1100f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0; 1101f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.clearTypeMask(kTranslate_Mask); 1102f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.mapPoints(dst, src, count); 1103f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1104f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1105f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1106f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const { 1107f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(dst && &src); 1108f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1109f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (this->rectStaysRect()) { 1110f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2); 1111f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->sort(); 1112f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1113f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 1114f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint quad[4]; 1115f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1116f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger src.toQuad(quad); 1117f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->mapPoints(quad, quad, 4); 1118f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->set(quad, 4); 1119f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1120f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1121f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1122f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1123f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkScalar SkMatrix::mapRadius(SkScalar radius) const { 1124f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkVector vec[2]; 1125f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1126f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger vec[0].set(radius, 0); 1127f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger vec[1].set(0, radius); 1128f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->mapVectors(vec, 2); 1129f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1130f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar d0 = vec[0].length(); 1131f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar d1 = vec[1].length(); 1132f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1133f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return SkScalarMean(d0, d1); 1134f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1135f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1136f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1137f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1138f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1139f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint* pt) { 1140f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(m.hasPerspective()); 1141f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1142f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) + 1143f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 1144f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) + 1145f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 1146f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 1147f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) + 1148f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFractMul(sy, m.fMat[kMPersp1]) + 1149f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFractToFixed(m.fMat[kMPersp2]); 1150f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 1151f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float z = SkScalarMul(sx, m.fMat[kMPersp0]) + 1152f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2]; 1153f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1154f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (z) { 1155f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger z = SkScalarFastInvert(z); 1156f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1157f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fX = SkScalarMul(x, z); 1158f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fY = SkScalarMul(y, z); 1159f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1160f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1161f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 1162f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkFixed fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d) { 1163f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger Sk64 tmp, tmp1; 1164f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1165f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp.setMul(a, b); 1166f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tmp1.setMul(c, d); 1167f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return tmp.addGetFixed(tmp1); 1168f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// tmp.add(tmp1); 1169f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// return tmp.getFixed(); 1170f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1171f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1172f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1173f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1174f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint* pt) { 1175f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask); 1176f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1177f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 1178f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + 1179f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.fMat[kMTransX]; 1180f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + 1181f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger m.fMat[kMTransY]; 1182f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 1183f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) + 1184f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]); 1185f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) + 1186f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]); 1187f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1188f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1189f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1190f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1191f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint* pt) { 1192f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask); 1193f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(0 == m.fMat[kMTransX]); 1194f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(0 == m.fMat[kMTransY]); 1195f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1196f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 1197f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]); 1198f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]); 1199f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 1200f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) + 1201f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]); 1202f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) + 1203f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]); 1204f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1205f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1206f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1207f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1208f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint* pt) { 1209f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) 1210f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger == kScale_Mask); 1211f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1212f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fX = SkScalarMulAdd(sx, m.fMat[kMScaleX], m.fMat[kMTransX]); 1213f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fY = SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]); 1214f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1215f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1216f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1217f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint* pt) { 1218f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) 1219f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger == kScale_Mask); 1220f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(0 == m.fMat[kMTransX]); 1221f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(0 == m.fMat[kMTransY]); 1222f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1223f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]); 1224f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fY = SkScalarMul(sy, m.fMat[kMScaleY]); 1225f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1226f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1227f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1228f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint* pt) { 1229f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(m.getType() == kTranslate_Mask); 1230f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1231f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fX = sx + m.fMat[kMTransX]; 1232f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fY = sy + m.fMat[kMTransY]; 1233f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1234f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1235f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1236f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint* pt) { 1237f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkASSERT(0 == m.getType()); 1238f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1239f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fX = sx; 1240f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->fY = sy; 1241f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1242f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1243f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = { 1244f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Identity_xy, SkMatrix::Trans_xy, 1245f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Scale_xy, SkMatrix::ScaleTrans_xy, 1246f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Rot_xy, SkMatrix::RotTrans_xy, 1247f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Rot_xy, SkMatrix::RotTrans_xy, 1248f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // repeat the persp proc 8 times 1249f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1250f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1251f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1252f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_xy, SkMatrix::Persp_xy 1253f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}; 1254f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1255f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1256f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1257f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger// if its nearly zero (just made up 26, perhaps it should be bigger or smaller) 1258f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 1259f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger typedef SkFract SkPerspElemType; 1260f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger #define PerspNearlyZero(x) (SkAbs32(x) < (SK_Fract1 >> 26)) 1261f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 1262f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger typedef float SkPerspElemType; 1263f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger #define PerspNearlyZero(x) SkScalarNearlyZero(x, (1.0f / (1 << 26))) 1264f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1265f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1266f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const { 1267f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (PerspNearlyZero(fMat[kMPersp0])) { 1268f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (stepX || stepY) { 1269f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (PerspNearlyZero(fMat[kMPersp1]) && 1270f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger PerspNearlyZero(fMat[kMPersp2] - kMatrix22Elem)) { 1271f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (stepX) { 1272f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *stepX = SkScalarToFixed(fMat[kMScaleX]); 1273f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1274f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (stepY) { 1275f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *stepY = SkScalarToFixed(fMat[kMSkewY]); 1276f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1277f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 1278f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 1279f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed z = SkFractMul(y, fMat[kMPersp1]) + 1280f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFractToFixed(fMat[kMPersp2]); 1281f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 1282f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float z = y * fMat[kMPersp1] + fMat[kMPersp2]; 1283f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1284f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (stepX) { 1285f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *stepX = SkScalarToFixed(SkScalarDiv(fMat[kMScaleX], z)); 1286f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1287f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (stepY) { 1288f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *stepY = SkScalarToFixed(SkScalarDiv(fMat[kMSkewY], z)); 1289f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1290f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1291f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1292f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1293f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1294f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1295f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1296f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1297f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1298f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1299f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkPerspIter.h" 1300f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1301f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count) 1302f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger : fMatrix(m), fSX(x0), fSY(y0), fCount(count) { 1303f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint pt; 1304f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1305f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_xy(m, x0, y0, &pt); 1306f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fX = SkScalarToFixed(pt.fX); 1307f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fY = SkScalarToFixed(pt.fY); 1308f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1309f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1310f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerint SkPerspIter::next() { 1311f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int n = fCount; 1312f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1313f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (0 == n) { 1314f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return 0; 1315f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1316f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint pt; 1317f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed x = fX; 1318f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed y = fY; 1319f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed dx, dy; 1320f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1321f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (n >= kCount) { 1322f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger n = kCount; 1323f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fSX += SkIntToScalar(kCount); 1324f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt); 1325f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fX = SkScalarToFixed(pt.fX); 1326f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fY = SkScalarToFixed(pt.fY); 1327f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dx = (fX - x) >> kShift; 1328f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dy = (fY - y) >> kShift; 1329f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 1330f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fSX += SkIntToScalar(n); 1331f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt); 1332f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fX = SkScalarToFixed(pt.fX); 1333f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fY = SkScalarToFixed(pt.fY); 1334f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dx = (fX - x) / n; 1335f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dy = (fY - y) / n; 1336f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1337f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1338f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed* p = fStorage; 1339f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger for (int i = 0; i < n; i++) { 1340f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *p++ = x; x += dx; 1341f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *p++ = y; y += dy; 1342f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1343f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1344f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fCount -= n; 1345f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return n; 1346f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1347f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1348f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1349f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1350f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FIXED 1351f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1352f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) { 1353f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed x = SK_Fixed1, y = SK_Fixed1; 1354f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint pt1, pt2; 1355f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger Sk64 w1, w2; 1356f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1357f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (count > 1) { 1358f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt1.fX = poly[1].fX - poly[0].fX; 1359f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt1.fY = poly[1].fY - poly[0].fY; 1360f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger y = SkPoint::Length(pt1.fX, pt1.fY); 1361f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (y == 0) { 1362f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1363f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1364f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger switch (count) { 1365f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger case 2: 1366f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger break; 1367f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger case 3: 1368f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt2.fX = poly[0].fY - poly[2].fY; 1369f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt2.fY = poly[2].fX - poly[0].fX; 1370f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger goto CALC_X; 1371f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger default: 1372f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt2.fX = poly[0].fY - poly[3].fY; 1373f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt2.fY = poly[3].fX - poly[0].fX; 1374f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger CALC_X: 1375f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger w1.setMul(pt1.fX, pt2.fX); 1376f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger w2.setMul(pt1.fY, pt2.fY); 1377f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger w1.add(w2); 1378f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger w1.div(y, Sk64::kRound_DivOption); 1379f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!w1.is32()) { 1380f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1381f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1382f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger x = w1.get32(); 1383f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger break; 1384f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1385f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1386f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->set(x, y); 1387f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1388f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1389f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1390f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst, 1391f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint& scalePt) { 1392f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // need to check if SkFixedDiv overflows... 1393f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1394f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkFixed scale = scalePt.fY; 1395f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleX] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale); 1396f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewY] = SkFixedDiv(srcPt[0].fX - srcPt[1].fX, scale); 1397f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp0] = 0; 1398f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewX] = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale); 1399f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale); 1400f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp1] = 0; 1401f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransX] = srcPt[0].fX; 1402f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransY] = srcPt[0].fY; 1403f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp2] = SK_Fract1; 1404f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->setTypeMask(kUnknown_Mask); 1405f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1406f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1407f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1408f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst, 1409f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint& scale) { 1410f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // really, need to check if SkFixedDiv overflow'd 1411f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1412f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleX] = SkFixedDiv(srcPt[2].fX - srcPt[0].fX, scale.fX); 1413f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewY] = SkFixedDiv(srcPt[2].fY - srcPt[0].fY, scale.fX); 1414f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp0] = 0; 1415f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewX] = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale.fY); 1416f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale.fY); 1417f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp1] = 0; 1418f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransX] = srcPt[0].fX; 1419f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransY] = srcPt[0].fY; 1420f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp2] = SK_Fract1; 1421f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->setTypeMask(kUnknown_Mask); 1422f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1423f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1424f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1425f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst, 1426f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint& scale) { 1427f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFract a1, a2; 1428f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed x0, y0, x1, y1, x2, y2; 1429f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1430f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger x0 = srcPt[2].fX - srcPt[0].fX; 1431f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger y0 = srcPt[2].fY - srcPt[0].fY; 1432f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger x1 = srcPt[2].fX - srcPt[1].fX; 1433f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger y1 = srcPt[2].fY - srcPt[1].fY; 1434f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger x2 = srcPt[2].fX - srcPt[3].fX; 1435f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger y2 = srcPt[2].fY - srcPt[3].fY; 1436f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1437f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger /* check if abs(x2) > abs(y2) */ 1438f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) { 1439f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed denom = SkMulDiv(x1, y2, x2) - y1; 1440f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (0 == denom) { 1441f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1442f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1443f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a1 = SkFractDiv(SkMulDiv(x0 - x1, y2, x2) - y0 + y1, denom); 1444f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 1445f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed denom = x1 - SkMulDiv(y1, x2, y2); 1446f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (0 == denom) { 1447f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1448f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1449f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a1 = SkFractDiv(x0 - x1 - SkMulDiv(y0 - y1, x2, y2), denom); 1450f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1451f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1452f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger /* check if abs(x1) > abs(y1) */ 1453f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) { 1454f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed denom = y2 - SkMulDiv(x2, y1, x1); 1455f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (0 == denom) { 1456f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1457f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1458f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a2 = SkFractDiv(y0 - y2 - SkMulDiv(x0 - x2, y1, x1), denom); 1459f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 1460f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixed denom = SkMulDiv(y2, x1, y1) - x2; 1461f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (0 == denom) { 1462f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1463f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1464f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a2 = SkFractDiv(SkMulDiv(y0 - y2, x1, y1) - x0 + x2, denom); 1465f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1466f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1467f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // need to check if SkFixedDiv overflows... 1468f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleX] = SkFixedDiv(SkFractMul(a2, srcPt[3].fX) + 1469f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger srcPt[3].fX - srcPt[0].fX, scale.fX); 1470f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewY] = SkFixedDiv(SkFractMul(a2, srcPt[3].fY) + 1471f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger srcPt[3].fY - srcPt[0].fY, scale.fX); 1472f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp0] = SkFixedDiv(a2, scale.fX); 1473f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewX] = SkFixedDiv(SkFractMul(a1, srcPt[1].fX) + 1474f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger srcPt[1].fX - srcPt[0].fX, scale.fY); 1475f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleY] = SkFixedDiv(SkFractMul(a1, srcPt[1].fY) + 1476f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger srcPt[1].fY - srcPt[0].fY, scale.fY); 1477f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp1] = SkFixedDiv(a1, scale.fY); 1478f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransX] = srcPt[0].fX; 1479f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransY] = srcPt[0].fY; 1480f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp2] = SK_Fract1; 1481f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->setTypeMask(kUnknown_Mask); 1482f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1483f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1484f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1485f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else /* Scalar is float */ 1486f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1487f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline bool checkForZero(float x) { 1488f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return x*x == 0; 1489f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1490f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1491f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) { 1492f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float x = 1, y = 1; 1493f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint pt1, pt2; 1494f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1495f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (count > 1) { 1496f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt1.fX = poly[1].fX - poly[0].fX; 1497f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt1.fY = poly[1].fY - poly[0].fY; 1498f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger y = SkPoint::Length(pt1.fX, pt1.fY); 1499f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (checkForZero(y)) { 1500f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1501f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1502f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger switch (count) { 1503f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger case 2: 1504f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger break; 1505f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger case 3: 1506f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt2.fX = poly[0].fY - poly[2].fY; 1507f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt2.fY = poly[2].fX - poly[0].fX; 1508f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger goto CALC_X; 1509f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger default: 1510f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt2.fX = poly[0].fY - poly[3].fY; 1511f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt2.fY = poly[3].fX - poly[0].fX; 1512f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger CALC_X: 1513f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger x = SkScalarDiv(SkScalarMul(pt1.fX, pt2.fX) + 1514f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(pt1.fY, pt2.fY), y); 1515f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger break; 1516f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1517f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1518f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger pt->set(x, y); 1519f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1520f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1521f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1522f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst, 1523f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint& scale) { 1524f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float invScale = 1 / scale.fY; 1525f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1526f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1527f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale; 1528f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp0] = 0; 1529f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; 1530f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1531f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp1] = 0; 1532f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransX] = srcPt[0].fX; 1533f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransY] = srcPt[0].fY; 1534f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp2] = 1; 1535f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->setTypeMask(kUnknown_Mask); 1536f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1537f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1538f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1539f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst, 1540f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint& scale) { 1541f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float invScale = 1 / scale.fX; 1542f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale; 1543f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale; 1544f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp0] = 0; 1545f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1546f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger invScale = 1 / scale.fY; 1547f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale; 1548f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale; 1549f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp1] = 0; 1550f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1551f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransX] = srcPt[0].fX; 1552f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransY] = srcPt[0].fY; 1553f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp2] = 1; 1554f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->setTypeMask(kUnknown_Mask); 1555f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1556f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1557f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1558f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst, 1559f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger const SkPoint& scale) { 1560f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float a1, a2; 1561f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float x0, y0, x1, y1, x2, y2; 1562f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1563f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger x0 = srcPt[2].fX - srcPt[0].fX; 1564f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger y0 = srcPt[2].fY - srcPt[0].fY; 1565f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger x1 = srcPt[2].fX - srcPt[1].fX; 1566f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger y1 = srcPt[2].fY - srcPt[1].fY; 1567f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger x2 = srcPt[2].fX - srcPt[3].fX; 1568f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger y2 = srcPt[2].fY - srcPt[3].fY; 1569f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1570f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger /* check if abs(x2) > abs(y2) */ 1571f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) { 1572f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float denom = SkScalarMulDiv(x1, y2, x2) - y1; 1573f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (checkForZero(denom)) { 1574f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1575f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1576f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a1 = SkScalarDiv(SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1, denom); 1577f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 1578f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float denom = x1 - SkScalarMulDiv(y1, x2, y2); 1579f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (checkForZero(denom)) { 1580f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1581f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1582f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a1 = SkScalarDiv(x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2), denom); 1583f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1584f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1585f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger /* check if abs(x1) > abs(y1) */ 1586f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) { 1587f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float denom = y2 - SkScalarMulDiv(x2, y1, x1); 1588f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (checkForZero(denom)) { 1589f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1590f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1591f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a2 = SkScalarDiv(y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1), denom); 1592f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 1593f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float denom = SkScalarMulDiv(y2, x1, y1) - x2; 1594f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (checkForZero(denom)) { 1595f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1596f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1597f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger a2 = SkScalarDiv(SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2, denom); 1598f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1599f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1600f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger float invScale = 1 / scale.fX; 1601f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleX] = SkScalarMul(SkScalarMul(a2, srcPt[3].fX) + 1602f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger srcPt[3].fX - srcPt[0].fX, invScale); 1603f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewY] = SkScalarMul(SkScalarMul(a2, srcPt[3].fY) + 1604f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger srcPt[3].fY - srcPt[0].fY, invScale); 1605f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp0] = SkScalarMul(a2, invScale); 1606f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger invScale = 1 / scale.fY; 1607f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMSkewX] = SkScalarMul(SkScalarMul(a1, srcPt[1].fX) + 1608f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger srcPt[1].fX - srcPt[0].fX, invScale); 1609f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMScaleY] = SkScalarMul(SkScalarMul(a1, srcPt[1].fY) + 1610f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger srcPt[1].fY - srcPt[0].fY, invScale); 1611f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp1] = SkScalarMul(a1, invScale); 1612f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransX] = srcPt[0].fX; 1613f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMTransY] = srcPt[0].fY; 1614f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->fMat[kMPersp2] = 1; 1615f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger dst->setTypeMask(kUnknown_Mask); 1616f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1617f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1618f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1619f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1620f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1621f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergertypedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&); 1622f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1623f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/* Taken from Rob Johnson's original sample code in QuickDraw GX 1624f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger*/ 1625f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerbool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[], 1626f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger int count) { 1627f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if ((unsigned)count > 4) { 1628f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count); 1629f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1630f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1631f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1632f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (0 == count) { 1633f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->reset(); 1634f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1635f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1636f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (1 == count) { 1637f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY); 1638f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1639f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1640f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1641f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkPoint scale; 1642f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!poly_to_point(&scale, src, count) || 1643f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarNearlyZero(scale.fX) || 1644f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarNearlyZero(scale.fY)) { 1645f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1646f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1647f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1648f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static const PolyMapProc gPolyMapProcs[] = { 1649f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc 1650f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger }; 1651f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger PolyMapProc proc = gPolyMapProcs[count - 2]; 1652f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1653f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkMatrix tempMap, result; 1654f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger tempMap.setTypeMask(kUnknown_Mask); 1655f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1656f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!proc(src, &tempMap, scale)) { 1657f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1658f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1659f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!tempMap.invert(&result)) { 1660f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1661f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1662f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!proc(dst, &tempMap, scale)) { 1663f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1664f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1665f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!result.setConcat(tempMap, result)) { 1666f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return false; 1667f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1668f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *this = result; 1669f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return true; 1670f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1671f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1672f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1673f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1674f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkScalar SkMatrix::getMaxStretch() const { 1675f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger TypeMask mask = this->getType(); 1676f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1677f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (this->hasPerspective()) { 1678f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return -SK_Scalar1; 1679f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1680f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (this->isIdentity()) { 1681f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return SK_Scalar1; 1682f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1683f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!(mask & kAffine_Mask)) { 1684f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return SkMaxScalar(SkScalarAbs(fMat[kMScaleX]), 1685f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarAbs(fMat[kMScaleY])); 1686f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1687f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // ignore the translation part of the matrix, just look at 2x2 portion. 1688f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // compute singular values, take largest abs value. 1689f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // [a b; b c] = A^T*A 1690f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar a = SkScalarMul(fMat[kMScaleX], fMat[kMScaleX]) + 1691f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(fMat[kMSkewY], fMat[kMSkewY]); 1692f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar b = SkScalarMul(fMat[kMScaleX], fMat[kMSkewX]) + 1693f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(fMat[kMScaleY], fMat[kMSkewY]); 1694f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar c = SkScalarMul(fMat[kMSkewX], fMat[kMSkewX]) + 1695f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalarMul(fMat[kMScaleY], fMat[kMScaleY]); 1696f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // eigenvalues of A^T*A are the squared singular values of A. 1697f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // characteristic equation is det((A^T*A) - l*I) = 0 1698f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // l^2 - (a + c)l + (ac-b^2) 1699f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff 1700f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // and roots are guaraunteed to be pos and real). 1701f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar largerRoot; 1702f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar bSqd = SkScalarMul(b,b); 1703f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // if upper left 2x2 is orthogonal save some math 1704f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (bSqd <= SK_ScalarNearlyZero) { 1705f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger largerRoot = SkMaxScalar(a, c); 1706f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } else { 1707f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar aminusc = a - c; 1708f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar apluscdiv2 = SkScalarHalf(a + c); 1709f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkScalar x = SkScalarHalf(SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd)); 1710f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger largerRoot = apluscdiv2 + x; 1711f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1712f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return SkScalarSqrt(largerRoot); 1713f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1714f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1715f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkMatrix& SkMatrix::I() { 1716f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static SkMatrix gIdentity; 1717f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static bool gOnce; 1718f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!gOnce) { 1719f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger gIdentity.reset(); 1720f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger gOnce = true; 1721f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1722f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return gIdentity; 1723f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}; 1724f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1725f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerconst SkMatrix& SkMatrix::InvalidMatrix() { 1726f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static SkMatrix gInvalid; 1727f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger static bool gOnce; 1728f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (!gOnce) { 1729f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger gInvalid.setAll(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1730f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1731f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); 1732f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger gInvalid.getType(); // force the type to be computed 1733f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger gOnce = true; 1734f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1735f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return gInvalid; 1736f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1737f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1738f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1739f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1740f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergeruint32_t SkMatrix::flatten(void* buffer) const { 1741f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger // TODO write less for simple matrices 1742f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (buffer) { 1743f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger memcpy(buffer, fMat, 9 * sizeof(SkScalar)); 1744f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1745f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return 9 * sizeof(SkScalar); 1746f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1747f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1748f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergeruint32_t SkMatrix::unflatten(const void* buffer) { 1749f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger if (buffer) { 1750f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger memcpy(fMat, buffer, 9 * sizeof(SkScalar)); 1751f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->setTypeMask(kUnknown_Mask); 1752f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger } 1753f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger return 9 * sizeof(SkScalar); 1754f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1755f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1756f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::dump() const { 1757f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkString str; 1758f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger this->toDumpString(&str); 1759f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkDebugf("%s\n", str.c_str()); 1760f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1761f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger 1762f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix::toDumpString(SkString* str) const { 1763f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_CAN_USE_FLOAT 1764f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger str->printf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]", 1765f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT 1766f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5], 1767f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[6], fMat[7], fMat[8]); 1768f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else 1769f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixedToFloat(fMat[0]), SkFixedToFloat(fMat[1]), SkFixedToFloat(fMat[2]), 1770f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFixedToFloat(fMat[3]), SkFixedToFloat(fMat[4]), SkFixedToFloat(fMat[5]), 1771f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger SkFractToFloat(fMat[6]), SkFractToFloat(fMat[7]), SkFractToFloat(fMat[8])); 1772f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1773f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else // can't use float 1774f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger str->printf("[%x %x %x][%x %x %x][%x %x %x]", 1775f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5], 1776f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger fMat[6], fMat[7], fMat[8]); 1777f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif 1778f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger} 1779