• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/SkFilterQuality.h"
12 #include "include/core/SkMatrix.h"
13 #include "include/core/SkM44.h"
14 #include "include/private/SkNx.h"
15 #include "src/core/SkPointPriv.h"
16 
17 class SkMatrixPriv {
18 public:
19     enum {
20         // writeTo/readFromMemory will never return a value larger than this
21         kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t),
22     };
23 
WriteToMemory(const SkMatrix & matrix,void * buffer)24     static size_t WriteToMemory(const SkMatrix& matrix, void* buffer) {
25         return matrix.writeToMemory(buffer);
26     }
27 
ReadFromMemory(SkMatrix * matrix,const void * buffer,size_t length)28     static size_t ReadFromMemory(SkMatrix* matrix, const void* buffer, size_t length) {
29         return matrix->readFromMemory(buffer, length);
30     }
31 
32     typedef SkMatrix::MapXYProc MapXYProc;
33     typedef SkMatrix::MapPtsProc MapPtsProc;
34 
35 
GetMapPtsProc(const SkMatrix & matrix)36     static MapPtsProc GetMapPtsProc(const SkMatrix& matrix) {
37         return SkMatrix::GetMapPtsProc(matrix.getType());
38     }
39 
GetMapXYProc(const SkMatrix & matrix)40     static MapXYProc GetMapXYProc(const SkMatrix& matrix) {
41         return SkMatrix::GetMapXYProc(matrix.getType());
42     }
43 
44     /**
45      *  Attempt to map the rect through the inverse of the matrix. If it is not invertible,
46      *  then this returns false and dst is unchanged.
47      */
InverseMapRect(const SkMatrix & mx,SkRect * dst,const SkRect & src)48     static bool SK_WARN_UNUSED_RESULT InverseMapRect(const SkMatrix& mx,
49                                                      SkRect* dst, const SkRect& src) {
50         if (mx.getType() <= SkMatrix::kTranslate_Mask) {
51             SkScalar tx = mx.getTranslateX();
52             SkScalar ty = mx.getTranslateY();
53             Sk4f trans(tx, ty, tx, ty);
54             (Sk4f::Load(&src.fLeft) - trans).store(&dst->fLeft);
55             return true;
56         }
57         // Insert other special-cases here (e.g. scale+translate)
58 
59         // general case
60         SkMatrix inverse;
61         if (mx.invert(&inverse)) {
62             inverse.mapRect(dst, src);
63             return true;
64         }
65         return false;
66     }
67 
68     /** Maps count pts, skipping stride bytes to advance from one SkPoint to the next.
69         Points are mapped by multiplying each SkPoint by SkMatrix. Given:
70 
71                      | A B C |        | x |
72             Matrix = | D E F |,  pt = | y |
73                      | G H I |        | 1 |
74 
75         each resulting pts SkPoint is computed as:
76 
77                           |A B C| |x|                               Ax+By+C   Dx+Ey+F
78             Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
79                           |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
80 
81         @param mx      matrix used to map the points
82         @param pts     storage for mapped points
83         @param stride  size of record starting with SkPoint, in bytes
84         @param count   number of points to transform
85     */
MapPointsWithStride(const SkMatrix & mx,SkPoint pts[],size_t stride,int count)86     static void MapPointsWithStride(const SkMatrix& mx, SkPoint pts[], size_t stride, int count) {
87         SkASSERT(stride >= sizeof(SkPoint));
88         SkASSERT(0 == stride % sizeof(SkScalar));
89 
90         SkMatrix::TypeMask tm = mx.getType();
91 
92         if (SkMatrix::kIdentity_Mask == tm) {
93             return;
94         }
95         if (SkMatrix::kTranslate_Mask == tm) {
96             const SkScalar tx = mx.getTranslateX();
97             const SkScalar ty = mx.getTranslateY();
98             Sk2s trans(tx, ty);
99             for (int i = 0; i < count; ++i) {
100                 (Sk2s::Load(&pts->fX) + trans).store(&pts->fX);
101                 pts = (SkPoint*)((intptr_t)pts + stride);
102             }
103             return;
104         }
105         // Insert other special-cases here (e.g. scale+translate)
106 
107         // general case
108         SkMatrix::MapXYProc proc = mx.getMapXYProc();
109         for (int i = 0; i < count; ++i) {
110             proc(mx, pts->fX, pts->fY, pts);
111             pts = (SkPoint*)((intptr_t)pts + stride);
112         }
113     }
114 
115     /** Maps src SkPoint array of length count to dst SkPoint array, skipping stride bytes
116         to advance from one SkPoint to the next.
117         Points are mapped by multiplying each SkPoint by SkMatrix. Given:
118 
119                      | A B C |         | x |
120             Matrix = | D E F |,  src = | y |
121                      | G H I |         | 1 |
122 
123         each resulting dst SkPoint is computed as:
124 
125                           |A B C| |x|                               Ax+By+C   Dx+Ey+F
126             Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
127                           |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
128 
129         @param mx      matrix used to map the points
130         @param dst     storage for mapped points
131         @param src     points to transform
132         @param stride  size of record starting with SkPoint, in bytes
133         @param count   number of points to transform
134     */
MapPointsWithStride(const SkMatrix & mx,SkPoint dst[],size_t dstStride,const SkPoint src[],size_t srcStride,int count)135     static void MapPointsWithStride(const SkMatrix& mx, SkPoint dst[], size_t dstStride,
136                                     const SkPoint src[], size_t srcStride, int count) {
137         SkASSERT(srcStride >= sizeof(SkPoint));
138         SkASSERT(dstStride >= sizeof(SkPoint));
139         SkASSERT(0 == srcStride % sizeof(SkScalar));
140         SkASSERT(0 == dstStride % sizeof(SkScalar));
141         for (int i = 0; i < count; ++i) {
142             mx.mapPoints(dst, src, 1);
143             src = (SkPoint*)((intptr_t)src + srcStride);
144             dst = (SkPoint*)((intptr_t)dst + dstStride);
145         }
146     }
147 
148     static void MapHomogeneousPointsWithStride(const SkMatrix& mx, SkPoint3 dst[], size_t dstStride,
149                                                const SkPoint3 src[], size_t srcStride, int count);
150 
151     // Returns the recommended filterquality, assuming the caller originally wanted kHigh (bicubic)
152     static SkFilterQuality AdjustHighQualityFilterLevel(const SkMatrix&,
153                                                         bool matrixIsInverse = false);
154 
PostIDiv(SkMatrix * matrix,int divx,int divy)155     static bool PostIDiv(SkMatrix* matrix, int divx, int divy) {
156         return matrix->postIDiv(divx, divy);
157     }
158 
CheapEqual(const SkMatrix & a,const SkMatrix & b)159     static bool CheapEqual(const SkMatrix& a, const SkMatrix& b) {
160         return &a == &b || 0 == memcmp(a.fMat, b.fMat, sizeof(a.fMat));
161     }
162 
M44ColMajor(const SkM44 & m)163     static const SkScalar* M44ColMajor(const SkM44& m) { return m.fMat; }
164 };
165 
166 #endif
167