Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Functions
SkMatrixUtils.h File Reference
#include "include/core/SkPoint.h"
#include "include/core/SkSize.h"

Go to the source code of this file.

Functions

bool SkTreatAsSprite (const SkMatrix &, const SkISize &size, const SkSamplingOptions &, bool isAntiAlias)
 
bool SkDecomposeUpper2x2 (const SkMatrix &matrix, SkPoint *rotation1, SkPoint *scale, SkPoint *rotation2)
 

Function Documentation

◆ SkDecomposeUpper2x2()

bool SkDecomposeUpper2x2 ( const SkMatrix matrix,
SkPoint rotation1,
SkPoint scale,
SkPoint rotation2 
)

Decomposes the upper-left 2x2 of the matrix into a rotation (represented by the cosine and sine of the rotation angle), followed by a non-uniform scale, followed by another rotation. If there is a reflection, one of the scale factors will be negative. Returns true if successful. Returns false if the matrix is degenerate.

Definition at line 1689 of file SkMatrix.cpp.

1692 {
1693
1698
1699 if (is_degenerate_2x2(A, B, C, D)) {
1700 return false;
1701 }
1702
1703 double w1, w2;
1704 SkScalar cos1, sin1;
1705 SkScalar cos2, sin2;
1706
1707 // do polar decomposition (M = Q*S)
1708 SkScalar cosQ, sinQ;
1709 double Sa, Sb, Sd;
1710 // if M is already symmetric (i.e., M = I*S)
1711 if (SkScalarNearlyEqual(B, C)) {
1712 cosQ = 1;
1713 sinQ = 0;
1714
1715 Sa = A;
1716 Sb = B;
1717 Sd = D;
1718 } else {
1719 cosQ = A + D;
1720 sinQ = C - B;
1721 SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cosQ*cosQ + sinQ*sinQ));
1722 cosQ *= reciplen;
1723 sinQ *= reciplen;
1724
1725 // S = Q^-1*M
1726 // we don't calc Sc since it's symmetric
1727 Sa = A*cosQ + C*sinQ;
1728 Sb = B*cosQ + D*sinQ;
1729 Sd = -B*sinQ + D*cosQ;
1730 }
1731
1732 // Now we need to compute eigenvalues of S (our scale factors)
1733 // and eigenvectors (bases for our rotation)
1734 // From this, should be able to reconstruct S as U*W*U^T
1736 // already diagonalized
1737 cos1 = 1;
1738 sin1 = 0;
1739 w1 = Sa;
1740 w2 = Sd;
1741 cos2 = cosQ;
1742 sin2 = sinQ;
1743 } else {
1744 double diff = Sa - Sd;
1745 double discriminant = sqrt(diff*diff + 4.0*Sb*Sb);
1746 double trace = Sa + Sd;
1747 if (diff > 0) {
1748 w1 = 0.5*(trace + discriminant);
1749 w2 = 0.5*(trace - discriminant);
1750 } else {
1751 w1 = 0.5*(trace - discriminant);
1752 w2 = 0.5*(trace + discriminant);
1753 }
1754
1755 cos1 = SkDoubleToScalar(Sb); sin1 = SkDoubleToScalar(w1 - Sa);
1756 SkScalar reciplen = SkScalarInvert(SkScalarSqrt(cos1*cos1 + sin1*sin1));
1757 cos1 *= reciplen;
1758 sin1 *= reciplen;
1759
1760 // rotation 2 is composition of Q and U
1761 cos2 = cos1*cosQ - sin1*sinQ;
1762 sin2 = sin1*cosQ + cos1*sinQ;
1763
1764 // rotation 1 is U^T
1765 sin1 = -sin1;
1766 }
1767
1768 if (scale) {
1769 scale->fX = SkDoubleToScalar(w1);
1770 scale->fY = SkDoubleToScalar(w2);
1771 }
1772 if (rotation1) {
1773 rotation1->fX = cos1;
1774 rotation1->fY = sin1;
1775 }
1776 if (rotation2) {
1777 rotation2->fX = cos2;
1778 rotation2->fY = sin2;
1779 }
1780
1781 return true;
1782}
static bool is_degenerate_2x2(SkScalar scaleX, SkScalar skewX, SkScalar skewY, SkScalar scaleY)
Definition SkMatrix.cpp:172
#define SkScalarInvert(x)
Definition SkScalar.h:73
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition SkScalar.h:101
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition SkScalar.h:107
#define SkDoubleToScalar(x)
Definition SkScalar.h:64
#define SkScalarSqrt(x)
Definition SkScalar.h:42
static constexpr int kMScaleX
horizontal scale factor
Definition SkMatrix.h:353
static constexpr int kMSkewY
vertical skew factor
Definition SkMatrix.h:356
static constexpr int kMScaleY
vertical scale factor
Definition SkMatrix.h:357
static constexpr int kMSkewX
horizontal skew factor
Definition SkMatrix.h:354
float SkScalar
Definition extension.cpp:12
#define B
unsigned useCenter Optional< SkMatrix > matrix
Definition SkRecords.h:258
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
Definition SkVx.h:706
const Scalar scale
float fX
x-axis value
float fY
y-axis value

◆ SkTreatAsSprite()

bool SkTreatAsSprite ( const SkMatrix mat,
const SkISize size,
const SkSamplingOptions sampling,
bool  isAntiAlias 
)

Given a matrix, size and an antialias setting, return true if the computed dst-rect would align such that there is a 1-to-1 coorspondence between src and dst pixels. This can be called by drawing code to see if drawBitmap can be turned into drawSprite (which is faster).

The src-rect is defined to be { 0, 0, size.width(), size.height() }

Definition at line 1614 of file SkMatrix.cpp.

1615 {
1617 return false;
1618 }
1619
1620 // Our path aa is 2-bits, and our rect aa is 8, so we could use 8,
1621 // but in practice 4 seems enough (still looks smooth) and allows
1622 // more slightly fractional cases to fall into the fast (sprite) case.
1623 static const unsigned kAntiAliasSubpixelBits = 4;
1624
1625 const unsigned subpixelBits = isAntiAlias ? kAntiAliasSubpixelBits : 0;
1626
1627 // quick reject on affine or perspective
1629 return false;
1630 }
1631
1632 // We don't want to snap to pixels if we're asking for linear filtering with
1633 // a subpixel translation. (b/41322892).
1634 // This mirrors `tweak_sampling` in SkImageShader.cpp
1636 (mat.getTranslateX() != (int)mat.getTranslateX() ||
1637 mat.getTranslateY() != (int)mat.getTranslateY())) {
1638 return false;
1639 }
1640
1641 // quick success check
1642 if (!subpixelBits && !(mat.getType() & ~SkMatrix::kTranslate_Mask)) {
1643 return true;
1644 }
1645
1646 // mapRect supports negative scales, so we eliminate those first
1647 if (mat.getScaleX() < 0 || mat.getScaleY() < 0) {
1648 return false;
1649 }
1650
1651 SkRect dst;
1652 SkIRect isrc = SkIRect::MakeSize(size);
1653
1654 {
1655 SkRect src;
1656 src.set(isrc);
1657 mat.mapRect(&dst, src);
1658 }
1659
1660 // just apply the translate to isrc
1663
1664 if (subpixelBits) {
1665 isrc.fLeft = SkLeftShift(isrc.fLeft, subpixelBits);
1666 isrc.fTop = SkLeftShift(isrc.fTop, subpixelBits);
1667 isrc.fRight = SkLeftShift(isrc.fRight, subpixelBits);
1668 isrc.fBottom = SkLeftShift(isrc.fBottom, subpixelBits);
1669
1670 const float scale = 1 << subpixelBits;
1671 dst.fLeft *= scale;
1672 dst.fTop *= scale;
1673 dst.fRight *= scale;
1674 dst.fBottom *= scale;
1675 }
1676
1677 SkIRect idst;
1678 dst.round(&idst);
1679 return isrc == idst;
1680}
static constexpr int32_t SkLeftShift(int32_t value, int32_t shift)
Definition SkMath.h:37
#define SkScalarRoundToInt(x)
Definition SkScalar.h:37
SkScalar getTranslateY() const
Definition SkMatrix.h:452
SkScalar getScaleX() const
Definition SkMatrix.h:415
SkScalar getScaleY() const
Definition SkMatrix.h:422
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
SkScalar getTranslateX() const
Definition SkMatrix.h:445
@ kTranslate_Mask
translation SkMatrix
Definition SkMatrix.h:193
@ kScale_Mask
scale SkMatrix
Definition SkMatrix.h:194
TypeMask getType() const
Definition SkMatrix.h:207
static bool NoChangeWithIdentityMatrix(const SkSamplingOptions &sampling)
SkSamplingOptions sampling
Definition SkRecords.h:337
dst
Definition cp.py:12
int32_t fBottom
larger y-axis bounds
Definition SkRect.h:36
int32_t fTop
smaller y-axis bounds
Definition SkRect.h:34
static constexpr SkIRect MakeSize(const SkISize &size)
Definition SkRect.h:66
void offset(int32_t dx, int32_t dy)
Definition SkRect.h:367
int32_t fLeft
smaller x-axis bounds
Definition SkRect.h:33
int32_t fRight
larger x-axis bounds
Definition SkRect.h:35
const SkFilterMode filter