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