| 1393 | }; |
| 1394 | |
| 1395 | template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask typeMask, |
| 1396 | const SkScalar m[9], |
| 1397 | SkScalar results[/*1 or 2*/]) { |
| 1398 | if (typeMask & SkMatrix::kPerspective_Mask) { |
| 1399 | return false; |
| 1400 | } |
| 1401 | if (SkMatrix::kIdentity_Mask == typeMask) { |
| 1402 | results[0] = SK_Scalar1; |
| 1403 | if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
| 1404 | results[1] = SK_Scalar1; |
| 1405 | } |
| 1406 | return true; |
| 1407 | } |
| 1408 | if (!(typeMask & SkMatrix::kAffine_Mask)) { |
| 1409 | if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
| 1410 | results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), |
| 1411 | SkScalarAbs(m[SkMatrix::kMScaleY])); |
| 1412 | } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
| 1413 | results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), |
| 1414 | SkScalarAbs(m[SkMatrix::kMScaleY])); |
| 1415 | } else { |
| 1416 | results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]); |
| 1417 | results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]); |
| 1418 | if (results[0] > results[1]) { |
| 1419 | SkTSwap(results[0], results[1]); |
| 1420 | } |
| 1421 | } |
| 1422 | return true; |
| 1423 | } |
| 1424 | // ignore the translation part of the matrix, just look at 2x2 portion. |
| 1425 | // compute singular values, take largest or smallest abs value. |
| 1426 | // [a b; b c] = A^T*A |
| 1427 | SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX], |
| 1428 | m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]); |
| 1429 | SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX], |
| 1430 | m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]); |
| 1431 | SkScalar c = sdot(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX], |
| 1432 | m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]); |
| 1433 | // eigenvalues of A^T*A are the squared singular values of A. |
| 1434 | // characteristic equation is det((A^T*A) - l*I) = 0 |
| 1435 | // l^2 - (a + c)l + (ac-b^2) |
| 1436 | // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff |
| 1437 | // and roots are guaranteed to be pos and real). |
| 1438 | SkScalar bSqd = b * b; |
| 1439 | // if upper left 2x2 is orthogonal save some math |
| 1440 | if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { |
| 1441 | if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
| 1442 | results[0] = SkMinScalar(a, c); |
| 1443 | } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
| 1444 | results[0] = SkMaxScalar(a, c); |
| 1445 | } else { |
| 1446 | results[0] = a; |
| 1447 | results[1] = c; |
| 1448 | if (results[0] > results[1]) { |
| 1449 | SkTSwap(results[0], results[1]); |
| 1450 | } |
| 1451 | } |
| 1452 | } else { |
nothing calls this directly
no test coverage detected