Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkMatrixPriv.h
Go to the documentation of this file.
1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkMatrixPriv_DEFINE
9#define SkMatrixPriv_DEFINE
10
11#include "include/core/SkM44.h"
14#include "include/core/SkRect.h"
17#include "src/base/SkVx.h"
18
19#include <cstdint>
20#include <cstring>
21struct SkPoint3;
22
24public:
25 enum {
26 // writeTo/readFromMemory will never return a value larger than this
27 kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t),
28 };
29
30 static size_t WriteToMemory(const SkMatrix& matrix, void* buffer) {
31 return matrix.writeToMemory(buffer);
32 }
33
34 static size_t ReadFromMemory(SkMatrix* matrix, const void* buffer, size_t length) {
35 return matrix->readFromMemory(buffer, length);
36 }
37
38 typedef SkMatrix::MapXYProc MapXYProc;
39 typedef SkMatrix::MapPtsProc MapPtsProc;
40
41
42 static MapPtsProc GetMapPtsProc(const SkMatrix& matrix) {
43 return SkMatrix::GetMapPtsProc(matrix.getType());
44 }
45
46 static MapXYProc GetMapXYProc(const SkMatrix& matrix) {
47 return SkMatrix::GetMapXYProc(matrix.getType());
48 }
49
50 /**
51 * Attempt to map the rect through the inverse of the matrix. If it is not invertible,
52 * then this returns false and dst is unchanged.
53 */
54 [[nodiscard]] static bool InverseMapRect(const SkMatrix& mx, SkRect* dst, const SkRect& src) {
55 if (mx.isScaleTranslate()) {
56 // A scale-translate matrix with a 0 scale factor is not invertible.
57 if (mx.getScaleX() == 0.f || mx.getScaleY() == 0.f) {
58 return false;
59 }
60
61 const SkScalar tx = mx.getTranslateX();
62 const SkScalar ty = mx.getTranslateY();
63 // mx maps coordinates as ((sx*x + tx), (sy*y + ty)) so the inverse is
64 // ((x - tx)/sx), (y - ty)/sy). If sx or sy are negative, we have to swap the edge
65 // values to maintain a sorted rect.
66 auto inverted = skvx::float4::Load(&src.fLeft);
67 inverted -= skvx::float4(tx, ty, tx, ty);
68
70 const SkScalar sx = 1.f / mx.getScaleX();
71 const SkScalar sy = 1.f / mx.getScaleY();
72 inverted *= skvx::float4(sx, sy, sx, sy);
73 if (sx < 0.f && sy < 0.f) {
74 inverted = skvx::shuffle<2, 3, 0, 1>(inverted); // swap L|R and T|B
75 } else if (sx < 0.f) {
76 inverted = skvx::shuffle<2, 1, 0, 3>(inverted); // swap L|R
77 } else if (sy < 0.f) {
78 inverted = skvx::shuffle<0, 3, 2, 1>(inverted); // swap T|B
79 }
80 }
81 inverted.store(&dst->fLeft);
82 return true;
83 }
84
85 // general case
86 SkMatrix inverse;
87 if (mx.invert(&inverse)) {
88 inverse.mapRect(dst, src);
89 return true;
90 }
91 return false;
92 }
93
94 /** Maps count pts, skipping stride bytes to advance from one SkPoint to the next.
95 Points are mapped by multiplying each SkPoint by SkMatrix. Given:
96
97 | A B C | | x |
98 Matrix = | D E F |, pt = | y |
99 | G H I | | 1 |
100
101 each resulting pts SkPoint is computed as:
102
103 |A B C| |x| Ax+By+C Dx+Ey+F
104 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
105 |G H I| |1| Gx+Hy+I Gx+Hy+I
106
107 @param mx matrix used to map the points
108 @param pts storage for mapped points
109 @param stride size of record starting with SkPoint, in bytes
110 @param count number of points to transform
111 */
112 static void MapPointsWithStride(const SkMatrix& mx, SkPoint pts[], size_t stride, int count) {
113 SkASSERT(stride >= sizeof(SkPoint));
114 SkASSERT(0 == stride % sizeof(SkScalar));
115
116 SkMatrix::TypeMask tm = mx.getType();
117
118 if (SkMatrix::kIdentity_Mask == tm) {
119 return;
120 }
121 if (SkMatrix::kTranslate_Mask == tm) {
122 const SkScalar tx = mx.getTranslateX();
123 const SkScalar ty = mx.getTranslateY();
124 skvx::float2 trans(tx, ty);
125 for (int i = 0; i < count; ++i) {
126 (skvx::float2::Load(&pts->fX) + trans).store(&pts->fX);
127 pts = (SkPoint*)((intptr_t)pts + stride);
128 }
129 return;
130 }
131 // Insert other special-cases here (e.g. scale+translate)
132
133 // general case
134 SkMatrix::MapXYProc proc = mx.getMapXYProc();
135 for (int i = 0; i < count; ++i) {
136 proc(mx, pts->fX, pts->fY, pts);
137 pts = (SkPoint*)((intptr_t)pts + stride);
138 }
139 }
140
141 /** Maps src SkPoint array of length count to dst SkPoint array, skipping stride bytes
142 to advance from one SkPoint to the next.
143 Points are mapped by multiplying each SkPoint by SkMatrix. Given:
144
145 | A B C | | x |
146 Matrix = | D E F |, src = | y |
147 | G H I | | 1 |
148
149 each resulting dst SkPoint is computed as:
150
151 |A B C| |x| Ax+By+C Dx+Ey+F
152 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
153 |G H I| |1| Gx+Hy+I Gx+Hy+I
154
155 @param mx matrix used to map the points
156 @param dst storage for mapped points
157 @param src points to transform
158 @param stride size of record starting with SkPoint, in bytes
159 @param count number of points to transform
160 */
161 static void MapPointsWithStride(const SkMatrix& mx, SkPoint dst[], size_t dstStride,
162 const SkPoint src[], size_t srcStride, int count) {
163 SkASSERT(srcStride >= sizeof(SkPoint));
164 SkASSERT(dstStride >= sizeof(SkPoint));
165 SkASSERT(0 == srcStride % sizeof(SkScalar));
166 SkASSERT(0 == dstStride % sizeof(SkScalar));
167 for (int i = 0; i < count; ++i) {
168 mx.mapPoints(dst, src, 1);
169 src = (SkPoint*)((intptr_t)src + srcStride);
170 dst = (SkPoint*)((intptr_t)dst + dstStride);
171 }
172 }
173
174 static void MapHomogeneousPointsWithStride(const SkMatrix& mx, SkPoint3 dst[], size_t dstStride,
175 const SkPoint3 src[], size_t srcStride, int count);
176
177 static bool PostIDiv(SkMatrix* matrix, int divx, int divy) {
178 return matrix->postIDiv(divx, divy);
179 }
180
181 static bool CheapEqual(const SkMatrix& a, const SkMatrix& b) {
182 return &a == &b || 0 == memcmp(a.fMat, b.fMat, sizeof(a.fMat));
183 }
184
185 static const SkScalar* M44ColMajor(const SkM44& m) { return m.fMat; }
186
187 // This is legacy functionality that only checks the 3x3 portion. The matrix could have Z-based
188 // shear, or other complex behavior. Only use this if you're planning to use the information
189 // to accelerate some purely 2D operation.
190 static bool IsScaleTranslateAsM33(const SkM44& m) {
191 return m.rc(1,0) == 0 && m.rc(3,0) == 0 &&
192 m.rc(0,1) == 0 && m.rc(3,1) == 0 &&
193 m.rc(3,3) == 1;
194
195 }
196
197 // Map the four corners of 'r' and return the bounding box of those points. The four corners of
198 // 'r' are assumed to have z = 0 and w = 1. If the matrix has perspective, the returned
199 // rectangle will be the bounding box of the projected points after being clipped to w > 0.
200 static SkRect MapRect(const SkM44& m, const SkRect& r);
201
202 // Returns the differential area scale factor for a local point 'p' that will be transformed
203 // by 'm' (which may have perspective). If 'm' does not have perspective, this scale factor is
204 // constant regardless of 'p'; when it does have perspective, it is specific to that point.
205 //
206 // This can be crudely thought of as "device pixel area" / "local pixel area" at 'p'.
207 //
208 // Returns positive infinity if the transformed homogeneous point has w <= 0.
209 static SkScalar DifferentialAreaScale(const SkMatrix& m, const SkPoint& p);
210
211 // Determines if the transformation m applied to the bounds can be approximated by
212 // an affine transformation, i.e., the perspective part of the transformation has little
213 // visible effect.
214 static bool NearlyAffine(const SkMatrix& m,
215 const SkRect& bounds,
216 SkScalar tolerance = SK_ScalarNearlyZero);
217
218 static SkScalar ComputeResScaleForStroking(const SkMatrix& matrix);
219};
220
221#endif
int count
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SK_ScalarNearlyZero
Definition SkScalar.h:99
SI void store(P *ptr, const T &val)
Definition SkM44.h:150
static MapXYProc GetMapXYProc(const SkMatrix &matrix)
static MapPtsProc GetMapPtsProc(const SkMatrix &matrix)
static size_t WriteToMemory(const SkMatrix &matrix, void *buffer)
SkMatrix::MapXYProc MapXYProc
SkMatrix::MapPtsProc MapPtsProc
static SkRect MapRect(const SkM44 &m, const SkRect &r)
Definition SkM44.cpp:216
static bool CheapEqual(const SkMatrix &a, const SkMatrix &b)
static SkScalar DifferentialAreaScale(const SkMatrix &m, const SkPoint &p)
static const SkScalar * M44ColMajor(const SkM44 &m)
static void MapHomogeneousPointsWithStride(const SkMatrix &mx, SkPoint3 dst[], size_t dstStride, const SkPoint3 src[], size_t srcStride, int count)
static size_t ReadFromMemory(SkMatrix *matrix, const void *buffer, size_t length)
static bool IsScaleTranslateAsM33(const SkM44 &m)
static bool PostIDiv(SkMatrix *matrix, int divx, int divy)
static void MapPointsWithStride(const SkMatrix &mx, SkPoint pts[], size_t stride, int count)
static bool NearlyAffine(const SkMatrix &m, const SkRect &bounds, SkScalar tolerance=SK_ScalarNearlyZero)
static void MapPointsWithStride(const SkMatrix &mx, SkPoint dst[], size_t dstStride, const SkPoint src[], size_t srcStride, int count)
static bool InverseMapRect(const SkMatrix &mx, SkRect *dst, const SkRect &src)
static SkScalar ComputeResScaleForStroking(const SkMatrix &matrix)
SkScalar getTranslateY() const
Definition SkMatrix.h:452
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition SkMatrix.cpp:770
bool invert(SkMatrix *inverse) const
Definition SkMatrix.h:1206
SkScalar getScaleX() const
Definition SkMatrix.h:415
SkScalar getScaleY() const
Definition SkMatrix.h:422
bool isScaleTranslate() const
Definition SkMatrix.h:236
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
@ kIdentity_Mask
identity SkMatrix; all bits clear
Definition SkMatrix.h:192
TypeMask getType() const
Definition SkMatrix.h:207
float SkScalar
Definition extension.cpp:12
static bool b
struct MyStruct a[10]
static const uint8_t buffer[]
size_t length
Vec< 4, float > float4
Definition SkVx.h:1146
float fX
x-axis value
float fY
y-axis value
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
Definition SkVx.h:109