OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkMatrix.h" | 8 #include "SkMatrix.h" |
9 #include "SkFloatBits.h" | 9 #include "SkFloatBits.h" |
10 #include "SkOnce.h" | 10 #include "SkOnce.h" |
(...skipping 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1444 } | 1444 } |
1445 if (!proc(dst, &tempMap, scale)) { | 1445 if (!proc(dst, &tempMap, scale)) { |
1446 return false; | 1446 return false; |
1447 } | 1447 } |
1448 this->setConcat(tempMap, result); | 1448 this->setConcat(tempMap, result); |
1449 return true; | 1449 return true; |
1450 } | 1450 } |
1451 | 1451 |
1452 /////////////////////////////////////////////////////////////////////////////// | 1452 /////////////////////////////////////////////////////////////////////////////// |
1453 | 1453 |
1454 enum MinOrMax { | 1454 enum MinMaxOrBoth { |
1455 kMin_MinOrMax, | 1455 kMin_MinMaxOrBoth, |
1456 kMax_MinOrMax | 1456 kMax_MinMaxOrBoth, |
| 1457 kBoth_MinMaxOrBoth |
1457 }; | 1458 }; |
1458 | 1459 |
1459 template <MinOrMax MIN_OR_MAX> SkScalar get_scale_factor(SkMatrix::TypeMask type
Mask, | 1460 template <MinMaxOrBoth MIN_MAX_OR_BOTH> bool get_scale_factor(SkMatrix::TypeMask
typeMask, |
1460 const SkScalar m[9]) { | 1461 const SkScalar m[9
], |
| 1462 SkScalar results[/
*1 or 2*/]) { |
1461 if (typeMask & SkMatrix::kPerspective_Mask) { | 1463 if (typeMask & SkMatrix::kPerspective_Mask) { |
1462 return -1; | 1464 return false; |
1463 } | 1465 } |
1464 if (SkMatrix::kIdentity_Mask == typeMask) { | 1466 if (SkMatrix::kIdentity_Mask == typeMask) { |
1465 return 1; | 1467 results[0] = SK_Scalar1; |
| 1468 if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
| 1469 results[1] = SK_Scalar1; |
| 1470 } |
| 1471 return true; |
1466 } | 1472 } |
1467 if (!(typeMask & SkMatrix::kAffine_Mask)) { | 1473 if (!(typeMask & SkMatrix::kAffine_Mask)) { |
1468 if (kMin_MinOrMax == MIN_OR_MAX) { | 1474 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
1469 return SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), | 1475 results[0] = SkMinScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), |
1470 SkScalarAbs(m[SkMatrix::kMScaleY])); | 1476 SkScalarAbs(m[SkMatrix::kMScaleY])); |
| 1477 } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
| 1478 results[0] = SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), |
| 1479 SkScalarAbs(m[SkMatrix::kMScaleY])); |
1471 } else { | 1480 } else { |
1472 return SkMaxScalar(SkScalarAbs(m[SkMatrix::kMScaleX]), | 1481 results[0] = SkScalarAbs(m[SkMatrix::kMScaleX]); |
1473 SkScalarAbs(m[SkMatrix::kMScaleY])); | 1482 results[1] = SkScalarAbs(m[SkMatrix::kMScaleY]); |
| 1483 if (results[0] > results[1]) { |
| 1484 SkTSwap(results[0], results[1]); |
| 1485 } |
1474 } | 1486 } |
| 1487 return true; |
1475 } | 1488 } |
1476 // ignore the translation part of the matrix, just look at 2x2 portion. | 1489 // ignore the translation part of the matrix, just look at 2x2 portion. |
1477 // compute singular values, take largest or smallest abs value. | 1490 // compute singular values, take largest or smallest abs value. |
1478 // [a b; b c] = A^T*A | 1491 // [a b; b c] = A^T*A |
1479 SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX], | 1492 SkScalar a = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMScaleX], |
1480 m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]); | 1493 m[SkMatrix::kMSkewY], m[SkMatrix::kMSkewY]); |
1481 SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX], | 1494 SkScalar b = sdot(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewX], |
1482 m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]); | 1495 m[SkMatrix::kMScaleY], m[SkMatrix::kMSkewY]); |
1483 SkScalar c = sdot(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX], | 1496 SkScalar c = sdot(m[SkMatrix::kMSkewX], m[SkMatrix::kMSkewX], |
1484 m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]); | 1497 m[SkMatrix::kMScaleY], m[SkMatrix::kMScaleY]); |
1485 // eigenvalues of A^T*A are the squared singular values of A. | 1498 // eigenvalues of A^T*A are the squared singular values of A. |
1486 // characteristic equation is det((A^T*A) - l*I) = 0 | 1499 // characteristic equation is det((A^T*A) - l*I) = 0 |
1487 // l^2 - (a + c)l + (ac-b^2) | 1500 // l^2 - (a + c)l + (ac-b^2) |
1488 // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff | 1501 // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff |
1489 // and roots are guaranteed to be pos and real). | 1502 // and roots are guaranteed to be pos and real). |
1490 SkScalar chosenRoot; | |
1491 SkScalar bSqd = b * b; | 1503 SkScalar bSqd = b * b; |
1492 // if upper left 2x2 is orthogonal save some math | 1504 // if upper left 2x2 is orthogonal save some math |
1493 if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { | 1505 if (bSqd <= SK_ScalarNearlyZero*SK_ScalarNearlyZero) { |
1494 if (kMin_MinOrMax == MIN_OR_MAX) { | 1506 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
1495 chosenRoot = SkMinScalar(a, c); | 1507 results[0] = SkMinScalar(a, c); |
| 1508 } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
| 1509 results[0] = SkMaxScalar(a, c); |
1496 } else { | 1510 } else { |
1497 chosenRoot = SkMaxScalar(a, c); | 1511 results[0] = a; |
| 1512 results[1] = c; |
| 1513 if (results[0] > results[1]) { |
| 1514 SkTSwap(results[0], results[1]); |
| 1515 } |
1498 } | 1516 } |
1499 } else { | 1517 } else { |
1500 SkScalar aminusc = a - c; | 1518 SkScalar aminusc = a - c; |
1501 SkScalar apluscdiv2 = SkScalarHalf(a + c); | 1519 SkScalar apluscdiv2 = SkScalarHalf(a + c); |
1502 SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd)); | 1520 SkScalar x = SkScalarHalf(SkScalarSqrt(aminusc * aminusc + 4 * bSqd)); |
1503 if (kMin_MinOrMax == MIN_OR_MAX) { | 1521 if (kMin_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
1504 chosenRoot = apluscdiv2 - x; | 1522 results[0] = apluscdiv2 - x; |
| 1523 } else if (kMax_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
| 1524 results[0] = apluscdiv2 + x; |
1505 } else { | 1525 } else { |
1506 chosenRoot = apluscdiv2 + x; | 1526 results[0] = apluscdiv2 - x; |
| 1527 results[1] = apluscdiv2 + x; |
1507 } | 1528 } |
1508 } | 1529 } |
1509 SkASSERT(chosenRoot >= 0); | 1530 SkASSERT(results[0] >= 0); |
1510 return SkScalarSqrt(chosenRoot); | 1531 results[0] = SkScalarSqrt(results[0]); |
| 1532 if (kBoth_MinMaxOrBoth == MIN_MAX_OR_BOTH) { |
| 1533 SkASSERT(results[1] >= 0); |
| 1534 results[1] = SkScalarSqrt(results[1]); |
| 1535 } |
| 1536 return true; |
1511 } | 1537 } |
1512 | 1538 |
1513 SkScalar SkMatrix::getMinScale() const { | 1539 SkScalar SkMatrix::getMinScale() const { |
1514 return get_scale_factor<kMin_MinOrMax>(this->getType(), fMat); | 1540 SkScalar factor; |
| 1541 if (get_scale_factor<kMin_MinMaxOrBoth>(this->getType(), fMat, &factor)) { |
| 1542 return factor; |
| 1543 } else { |
| 1544 return -1; |
| 1545 } |
1515 } | 1546 } |
1516 | 1547 |
1517 SkScalar SkMatrix::getMaxScale() const { | 1548 SkScalar SkMatrix::getMaxScale() const { |
1518 return get_scale_factor<kMax_MinOrMax>(this->getType(), fMat); | 1549 SkScalar factor; |
| 1550 if (get_scale_factor<kMax_MinMaxOrBoth>(this->getType(), fMat, &factor)) { |
| 1551 return factor; |
| 1552 } else { |
| 1553 return -1; |
| 1554 } |
| 1555 } |
| 1556 |
| 1557 bool SkMatrix::getMinMaxScales(SkScalar scaleFactors[2]) const { |
| 1558 return get_scale_factor<kBoth_MinMaxOrBoth>(this->getType(), fMat, scaleFact
ors); |
1519 } | 1559 } |
1520 | 1560 |
1521 static void reset_identity_matrix(SkMatrix* identity) { | 1561 static void reset_identity_matrix(SkMatrix* identity) { |
1522 identity->reset(); | 1562 identity->reset(); |
1523 } | 1563 } |
1524 | 1564 |
1525 const SkMatrix& SkMatrix::I() { | 1565 const SkMatrix& SkMatrix::I() { |
1526 // If you can use C++11 now, you might consider replacing this with a conste
xpr constructor. | 1566 // If you can use C++11 now, you might consider replacing this with a conste
xpr constructor. |
1527 static SkMatrix gIdentity; | 1567 static SkMatrix gIdentity; |
1528 SK_DECLARE_STATIC_ONCE(once); | 1568 SK_DECLARE_STATIC_ONCE(once); |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1728 rotation1->fX = cos1; | 1768 rotation1->fX = cos1; |
1729 rotation1->fY = sin1; | 1769 rotation1->fY = sin1; |
1730 } | 1770 } |
1731 if (NULL != rotation2) { | 1771 if (NULL != rotation2) { |
1732 rotation2->fX = cos2; | 1772 rotation2->fX = cos2; |
1733 rotation2->fY = sin2; | 1773 rotation2->fY = sin2; |
1734 } | 1774 } |
1735 | 1775 |
1736 return true; | 1776 return true; |
1737 } | 1777 } |
OLD | NEW |