Flutter Engine
The Flutter Engine
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
43 return SkMatrix::GetMapPtsProc(matrix.getType());
44 }
45
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
219};
220
221#endif
int count
Definition: FontMgrTest.cpp:50
#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)
Definition: SkMatrixPriv.h:46
static MapPtsProc GetMapPtsProc(const SkMatrix &matrix)
Definition: SkMatrixPriv.h:42
static size_t WriteToMemory(const SkMatrix &matrix, void *buffer)
Definition: SkMatrixPriv.h:30
SkMatrix::MapXYProc MapXYProc
Definition: SkMatrixPriv.h:38
SkMatrix::MapPtsProc MapPtsProc
Definition: SkMatrixPriv.h:39
static SkRect MapRect(const SkM44 &m, const SkRect &r)
Definition: SkM44.cpp:216
static bool CheapEqual(const SkMatrix &a, const SkMatrix &b)
Definition: SkMatrixPriv.h:181
static SkScalar DifferentialAreaScale(const SkMatrix &m, const SkPoint &p)
Definition: SkMatrix.cpp:1786
static const SkScalar * M44ColMajor(const SkM44 &m)
Definition: SkMatrixPriv.h:185
static void MapHomogeneousPointsWithStride(const SkMatrix &mx, SkPoint3 dst[], size_t dstStride, const SkPoint3 src[], size_t srcStride, int count)
Definition: SkMatrix.cpp:1026
static size_t ReadFromMemory(SkMatrix *matrix, const void *buffer, size_t length)
Definition: SkMatrixPriv.h:34
static bool IsScaleTranslateAsM33(const SkM44 &m)
Definition: SkMatrixPriv.h:190
static bool PostIDiv(SkMatrix *matrix, int divx, int divy)
Definition: SkMatrixPriv.h:177
static void MapPointsWithStride(const SkMatrix &mx, SkPoint pts[], size_t stride, int count)
Definition: SkMatrixPriv.h:112
static bool NearlyAffine(const SkMatrix &m, const SkRect &bounds, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkMatrix.cpp:1820
static void MapPointsWithStride(const SkMatrix &mx, SkPoint dst[], size_t dstStride, const SkPoint src[], size_t srcStride, int count)
Definition: SkMatrixPriv.h:161
static bool InverseMapRect(const SkMatrix &mx, SkRect *dst, const SkRect &src)
Definition: SkMatrixPriv.h:54
static SkScalar ComputeResScaleForStroking(const SkMatrix &matrix)
Definition: SkMatrix.cpp:1877
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
Definition: SkMatrix.cpp:1141
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]
size_t length
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
Optional< SkRect > bounds
Definition: SkRecords.h:189
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
dst
Definition: cp.py:12
Vec< 4, float > float4
Definition: SkVx.h:1146
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165
Definition: SkVx.h:83
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
Definition: SkVx.h:109