1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 11cb93a386Sopenharmony_ci#include "include/core/SkPoint3.h" 12cb93a386Sopenharmony_ci#include "include/core/SkRSXform.h" 13cb93a386Sopenharmony_ci#include "include/core/SkString.h" 14cb93a386Sopenharmony_ci#include "include/private/SkFloatBits.h" 15cb93a386Sopenharmony_ci#include "include/private/SkNx.h" 16cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 17cb93a386Sopenharmony_ci#include "src/core/SkMathPriv.h" 18cb93a386Sopenharmony_ci#include "src/core/SkMatrixPriv.h" 19cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci#include <cstddef> 22cb93a386Sopenharmony_ci#include <utility> 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_civoid SkMatrix::doNormalizePerspective() { 25cb93a386Sopenharmony_ci // If the bottom row of the matrix is [0, 0, not_one], we will treat the matrix as if it 26cb93a386Sopenharmony_ci // is in perspective, even though it stills behaves like its affine. If we divide everything 27cb93a386Sopenharmony_ci // by the not_one value, then it will behave the same, but will be treated as affine, 28cb93a386Sopenharmony_ci // and therefore faster (e.g. clients can forward-difference calculations). 29cb93a386Sopenharmony_ci // 30cb93a386Sopenharmony_ci if (0 == fMat[SkMatrix::kMPersp0] && 0 == fMat[SkMatrix::kMPersp1]) { 31cb93a386Sopenharmony_ci SkScalar p2 = fMat[SkMatrix::kMPersp2]; 32cb93a386Sopenharmony_ci if (p2 != 0 && p2 != 1) { 33cb93a386Sopenharmony_ci double inv = 1.0 / p2; 34cb93a386Sopenharmony_ci for (int i = 0; i < 6; ++i) { 35cb93a386Sopenharmony_ci fMat[i] = SkDoubleToScalar(fMat[i] * inv); 36cb93a386Sopenharmony_ci } 37cb93a386Sopenharmony_ci fMat[SkMatrix::kMPersp2] = 1; 38cb93a386Sopenharmony_ci } 39cb93a386Sopenharmony_ci this->setTypeMask(kUnknown_Mask); 40cb93a386Sopenharmony_ci } 41cb93a386Sopenharmony_ci} 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci// In a few places, we performed the following 44cb93a386Sopenharmony_ci// a * b + c * d + e 45cb93a386Sopenharmony_ci// as 46cb93a386Sopenharmony_ci// a * b + (c * d + e) 47cb93a386Sopenharmony_ci// 48cb93a386Sopenharmony_ci// sdot and scross are indended to capture these compound operations into a 49cb93a386Sopenharmony_ci// function, with an eye toward considering upscaling the intermediates to 50cb93a386Sopenharmony_ci// doubles for more precision (as we do in concat and invert). 51cb93a386Sopenharmony_ci// 52cb93a386Sopenharmony_ci// However, these few lines that performed the last add before the "dot", cause 53cb93a386Sopenharmony_ci// tiny image differences, so we guard that change until we see the impact on 54cb93a386Sopenharmony_ci// chrome's layouttests. 55cb93a386Sopenharmony_ci// 56cb93a386Sopenharmony_ci#define SK_LEGACY_MATRIX_MATH_ORDER 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_ci/* [scale-x skew-x trans-x] [X] [X'] 59cb93a386Sopenharmony_ci [skew-y scale-y trans-y] * [Y] = [Y'] 60cb93a386Sopenharmony_ci [persp-0 persp-1 persp-2] [1] [1 ] 61cb93a386Sopenharmony_ci*/ 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ciSkMatrix& SkMatrix::reset() { *this = SkMatrix(); return *this; } 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ciSkMatrix& SkMatrix::set9(const SkScalar buffer[]) { 66cb93a386Sopenharmony_ci memcpy(fMat, buffer, 9 * sizeof(SkScalar)); 67cb93a386Sopenharmony_ci this->setTypeMask(kUnknown_Mask); 68cb93a386Sopenharmony_ci return *this; 69cb93a386Sopenharmony_ci} 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setAffine(const SkScalar buffer[]) { 72cb93a386Sopenharmony_ci fMat[kMScaleX] = buffer[kAScaleX]; 73cb93a386Sopenharmony_ci fMat[kMSkewX] = buffer[kASkewX]; 74cb93a386Sopenharmony_ci fMat[kMTransX] = buffer[kATransX]; 75cb93a386Sopenharmony_ci fMat[kMSkewY] = buffer[kASkewY]; 76cb93a386Sopenharmony_ci fMat[kMScaleY] = buffer[kAScaleY]; 77cb93a386Sopenharmony_ci fMat[kMTransY] = buffer[kATransY]; 78cb93a386Sopenharmony_ci fMat[kMPersp0] = 0; 79cb93a386Sopenharmony_ci fMat[kMPersp1] = 0; 80cb93a386Sopenharmony_ci fMat[kMPersp2] = 1; 81cb93a386Sopenharmony_ci this->setTypeMask(kUnknown_Mask); 82cb93a386Sopenharmony_ci return *this; 83cb93a386Sopenharmony_ci} 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci// this aligns with the masks, so we can compute a mask from a variable 0/1 86cb93a386Sopenharmony_cienum { 87cb93a386Sopenharmony_ci kTranslate_Shift, 88cb93a386Sopenharmony_ci kScale_Shift, 89cb93a386Sopenharmony_ci kAffine_Shift, 90cb93a386Sopenharmony_ci kPerspective_Shift, 91cb93a386Sopenharmony_ci kRectStaysRect_Shift 92cb93a386Sopenharmony_ci}; 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_cistatic const int32_t kScalar1Int = 0x3f800000; 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ciuint8_t SkMatrix::computePerspectiveTypeMask() const { 97cb93a386Sopenharmony_ci // Benchmarking suggests that replacing this set of SkScalarAs2sCompliment 98cb93a386Sopenharmony_ci // is a win, but replacing those below is not. We don't yet understand 99cb93a386Sopenharmony_ci // that result. 100cb93a386Sopenharmony_ci if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) { 101cb93a386Sopenharmony_ci // If this is a perspective transform, we return true for all other 102cb93a386Sopenharmony_ci // transform flags - this does not disable any optimizations, respects 103cb93a386Sopenharmony_ci // the rule that the type mask must be conservative, and speeds up 104cb93a386Sopenharmony_ci // type mask computation. 105cb93a386Sopenharmony_ci return SkToU8(kORableMasks); 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci return SkToU8(kOnlyPerspectiveValid_Mask | kUnknown_Mask); 109cb93a386Sopenharmony_ci} 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ciuint8_t SkMatrix::computeTypeMask() const { 112cb93a386Sopenharmony_ci unsigned mask = 0; 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ci if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 || fMat[kMPersp2] != 1) { 115cb93a386Sopenharmony_ci // Once it is determined that that this is a perspective transform, 116cb93a386Sopenharmony_ci // all other flags are moot as far as optimizations are concerned. 117cb93a386Sopenharmony_ci return SkToU8(kORableMasks); 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci if (fMat[kMTransX] != 0 || fMat[kMTransY] != 0) { 121cb93a386Sopenharmony_ci mask |= kTranslate_Mask; 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci int m00 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleX]); 125cb93a386Sopenharmony_ci int m01 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewX]); 126cb93a386Sopenharmony_ci int m10 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewY]); 127cb93a386Sopenharmony_ci int m11 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleY]); 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci if (m01 | m10) { 130cb93a386Sopenharmony_ci // The skew components may be scale-inducing, unless we are dealing 131cb93a386Sopenharmony_ci // with a pure rotation. Testing for a pure rotation is expensive, 132cb93a386Sopenharmony_ci // so we opt for being conservative by always setting the scale bit. 133cb93a386Sopenharmony_ci // along with affine. 134cb93a386Sopenharmony_ci // By doing this, we are also ensuring that matrices have the same 135cb93a386Sopenharmony_ci // type masks as their inverses. 136cb93a386Sopenharmony_ci mask |= kAffine_Mask | kScale_Mask; 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci // For rectStaysRect, in the affine case, we only need check that 139cb93a386Sopenharmony_ci // the primary diagonal is all zeros and that the secondary diagonal 140cb93a386Sopenharmony_ci // is all non-zero. 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci // map non-zero to 1 143cb93a386Sopenharmony_ci m01 = m01 != 0; 144cb93a386Sopenharmony_ci m10 = m10 != 0; 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci int dp0 = 0 == (m00 | m11) ; // true if both are 0 147cb93a386Sopenharmony_ci int ds1 = m01 & m10; // true if both are 1 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_ci mask |= (dp0 & ds1) << kRectStaysRect_Shift; 150cb93a386Sopenharmony_ci } else { 151cb93a386Sopenharmony_ci // Only test for scale explicitly if not affine, since affine sets the 152cb93a386Sopenharmony_ci // scale bit. 153cb93a386Sopenharmony_ci if ((m00 ^ kScalar1Int) | (m11 ^ kScalar1Int)) { 154cb93a386Sopenharmony_ci mask |= kScale_Mask; 155cb93a386Sopenharmony_ci } 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ci // Not affine, therefore we already know secondary diagonal is 158cb93a386Sopenharmony_ci // all zeros, so we just need to check that primary diagonal is 159cb93a386Sopenharmony_ci // all non-zero. 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ci // map non-zero to 1 162cb93a386Sopenharmony_ci m00 = m00 != 0; 163cb93a386Sopenharmony_ci m11 = m11 != 0; 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci // record if the (p)rimary diagonal is all non-zero 166cb93a386Sopenharmony_ci mask |= (m00 & m11) << kRectStaysRect_Shift; 167cb93a386Sopenharmony_ci } 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ci return SkToU8(mask); 170cb93a386Sopenharmony_ci} 171cb93a386Sopenharmony_ci 172cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_cibool operator==(const SkMatrix& a, const SkMatrix& b) { 175cb93a386Sopenharmony_ci const SkScalar* SK_RESTRICT ma = a.fMat; 176cb93a386Sopenharmony_ci const SkScalar* SK_RESTRICT mb = b.fMat; 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_ci return ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] && 179cb93a386Sopenharmony_ci ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] && 180cb93a386Sopenharmony_ci ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8]; 181cb93a386Sopenharmony_ci} 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 184cb93a386Sopenharmony_ci 185cb93a386Sopenharmony_ci// helper function to determine if upper-left 2x2 of matrix is degenerate 186cb93a386Sopenharmony_cistatic inline bool is_degenerate_2x2(SkScalar scaleX, SkScalar skewX, 187cb93a386Sopenharmony_ci SkScalar skewY, SkScalar scaleY) { 188cb93a386Sopenharmony_ci SkScalar perp_dot = scaleX*scaleY - skewX*skewY; 189cb93a386Sopenharmony_ci return SkScalarNearlyZero(perp_dot, SK_ScalarNearlyZero*SK_ScalarNearlyZero); 190cb93a386Sopenharmony_ci} 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_cibool SkMatrix::isSimilarity(SkScalar tol) const { 195cb93a386Sopenharmony_ci // if identity or translate matrix 196cb93a386Sopenharmony_ci TypeMask mask = this->getType(); 197cb93a386Sopenharmony_ci if (mask <= kTranslate_Mask) { 198cb93a386Sopenharmony_ci return true; 199cb93a386Sopenharmony_ci } 200cb93a386Sopenharmony_ci if (mask & kPerspective_Mask) { 201cb93a386Sopenharmony_ci return false; 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_ci SkScalar mx = fMat[kMScaleX]; 205cb93a386Sopenharmony_ci SkScalar my = fMat[kMScaleY]; 206cb93a386Sopenharmony_ci // if no skew, can just compare scale factors 207cb93a386Sopenharmony_ci if (!(mask & kAffine_Mask)) { 208cb93a386Sopenharmony_ci return !SkScalarNearlyZero(mx) && SkScalarNearlyEqual(SkScalarAbs(mx), SkScalarAbs(my)); 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci SkScalar sx = fMat[kMSkewX]; 211cb93a386Sopenharmony_ci SkScalar sy = fMat[kMSkewY]; 212cb93a386Sopenharmony_ci 213cb93a386Sopenharmony_ci if (is_degenerate_2x2(mx, sx, sy, my)) { 214cb93a386Sopenharmony_ci return false; 215cb93a386Sopenharmony_ci } 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_ci // upper 2x2 is rotation/reflection + uniform scale if basis vectors 218cb93a386Sopenharmony_ci // are 90 degree rotations of each other 219cb93a386Sopenharmony_ci return (SkScalarNearlyEqual(mx, my, tol) && SkScalarNearlyEqual(sx, -sy, tol)) 220cb93a386Sopenharmony_ci || (SkScalarNearlyEqual(mx, -my, tol) && SkScalarNearlyEqual(sx, sy, tol)); 221cb93a386Sopenharmony_ci} 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_cibool SkMatrix::preservesRightAngles(SkScalar tol) const { 224cb93a386Sopenharmony_ci TypeMask mask = this->getType(); 225cb93a386Sopenharmony_ci 226cb93a386Sopenharmony_ci if (mask <= kTranslate_Mask) { 227cb93a386Sopenharmony_ci // identity, translate and/or scale 228cb93a386Sopenharmony_ci return true; 229cb93a386Sopenharmony_ci } 230cb93a386Sopenharmony_ci if (mask & kPerspective_Mask) { 231cb93a386Sopenharmony_ci return false; 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci 234cb93a386Sopenharmony_ci SkASSERT(mask & (kAffine_Mask | kScale_Mask)); 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ci SkScalar mx = fMat[kMScaleX]; 237cb93a386Sopenharmony_ci SkScalar my = fMat[kMScaleY]; 238cb93a386Sopenharmony_ci SkScalar sx = fMat[kMSkewX]; 239cb93a386Sopenharmony_ci SkScalar sy = fMat[kMSkewY]; 240cb93a386Sopenharmony_ci 241cb93a386Sopenharmony_ci if (is_degenerate_2x2(mx, sx, sy, my)) { 242cb93a386Sopenharmony_ci return false; 243cb93a386Sopenharmony_ci } 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci // upper 2x2 is scale + rotation/reflection if basis vectors are orthogonal 246cb93a386Sopenharmony_ci SkVector vec[2]; 247cb93a386Sopenharmony_ci vec[0].set(mx, sy); 248cb93a386Sopenharmony_ci vec[1].set(sx, my); 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_ci return SkScalarNearlyZero(vec[0].dot(vec[1]), SkScalarSquare(tol)); 251cb93a386Sopenharmony_ci} 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 254cb93a386Sopenharmony_ci 255cb93a386Sopenharmony_cistatic inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d) { 256cb93a386Sopenharmony_ci return a * b + c * d; 257cb93a386Sopenharmony_ci} 258cb93a386Sopenharmony_ci 259cb93a386Sopenharmony_cistatic inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d, 260cb93a386Sopenharmony_ci SkScalar e, SkScalar f) { 261cb93a386Sopenharmony_ci return a * b + c * d + e * f; 262cb93a386Sopenharmony_ci} 263cb93a386Sopenharmony_ci 264cb93a386Sopenharmony_cistatic inline SkScalar scross(SkScalar a, SkScalar b, SkScalar c, SkScalar d) { 265cb93a386Sopenharmony_ci return a * b - c * d; 266cb93a386Sopenharmony_ci} 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setTranslate(SkScalar dx, SkScalar dy) { 269cb93a386Sopenharmony_ci *this = SkMatrix(1, 0, dx, 270cb93a386Sopenharmony_ci 0, 1, dy, 271cb93a386Sopenharmony_ci 0, 0, 1, 272cb93a386Sopenharmony_ci (dx != 0 || dy != 0) ? kTranslate_Mask | kRectStaysRect_Mask 273cb93a386Sopenharmony_ci : kIdentity_Mask | kRectStaysRect_Mask); 274cb93a386Sopenharmony_ci return *this; 275cb93a386Sopenharmony_ci} 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ciSkMatrix& SkMatrix::preTranslate(SkScalar dx, SkScalar dy) { 278cb93a386Sopenharmony_ci const unsigned mask = this->getType(); 279cb93a386Sopenharmony_ci 280cb93a386Sopenharmony_ci if (mask <= kTranslate_Mask) { 281cb93a386Sopenharmony_ci fMat[kMTransX] += dx; 282cb93a386Sopenharmony_ci fMat[kMTransY] += dy; 283cb93a386Sopenharmony_ci } else if (mask & kPerspective_Mask) { 284cb93a386Sopenharmony_ci SkMatrix m; 285cb93a386Sopenharmony_ci m.setTranslate(dx, dy); 286cb93a386Sopenharmony_ci return this->preConcat(m); 287cb93a386Sopenharmony_ci } else { 288cb93a386Sopenharmony_ci fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy); 289cb93a386Sopenharmony_ci fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy); 290cb93a386Sopenharmony_ci } 291cb93a386Sopenharmony_ci this->updateTranslateMask(); 292cb93a386Sopenharmony_ci return *this; 293cb93a386Sopenharmony_ci} 294cb93a386Sopenharmony_ci 295cb93a386Sopenharmony_ciSkMatrix& SkMatrix::postTranslate(SkScalar dx, SkScalar dy) { 296cb93a386Sopenharmony_ci if (this->hasPerspective()) { 297cb93a386Sopenharmony_ci SkMatrix m; 298cb93a386Sopenharmony_ci m.setTranslate(dx, dy); 299cb93a386Sopenharmony_ci this->postConcat(m); 300cb93a386Sopenharmony_ci } else { 301cb93a386Sopenharmony_ci fMat[kMTransX] += dx; 302cb93a386Sopenharmony_ci fMat[kMTransY] += dy; 303cb93a386Sopenharmony_ci this->updateTranslateMask(); 304cb93a386Sopenharmony_ci } 305cb93a386Sopenharmony_ci return *this; 306cb93a386Sopenharmony_ci} 307cb93a386Sopenharmony_ci 308cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 309cb93a386Sopenharmony_ci 310cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 311cb93a386Sopenharmony_ci if (1 == sx && 1 == sy) { 312cb93a386Sopenharmony_ci this->reset(); 313cb93a386Sopenharmony_ci } else { 314cb93a386Sopenharmony_ci this->setScaleTranslate(sx, sy, px - sx * px, py - sy * py); 315cb93a386Sopenharmony_ci } 316cb93a386Sopenharmony_ci return *this; 317cb93a386Sopenharmony_ci} 318cb93a386Sopenharmony_ci 319cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setScale(SkScalar sx, SkScalar sy) { 320cb93a386Sopenharmony_ci *this = SkMatrix(sx, 0, 0, 321cb93a386Sopenharmony_ci 0, sy, 0, 322cb93a386Sopenharmony_ci 0, 0, 1, 323cb93a386Sopenharmony_ci (sx == 1 && sy == 1) ? kIdentity_Mask | kRectStaysRect_Mask 324cb93a386Sopenharmony_ci : kScale_Mask | kRectStaysRect_Mask); 325cb93a386Sopenharmony_ci return *this; 326cb93a386Sopenharmony_ci} 327cb93a386Sopenharmony_ci 328cb93a386Sopenharmony_ciSkMatrix& SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 329cb93a386Sopenharmony_ci if (1 == sx && 1 == sy) { 330cb93a386Sopenharmony_ci return *this; 331cb93a386Sopenharmony_ci } 332cb93a386Sopenharmony_ci 333cb93a386Sopenharmony_ci SkMatrix m; 334cb93a386Sopenharmony_ci m.setScale(sx, sy, px, py); 335cb93a386Sopenharmony_ci return this->preConcat(m); 336cb93a386Sopenharmony_ci} 337cb93a386Sopenharmony_ci 338cb93a386Sopenharmony_ciSkMatrix& SkMatrix::preScale(SkScalar sx, SkScalar sy) { 339cb93a386Sopenharmony_ci if (1 == sx && 1 == sy) { 340cb93a386Sopenharmony_ci return *this; 341cb93a386Sopenharmony_ci } 342cb93a386Sopenharmony_ci 343cb93a386Sopenharmony_ci // the assumption is that these multiplies are very cheap, and that 344cb93a386Sopenharmony_ci // a full concat and/or just computing the matrix type is more expensive. 345cb93a386Sopenharmony_ci // Also, the fixed-point case checks for overflow, but the float doesn't, 346cb93a386Sopenharmony_ci // so we can get away with these blind multiplies. 347cb93a386Sopenharmony_ci 348cb93a386Sopenharmony_ci fMat[kMScaleX] *= sx; 349cb93a386Sopenharmony_ci fMat[kMSkewY] *= sx; 350cb93a386Sopenharmony_ci fMat[kMPersp0] *= sx; 351cb93a386Sopenharmony_ci 352cb93a386Sopenharmony_ci fMat[kMSkewX] *= sy; 353cb93a386Sopenharmony_ci fMat[kMScaleY] *= sy; 354cb93a386Sopenharmony_ci fMat[kMPersp1] *= sy; 355cb93a386Sopenharmony_ci 356cb93a386Sopenharmony_ci // Attempt to simplify our type when applying an inverse scale. 357cb93a386Sopenharmony_ci // TODO: The persp/affine preconditions are in place to keep the mask consistent with 358cb93a386Sopenharmony_ci // what computeTypeMask() would produce (persp/skew always implies kScale). 359cb93a386Sopenharmony_ci // We should investigate whether these flag dependencies are truly needed. 360cb93a386Sopenharmony_ci if (fMat[kMScaleX] == 1 && fMat[kMScaleY] == 1 361cb93a386Sopenharmony_ci && !(fTypeMask & (kPerspective_Mask | kAffine_Mask))) { 362cb93a386Sopenharmony_ci this->clearTypeMask(kScale_Mask); 363cb93a386Sopenharmony_ci } else { 364cb93a386Sopenharmony_ci this->orTypeMask(kScale_Mask); 365cb93a386Sopenharmony_ci } 366cb93a386Sopenharmony_ci return *this; 367cb93a386Sopenharmony_ci} 368cb93a386Sopenharmony_ci 369cb93a386Sopenharmony_ciSkMatrix& SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 370cb93a386Sopenharmony_ci if (1 == sx && 1 == sy) { 371cb93a386Sopenharmony_ci return *this; 372cb93a386Sopenharmony_ci } 373cb93a386Sopenharmony_ci SkMatrix m; 374cb93a386Sopenharmony_ci m.setScale(sx, sy, px, py); 375cb93a386Sopenharmony_ci return this->postConcat(m); 376cb93a386Sopenharmony_ci} 377cb93a386Sopenharmony_ci 378cb93a386Sopenharmony_ciSkMatrix& SkMatrix::postScale(SkScalar sx, SkScalar sy) { 379cb93a386Sopenharmony_ci if (1 == sx && 1 == sy) { 380cb93a386Sopenharmony_ci return *this; 381cb93a386Sopenharmony_ci } 382cb93a386Sopenharmony_ci SkMatrix m; 383cb93a386Sopenharmony_ci m.setScale(sx, sy); 384cb93a386Sopenharmony_ci return this->postConcat(m); 385cb93a386Sopenharmony_ci} 386cb93a386Sopenharmony_ci 387cb93a386Sopenharmony_ci// this perhaps can go away, if we have a fract/high-precision way to 388cb93a386Sopenharmony_ci// scale matrices 389cb93a386Sopenharmony_cibool SkMatrix::postIDiv(int divx, int divy) { 390cb93a386Sopenharmony_ci if (divx == 0 || divy == 0) { 391cb93a386Sopenharmony_ci return false; 392cb93a386Sopenharmony_ci } 393cb93a386Sopenharmony_ci 394cb93a386Sopenharmony_ci const float invX = 1.f / divx; 395cb93a386Sopenharmony_ci const float invY = 1.f / divy; 396cb93a386Sopenharmony_ci 397cb93a386Sopenharmony_ci fMat[kMScaleX] *= invX; 398cb93a386Sopenharmony_ci fMat[kMSkewX] *= invX; 399cb93a386Sopenharmony_ci fMat[kMTransX] *= invX; 400cb93a386Sopenharmony_ci 401cb93a386Sopenharmony_ci fMat[kMScaleY] *= invY; 402cb93a386Sopenharmony_ci fMat[kMSkewY] *= invY; 403cb93a386Sopenharmony_ci fMat[kMTransY] *= invY; 404cb93a386Sopenharmony_ci 405cb93a386Sopenharmony_ci this->setTypeMask(kUnknown_Mask); 406cb93a386Sopenharmony_ci return true; 407cb93a386Sopenharmony_ci} 408cb93a386Sopenharmony_ci 409cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////// 410cb93a386Sopenharmony_ci 411cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV, SkScalar px, SkScalar py) { 412cb93a386Sopenharmony_ci const SkScalar oneMinusCosV = 1 - cosV; 413cb93a386Sopenharmony_ci 414cb93a386Sopenharmony_ci fMat[kMScaleX] = cosV; 415cb93a386Sopenharmony_ci fMat[kMSkewX] = -sinV; 416cb93a386Sopenharmony_ci fMat[kMTransX] = sdot(sinV, py, oneMinusCosV, px); 417cb93a386Sopenharmony_ci 418cb93a386Sopenharmony_ci fMat[kMSkewY] = sinV; 419cb93a386Sopenharmony_ci fMat[kMScaleY] = cosV; 420cb93a386Sopenharmony_ci fMat[kMTransY] = sdot(-sinV, px, oneMinusCosV, py); 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_ci fMat[kMPersp0] = fMat[kMPersp1] = 0; 423cb93a386Sopenharmony_ci fMat[kMPersp2] = 1; 424cb93a386Sopenharmony_ci 425cb93a386Sopenharmony_ci this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 426cb93a386Sopenharmony_ci return *this; 427cb93a386Sopenharmony_ci} 428cb93a386Sopenharmony_ci 429cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setRSXform(const SkRSXform& xform) { 430cb93a386Sopenharmony_ci fMat[kMScaleX] = xform.fSCos; 431cb93a386Sopenharmony_ci fMat[kMSkewX] = -xform.fSSin; 432cb93a386Sopenharmony_ci fMat[kMTransX] = xform.fTx; 433cb93a386Sopenharmony_ci 434cb93a386Sopenharmony_ci fMat[kMSkewY] = xform.fSSin; 435cb93a386Sopenharmony_ci fMat[kMScaleY] = xform.fSCos; 436cb93a386Sopenharmony_ci fMat[kMTransY] = xform.fTy; 437cb93a386Sopenharmony_ci 438cb93a386Sopenharmony_ci fMat[kMPersp0] = fMat[kMPersp1] = 0; 439cb93a386Sopenharmony_ci fMat[kMPersp2] = 1; 440cb93a386Sopenharmony_ci 441cb93a386Sopenharmony_ci this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 442cb93a386Sopenharmony_ci return *this; 443cb93a386Sopenharmony_ci} 444cb93a386Sopenharmony_ci 445cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) { 446cb93a386Sopenharmony_ci fMat[kMScaleX] = cosV; 447cb93a386Sopenharmony_ci fMat[kMSkewX] = -sinV; 448cb93a386Sopenharmony_ci fMat[kMTransX] = 0; 449cb93a386Sopenharmony_ci 450cb93a386Sopenharmony_ci fMat[kMSkewY] = sinV; 451cb93a386Sopenharmony_ci fMat[kMScaleY] = cosV; 452cb93a386Sopenharmony_ci fMat[kMTransY] = 0; 453cb93a386Sopenharmony_ci 454cb93a386Sopenharmony_ci fMat[kMPersp0] = fMat[kMPersp1] = 0; 455cb93a386Sopenharmony_ci fMat[kMPersp2] = 1; 456cb93a386Sopenharmony_ci 457cb93a386Sopenharmony_ci this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 458cb93a386Sopenharmony_ci return *this; 459cb93a386Sopenharmony_ci} 460cb93a386Sopenharmony_ci 461cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) { 462cb93a386Sopenharmony_ci SkScalar rad = SkDegreesToRadians(degrees); 463cb93a386Sopenharmony_ci return this->setSinCos(SkScalarSinSnapToZero(rad), SkScalarCosSnapToZero(rad), px, py); 464cb93a386Sopenharmony_ci} 465cb93a386Sopenharmony_ci 466cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setRotate(SkScalar degrees) { 467cb93a386Sopenharmony_ci SkScalar rad = SkDegreesToRadians(degrees); 468cb93a386Sopenharmony_ci return this->setSinCos(SkScalarSinSnapToZero(rad), SkScalarCosSnapToZero(rad)); 469cb93a386Sopenharmony_ci} 470cb93a386Sopenharmony_ci 471cb93a386Sopenharmony_ciSkMatrix& SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) { 472cb93a386Sopenharmony_ci SkMatrix m; 473cb93a386Sopenharmony_ci m.setRotate(degrees, px, py); 474cb93a386Sopenharmony_ci return this->preConcat(m); 475cb93a386Sopenharmony_ci} 476cb93a386Sopenharmony_ci 477cb93a386Sopenharmony_ciSkMatrix& SkMatrix::preRotate(SkScalar degrees) { 478cb93a386Sopenharmony_ci SkMatrix m; 479cb93a386Sopenharmony_ci m.setRotate(degrees); 480cb93a386Sopenharmony_ci return this->preConcat(m); 481cb93a386Sopenharmony_ci} 482cb93a386Sopenharmony_ci 483cb93a386Sopenharmony_ciSkMatrix& SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) { 484cb93a386Sopenharmony_ci SkMatrix m; 485cb93a386Sopenharmony_ci m.setRotate(degrees, px, py); 486cb93a386Sopenharmony_ci return this->postConcat(m); 487cb93a386Sopenharmony_ci} 488cb93a386Sopenharmony_ci 489cb93a386Sopenharmony_ciSkMatrix& SkMatrix::postRotate(SkScalar degrees) { 490cb93a386Sopenharmony_ci SkMatrix m; 491cb93a386Sopenharmony_ci m.setRotate(degrees); 492cb93a386Sopenharmony_ci return this->postConcat(m); 493cb93a386Sopenharmony_ci} 494cb93a386Sopenharmony_ci 495cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////// 496cb93a386Sopenharmony_ci 497cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 498cb93a386Sopenharmony_ci *this = SkMatrix(1, sx, -sx * py, 499cb93a386Sopenharmony_ci sy, 1, -sy * px, 500cb93a386Sopenharmony_ci 0, 0, 1, 501cb93a386Sopenharmony_ci kUnknown_Mask | kOnlyPerspectiveValid_Mask); 502cb93a386Sopenharmony_ci return *this; 503cb93a386Sopenharmony_ci} 504cb93a386Sopenharmony_ci 505cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setSkew(SkScalar sx, SkScalar sy) { 506cb93a386Sopenharmony_ci fMat[kMScaleX] = 1; 507cb93a386Sopenharmony_ci fMat[kMSkewX] = sx; 508cb93a386Sopenharmony_ci fMat[kMTransX] = 0; 509cb93a386Sopenharmony_ci 510cb93a386Sopenharmony_ci fMat[kMSkewY] = sy; 511cb93a386Sopenharmony_ci fMat[kMScaleY] = 1; 512cb93a386Sopenharmony_ci fMat[kMTransY] = 0; 513cb93a386Sopenharmony_ci 514cb93a386Sopenharmony_ci fMat[kMPersp0] = fMat[kMPersp1] = 0; 515cb93a386Sopenharmony_ci fMat[kMPersp2] = 1; 516cb93a386Sopenharmony_ci 517cb93a386Sopenharmony_ci this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 518cb93a386Sopenharmony_ci return *this; 519cb93a386Sopenharmony_ci} 520cb93a386Sopenharmony_ci 521cb93a386Sopenharmony_ciSkMatrix& SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 522cb93a386Sopenharmony_ci SkMatrix m; 523cb93a386Sopenharmony_ci m.setSkew(sx, sy, px, py); 524cb93a386Sopenharmony_ci return this->preConcat(m); 525cb93a386Sopenharmony_ci} 526cb93a386Sopenharmony_ci 527cb93a386Sopenharmony_ciSkMatrix& SkMatrix::preSkew(SkScalar sx, SkScalar sy) { 528cb93a386Sopenharmony_ci SkMatrix m; 529cb93a386Sopenharmony_ci m.setSkew(sx, sy); 530cb93a386Sopenharmony_ci return this->preConcat(m); 531cb93a386Sopenharmony_ci} 532cb93a386Sopenharmony_ci 533cb93a386Sopenharmony_ciSkMatrix& SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) { 534cb93a386Sopenharmony_ci SkMatrix m; 535cb93a386Sopenharmony_ci m.setSkew(sx, sy, px, py); 536cb93a386Sopenharmony_ci return this->postConcat(m); 537cb93a386Sopenharmony_ci} 538cb93a386Sopenharmony_ci 539cb93a386Sopenharmony_ciSkMatrix& SkMatrix::postSkew(SkScalar sx, SkScalar sy) { 540cb93a386Sopenharmony_ci SkMatrix m; 541cb93a386Sopenharmony_ci m.setSkew(sx, sy); 542cb93a386Sopenharmony_ci return this->postConcat(m); 543cb93a386Sopenharmony_ci} 544cb93a386Sopenharmony_ci 545cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 546cb93a386Sopenharmony_ci 547cb93a386Sopenharmony_cibool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit align) { 548cb93a386Sopenharmony_ci if (src.isEmpty()) { 549cb93a386Sopenharmony_ci this->reset(); 550cb93a386Sopenharmony_ci return false; 551cb93a386Sopenharmony_ci } 552cb93a386Sopenharmony_ci 553cb93a386Sopenharmony_ci if (dst.isEmpty()) { 554cb93a386Sopenharmony_ci sk_bzero(fMat, 8 * sizeof(SkScalar)); 555cb93a386Sopenharmony_ci fMat[kMPersp2] = 1; 556cb93a386Sopenharmony_ci this->setTypeMask(kScale_Mask | kRectStaysRect_Mask); 557cb93a386Sopenharmony_ci } else { 558cb93a386Sopenharmony_ci SkScalar tx, sx = dst.width() / src.width(); 559cb93a386Sopenharmony_ci SkScalar ty, sy = dst.height() / src.height(); 560cb93a386Sopenharmony_ci bool xLarger = false; 561cb93a386Sopenharmony_ci 562cb93a386Sopenharmony_ci if (align != kFill_ScaleToFit) { 563cb93a386Sopenharmony_ci if (sx > sy) { 564cb93a386Sopenharmony_ci xLarger = true; 565cb93a386Sopenharmony_ci sx = sy; 566cb93a386Sopenharmony_ci } else { 567cb93a386Sopenharmony_ci sy = sx; 568cb93a386Sopenharmony_ci } 569cb93a386Sopenharmony_ci } 570cb93a386Sopenharmony_ci 571cb93a386Sopenharmony_ci tx = dst.fLeft - src.fLeft * sx; 572cb93a386Sopenharmony_ci ty = dst.fTop - src.fTop * sy; 573cb93a386Sopenharmony_ci if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) { 574cb93a386Sopenharmony_ci SkScalar diff; 575cb93a386Sopenharmony_ci 576cb93a386Sopenharmony_ci if (xLarger) { 577cb93a386Sopenharmony_ci diff = dst.width() - src.width() * sy; 578cb93a386Sopenharmony_ci } else { 579cb93a386Sopenharmony_ci diff = dst.height() - src.height() * sy; 580cb93a386Sopenharmony_ci } 581cb93a386Sopenharmony_ci 582cb93a386Sopenharmony_ci if (align == kCenter_ScaleToFit) { 583cb93a386Sopenharmony_ci diff = SkScalarHalf(diff); 584cb93a386Sopenharmony_ci } 585cb93a386Sopenharmony_ci 586cb93a386Sopenharmony_ci if (xLarger) { 587cb93a386Sopenharmony_ci tx += diff; 588cb93a386Sopenharmony_ci } else { 589cb93a386Sopenharmony_ci ty += diff; 590cb93a386Sopenharmony_ci } 591cb93a386Sopenharmony_ci } 592cb93a386Sopenharmony_ci 593cb93a386Sopenharmony_ci this->setScaleTranslate(sx, sy, tx, ty); 594cb93a386Sopenharmony_ci } 595cb93a386Sopenharmony_ci return true; 596cb93a386Sopenharmony_ci} 597cb93a386Sopenharmony_ci 598cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 599cb93a386Sopenharmony_ci 600cb93a386Sopenharmony_cistatic inline float muladdmul(float a, float b, float c, float d) { 601cb93a386Sopenharmony_ci return sk_double_to_float((double)a * b + (double)c * d); 602cb93a386Sopenharmony_ci} 603cb93a386Sopenharmony_ci 604cb93a386Sopenharmony_cistatic inline float rowcol3(const float row[], const float col[]) { 605cb93a386Sopenharmony_ci return row[0] * col[0] + row[1] * col[3] + row[2] * col[6]; 606cb93a386Sopenharmony_ci} 607cb93a386Sopenharmony_ci 608cb93a386Sopenharmony_cistatic bool only_scale_and_translate(unsigned mask) { 609cb93a386Sopenharmony_ci return 0 == (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)); 610cb93a386Sopenharmony_ci} 611cb93a386Sopenharmony_ci 612cb93a386Sopenharmony_ciSkMatrix& SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) { 613cb93a386Sopenharmony_ci TypeMask aType = a.getType(); 614cb93a386Sopenharmony_ci TypeMask bType = b.getType(); 615cb93a386Sopenharmony_ci 616cb93a386Sopenharmony_ci if (a.isTriviallyIdentity()) { 617cb93a386Sopenharmony_ci *this = b; 618cb93a386Sopenharmony_ci } else if (b.isTriviallyIdentity()) { 619cb93a386Sopenharmony_ci *this = a; 620cb93a386Sopenharmony_ci } else if (only_scale_and_translate(aType | bType)) { 621cb93a386Sopenharmony_ci this->setScaleTranslate(a.fMat[kMScaleX] * b.fMat[kMScaleX], 622cb93a386Sopenharmony_ci a.fMat[kMScaleY] * b.fMat[kMScaleY], 623cb93a386Sopenharmony_ci a.fMat[kMScaleX] * b.fMat[kMTransX] + a.fMat[kMTransX], 624cb93a386Sopenharmony_ci a.fMat[kMScaleY] * b.fMat[kMTransY] + a.fMat[kMTransY]); 625cb93a386Sopenharmony_ci } else { 626cb93a386Sopenharmony_ci SkMatrix tmp; 627cb93a386Sopenharmony_ci 628cb93a386Sopenharmony_ci if ((aType | bType) & kPerspective_Mask) { 629cb93a386Sopenharmony_ci tmp.fMat[kMScaleX] = rowcol3(&a.fMat[0], &b.fMat[0]); 630cb93a386Sopenharmony_ci tmp.fMat[kMSkewX] = rowcol3(&a.fMat[0], &b.fMat[1]); 631cb93a386Sopenharmony_ci tmp.fMat[kMTransX] = rowcol3(&a.fMat[0], &b.fMat[2]); 632cb93a386Sopenharmony_ci tmp.fMat[kMSkewY] = rowcol3(&a.fMat[3], &b.fMat[0]); 633cb93a386Sopenharmony_ci tmp.fMat[kMScaleY] = rowcol3(&a.fMat[3], &b.fMat[1]); 634cb93a386Sopenharmony_ci tmp.fMat[kMTransY] = rowcol3(&a.fMat[3], &b.fMat[2]); 635cb93a386Sopenharmony_ci tmp.fMat[kMPersp0] = rowcol3(&a.fMat[6], &b.fMat[0]); 636cb93a386Sopenharmony_ci tmp.fMat[kMPersp1] = rowcol3(&a.fMat[6], &b.fMat[1]); 637cb93a386Sopenharmony_ci tmp.fMat[kMPersp2] = rowcol3(&a.fMat[6], &b.fMat[2]); 638cb93a386Sopenharmony_ci 639cb93a386Sopenharmony_ci tmp.setTypeMask(kUnknown_Mask); 640cb93a386Sopenharmony_ci } else { 641cb93a386Sopenharmony_ci tmp.fMat[kMScaleX] = muladdmul(a.fMat[kMScaleX], 642cb93a386Sopenharmony_ci b.fMat[kMScaleX], 643cb93a386Sopenharmony_ci a.fMat[kMSkewX], 644cb93a386Sopenharmony_ci b.fMat[kMSkewY]); 645cb93a386Sopenharmony_ci 646cb93a386Sopenharmony_ci tmp.fMat[kMSkewX] = muladdmul(a.fMat[kMScaleX], 647cb93a386Sopenharmony_ci b.fMat[kMSkewX], 648cb93a386Sopenharmony_ci a.fMat[kMSkewX], 649cb93a386Sopenharmony_ci b.fMat[kMScaleY]); 650cb93a386Sopenharmony_ci 651cb93a386Sopenharmony_ci tmp.fMat[kMTransX] = muladdmul(a.fMat[kMScaleX], 652cb93a386Sopenharmony_ci b.fMat[kMTransX], 653cb93a386Sopenharmony_ci a.fMat[kMSkewX], 654cb93a386Sopenharmony_ci b.fMat[kMTransY]) + a.fMat[kMTransX]; 655cb93a386Sopenharmony_ci 656cb93a386Sopenharmony_ci tmp.fMat[kMSkewY] = muladdmul(a.fMat[kMSkewY], 657cb93a386Sopenharmony_ci b.fMat[kMScaleX], 658cb93a386Sopenharmony_ci a.fMat[kMScaleY], 659cb93a386Sopenharmony_ci b.fMat[kMSkewY]); 660cb93a386Sopenharmony_ci 661cb93a386Sopenharmony_ci tmp.fMat[kMScaleY] = muladdmul(a.fMat[kMSkewY], 662cb93a386Sopenharmony_ci b.fMat[kMSkewX], 663cb93a386Sopenharmony_ci a.fMat[kMScaleY], 664cb93a386Sopenharmony_ci b.fMat[kMScaleY]); 665cb93a386Sopenharmony_ci 666cb93a386Sopenharmony_ci tmp.fMat[kMTransY] = muladdmul(a.fMat[kMSkewY], 667cb93a386Sopenharmony_ci b.fMat[kMTransX], 668cb93a386Sopenharmony_ci a.fMat[kMScaleY], 669cb93a386Sopenharmony_ci b.fMat[kMTransY]) + a.fMat[kMTransY]; 670cb93a386Sopenharmony_ci 671cb93a386Sopenharmony_ci tmp.fMat[kMPersp0] = 0; 672cb93a386Sopenharmony_ci tmp.fMat[kMPersp1] = 0; 673cb93a386Sopenharmony_ci tmp.fMat[kMPersp2] = 1; 674cb93a386Sopenharmony_ci //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType()); 675cb93a386Sopenharmony_ci //SkASSERT(!(tmp.getType() & kPerspective_Mask)); 676cb93a386Sopenharmony_ci tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask); 677cb93a386Sopenharmony_ci } 678cb93a386Sopenharmony_ci *this = tmp; 679cb93a386Sopenharmony_ci } 680cb93a386Sopenharmony_ci return *this; 681cb93a386Sopenharmony_ci} 682cb93a386Sopenharmony_ci 683cb93a386Sopenharmony_ciSkMatrix& SkMatrix::preConcat(const SkMatrix& mat) { 684cb93a386Sopenharmony_ci // check for identity first, so we don't do a needless copy of ourselves 685cb93a386Sopenharmony_ci // to ourselves inside setConcat() 686cb93a386Sopenharmony_ci if(!mat.isIdentity()) { 687cb93a386Sopenharmony_ci this->setConcat(*this, mat); 688cb93a386Sopenharmony_ci } 689cb93a386Sopenharmony_ci return *this; 690cb93a386Sopenharmony_ci} 691cb93a386Sopenharmony_ci 692cb93a386Sopenharmony_ciSkMatrix& SkMatrix::postConcat(const SkMatrix& mat) { 693cb93a386Sopenharmony_ci // check for identity first, so we don't do a needless copy of ourselves 694cb93a386Sopenharmony_ci // to ourselves inside setConcat() 695cb93a386Sopenharmony_ci if (!mat.isIdentity()) { 696cb93a386Sopenharmony_ci this->setConcat(mat, *this); 697cb93a386Sopenharmony_ci } 698cb93a386Sopenharmony_ci return *this; 699cb93a386Sopenharmony_ci} 700cb93a386Sopenharmony_ci 701cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 702cb93a386Sopenharmony_ci 703cb93a386Sopenharmony_ci/* Matrix inversion is very expensive, but also the place where keeping 704cb93a386Sopenharmony_ci precision may be most important (here and matrix concat). Hence to avoid 705cb93a386Sopenharmony_ci bitmap blitting artifacts when walking the inverse, we use doubles for 706cb93a386Sopenharmony_ci the intermediate math, even though we know that is more expensive. 707cb93a386Sopenharmony_ci */ 708cb93a386Sopenharmony_ci 709cb93a386Sopenharmony_cistatic inline SkScalar scross_dscale(SkScalar a, SkScalar b, 710cb93a386Sopenharmony_ci SkScalar c, SkScalar d, double scale) { 711cb93a386Sopenharmony_ci return SkDoubleToScalar(scross(a, b, c, d) * scale); 712cb93a386Sopenharmony_ci} 713cb93a386Sopenharmony_ci 714cb93a386Sopenharmony_cistatic inline double dcross(double a, double b, double c, double d) { 715cb93a386Sopenharmony_ci return a * b - c * d; 716cb93a386Sopenharmony_ci} 717cb93a386Sopenharmony_ci 718cb93a386Sopenharmony_cistatic inline SkScalar dcross_dscale(double a, double b, 719cb93a386Sopenharmony_ci double c, double d, double scale) { 720cb93a386Sopenharmony_ci return SkDoubleToScalar(dcross(a, b, c, d) * scale); 721cb93a386Sopenharmony_ci} 722cb93a386Sopenharmony_ci 723cb93a386Sopenharmony_cistatic double sk_determinant(const float mat[9], int isPerspective) { 724cb93a386Sopenharmony_ci if (isPerspective) { 725cb93a386Sopenharmony_ci return mat[SkMatrix::kMScaleX] * 726cb93a386Sopenharmony_ci dcross(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2], 727cb93a386Sopenharmony_ci mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1]) 728cb93a386Sopenharmony_ci + 729cb93a386Sopenharmony_ci mat[SkMatrix::kMSkewX] * 730cb93a386Sopenharmony_ci dcross(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0], 731cb93a386Sopenharmony_ci mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2]) 732cb93a386Sopenharmony_ci + 733cb93a386Sopenharmony_ci mat[SkMatrix::kMTransX] * 734cb93a386Sopenharmony_ci dcross(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1], 735cb93a386Sopenharmony_ci mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]); 736cb93a386Sopenharmony_ci } else { 737cb93a386Sopenharmony_ci return dcross(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY], 738cb93a386Sopenharmony_ci mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]); 739cb93a386Sopenharmony_ci } 740cb93a386Sopenharmony_ci} 741cb93a386Sopenharmony_ci 742cb93a386Sopenharmony_cistatic double sk_inv_determinant(const float mat[9], int isPerspective) { 743cb93a386Sopenharmony_ci double det = sk_determinant(mat, isPerspective); 744cb93a386Sopenharmony_ci 745cb93a386Sopenharmony_ci // Since the determinant is on the order of the cube of the matrix members, 746cb93a386Sopenharmony_ci // compare to the cube of the default nearly-zero constant (although an 747cb93a386Sopenharmony_ci // estimate of the condition number would be better if it wasn't so expensive). 748cb93a386Sopenharmony_ci if (SkScalarNearlyZero(sk_double_to_float(det), 749cb93a386Sopenharmony_ci SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) { 750cb93a386Sopenharmony_ci return 0; 751cb93a386Sopenharmony_ci } 752cb93a386Sopenharmony_ci return 1.0 / det; 753cb93a386Sopenharmony_ci} 754cb93a386Sopenharmony_ci 755cb93a386Sopenharmony_civoid SkMatrix::SetAffineIdentity(SkScalar affine[6]) { 756cb93a386Sopenharmony_ci affine[kAScaleX] = 1; 757cb93a386Sopenharmony_ci affine[kASkewY] = 0; 758cb93a386Sopenharmony_ci affine[kASkewX] = 0; 759cb93a386Sopenharmony_ci affine[kAScaleY] = 1; 760cb93a386Sopenharmony_ci affine[kATransX] = 0; 761cb93a386Sopenharmony_ci affine[kATransY] = 0; 762cb93a386Sopenharmony_ci} 763cb93a386Sopenharmony_ci 764cb93a386Sopenharmony_cibool SkMatrix::asAffine(SkScalar affine[6]) const { 765cb93a386Sopenharmony_ci if (this->hasPerspective()) { 766cb93a386Sopenharmony_ci return false; 767cb93a386Sopenharmony_ci } 768cb93a386Sopenharmony_ci if (affine) { 769cb93a386Sopenharmony_ci affine[kAScaleX] = this->fMat[kMScaleX]; 770cb93a386Sopenharmony_ci affine[kASkewY] = this->fMat[kMSkewY]; 771cb93a386Sopenharmony_ci affine[kASkewX] = this->fMat[kMSkewX]; 772cb93a386Sopenharmony_ci affine[kAScaleY] = this->fMat[kMScaleY]; 773cb93a386Sopenharmony_ci affine[kATransX] = this->fMat[kMTransX]; 774cb93a386Sopenharmony_ci affine[kATransY] = this->fMat[kMTransY]; 775cb93a386Sopenharmony_ci } 776cb93a386Sopenharmony_ci return true; 777cb93a386Sopenharmony_ci} 778cb93a386Sopenharmony_ci 779cb93a386Sopenharmony_civoid SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const { 780cb93a386Sopenharmony_ci SkASSERT((dst && src && count > 0) || 0 == count); 781cb93a386Sopenharmony_ci // no partial overlap 782cb93a386Sopenharmony_ci SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]); 783cb93a386Sopenharmony_ci this->getMapPtsProc()(*this, dst, src, count); 784cb93a386Sopenharmony_ci} 785cb93a386Sopenharmony_ci 786cb93a386Sopenharmony_civoid SkMatrix::mapXY(SkScalar x, SkScalar y, SkPoint* result) const { 787cb93a386Sopenharmony_ci SkASSERT(result); 788cb93a386Sopenharmony_ci this->getMapXYProc()(*this, x, y, result); 789cb93a386Sopenharmony_ci} 790cb93a386Sopenharmony_ci 791cb93a386Sopenharmony_civoid SkMatrix::ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp) { 792cb93a386Sopenharmony_ci SkASSERT(src != dst); 793cb93a386Sopenharmony_ci SkASSERT(src && dst); 794cb93a386Sopenharmony_ci 795cb93a386Sopenharmony_ci if (isPersp) { 796cb93a386Sopenharmony_ci dst[kMScaleX] = scross_dscale(src[kMScaleY], src[kMPersp2], src[kMTransY], src[kMPersp1], invDet); 797cb93a386Sopenharmony_ci dst[kMSkewX] = scross_dscale(src[kMTransX], src[kMPersp1], src[kMSkewX], src[kMPersp2], invDet); 798cb93a386Sopenharmony_ci dst[kMTransX] = scross_dscale(src[kMSkewX], src[kMTransY], src[kMTransX], src[kMScaleY], invDet); 799cb93a386Sopenharmony_ci 800cb93a386Sopenharmony_ci dst[kMSkewY] = scross_dscale(src[kMTransY], src[kMPersp0], src[kMSkewY], src[kMPersp2], invDet); 801cb93a386Sopenharmony_ci dst[kMScaleY] = scross_dscale(src[kMScaleX], src[kMPersp2], src[kMTransX], src[kMPersp0], invDet); 802cb93a386Sopenharmony_ci dst[kMTransY] = scross_dscale(src[kMTransX], src[kMSkewY], src[kMScaleX], src[kMTransY], invDet); 803cb93a386Sopenharmony_ci 804cb93a386Sopenharmony_ci dst[kMPersp0] = scross_dscale(src[kMSkewY], src[kMPersp1], src[kMScaleY], src[kMPersp0], invDet); 805cb93a386Sopenharmony_ci dst[kMPersp1] = scross_dscale(src[kMSkewX], src[kMPersp0], src[kMScaleX], src[kMPersp1], invDet); 806cb93a386Sopenharmony_ci dst[kMPersp2] = scross_dscale(src[kMScaleX], src[kMScaleY], src[kMSkewX], src[kMSkewY], invDet); 807cb93a386Sopenharmony_ci } else { // not perspective 808cb93a386Sopenharmony_ci dst[kMScaleX] = SkDoubleToScalar(src[kMScaleY] * invDet); 809cb93a386Sopenharmony_ci dst[kMSkewX] = SkDoubleToScalar(-src[kMSkewX] * invDet); 810cb93a386Sopenharmony_ci dst[kMTransX] = dcross_dscale(src[kMSkewX], src[kMTransY], src[kMScaleY], src[kMTransX], invDet); 811cb93a386Sopenharmony_ci 812cb93a386Sopenharmony_ci dst[kMSkewY] = SkDoubleToScalar(-src[kMSkewY] * invDet); 813cb93a386Sopenharmony_ci dst[kMScaleY] = SkDoubleToScalar(src[kMScaleX] * invDet); 814cb93a386Sopenharmony_ci dst[kMTransY] = dcross_dscale(src[kMSkewY], src[kMTransX], src[kMScaleX], src[kMTransY], invDet); 815cb93a386Sopenharmony_ci 816cb93a386Sopenharmony_ci dst[kMPersp0] = 0; 817cb93a386Sopenharmony_ci dst[kMPersp1] = 0; 818cb93a386Sopenharmony_ci dst[kMPersp2] = 1; 819cb93a386Sopenharmony_ci } 820cb93a386Sopenharmony_ci} 821cb93a386Sopenharmony_ci 822cb93a386Sopenharmony_cibool SkMatrix::invertNonIdentity(SkMatrix* inv) const { 823cb93a386Sopenharmony_ci SkASSERT(!this->isIdentity()); 824cb93a386Sopenharmony_ci 825cb93a386Sopenharmony_ci TypeMask mask = this->getType(); 826cb93a386Sopenharmony_ci 827cb93a386Sopenharmony_ci if (0 == (mask & ~(kScale_Mask | kTranslate_Mask))) { 828cb93a386Sopenharmony_ci bool invertible = true; 829cb93a386Sopenharmony_ci if (inv) { 830cb93a386Sopenharmony_ci if (mask & kScale_Mask) { 831cb93a386Sopenharmony_ci SkScalar invX = fMat[kMScaleX]; 832cb93a386Sopenharmony_ci SkScalar invY = fMat[kMScaleY]; 833cb93a386Sopenharmony_ci if (0 == invX || 0 == invY) { 834cb93a386Sopenharmony_ci return false; 835cb93a386Sopenharmony_ci } 836cb93a386Sopenharmony_ci invX = SkScalarInvert(invX); 837cb93a386Sopenharmony_ci invY = SkScalarInvert(invY); 838cb93a386Sopenharmony_ci 839cb93a386Sopenharmony_ci // Must be careful when writing to inv, since it may be the 840cb93a386Sopenharmony_ci // same memory as this. 841cb93a386Sopenharmony_ci 842cb93a386Sopenharmony_ci inv->fMat[kMSkewX] = inv->fMat[kMSkewY] = 843cb93a386Sopenharmony_ci inv->fMat[kMPersp0] = inv->fMat[kMPersp1] = 0; 844cb93a386Sopenharmony_ci 845cb93a386Sopenharmony_ci inv->fMat[kMScaleX] = invX; 846cb93a386Sopenharmony_ci inv->fMat[kMScaleY] = invY; 847cb93a386Sopenharmony_ci inv->fMat[kMPersp2] = 1; 848cb93a386Sopenharmony_ci inv->fMat[kMTransX] = -fMat[kMTransX] * invX; 849cb93a386Sopenharmony_ci inv->fMat[kMTransY] = -fMat[kMTransY] * invY; 850cb93a386Sopenharmony_ci 851cb93a386Sopenharmony_ci inv->setTypeMask(mask | kRectStaysRect_Mask); 852cb93a386Sopenharmony_ci } else { 853cb93a386Sopenharmony_ci // translate only 854cb93a386Sopenharmony_ci inv->setTranslate(-fMat[kMTransX], -fMat[kMTransY]); 855cb93a386Sopenharmony_ci } 856cb93a386Sopenharmony_ci } else { // inv is nullptr, just check if we're invertible 857cb93a386Sopenharmony_ci if (!fMat[kMScaleX] || !fMat[kMScaleY]) { 858cb93a386Sopenharmony_ci invertible = false; 859cb93a386Sopenharmony_ci } 860cb93a386Sopenharmony_ci } 861cb93a386Sopenharmony_ci return invertible; 862cb93a386Sopenharmony_ci } 863cb93a386Sopenharmony_ci 864cb93a386Sopenharmony_ci int isPersp = mask & kPerspective_Mask; 865cb93a386Sopenharmony_ci double invDet = sk_inv_determinant(fMat, isPersp); 866cb93a386Sopenharmony_ci 867cb93a386Sopenharmony_ci if (invDet == 0) { // underflow 868cb93a386Sopenharmony_ci return false; 869cb93a386Sopenharmony_ci } 870cb93a386Sopenharmony_ci 871cb93a386Sopenharmony_ci bool applyingInPlace = (inv == this); 872cb93a386Sopenharmony_ci 873cb93a386Sopenharmony_ci SkMatrix* tmp = inv; 874cb93a386Sopenharmony_ci 875cb93a386Sopenharmony_ci SkMatrix storage; 876cb93a386Sopenharmony_ci if (applyingInPlace || nullptr == tmp) { 877cb93a386Sopenharmony_ci tmp = &storage; // we either need to avoid trampling memory or have no memory 878cb93a386Sopenharmony_ci } 879cb93a386Sopenharmony_ci 880cb93a386Sopenharmony_ci ComputeInv(tmp->fMat, fMat, invDet, isPersp); 881cb93a386Sopenharmony_ci if (!tmp->isFinite()) { 882cb93a386Sopenharmony_ci return false; 883cb93a386Sopenharmony_ci } 884cb93a386Sopenharmony_ci 885cb93a386Sopenharmony_ci tmp->setTypeMask(fTypeMask); 886cb93a386Sopenharmony_ci 887cb93a386Sopenharmony_ci if (applyingInPlace) { 888cb93a386Sopenharmony_ci *inv = storage; // need to copy answer back 889cb93a386Sopenharmony_ci } 890cb93a386Sopenharmony_ci 891cb93a386Sopenharmony_ci return true; 892cb93a386Sopenharmony_ci} 893cb93a386Sopenharmony_ci 894cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 895cb93a386Sopenharmony_ci 896cb93a386Sopenharmony_civoid SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) { 897cb93a386Sopenharmony_ci SkASSERT(m.getType() == 0); 898cb93a386Sopenharmony_ci 899cb93a386Sopenharmony_ci if (dst != src && count > 0) { 900cb93a386Sopenharmony_ci memcpy(dst, src, count * sizeof(SkPoint)); 901cb93a386Sopenharmony_ci } 902cb93a386Sopenharmony_ci} 903cb93a386Sopenharmony_ci 904cb93a386Sopenharmony_civoid SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) { 905cb93a386Sopenharmony_ci SkASSERT(m.getType() <= SkMatrix::kTranslate_Mask); 906cb93a386Sopenharmony_ci if (count > 0) { 907cb93a386Sopenharmony_ci SkScalar tx = m.getTranslateX(); 908cb93a386Sopenharmony_ci SkScalar ty = m.getTranslateY(); 909cb93a386Sopenharmony_ci if (count & 1) { 910cb93a386Sopenharmony_ci dst->fX = src->fX + tx; 911cb93a386Sopenharmony_ci dst->fY = src->fY + ty; 912cb93a386Sopenharmony_ci src += 1; 913cb93a386Sopenharmony_ci dst += 1; 914cb93a386Sopenharmony_ci } 915cb93a386Sopenharmony_ci Sk4s trans4(tx, ty, tx, ty); 916cb93a386Sopenharmony_ci count >>= 1; 917cb93a386Sopenharmony_ci if (count & 1) { 918cb93a386Sopenharmony_ci (Sk4s::Load(src) + trans4).store(dst); 919cb93a386Sopenharmony_ci src += 2; 920cb93a386Sopenharmony_ci dst += 2; 921cb93a386Sopenharmony_ci } 922cb93a386Sopenharmony_ci count >>= 1; 923cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 924cb93a386Sopenharmony_ci (Sk4s::Load(src+0) + trans4).store(dst+0); 925cb93a386Sopenharmony_ci (Sk4s::Load(src+2) + trans4).store(dst+2); 926cb93a386Sopenharmony_ci src += 4; 927cb93a386Sopenharmony_ci dst += 4; 928cb93a386Sopenharmony_ci } 929cb93a386Sopenharmony_ci } 930cb93a386Sopenharmony_ci} 931cb93a386Sopenharmony_ci 932cb93a386Sopenharmony_civoid SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) { 933cb93a386Sopenharmony_ci SkASSERT(m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)); 934cb93a386Sopenharmony_ci if (count > 0) { 935cb93a386Sopenharmony_ci SkScalar tx = m.getTranslateX(); 936cb93a386Sopenharmony_ci SkScalar ty = m.getTranslateY(); 937cb93a386Sopenharmony_ci SkScalar sx = m.getScaleX(); 938cb93a386Sopenharmony_ci SkScalar sy = m.getScaleY(); 939cb93a386Sopenharmony_ci if (count & 1) { 940cb93a386Sopenharmony_ci dst->fX = src->fX * sx + tx; 941cb93a386Sopenharmony_ci dst->fY = src->fY * sy + ty; 942cb93a386Sopenharmony_ci src += 1; 943cb93a386Sopenharmony_ci dst += 1; 944cb93a386Sopenharmony_ci } 945cb93a386Sopenharmony_ci Sk4s trans4(tx, ty, tx, ty); 946cb93a386Sopenharmony_ci Sk4s scale4(sx, sy, sx, sy); 947cb93a386Sopenharmony_ci count >>= 1; 948cb93a386Sopenharmony_ci if (count & 1) { 949cb93a386Sopenharmony_ci (Sk4s::Load(src) * scale4 + trans4).store(dst); 950cb93a386Sopenharmony_ci src += 2; 951cb93a386Sopenharmony_ci dst += 2; 952cb93a386Sopenharmony_ci } 953cb93a386Sopenharmony_ci count >>= 1; 954cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 955cb93a386Sopenharmony_ci (Sk4s::Load(src+0) * scale4 + trans4).store(dst+0); 956cb93a386Sopenharmony_ci (Sk4s::Load(src+2) * scale4 + trans4).store(dst+2); 957cb93a386Sopenharmony_ci src += 4; 958cb93a386Sopenharmony_ci dst += 4; 959cb93a386Sopenharmony_ci } 960cb93a386Sopenharmony_ci } 961cb93a386Sopenharmony_ci} 962cb93a386Sopenharmony_ci 963cb93a386Sopenharmony_civoid SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[], 964cb93a386Sopenharmony_ci const SkPoint src[], int count) { 965cb93a386Sopenharmony_ci SkASSERT(m.hasPerspective()); 966cb93a386Sopenharmony_ci 967cb93a386Sopenharmony_ci if (count > 0) { 968cb93a386Sopenharmony_ci do { 969cb93a386Sopenharmony_ci SkScalar sy = src->fY; 970cb93a386Sopenharmony_ci SkScalar sx = src->fX; 971cb93a386Sopenharmony_ci src += 1; 972cb93a386Sopenharmony_ci 973cb93a386Sopenharmony_ci SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 974cb93a386Sopenharmony_ci SkScalar y = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 975cb93a386Sopenharmony_ci#ifdef SK_LEGACY_MATRIX_MATH_ORDER 976cb93a386Sopenharmony_ci SkScalar z = sx * m.fMat[kMPersp0] + (sy * m.fMat[kMPersp1] + m.fMat[kMPersp2]); 977cb93a386Sopenharmony_ci#else 978cb93a386Sopenharmony_ci SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2]; 979cb93a386Sopenharmony_ci#endif 980cb93a386Sopenharmony_ci if (z) { 981cb93a386Sopenharmony_ci z = 1 / z; 982cb93a386Sopenharmony_ci } 983cb93a386Sopenharmony_ci 984cb93a386Sopenharmony_ci dst->fY = y * z; 985cb93a386Sopenharmony_ci dst->fX = x * z; 986cb93a386Sopenharmony_ci dst += 1; 987cb93a386Sopenharmony_ci } while (--count); 988cb93a386Sopenharmony_ci } 989cb93a386Sopenharmony_ci} 990cb93a386Sopenharmony_ci 991cb93a386Sopenharmony_civoid SkMatrix::Affine_vpts(const SkMatrix& m, SkPoint dst[], const SkPoint src[], int count) { 992cb93a386Sopenharmony_ci SkASSERT(m.getType() != SkMatrix::kPerspective_Mask); 993cb93a386Sopenharmony_ci if (count > 0) { 994cb93a386Sopenharmony_ci SkScalar tx = m.getTranslateX(); 995cb93a386Sopenharmony_ci SkScalar ty = m.getTranslateY(); 996cb93a386Sopenharmony_ci SkScalar sx = m.getScaleX(); 997cb93a386Sopenharmony_ci SkScalar sy = m.getScaleY(); 998cb93a386Sopenharmony_ci SkScalar kx = m.getSkewX(); 999cb93a386Sopenharmony_ci SkScalar ky = m.getSkewY(); 1000cb93a386Sopenharmony_ci if (count & 1) { 1001cb93a386Sopenharmony_ci dst->set(src->fX * sx + src->fY * kx + tx, 1002cb93a386Sopenharmony_ci src->fX * ky + src->fY * sy + ty); 1003cb93a386Sopenharmony_ci src += 1; 1004cb93a386Sopenharmony_ci dst += 1; 1005cb93a386Sopenharmony_ci } 1006cb93a386Sopenharmony_ci Sk4s trans4(tx, ty, tx, ty); 1007cb93a386Sopenharmony_ci Sk4s scale4(sx, sy, sx, sy); 1008cb93a386Sopenharmony_ci Sk4s skew4(kx, ky, kx, ky); // applied to swizzle of src4 1009cb93a386Sopenharmony_ci count >>= 1; 1010cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 1011cb93a386Sopenharmony_ci Sk4s src4 = Sk4s::Load(src); 1012cb93a386Sopenharmony_ci Sk4s swz4 = SkNx_shuffle<1,0,3,2>(src4); // y0 x0, y1 x1 1013cb93a386Sopenharmony_ci (src4 * scale4 + swz4 * skew4 + trans4).store(dst); 1014cb93a386Sopenharmony_ci src += 2; 1015cb93a386Sopenharmony_ci dst += 2; 1016cb93a386Sopenharmony_ci } 1017cb93a386Sopenharmony_ci } 1018cb93a386Sopenharmony_ci} 1019cb93a386Sopenharmony_ci 1020cb93a386Sopenharmony_ciconst SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = { 1021cb93a386Sopenharmony_ci SkMatrix::Identity_pts, SkMatrix::Trans_pts, 1022cb93a386Sopenharmony_ci SkMatrix::Scale_pts, SkMatrix::Scale_pts, 1023cb93a386Sopenharmony_ci SkMatrix::Affine_vpts, SkMatrix::Affine_vpts, 1024cb93a386Sopenharmony_ci SkMatrix::Affine_vpts, SkMatrix::Affine_vpts, 1025cb93a386Sopenharmony_ci // repeat the persp proc 8 times 1026cb93a386Sopenharmony_ci SkMatrix::Persp_pts, SkMatrix::Persp_pts, 1027cb93a386Sopenharmony_ci SkMatrix::Persp_pts, SkMatrix::Persp_pts, 1028cb93a386Sopenharmony_ci SkMatrix::Persp_pts, SkMatrix::Persp_pts, 1029cb93a386Sopenharmony_ci SkMatrix::Persp_pts, SkMatrix::Persp_pts 1030cb93a386Sopenharmony_ci}; 1031cb93a386Sopenharmony_ci 1032cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1033cb93a386Sopenharmony_ci 1034cb93a386Sopenharmony_civoid SkMatrixPriv::MapHomogeneousPointsWithStride(const SkMatrix& mx, SkPoint3 dst[], 1035cb93a386Sopenharmony_ci size_t dstStride, const SkPoint3 src[], 1036cb93a386Sopenharmony_ci size_t srcStride, int count) { 1037cb93a386Sopenharmony_ci SkASSERT((dst && src && count > 0) || 0 == count); 1038cb93a386Sopenharmony_ci // no partial overlap 1039cb93a386Sopenharmony_ci SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]); 1040cb93a386Sopenharmony_ci 1041cb93a386Sopenharmony_ci if (count > 0) { 1042cb93a386Sopenharmony_ci if (mx.isIdentity()) { 1043cb93a386Sopenharmony_ci if (src != dst) { 1044cb93a386Sopenharmony_ci if (srcStride == sizeof(SkPoint3) && dstStride == sizeof(SkPoint3)) { 1045cb93a386Sopenharmony_ci memcpy(dst, src, count * sizeof(SkPoint3)); 1046cb93a386Sopenharmony_ci } else { 1047cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 1048cb93a386Sopenharmony_ci *dst = *src; 1049cb93a386Sopenharmony_ci dst = reinterpret_cast<SkPoint3*>(reinterpret_cast<char*>(dst) + dstStride); 1050cb93a386Sopenharmony_ci src = reinterpret_cast<const SkPoint3*>(reinterpret_cast<const char*>(src) + 1051cb93a386Sopenharmony_ci srcStride); 1052cb93a386Sopenharmony_ci } 1053cb93a386Sopenharmony_ci } 1054cb93a386Sopenharmony_ci } 1055cb93a386Sopenharmony_ci return; 1056cb93a386Sopenharmony_ci } 1057cb93a386Sopenharmony_ci do { 1058cb93a386Sopenharmony_ci SkScalar sx = src->fX; 1059cb93a386Sopenharmony_ci SkScalar sy = src->fY; 1060cb93a386Sopenharmony_ci SkScalar sw = src->fZ; 1061cb93a386Sopenharmony_ci src = reinterpret_cast<const SkPoint3*>(reinterpret_cast<const char*>(src) + srcStride); 1062cb93a386Sopenharmony_ci const SkScalar* mat = mx.fMat; 1063cb93a386Sopenharmony_ci typedef SkMatrix M; 1064cb93a386Sopenharmony_ci SkScalar x = sdot(sx, mat[M::kMScaleX], sy, mat[M::kMSkewX], sw, mat[M::kMTransX]); 1065cb93a386Sopenharmony_ci SkScalar y = sdot(sx, mat[M::kMSkewY], sy, mat[M::kMScaleY], sw, mat[M::kMTransY]); 1066cb93a386Sopenharmony_ci SkScalar w = sdot(sx, mat[M::kMPersp0], sy, mat[M::kMPersp1], sw, mat[M::kMPersp2]); 1067cb93a386Sopenharmony_ci 1068cb93a386Sopenharmony_ci dst->set(x, y, w); 1069cb93a386Sopenharmony_ci dst = reinterpret_cast<SkPoint3*>(reinterpret_cast<char*>(dst) + dstStride); 1070cb93a386Sopenharmony_ci } while (--count); 1071cb93a386Sopenharmony_ci } 1072cb93a386Sopenharmony_ci} 1073cb93a386Sopenharmony_ci 1074cb93a386Sopenharmony_civoid SkMatrix::mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const { 1075cb93a386Sopenharmony_ci SkMatrixPriv::MapHomogeneousPointsWithStride(*this, dst, sizeof(SkPoint3), src, 1076cb93a386Sopenharmony_ci sizeof(SkPoint3), count); 1077cb93a386Sopenharmony_ci} 1078cb93a386Sopenharmony_ci 1079cb93a386Sopenharmony_civoid SkMatrix::mapHomogeneousPoints(SkPoint3 dst[], const SkPoint src[], int count) const { 1080cb93a386Sopenharmony_ci if (this->isIdentity()) { 1081cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 1082cb93a386Sopenharmony_ci dst[i] = { src[i].fX, src[i].fY, 1 }; 1083cb93a386Sopenharmony_ci } 1084cb93a386Sopenharmony_ci } else if (this->hasPerspective()) { 1085cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 1086cb93a386Sopenharmony_ci dst[i] = { 1087cb93a386Sopenharmony_ci fMat[0] * src[i].fX + fMat[1] * src[i].fY + fMat[2], 1088cb93a386Sopenharmony_ci fMat[3] * src[i].fX + fMat[4] * src[i].fY + fMat[5], 1089cb93a386Sopenharmony_ci fMat[6] * src[i].fX + fMat[7] * src[i].fY + fMat[8], 1090cb93a386Sopenharmony_ci }; 1091cb93a386Sopenharmony_ci } 1092cb93a386Sopenharmony_ci } else { // affine 1093cb93a386Sopenharmony_ci for (int i = 0; i < count; ++i) { 1094cb93a386Sopenharmony_ci dst[i] = { 1095cb93a386Sopenharmony_ci fMat[0] * src[i].fX + fMat[1] * src[i].fY + fMat[2], 1096cb93a386Sopenharmony_ci fMat[3] * src[i].fX + fMat[4] * src[i].fY + fMat[5], 1097cb93a386Sopenharmony_ci 1, 1098cb93a386Sopenharmony_ci }; 1099cb93a386Sopenharmony_ci } 1100cb93a386Sopenharmony_ci } 1101cb93a386Sopenharmony_ci} 1102cb93a386Sopenharmony_ci 1103cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1104cb93a386Sopenharmony_ci 1105cb93a386Sopenharmony_civoid SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const { 1106cb93a386Sopenharmony_ci if (this->hasPerspective()) { 1107cb93a386Sopenharmony_ci SkPoint origin; 1108cb93a386Sopenharmony_ci 1109cb93a386Sopenharmony_ci MapXYProc proc = this->getMapXYProc(); 1110cb93a386Sopenharmony_ci proc(*this, 0, 0, &origin); 1111cb93a386Sopenharmony_ci 1112cb93a386Sopenharmony_ci for (int i = count - 1; i >= 0; --i) { 1113cb93a386Sopenharmony_ci SkPoint tmp; 1114cb93a386Sopenharmony_ci 1115cb93a386Sopenharmony_ci proc(*this, src[i].fX, src[i].fY, &tmp); 1116cb93a386Sopenharmony_ci dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY); 1117cb93a386Sopenharmony_ci } 1118cb93a386Sopenharmony_ci } else { 1119cb93a386Sopenharmony_ci SkMatrix tmp = *this; 1120cb93a386Sopenharmony_ci 1121cb93a386Sopenharmony_ci tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0; 1122cb93a386Sopenharmony_ci tmp.clearTypeMask(kTranslate_Mask); 1123cb93a386Sopenharmony_ci tmp.mapPoints(dst, src, count); 1124cb93a386Sopenharmony_ci } 1125cb93a386Sopenharmony_ci} 1126cb93a386Sopenharmony_ci 1127cb93a386Sopenharmony_cistatic Sk4f sort_as_rect(const Sk4f& ltrb) { 1128cb93a386Sopenharmony_ci Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]); 1129cb93a386Sopenharmony_ci Sk4f min = Sk4f::Min(ltrb, rblt); 1130cb93a386Sopenharmony_ci Sk4f max = Sk4f::Max(ltrb, rblt); 1131cb93a386Sopenharmony_ci // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on 1132cb93a386Sopenharmony_ci // ARM this sequence generates the fastest (a single instruction). 1133cb93a386Sopenharmony_ci return Sk4f(min[2], min[3], max[0], max[1]); 1134cb93a386Sopenharmony_ci} 1135cb93a386Sopenharmony_ci 1136cb93a386Sopenharmony_civoid SkMatrix::mapRectScaleTranslate(SkRect* dst, const SkRect& src) const { 1137cb93a386Sopenharmony_ci SkASSERT(dst); 1138cb93a386Sopenharmony_ci SkASSERT(this->isScaleTranslate()); 1139cb93a386Sopenharmony_ci 1140cb93a386Sopenharmony_ci SkScalar sx = fMat[kMScaleX]; 1141cb93a386Sopenharmony_ci SkScalar sy = fMat[kMScaleY]; 1142cb93a386Sopenharmony_ci SkScalar tx = fMat[kMTransX]; 1143cb93a386Sopenharmony_ci SkScalar ty = fMat[kMTransY]; 1144cb93a386Sopenharmony_ci Sk4f scale(sx, sy, sx, sy); 1145cb93a386Sopenharmony_ci Sk4f trans(tx, ty, tx, ty); 1146cb93a386Sopenharmony_ci sort_as_rect(Sk4f::Load(&src.fLeft) * scale + trans).store(&dst->fLeft); 1147cb93a386Sopenharmony_ci} 1148cb93a386Sopenharmony_ci 1149cb93a386Sopenharmony_cibool SkMatrix::mapRect(SkRect* dst, const SkRect& src, SkApplyPerspectiveClip pc) const { 1150cb93a386Sopenharmony_ci SkASSERT(dst); 1151cb93a386Sopenharmony_ci 1152cb93a386Sopenharmony_ci if (this->getType() <= kTranslate_Mask) { 1153cb93a386Sopenharmony_ci SkScalar tx = fMat[kMTransX]; 1154cb93a386Sopenharmony_ci SkScalar ty = fMat[kMTransY]; 1155cb93a386Sopenharmony_ci Sk4f trans(tx, ty, tx, ty); 1156cb93a386Sopenharmony_ci sort_as_rect(Sk4f::Load(&src.fLeft) + trans).store(&dst->fLeft); 1157cb93a386Sopenharmony_ci return true; 1158cb93a386Sopenharmony_ci } 1159cb93a386Sopenharmony_ci if (this->isScaleTranslate()) { 1160cb93a386Sopenharmony_ci this->mapRectScaleTranslate(dst, src); 1161cb93a386Sopenharmony_ci return true; 1162cb93a386Sopenharmony_ci } else if (pc == SkApplyPerspectiveClip::kYes && this->hasPerspective()) { 1163cb93a386Sopenharmony_ci SkPath path; 1164cb93a386Sopenharmony_ci path.addRect(src); 1165cb93a386Sopenharmony_ci path.transform(*this); 1166cb93a386Sopenharmony_ci *dst = path.getBounds(); 1167cb93a386Sopenharmony_ci return false; 1168cb93a386Sopenharmony_ci } else { 1169cb93a386Sopenharmony_ci SkPoint quad[4]; 1170cb93a386Sopenharmony_ci 1171cb93a386Sopenharmony_ci src.toQuad(quad); 1172cb93a386Sopenharmony_ci this->mapPoints(quad, quad, 4); 1173cb93a386Sopenharmony_ci dst->setBoundsNoCheck(quad, 4); 1174cb93a386Sopenharmony_ci return this->rectStaysRect(); // might still return true if rotated by 90, etc. 1175cb93a386Sopenharmony_ci } 1176cb93a386Sopenharmony_ci} 1177cb93a386Sopenharmony_ci 1178cb93a386Sopenharmony_ciSkScalar SkMatrix::mapRadius(SkScalar radius) const { 1179cb93a386Sopenharmony_ci SkVector vec[2]; 1180cb93a386Sopenharmony_ci 1181cb93a386Sopenharmony_ci vec[0].set(radius, 0); 1182cb93a386Sopenharmony_ci vec[1].set(0, radius); 1183cb93a386Sopenharmony_ci this->mapVectors(vec, 2); 1184cb93a386Sopenharmony_ci 1185cb93a386Sopenharmony_ci SkScalar d0 = vec[0].length(); 1186cb93a386Sopenharmony_ci SkScalar d1 = vec[1].length(); 1187cb93a386Sopenharmony_ci 1188cb93a386Sopenharmony_ci // return geometric mean 1189cb93a386Sopenharmony_ci return SkScalarSqrt(d0 * d1); 1190cb93a386Sopenharmony_ci} 1191cb93a386Sopenharmony_ci 1192cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1193cb93a386Sopenharmony_ci 1194cb93a386Sopenharmony_civoid SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1195cb93a386Sopenharmony_ci SkPoint* pt) { 1196cb93a386Sopenharmony_ci SkASSERT(m.hasPerspective()); 1197cb93a386Sopenharmony_ci 1198cb93a386Sopenharmony_ci SkScalar x = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 1199cb93a386Sopenharmony_ci SkScalar y = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 1200cb93a386Sopenharmony_ci SkScalar z = sdot(sx, m.fMat[kMPersp0], sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2]; 1201cb93a386Sopenharmony_ci if (z) { 1202cb93a386Sopenharmony_ci z = 1 / z; 1203cb93a386Sopenharmony_ci } 1204cb93a386Sopenharmony_ci pt->fX = x * z; 1205cb93a386Sopenharmony_ci pt->fY = y * z; 1206cb93a386Sopenharmony_ci} 1207cb93a386Sopenharmony_ci 1208cb93a386Sopenharmony_civoid SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1209cb93a386Sopenharmony_ci SkPoint* pt) { 1210cb93a386Sopenharmony_ci SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask); 1211cb93a386Sopenharmony_ci 1212cb93a386Sopenharmony_ci#ifdef SK_LEGACY_MATRIX_MATH_ORDER 1213cb93a386Sopenharmony_ci pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX] + m.fMat[kMTransX]); 1214cb93a386Sopenharmony_ci pt->fY = sx * m.fMat[kMSkewY] + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]); 1215cb93a386Sopenharmony_ci#else 1216cb93a386Sopenharmony_ci pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 1217cb93a386Sopenharmony_ci pt->fY = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 1218cb93a386Sopenharmony_ci#endif 1219cb93a386Sopenharmony_ci} 1220cb93a386Sopenharmony_ci 1221cb93a386Sopenharmony_civoid SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1222cb93a386Sopenharmony_ci SkPoint* pt) { 1223cb93a386Sopenharmony_ci SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask); 1224cb93a386Sopenharmony_ci SkASSERT(0 == m.fMat[kMTransX]); 1225cb93a386Sopenharmony_ci SkASSERT(0 == m.fMat[kMTransY]); 1226cb93a386Sopenharmony_ci 1227cb93a386Sopenharmony_ci#ifdef SK_LEGACY_MATRIX_MATH_ORDER 1228cb93a386Sopenharmony_ci pt->fX = sx * m.fMat[kMScaleX] + (sy * m.fMat[kMSkewX] + m.fMat[kMTransX]); 1229cb93a386Sopenharmony_ci pt->fY = sx * m.fMat[kMSkewY] + (sy * m.fMat[kMScaleY] + m.fMat[kMTransY]); 1230cb93a386Sopenharmony_ci#else 1231cb93a386Sopenharmony_ci pt->fX = sdot(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) + m.fMat[kMTransX]; 1232cb93a386Sopenharmony_ci pt->fY = sdot(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) + m.fMat[kMTransY]; 1233cb93a386Sopenharmony_ci#endif 1234cb93a386Sopenharmony_ci} 1235cb93a386Sopenharmony_ci 1236cb93a386Sopenharmony_civoid SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1237cb93a386Sopenharmony_ci SkPoint* pt) { 1238cb93a386Sopenharmony_ci SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) 1239cb93a386Sopenharmony_ci == kScale_Mask); 1240cb93a386Sopenharmony_ci 1241cb93a386Sopenharmony_ci pt->fX = sx * m.fMat[kMScaleX] + m.fMat[kMTransX]; 1242cb93a386Sopenharmony_ci pt->fY = sy * m.fMat[kMScaleY] + m.fMat[kMTransY]; 1243cb93a386Sopenharmony_ci} 1244cb93a386Sopenharmony_ci 1245cb93a386Sopenharmony_civoid SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1246cb93a386Sopenharmony_ci SkPoint* pt) { 1247cb93a386Sopenharmony_ci SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask)) 1248cb93a386Sopenharmony_ci == kScale_Mask); 1249cb93a386Sopenharmony_ci SkASSERT(0 == m.fMat[kMTransX]); 1250cb93a386Sopenharmony_ci SkASSERT(0 == m.fMat[kMTransY]); 1251cb93a386Sopenharmony_ci 1252cb93a386Sopenharmony_ci pt->fX = sx * m.fMat[kMScaleX]; 1253cb93a386Sopenharmony_ci pt->fY = sy * m.fMat[kMScaleY]; 1254cb93a386Sopenharmony_ci} 1255cb93a386Sopenharmony_ci 1256cb93a386Sopenharmony_civoid SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1257cb93a386Sopenharmony_ci SkPoint* pt) { 1258cb93a386Sopenharmony_ci SkASSERT(m.getType() == kTranslate_Mask); 1259cb93a386Sopenharmony_ci 1260cb93a386Sopenharmony_ci pt->fX = sx + m.fMat[kMTransX]; 1261cb93a386Sopenharmony_ci pt->fY = sy + m.fMat[kMTransY]; 1262cb93a386Sopenharmony_ci} 1263cb93a386Sopenharmony_ci 1264cb93a386Sopenharmony_civoid SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy, 1265cb93a386Sopenharmony_ci SkPoint* pt) { 1266cb93a386Sopenharmony_ci SkASSERT(0 == m.getType()); 1267cb93a386Sopenharmony_ci 1268cb93a386Sopenharmony_ci pt->fX = sx; 1269cb93a386Sopenharmony_ci pt->fY = sy; 1270cb93a386Sopenharmony_ci} 1271cb93a386Sopenharmony_ci 1272cb93a386Sopenharmony_ciconst SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = { 1273cb93a386Sopenharmony_ci SkMatrix::Identity_xy, SkMatrix::Trans_xy, 1274cb93a386Sopenharmony_ci SkMatrix::Scale_xy, SkMatrix::ScaleTrans_xy, 1275cb93a386Sopenharmony_ci SkMatrix::Rot_xy, SkMatrix::RotTrans_xy, 1276cb93a386Sopenharmony_ci SkMatrix::Rot_xy, SkMatrix::RotTrans_xy, 1277cb93a386Sopenharmony_ci // repeat the persp proc 8 times 1278cb93a386Sopenharmony_ci SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1279cb93a386Sopenharmony_ci SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1280cb93a386Sopenharmony_ci SkMatrix::Persp_xy, SkMatrix::Persp_xy, 1281cb93a386Sopenharmony_ci SkMatrix::Persp_xy, SkMatrix::Persp_xy 1282cb93a386Sopenharmony_ci}; 1283cb93a386Sopenharmony_ci 1284cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1285cb93a386Sopenharmony_ci#if 0 1286cb93a386Sopenharmony_ci// if its nearly zero (just made up 26, perhaps it should be bigger or smaller) 1287cb93a386Sopenharmony_ci#define PerspNearlyZero(x) SkScalarNearlyZero(x, (1.0f / (1 << 26))) 1288cb93a386Sopenharmony_ci 1289cb93a386Sopenharmony_cibool SkMatrix::isFixedStepInX() const { 1290cb93a386Sopenharmony_ci return PerspNearlyZero(fMat[kMPersp0]); 1291cb93a386Sopenharmony_ci} 1292cb93a386Sopenharmony_ci 1293cb93a386Sopenharmony_ciSkVector SkMatrix::fixedStepInX(SkScalar y) const { 1294cb93a386Sopenharmony_ci SkASSERT(PerspNearlyZero(fMat[kMPersp0])); 1295cb93a386Sopenharmony_ci if (PerspNearlyZero(fMat[kMPersp1]) && 1296cb93a386Sopenharmony_ci PerspNearlyZero(fMat[kMPersp2] - 1)) { 1297cb93a386Sopenharmony_ci return SkVector::Make(fMat[kMScaleX], fMat[kMSkewY]); 1298cb93a386Sopenharmony_ci } else { 1299cb93a386Sopenharmony_ci SkScalar z = y * fMat[kMPersp1] + fMat[kMPersp2]; 1300cb93a386Sopenharmony_ci return SkVector::Make(fMat[kMScaleX] / z, fMat[kMSkewY] / z); 1301cb93a386Sopenharmony_ci } 1302cb93a386Sopenharmony_ci} 1303cb93a386Sopenharmony_ci#endif 1304cb93a386Sopenharmony_ci 1305cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1306cb93a386Sopenharmony_ci 1307cb93a386Sopenharmony_cistatic inline bool checkForZero(float x) { 1308cb93a386Sopenharmony_ci return x*x == 0; 1309cb93a386Sopenharmony_ci} 1310cb93a386Sopenharmony_ci 1311cb93a386Sopenharmony_cibool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst) { 1312cb93a386Sopenharmony_ci dst->fMat[kMScaleX] = srcPt[1].fY - srcPt[0].fY; 1313cb93a386Sopenharmony_ci dst->fMat[kMSkewY] = srcPt[0].fX - srcPt[1].fX; 1314cb93a386Sopenharmony_ci dst->fMat[kMPersp0] = 0; 1315cb93a386Sopenharmony_ci 1316cb93a386Sopenharmony_ci dst->fMat[kMSkewX] = srcPt[1].fX - srcPt[0].fX; 1317cb93a386Sopenharmony_ci dst->fMat[kMScaleY] = srcPt[1].fY - srcPt[0].fY; 1318cb93a386Sopenharmony_ci dst->fMat[kMPersp1] = 0; 1319cb93a386Sopenharmony_ci 1320cb93a386Sopenharmony_ci dst->fMat[kMTransX] = srcPt[0].fX; 1321cb93a386Sopenharmony_ci dst->fMat[kMTransY] = srcPt[0].fY; 1322cb93a386Sopenharmony_ci dst->fMat[kMPersp2] = 1; 1323cb93a386Sopenharmony_ci dst->setTypeMask(kUnknown_Mask); 1324cb93a386Sopenharmony_ci return true; 1325cb93a386Sopenharmony_ci} 1326cb93a386Sopenharmony_ci 1327cb93a386Sopenharmony_cibool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst) { 1328cb93a386Sopenharmony_ci dst->fMat[kMScaleX] = srcPt[2].fX - srcPt[0].fX; 1329cb93a386Sopenharmony_ci dst->fMat[kMSkewY] = srcPt[2].fY - srcPt[0].fY; 1330cb93a386Sopenharmony_ci dst->fMat[kMPersp0] = 0; 1331cb93a386Sopenharmony_ci 1332cb93a386Sopenharmony_ci dst->fMat[kMSkewX] = srcPt[1].fX - srcPt[0].fX; 1333cb93a386Sopenharmony_ci dst->fMat[kMScaleY] = srcPt[1].fY - srcPt[0].fY; 1334cb93a386Sopenharmony_ci dst->fMat[kMPersp1] = 0; 1335cb93a386Sopenharmony_ci 1336cb93a386Sopenharmony_ci dst->fMat[kMTransX] = srcPt[0].fX; 1337cb93a386Sopenharmony_ci dst->fMat[kMTransY] = srcPt[0].fY; 1338cb93a386Sopenharmony_ci dst->fMat[kMPersp2] = 1; 1339cb93a386Sopenharmony_ci dst->setTypeMask(kUnknown_Mask); 1340cb93a386Sopenharmony_ci return true; 1341cb93a386Sopenharmony_ci} 1342cb93a386Sopenharmony_ci 1343cb93a386Sopenharmony_cibool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst) { 1344cb93a386Sopenharmony_ci float a1, a2; 1345cb93a386Sopenharmony_ci float x0, y0, x1, y1, x2, y2; 1346cb93a386Sopenharmony_ci 1347cb93a386Sopenharmony_ci x0 = srcPt[2].fX - srcPt[0].fX; 1348cb93a386Sopenharmony_ci y0 = srcPt[2].fY - srcPt[0].fY; 1349cb93a386Sopenharmony_ci x1 = srcPt[2].fX - srcPt[1].fX; 1350cb93a386Sopenharmony_ci y1 = srcPt[2].fY - srcPt[1].fY; 1351cb93a386Sopenharmony_ci x2 = srcPt[2].fX - srcPt[3].fX; 1352cb93a386Sopenharmony_ci y2 = srcPt[2].fY - srcPt[3].fY; 1353cb93a386Sopenharmony_ci 1354cb93a386Sopenharmony_ci /* check if abs(x2) > abs(y2) */ 1355cb93a386Sopenharmony_ci if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) { 1356cb93a386Sopenharmony_ci float denom = sk_ieee_float_divide(x1 * y2, x2) - y1; 1357cb93a386Sopenharmony_ci if (checkForZero(denom)) { 1358cb93a386Sopenharmony_ci return false; 1359cb93a386Sopenharmony_ci } 1360cb93a386Sopenharmony_ci a1 = (((x0 - x1) * y2 / x2) - y0 + y1) / denom; 1361cb93a386Sopenharmony_ci } else { 1362cb93a386Sopenharmony_ci float denom = x1 - sk_ieee_float_divide(y1 * x2, y2); 1363cb93a386Sopenharmony_ci if (checkForZero(denom)) { 1364cb93a386Sopenharmony_ci return false; 1365cb93a386Sopenharmony_ci } 1366cb93a386Sopenharmony_ci a1 = (x0 - x1 - sk_ieee_float_divide((y0 - y1) * x2, y2)) / denom; 1367cb93a386Sopenharmony_ci } 1368cb93a386Sopenharmony_ci 1369cb93a386Sopenharmony_ci /* check if abs(x1) > abs(y1) */ 1370cb93a386Sopenharmony_ci if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) { 1371cb93a386Sopenharmony_ci float denom = y2 - sk_ieee_float_divide(x2 * y1, x1); 1372cb93a386Sopenharmony_ci if (checkForZero(denom)) { 1373cb93a386Sopenharmony_ci return false; 1374cb93a386Sopenharmony_ci } 1375cb93a386Sopenharmony_ci a2 = (y0 - y2 - sk_ieee_float_divide((x0 - x2) * y1, x1)) / denom; 1376cb93a386Sopenharmony_ci } else { 1377cb93a386Sopenharmony_ci float denom = sk_ieee_float_divide(y2 * x1, y1) - x2; 1378cb93a386Sopenharmony_ci if (checkForZero(denom)) { 1379cb93a386Sopenharmony_ci return false; 1380cb93a386Sopenharmony_ci } 1381cb93a386Sopenharmony_ci a2 = (sk_ieee_float_divide((y0 - y2) * x1, y1) - x0 + x2) / denom; 1382cb93a386Sopenharmony_ci } 1383cb93a386Sopenharmony_ci 1384cb93a386Sopenharmony_ci dst->fMat[kMScaleX] = a2 * srcPt[3].fX + srcPt[3].fX - srcPt[0].fX; 1385cb93a386Sopenharmony_ci dst->fMat[kMSkewY] = a2 * srcPt[3].fY + srcPt[3].fY - srcPt[0].fY; 1386cb93a386Sopenharmony_ci dst->fMat[kMPersp0] = a2; 1387cb93a386Sopenharmony_ci 1388cb93a386Sopenharmony_ci dst->fMat[kMSkewX] = a1 * srcPt[1].fX + srcPt[1].fX - srcPt[0].fX; 1389cb93a386Sopenharmony_ci dst->fMat[kMScaleY] = a1 * srcPt[1].fY + srcPt[1].fY - srcPt[0].fY; 1390cb93a386Sopenharmony_ci dst->fMat[kMPersp1] = a1; 1391cb93a386Sopenharmony_ci 1392cb93a386Sopenharmony_ci dst->fMat[kMTransX] = srcPt[0].fX; 1393cb93a386Sopenharmony_ci dst->fMat[kMTransY] = srcPt[0].fY; 1394cb93a386Sopenharmony_ci dst->fMat[kMPersp2] = 1; 1395cb93a386Sopenharmony_ci dst->setTypeMask(kUnknown_Mask); 1396cb93a386Sopenharmony_ci return true; 1397cb93a386Sopenharmony_ci} 1398cb93a386Sopenharmony_ci 1399cb93a386Sopenharmony_citypedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*); 1400cb93a386Sopenharmony_ci 1401cb93a386Sopenharmony_ci/* Adapted from Rob Johnson's original sample code in QuickDraw GX 1402cb93a386Sopenharmony_ci*/ 1403cb93a386Sopenharmony_cibool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count) { 1404cb93a386Sopenharmony_ci if ((unsigned)count > 4) { 1405cb93a386Sopenharmony_ci SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count); 1406cb93a386Sopenharmony_ci return false; 1407cb93a386Sopenharmony_ci } 1408cb93a386Sopenharmony_ci 1409cb93a386Sopenharmony_ci if (0 == count) { 1410cb93a386Sopenharmony_ci this->reset(); 1411cb93a386Sopenharmony_ci return true; 1412cb93a386Sopenharmony_ci } 1413cb93a386Sopenharmony_ci if (1 == count) { 1414cb93a386Sopenharmony_ci this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY); 1415cb93a386Sopenharmony_ci return true; 1416cb93a386Sopenharmony_ci } 1417cb93a386Sopenharmony_ci 1418cb93a386Sopenharmony_ci const PolyMapProc gPolyMapProcs[] = { 1419cb93a386Sopenharmony_ci SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc 1420cb93a386Sopenharmony_ci }; 1421cb93a386Sopenharmony_ci PolyMapProc proc = gPolyMapProcs[count - 2]; 1422cb93a386Sopenharmony_ci 1423cb93a386Sopenharmony_ci SkMatrix tempMap, result; 1424cb93a386Sopenharmony_ci 1425cb93a386Sopenharmony_ci if (!proc(src, &tempMap)) { 1426cb93a386Sopenharmony_ci return false; 1427cb93a386Sopenharmony_ci } 1428cb93a386Sopenharmony_ci if (!tempMap.invert(&result)) { 1429cb93a386Sopenharmony_ci return false; 1430cb93a386Sopenharmony_ci } 1431cb93a386Sopenharmony_ci if (!proc(dst, &tempMap)) { 1432cb93a386Sopenharmony_ci return false; 1433cb93a386Sopenharmony_ci } 1434cb93a386Sopenharmony_ci this->setConcat(tempMap, result); 1435cb93a386Sopenharmony_ci return true; 1436cb93a386Sopenharmony_ci} 1437cb93a386Sopenharmony_ci 1438cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1439cb93a386Sopenharmony_ci 1440cb93a386Sopenharmony_cienum MinMaxOrBoth { 1441cb93a386Sopenharmony_ci kMin_MinMaxOrBoth, 1442cb93a386Sopenharmony_ci kMax_MinMaxOrBoth, 1443cb93a386Sopenharmony_ci kBoth_MinMaxOrBoth 1444cb93a386Sopenharmony_ci}; 1445cb93a386Sopenharmony_ci 1446cb93a386Sopenharmony_citemplate <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask, 1447cb93a386Sopenharmony_ci const SkScalar m[9], 1448cb93a386Sopenharmony_ci SkScalar results[/*1 or 2*/]) { 1449cb93a386Sopenharmony_ci if (typeMask & SkMatrix::kPerspective_Mask) { 1450cb93a386Sopenharmony_ci return false; 1451cb93a386Sopenharmony_ci } 1452cb93a386Sopenharmony_ci if (SkMatrix::kIdentity_Mask == typeMask) { 1453cb93a386Sopenharmony_ci results[0] = SK_Scalar1; 1454cb93a386Sopenharmony_ci if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1455cb93a386Sopenharmony_ci results[1] = SK_Scalar1; 1456cb93a386Sopenharmony_ci } 1457cb93a386Sopenharmony_ci return true; 1458cb93a386Sopenharmony_ci } 1459cb93a386Sopenharmony_ci if (!(typeMask & SkMatrix::kAffine_Mask)) { 1460cb93a386Sopenharmony_ci if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1461cb93a386Sopenharmony_ci results[0] = std::min(SkScalarAbs(m[SkMatrix::kMScaleX]), 1462cb93a386Sopenharmony_ci SkScalarAbs(m[SkMatrix::kMScaleY])); 1463cb93a386Sopenharmony_ci } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1464cb93a386Sopenharmony_ci results[0] = std::max(SkScalarAbs(m[SkMatrix::kMScaleX]), 1465cb93a386Sopenharmony_ci SkScalarAbs(m[SkMatrix::kMScaleY])); 1466cb93a386Sopenharmony_ci } else { 1467cb93a386Sopenharmony_ci results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]); 1468cb93a386Sopenharmony_ci results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]); 1469cb93a386Sopenharmony_ci if (results[0] > results[1]) { 1470cb93a386Sopenharmony_ci using std::swap; 1471cb93a386Sopenharmony_ci swap(results[0], results[1]); 1472cb93a386Sopenharmony_ci } 1473cb93a386Sopenharmony_ci } 1474cb93a386Sopenharmony_ci return true; 1475cb93a386Sopenharmony_ci } 1476cb93a386Sopenharmony_ci // ignore the translation part of the matrix, just look at 2x2 portion. 1477cb93a386Sopenharmony_ci // compute singular values, take largest or smallest abs value. 1478cb93a386Sopenharmony_ci // [a b; b c] = A^T*A 1479cb93a386Sopenharmony_ci SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX], 1480cb93a386Sopenharmony_ci m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]); 1481cb93a386Sopenharmony_ci SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX], 1482cb93a386Sopenharmony_ci m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]); 1483cb93a386Sopenharmony_ci SkScalar c = sdot(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX], 1484cb93a386Sopenharmony_ci m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]); 1485cb93a386Sopenharmony_ci // eigenvalues of A^T*A are the squared singular values of A. 1486cb93a386Sopenharmony_ci // characteristic equation is det((A^T*A) - l*I) = 0 1487cb93a386Sopenharmony_ci // l^2 - (a + c)l + (ac-b^2) 1488cb93a386Sopenharmony_ci // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff 1489cb93a386Sopenharmony_ci // and roots are guaranteed to be pos and real). 1490cb93a386Sopenharmony_ci SkScalar bSqd = b * b; 1491cb93a386Sopenharmony_ci // if upper left 2x2 is orthogonal save some math 1492cb93a386Sopenharmony_ci if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { 1493cb93a386Sopenharmony_ci if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1494cb93a386Sopenharmony_ci results[0] = std::min(a, c); 1495cb93a386Sopenharmony_ci } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1496cb93a386Sopenharmony_ci results[0] = std::max(a, c); 1497cb93a386Sopenharmony_ci } else { 1498cb93a386Sopenharmony_ci results[0] = a; 1499cb93a386Sopenharmony_ci results[1] = c; 1500cb93a386Sopenharmony_ci if (results[0] > results[1]) { 1501cb93a386Sopenharmony_ci using std::swap; 1502cb93a386Sopenharmony_ci swap(results[0], results[1]); 1503cb93a386Sopenharmony_ci } 1504cb93a386Sopenharmony_ci } 1505cb93a386Sopenharmony_ci } else { 1506cb93a386Sopenharmony_ci SkScalar aminusc = a - c; 1507cb93a386Sopenharmony_ci SkScalar apluscdiv2 = SkScalarHalf(a + c); 1508cb93a386Sopenharmony_ci SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd)); 1509cb93a386Sopenharmony_ci if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1510cb93a386Sopenharmony_ci results[0] = apluscdiv2 - x; 1511cb93a386Sopenharmony_ci } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1512cb93a386Sopenharmony_ci results[0] = apluscdiv2 + x; 1513cb93a386Sopenharmony_ci } else { 1514cb93a386Sopenharmony_ci results[0] = apluscdiv2 - x; 1515cb93a386Sopenharmony_ci results[1] = apluscdiv2 + x; 1516cb93a386Sopenharmony_ci } 1517cb93a386Sopenharmony_ci } 1518cb93a386Sopenharmony_ci if (!SkScalarIsFinite(results[0])) { 1519cb93a386Sopenharmony_ci return false; 1520cb93a386Sopenharmony_ci } 1521cb93a386Sopenharmony_ci // Due to the floating point inaccuracy, there might be an error in a, b, c 1522cb93a386Sopenharmony_ci // calculated by sdot, further deepened by subsequent arithmetic operations 1523cb93a386Sopenharmony_ci // on them. Therefore, we allow and cap the nearly-zero negative values. 1524cb93a386Sopenharmony_ci if (results[0] < 0) { 1525cb93a386Sopenharmony_ci results[0] = 0; 1526cb93a386Sopenharmony_ci } 1527cb93a386Sopenharmony_ci results[0] = SkScalarSqrt(results[0]); 1528cb93a386Sopenharmony_ci if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { 1529cb93a386Sopenharmony_ci if (!SkScalarIsFinite(results[1])) { 1530cb93a386Sopenharmony_ci return false; 1531cb93a386Sopenharmony_ci } 1532cb93a386Sopenharmony_ci if (results[1] < 0) { 1533cb93a386Sopenharmony_ci results[1] = 0; 1534cb93a386Sopenharmony_ci } 1535cb93a386Sopenharmony_ci results[1] = SkScalarSqrt(results[1]); 1536cb93a386Sopenharmony_ci } 1537cb93a386Sopenharmony_ci return true; 1538cb93a386Sopenharmony_ci} 1539cb93a386Sopenharmony_ci 1540cb93a386Sopenharmony_ciSkScalar SkMatrix::getMinScale() const { 1541cb93a386Sopenharmony_ci SkScalar factor; 1542cb93a386Sopenharmony_ci if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) { 1543cb93a386Sopenharmony_ci return factor; 1544cb93a386Sopenharmony_ci } else { 1545cb93a386Sopenharmony_ci return -1; 1546cb93a386Sopenharmony_ci } 1547cb93a386Sopenharmony_ci} 1548cb93a386Sopenharmony_ci 1549cb93a386Sopenharmony_ciSkScalar SkMatrix::getMaxScale() const { 1550cb93a386Sopenharmony_ci SkScalar factor; 1551cb93a386Sopenharmony_ci if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) { 1552cb93a386Sopenharmony_ci return factor; 1553cb93a386Sopenharmony_ci } else { 1554cb93a386Sopenharmony_ci return -1; 1555cb93a386Sopenharmony_ci } 1556cb93a386Sopenharmony_ci} 1557cb93a386Sopenharmony_ci 1558cb93a386Sopenharmony_cibool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const { 1559cb93a386Sopenharmony_ci return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFactors); 1560cb93a386Sopenharmony_ci} 1561cb93a386Sopenharmony_ci 1562cb93a386Sopenharmony_ciconst SkMatrix& SkMatrix::I() { 1563cb93a386Sopenharmony_ci static constexpr SkMatrix identity; 1564cb93a386Sopenharmony_ci SkASSERT(identity.isIdentity()); 1565cb93a386Sopenharmony_ci return identity; 1566cb93a386Sopenharmony_ci} 1567cb93a386Sopenharmony_ci 1568cb93a386Sopenharmony_ciconst SkMatrix& SkMatrix::InvalidMatrix() { 1569cb93a386Sopenharmony_ci static constexpr SkMatrix invalid(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1570cb93a386Sopenharmony_ci SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1571cb93a386Sopenharmony_ci SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, 1572cb93a386Sopenharmony_ci kTranslate_Mask | kScale_Mask | 1573cb93a386Sopenharmony_ci kAffine_Mask | kPerspective_Mask); 1574cb93a386Sopenharmony_ci return invalid; 1575cb93a386Sopenharmony_ci} 1576cb93a386Sopenharmony_ci 1577cb93a386Sopenharmony_cibool SkMatrix::decomposeScale(SkSize* scale, SkMatrix* remaining) const { 1578cb93a386Sopenharmony_ci if (this->hasPerspective()) { 1579cb93a386Sopenharmony_ci return false; 1580cb93a386Sopenharmony_ci } 1581cb93a386Sopenharmony_ci 1582cb93a386Sopenharmony_ci const SkScalar sx = SkVector::Length(this->getScaleX(), this->getSkewY()); 1583cb93a386Sopenharmony_ci const SkScalar sy = SkVector::Length(this->getSkewX(), this->getScaleY()); 1584cb93a386Sopenharmony_ci if (!SkScalarIsFinite(sx) || !SkScalarIsFinite(sy) || 1585cb93a386Sopenharmony_ci SkScalarNearlyZero(sx) || SkScalarNearlyZero(sy)) { 1586cb93a386Sopenharmony_ci return false; 1587cb93a386Sopenharmony_ci } 1588cb93a386Sopenharmony_ci 1589cb93a386Sopenharmony_ci if (scale) { 1590cb93a386Sopenharmony_ci scale->set(sx, sy); 1591cb93a386Sopenharmony_ci } 1592cb93a386Sopenharmony_ci if (remaining) { 1593cb93a386Sopenharmony_ci *remaining = *this; 1594cb93a386Sopenharmony_ci remaining->preScale(SkScalarInvert(sx), SkScalarInvert(sy)); 1595cb93a386Sopenharmony_ci } 1596cb93a386Sopenharmony_ci return true; 1597cb93a386Sopenharmony_ci} 1598cb93a386Sopenharmony_ci 1599cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1600cb93a386Sopenharmony_ci 1601cb93a386Sopenharmony_cisize_t SkMatrix::writeToMemory(void* buffer) const { 1602cb93a386Sopenharmony_ci // TODO write less for simple matrices 1603cb93a386Sopenharmony_ci static const size_t sizeInMemory = 9 * sizeof(SkScalar); 1604cb93a386Sopenharmony_ci if (buffer) { 1605cb93a386Sopenharmony_ci memcpy(buffer, fMat, sizeInMemory); 1606cb93a386Sopenharmony_ci } 1607cb93a386Sopenharmony_ci return sizeInMemory; 1608cb93a386Sopenharmony_ci} 1609cb93a386Sopenharmony_ci 1610cb93a386Sopenharmony_cisize_t SkMatrix::readFromMemory(const void* buffer, size_t length) { 1611cb93a386Sopenharmony_ci static const size_t sizeInMemory = 9 * sizeof(SkScalar); 1612cb93a386Sopenharmony_ci if (length < sizeInMemory) { 1613cb93a386Sopenharmony_ci return 0; 1614cb93a386Sopenharmony_ci } 1615cb93a386Sopenharmony_ci memcpy(fMat, buffer, sizeInMemory); 1616cb93a386Sopenharmony_ci this->setTypeMask(kUnknown_Mask); 1617cb93a386Sopenharmony_ci // Figure out the type now so that we're thread-safe 1618cb93a386Sopenharmony_ci (void)this->getType(); 1619cb93a386Sopenharmony_ci return sizeInMemory; 1620cb93a386Sopenharmony_ci} 1621cb93a386Sopenharmony_ci 1622cb93a386Sopenharmony_civoid SkMatrix::dump() const { 1623cb93a386Sopenharmony_ci SkString str; 1624cb93a386Sopenharmony_ci str.appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]", 1625cb93a386Sopenharmony_ci fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5], 1626cb93a386Sopenharmony_ci fMat[6], fMat[7], fMat[8]); 1627cb93a386Sopenharmony_ci SkDebugf("%s\n", str.c_str()); 1628cb93a386Sopenharmony_ci} 1629cb93a386Sopenharmony_ci 1630cb93a386Sopenharmony_civoid SkMatrix::dump(std::string& desc, int depth) const { 1631cb93a386Sopenharmony_ci SkString str; 1632cb93a386Sopenharmony_ci str.appendf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]", 1633cb93a386Sopenharmony_ci fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5], fMat[6], fMat[7], fMat[8]); 1634cb93a386Sopenharmony_ci std::string split(depth, '\t'); 1635cb93a386Sopenharmony_ci desc += split + "\n SkMatrix:{ \n"; 1636cb93a386Sopenharmony_ci desc += std::string(str.c_str()); 1637cb93a386Sopenharmony_ci desc += split + "}\n"; 1638cb93a386Sopenharmony_ci 1639cb93a386Sopenharmony_ci SkDebugf("%s\n", str.c_str()); 1640cb93a386Sopenharmony_ci} 1641cb93a386Sopenharmony_ci 1642cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1643cb93a386Sopenharmony_ci 1644cb93a386Sopenharmony_ci#include "src/core/SkMatrixUtils.h" 1645cb93a386Sopenharmony_ci#include "src/core/SkSamplingPriv.h" 1646cb93a386Sopenharmony_ci 1647cb93a386Sopenharmony_cibool SkTreatAsSprite(const SkMatrix& mat, const SkISize& size, const SkSamplingOptions& sampling, 1648cb93a386Sopenharmony_ci const SkPaint& paint) { 1649cb93a386Sopenharmony_ci if (!SkSamplingPriv::NoChangeWithIdentityMatrix(sampling)) { 1650cb93a386Sopenharmony_ci return false; 1651cb93a386Sopenharmony_ci } 1652cb93a386Sopenharmony_ci 1653cb93a386Sopenharmony_ci // Our path aa is 2-bits, and our rect aa is 8, so we could use 8, 1654cb93a386Sopenharmony_ci // but in practice 4 seems enough (still looks smooth) and allows 1655cb93a386Sopenharmony_ci // more slightly fractional cases to fall into the fast (sprite) case. 1656cb93a386Sopenharmony_ci static const unsigned kAntiAliasSubpixelBits = 4; 1657cb93a386Sopenharmony_ci 1658cb93a386Sopenharmony_ci const unsigned subpixelBits = paint.isAntiAlias() ? kAntiAliasSubpixelBits : 0; 1659cb93a386Sopenharmony_ci 1660cb93a386Sopenharmony_ci // quick reject on affine or perspective 1661cb93a386Sopenharmony_ci if (mat.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) { 1662cb93a386Sopenharmony_ci return false; 1663cb93a386Sopenharmony_ci } 1664cb93a386Sopenharmony_ci 1665cb93a386Sopenharmony_ci // quick success check 1666cb93a386Sopenharmony_ci if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) { 1667cb93a386Sopenharmony_ci return true; 1668cb93a386Sopenharmony_ci } 1669cb93a386Sopenharmony_ci 1670cb93a386Sopenharmony_ci // mapRect supports negative scales, so we eliminate those first 1671cb93a386Sopenharmony_ci if (mat.getScaleX() < 0 || mat.getScaleY() < 0) { 1672cb93a386Sopenharmony_ci return false; 1673cb93a386Sopenharmony_ci } 1674cb93a386Sopenharmony_ci 1675cb93a386Sopenharmony_ci SkRect dst; 1676cb93a386Sopenharmony_ci SkIRect isrc = SkIRect::MakeSize(size); 1677cb93a386Sopenharmony_ci 1678cb93a386Sopenharmony_ci { 1679cb93a386Sopenharmony_ci SkRect src; 1680cb93a386Sopenharmony_ci src.set(isrc); 1681cb93a386Sopenharmony_ci mat.mapRect(&dst, src); 1682cb93a386Sopenharmony_ci } 1683cb93a386Sopenharmony_ci 1684cb93a386Sopenharmony_ci // just apply the translate to isrc 1685cb93a386Sopenharmony_ci isrc.offset(SkScalarRoundToInt(mat.getTranslateX()), 1686cb93a386Sopenharmony_ci SkScalarRoundToInt(mat.getTranslateY())); 1687cb93a386Sopenharmony_ci 1688cb93a386Sopenharmony_ci if (subpixelBits) { 1689cb93a386Sopenharmony_ci isrc.fLeft = SkLeftShift(isrc.fLeft, subpixelBits); 1690cb93a386Sopenharmony_ci isrc.fTop = SkLeftShift(isrc.fTop, subpixelBits); 1691cb93a386Sopenharmony_ci isrc.fRight = SkLeftShift(isrc.fRight, subpixelBits); 1692cb93a386Sopenharmony_ci isrc.fBottom = SkLeftShift(isrc.fBottom, subpixelBits); 1693cb93a386Sopenharmony_ci 1694cb93a386Sopenharmony_ci const float scale = 1 << subpixelBits; 1695cb93a386Sopenharmony_ci dst.fLeft *= scale; 1696cb93a386Sopenharmony_ci dst.fTop *= scale; 1697cb93a386Sopenharmony_ci dst.fRight *= scale; 1698cb93a386Sopenharmony_ci dst.fBottom *= scale; 1699cb93a386Sopenharmony_ci } 1700cb93a386Sopenharmony_ci 1701cb93a386Sopenharmony_ci SkIRect idst; 1702cb93a386Sopenharmony_ci dst.round(&idst); 1703cb93a386Sopenharmony_ci return isrc == idst; 1704cb93a386Sopenharmony_ci} 1705cb93a386Sopenharmony_ci 1706cb93a386Sopenharmony_ci// A square matrix M can be decomposed (via polar decomposition) into two matrices -- 1707cb93a386Sopenharmony_ci// an orthogonal matrix Q and a symmetric matrix S. In turn we can decompose S into U*W*U^T, 1708cb93a386Sopenharmony_ci// where U is another orthogonal matrix and W is a scale matrix. These can be recombined 1709cb93a386Sopenharmony_ci// to give M = (Q*U)*W*U^T, i.e., the product of two orthogonal matrices and a scale matrix. 1710cb93a386Sopenharmony_ci// 1711cb93a386Sopenharmony_ci// The one wrinkle is that traditionally Q may contain a reflection -- the 1712cb93a386Sopenharmony_ci// calculation has been rejiggered to put that reflection into W. 1713cb93a386Sopenharmony_cibool SkDecomposeUpper2x2(const SkMatrix& matrix, 1714cb93a386Sopenharmony_ci SkPoint* rotation1, 1715cb93a386Sopenharmony_ci SkPoint* scale, 1716cb93a386Sopenharmony_ci SkPoint* rotation2) { 1717cb93a386Sopenharmony_ci 1718cb93a386Sopenharmony_ci SkScalar A = matrix[SkMatrix::kMScaleX]; 1719cb93a386Sopenharmony_ci SkScalar B = matrix[SkMatrix::kMSkewX]; 1720cb93a386Sopenharmony_ci SkScalar C = matrix[SkMatrix::kMSkewY]; 1721cb93a386Sopenharmony_ci SkScalar D = matrix[SkMatrix::kMScaleY]; 1722cb93a386Sopenharmony_ci 1723cb93a386Sopenharmony_ci if (is_degenerate_2x2(A, B, C, D)) { 1724cb93a386Sopenharmony_ci return false; 1725cb93a386Sopenharmony_ci } 1726cb93a386Sopenharmony_ci 1727cb93a386Sopenharmony_ci double w1, w2; 1728cb93a386Sopenharmony_ci SkScalar cos1, sin1; 1729cb93a386Sopenharmony_ci SkScalar cos2, sin2; 1730cb93a386Sopenharmony_ci 1731cb93a386Sopenharmony_ci // do polar decomposition (M = Q*S) 1732cb93a386Sopenharmony_ci SkScalar cosQ, sinQ; 1733cb93a386Sopenharmony_ci double Sa, Sb, Sd; 1734cb93a386Sopenharmony_ci // if M is already symmetric (i.e., M = I*S) 1735cb93a386Sopenharmony_ci if (SkScalarNearlyEqual(B, C)) { 1736cb93a386Sopenharmony_ci cosQ = 1; 1737cb93a386Sopenharmony_ci sinQ = 0; 1738cb93a386Sopenharmony_ci 1739cb93a386Sopenharmony_ci Sa = A; 1740cb93a386Sopenharmony_ci Sb = B; 1741cb93a386Sopenharmony_ci Sd = D; 1742cb93a386Sopenharmony_ci } else { 1743cb93a386Sopenharmony_ci cosQ = A + D; 1744cb93a386Sopenharmony_ci sinQ = C - B; 1745cb93a386Sopenharmony_ci SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ)); 1746cb93a386Sopenharmony_ci cosQ *= reciplen; 1747cb93a386Sopenharmony_ci sinQ *= reciplen; 1748cb93a386Sopenharmony_ci 1749cb93a386Sopenharmony_ci // S = Q^-1*M 1750cb93a386Sopenharmony_ci // we don't calc Sc since it's symmetric 1751cb93a386Sopenharmony_ci Sa = A*cosQ + C*sinQ; 1752cb93a386Sopenharmony_ci Sb = B*cosQ + D*sinQ; 1753cb93a386Sopenharmony_ci Sd = -B*sinQ + D*cosQ; 1754cb93a386Sopenharmony_ci } 1755cb93a386Sopenharmony_ci 1756cb93a386Sopenharmony_ci // Now we need to compute eigenvalues of S (our scale factors) 1757cb93a386Sopenharmony_ci // and eigenvectors (bases for our rotation) 1758cb93a386Sopenharmony_ci // From this, should be able to reconstruct S as U*W*U^T 1759cb93a386Sopenharmony_ci if (SkScalarNearlyZero(SkDoubleToScalar(Sb))) { 1760cb93a386Sopenharmony_ci // already diagonalized 1761cb93a386Sopenharmony_ci cos1 = 1; 1762cb93a386Sopenharmony_ci sin1 = 0; 1763cb93a386Sopenharmony_ci w1 = Sa; 1764cb93a386Sopenharmony_ci w2 = Sd; 1765cb93a386Sopenharmony_ci cos2 = cosQ; 1766cb93a386Sopenharmony_ci sin2 = sinQ; 1767cb93a386Sopenharmony_ci } else { 1768cb93a386Sopenharmony_ci double diff = Sa - Sd; 1769cb93a386Sopenharmony_ci double discriminant = sqrt(diff*diff + 4.0*Sb*Sb); 1770cb93a386Sopenharmony_ci double trace = Sa + Sd; 1771cb93a386Sopenharmony_ci if (diff > 0) { 1772cb93a386Sopenharmony_ci w1 = 0.5*(trace + discriminant); 1773cb93a386Sopenharmony_ci w2 = 0.5*(trace - discriminant); 1774cb93a386Sopenharmony_ci } else { 1775cb93a386Sopenharmony_ci w1 = 0.5*(trace - discriminant); 1776cb93a386Sopenharmony_ci w2 = 0.5*(trace + discriminant); 1777cb93a386Sopenharmony_ci } 1778cb93a386Sopenharmony_ci 1779cb93a386Sopenharmony_ci cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa); 1780cb93a386Sopenharmony_ci SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1)); 1781cb93a386Sopenharmony_ci cos1 *= reciplen; 1782cb93a386Sopenharmony_ci sin1 *= reciplen; 1783cb93a386Sopenharmony_ci 1784cb93a386Sopenharmony_ci // rotation 2 is composition of Q and U 1785cb93a386Sopenharmony_ci cos2 = cos1*cosQ - sin1*sinQ; 1786cb93a386Sopenharmony_ci sin2 = sin1*cosQ + cos1*sinQ; 1787cb93a386Sopenharmony_ci 1788cb93a386Sopenharmony_ci // rotation 1 is U^T 1789cb93a386Sopenharmony_ci sin1 = -sin1; 1790cb93a386Sopenharmony_ci } 1791cb93a386Sopenharmony_ci 1792cb93a386Sopenharmony_ci if (scale) { 1793cb93a386Sopenharmony_ci scale->fX = SkDoubleToScalar(w1); 1794cb93a386Sopenharmony_ci scale->fY = SkDoubleToScalar(w2); 1795cb93a386Sopenharmony_ci } 1796cb93a386Sopenharmony_ci if (rotation1) { 1797cb93a386Sopenharmony_ci rotation1->fX = cos1; 1798cb93a386Sopenharmony_ci rotation1->fY = sin1; 1799cb93a386Sopenharmony_ci } 1800cb93a386Sopenharmony_ci if (rotation2) { 1801cb93a386Sopenharmony_ci rotation2->fX = cos2; 1802cb93a386Sopenharmony_ci rotation2->fY = sin2; 1803cb93a386Sopenharmony_ci } 1804cb93a386Sopenharmony_ci 1805cb93a386Sopenharmony_ci return true; 1806cb93a386Sopenharmony_ci} 1807cb93a386Sopenharmony_ci 1808cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////// 1809cb93a386Sopenharmony_ci 1810cb93a386Sopenharmony_civoid SkRSXform::toQuad(SkScalar width, SkScalar height, SkPoint quad[4]) const { 1811cb93a386Sopenharmony_ci#if 0 1812cb93a386Sopenharmony_ci // This is the slow way, but it documents what we're doing 1813cb93a386Sopenharmony_ci quad[0].set(0, 0); 1814cb93a386Sopenharmony_ci quad[1].set(width, 0); 1815cb93a386Sopenharmony_ci quad[2].set(width, height); 1816cb93a386Sopenharmony_ci quad[3].set(0, height); 1817cb93a386Sopenharmony_ci SkMatrix m; 1818cb93a386Sopenharmony_ci m.setRSXform(*this).mapPoints(quad, quad, 4); 1819cb93a386Sopenharmony_ci#else 1820cb93a386Sopenharmony_ci const SkScalar m00 = fSCos; 1821cb93a386Sopenharmony_ci const SkScalar m01 = -fSSin; 1822cb93a386Sopenharmony_ci const SkScalar m02 = fTx; 1823cb93a386Sopenharmony_ci const SkScalar m10 = -m01; 1824cb93a386Sopenharmony_ci const SkScalar m11 = m00; 1825cb93a386Sopenharmony_ci const SkScalar m12 = fTy; 1826cb93a386Sopenharmony_ci 1827cb93a386Sopenharmony_ci quad[0].set(m02, m12); 1828cb93a386Sopenharmony_ci quad[1].set(m00 * width + m02, m10 * width + m12); 1829cb93a386Sopenharmony_ci quad[2].set(m00 * width + m01 * height + m02, m10 * width + m11 * height + m12); 1830cb93a386Sopenharmony_ci quad[3].set(m01 * height + m02, m11 * height + m12); 1831cb93a386Sopenharmony_ci#endif 1832cb93a386Sopenharmony_ci} 1833cb93a386Sopenharmony_ci 1834cb93a386Sopenharmony_civoid SkRSXform::toTriStrip(SkScalar width, SkScalar height, SkPoint strip[4]) const { 1835cb93a386Sopenharmony_ci const SkScalar m00 = fSCos; 1836cb93a386Sopenharmony_ci const SkScalar m01 = -fSSin; 1837cb93a386Sopenharmony_ci const SkScalar m02 = fTx; 1838cb93a386Sopenharmony_ci const SkScalar m10 = -m01; 1839cb93a386Sopenharmony_ci const SkScalar m11 = m00; 1840cb93a386Sopenharmony_ci const SkScalar m12 = fTy; 1841cb93a386Sopenharmony_ci 1842cb93a386Sopenharmony_ci strip[0].set(m02, m12); 1843cb93a386Sopenharmony_ci strip[1].set(m01 * height + m02, m11 * height + m12); 1844cb93a386Sopenharmony_ci strip[2].set(m00 * width + m02, m10 * width + m12); 1845cb93a386Sopenharmony_ci strip[3].set(m00 * width + m01 * height + m02, m10 * width + m11 * height + m12); 1846cb93a386Sopenharmony_ci} 1847cb93a386Sopenharmony_ci 1848cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////////////////// 1849cb93a386Sopenharmony_ci 1850cb93a386Sopenharmony_ciSkScalar SkMatrixPriv::DifferentialAreaScale(const SkMatrix& m, const SkPoint& p) { 1851cb93a386Sopenharmony_ci // [m00 m01 m02] [f(u,v)] 1852cb93a386Sopenharmony_ci // Assuming M = [m10 m11 m12], define the projected p'(u,v) = [g(u,v)] where 1853cb93a386Sopenharmony_ci // [m20 m12 m22] 1854cb93a386Sopenharmony_ci // [x] [u] 1855cb93a386Sopenharmony_ci // f(u,v) = x(u,v) / w(u,v), g(u,v) = y(u,v) / w(u,v) and [y] = M*[v] 1856cb93a386Sopenharmony_ci // [w] [1] 1857cb93a386Sopenharmony_ci // 1858cb93a386Sopenharmony_ci // Then the differential scale factor between p = (u,v) and p' is |det J|, 1859cb93a386Sopenharmony_ci // where J is the Jacobian for p': [df/du dg/du] 1860cb93a386Sopenharmony_ci // [df/dv dg/dv] 1861cb93a386Sopenharmony_ci // and df/du = (w*dx/du - x*dw/du)/w^2, dg/du = (w*dy/du - y*dw/du)/w^2 1862cb93a386Sopenharmony_ci // df/dv = (w*dx/dv - x*dw/dv)/w^2, dg/dv = (w*dy/dv - y*dw/dv)/w^2 1863cb93a386Sopenharmony_ci // 1864cb93a386Sopenharmony_ci // From here, |det J| can be rewritten as |det J'/w^3|, where 1865cb93a386Sopenharmony_ci // [x y w ] [x y w ] 1866cb93a386Sopenharmony_ci // J' = [dx/du dy/du dw/du] = [m00 m10 m20] 1867cb93a386Sopenharmony_ci // [dx/dv dy/dv dw/dv] [m01 m11 m21] 1868cb93a386Sopenharmony_ci SkPoint3 xyw; 1869cb93a386Sopenharmony_ci m.mapHomogeneousPoints(&xyw, &p, 1); 1870cb93a386Sopenharmony_ci 1871cb93a386Sopenharmony_ci if (xyw.fZ < SK_ScalarNearlyZero) { 1872cb93a386Sopenharmony_ci // Reaching the discontinuity of xy/w and where the point would clip to w >= 0 1873cb93a386Sopenharmony_ci return SK_ScalarInfinity; 1874cb93a386Sopenharmony_ci } 1875cb93a386Sopenharmony_ci SkMatrix jacobian = SkMatrix::MakeAll(xyw.fX, xyw.fY, xyw.fZ, 1876cb93a386Sopenharmony_ci m.getScaleX(), m.getSkewY(), m.getPerspX(), 1877cb93a386Sopenharmony_ci m.getSkewX(), m.getScaleY(), m.getPerspY()); 1878cb93a386Sopenharmony_ci 1879cb93a386Sopenharmony_ci double denom = 1.0 / xyw.fZ; // 1/w 1880cb93a386Sopenharmony_ci denom = denom * denom * denom; // 1/w^3 1881cb93a386Sopenharmony_ci return SkScalarAbs(SkDoubleToScalar(sk_determinant(jacobian.fMat, true) * denom)); 1882cb93a386Sopenharmony_ci} 1883