| /* | |
| * Copyright 2021 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef skgpu_graphite_geom_Transform_DEFINED | |
| #define skgpu_graphite_geom_Transform_DEFINED | |
| #include "include/core/SkM44.h" | |
| #include <algorithm> | |
| namespace skgpu::graphite { | |
| class Rect; | |
| // Transform encapsulates an SkM44 matrix, its inverse, and other properties dependent on the | |
| // original matrix value that are useful when rendering. | |
| class Transform { | |
| public: | |
| // Type classifies the transform into coarse categories so that certain optimizations or | |
| // properties can be queried efficiently | |
| enum class Type : unsigned { | |
| // Applying the matrix to a vector or point is a no-op, so could be skipped entirely. | |
| kIdentity, | |
| // The matrix transforms a rect to another rect, without mirrors or rotations, so both | |
| // pre-and-post transform coordinates can be exactly represented as rects. | |
| kSimpleRectStaysRect, | |
| // The matrix transforms a rect to another rect, but may mirror or rotate the corners | |
| // relative to each other. This means that the post-transformed rect completely fills | |
| // that space. | |
| kRectStaysRect, | |
| // The matrix transform may have skew or rotation, so a mapped rect does not fill space, | |
| // but there is no need to perform perspective division or w-plane clipping. | |
| kAffine, | |
| // The matrix includes perspective or modifies Z and requires further projection to 2D, | |
| // so care must be taken when w is less than or near 0, and homogeneous division and | |
| // perspective-correct interpolation are needed when rendering. | |
| kProjection, | |
| // The matrix is not invertible or not finite, so should not be used to draw. | |
| kInvalid, | |
| }; | |
| explicit Transform(const SkM44& m); | |
| Transform(const Transform& t) = default; | |
| static const Transform& Identity(); | |
| static const Transform& Invalid(); | |
| Transform& operator=(const Transform& t) = default; | |
| operator const SkM44&() const { return fM; } | |
| operator SkMatrix() const { return fM.asM33(); } | |
| bool operator==(const Transform& t) const; | |
| bool operator!=(const Transform& t) const { return !(*this == t); } | |
| const SkM44& matrix() const { return fM; } | |
| const SkM44& inverse() const { return fInvM; } | |
| const SkV2& scaleFactors() const { return fScale; } | |
| float maxScaleFactor() const { return std::max(fScale.x, fScale.y); } | |
| Type type() const { return fType; } | |
| bool valid() const { return fType != Type::kInvalid; } | |
| Rect mapRect(const Rect& rect) const; | |
| Rect inverseMapRect(const Rect& rect) const; | |
| void mapPoints(const Rect& localRect, SkV4 deviceOut[4]) const; | |
| void mapPoints(const SkV2* localIn, SkV4* deviceOut, int count) const; | |
| void mapPoints(const SkV4* localIn, SkV4* deviceOut, int count) const; | |
| void inverseMapPoints(const SkV4* deviceIn, SkV4* localOut, int count) const; | |
| // Returns a transform equal to the pre- or post-translating this matrix | |
| Transform preTranslate(float x, float y) const; | |
| Transform postTranslate(float x, float y) const; | |
| // Returns a transform equal to (this * t) | |
| Transform concat(const Transform& t) const; | |
| Transform concat(const SkM44& t) const { return Transform(fM * t); } | |
| // Returns a transform equal to (this * t^-1) | |
| Transform concatInverse(const Transform& t) const; | |
| Transform concatInverse(const SkM44& t) const; | |
| private: | |
| Transform(const SkM44& m, const SkM44& invM, Type type, const SkV2 scale) | |
| : fM(m), fInvM(invM), fType(type), fScale(scale) {} | |
| SkM44 fM; | |
| SkM44 fInvM; // M^-1 | |
| Type fType; | |
| // TODO: It would be nice to have a scale factor for perspective too, and there is | |
| // SkMatrixPriv::DifferentialAreaScale but that requires a specific location. | |
| SkV2 fScale; // always > 0 | |
| }; | |
| } // namespace skgpu::graphite | |
| #endif // skgpu_graphite_geom_Transform_DEFINED |