• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2010 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 
11 #include "GrMatrix.h"
12 #include "GrRect.h"
13 #include <stddef.h>
14 
15 #if 0
16 #if GR_SCALAR_IS_FLOAT
17     const GrScalar GrMatrix::gRESCALE(GR_Scalar1);
18 #else
19     GR_STATIC_ASSERT(GR_SCALAR_IS_FIXED);
20     // fixed point isn't supported right now
21     GR_STATIC_ASSERT(false);
22 const GrScalar GrMatrix::gRESCALE(1 << 30);
23 #endif
24 
25 const GrMatrix::MapProc GrMatrix::gMapProcs[] = {
26 // Scales are not both zero
27     &GrMatrix::mapIdentity,
28     &GrMatrix::mapScale,
29     &GrMatrix::mapTranslate,
30     &GrMatrix::mapScaleAndTranslate,
31     &GrMatrix::mapSkew,
32     &GrMatrix::mapScaleAndSkew,
33     &GrMatrix::mapSkewAndTranslate,
34     &GrMatrix::mapNonPerspective,
35     // no optimizations for perspective matrices
36     &GrMatrix::mapPerspective,
37     &GrMatrix::mapPerspective,
38     &GrMatrix::mapPerspective,
39     &GrMatrix::mapPerspective,
40     &GrMatrix::mapPerspective,
41     &GrMatrix::mapPerspective,
42     &GrMatrix::mapPerspective,
43     &GrMatrix::mapPerspective,
44 
45 // Scales are zero (every other is invalid because kScale_TypeBit must be set if
46 // kZeroScale_TypeBit is set)
47     &GrMatrix::mapInvalid,
48     &GrMatrix::mapZero,
49     &GrMatrix::mapInvalid,
50     &GrMatrix::mapSetToTranslate,
51     &GrMatrix::mapInvalid,
52     &GrMatrix::mapSwappedScale,
53     &GrMatrix::mapInvalid,
54     &GrMatrix::mapSwappedScaleAndTranslate,
55 
56     // no optimizations for perspective matrices
57     &GrMatrix::mapInvalid,
58     &GrMatrix::mapZero,
59     &GrMatrix::mapInvalid,
60     &GrMatrix::mapPerspective,
61     &GrMatrix::mapInvalid,
62     &GrMatrix::mapPerspective,
63     &GrMatrix::mapInvalid,
64     &GrMatrix::mapPerspective,
65 };
66 
67 void GrMatrix::setIdentity() {
68     fM[0] = GR_Scalar1; fM[1] = 0;          fM[2] = 0;
69     fM[3] = 0;          fM[4] = GR_Scalar1; fM[5] = 0;
70     fM[6] = 0;          fM[7] = 0;          fM[8] = gRESCALE;
71     fTypeMask = 0;
72 }
73 
74 void GrMatrix::setTranslate(GrScalar dx, GrScalar dy) {
75     fM[0] = GR_Scalar1; fM[1] = 0;          fM[2] = dx;
76     fM[3] = 0;          fM[4] = GR_Scalar1; fM[5] = dy;
77     fM[6] = 0;          fM[7] = 0;          fM[8] = gRESCALE;
78     fTypeMask = (0 != dx || 0 != dy) ? kTranslate_TypeBit : 0;
79 }
80 
81 void GrMatrix::setScale(GrScalar sx, GrScalar sy) {
82     fM[0] = sx; fM[1] = 0;  fM[2] = 0;
83     fM[3] = 0;  fM[4] = sy; fM[5] = 0;
84     fM[6] = 0;  fM[7] = 0;  fM[8] = gRESCALE;
85     fTypeMask = (GR_Scalar1 != sx || GR_Scalar1 != sy) ? kScale_TypeBit : 0;
86 }
87 
88 void GrMatrix::setSkew(GrScalar skx, GrScalar sky) {
89     fM[0] = GR_Scalar1; fM[1] = skx;        fM[2] = 0;
90     fM[3] = sky;        fM[4] = GR_Scalar1; fM[5] = 0;
91     fM[6] = 0;          fM[7] = 0;          fM[8] = gRESCALE;
92     fTypeMask = (0 != skx || 0 != sky) ? kSkew_TypeBit : 0;
93 }
94 
95 void GrMatrix::setConcat(const GrMatrix& a, const GrMatrix& b) {
96     if (a.isIdentity()) {
97         if (this != &b) {
98             for (int i = 0; i < 9; ++i) {
99                 fM[i] = b.fM[i];
100             }
101             fTypeMask = b.fTypeMask;
102         }
103         return;
104     }
105 
106     if (b.isIdentity()) {
107         GrAssert(!a.isIdentity());
108         if (this != &a) {
109             for (int i = 0; i < 9; ++i) {
110                     fM[i] = a.fM[i];
111             }
112             fTypeMask = a.fTypeMask;
113         }
114         return;
115     }
116 
117     // a and/or b could be this
118     GrMatrix tmp;
119 
120     // could do more optimizations based on type bits. Hopefully this call is
121     // low frequency.
122     // TODO: make this work for fixed point
123     if (!((b.fTypeMask | a.fTypeMask) & kPerspective_TypeBit)) {
124         tmp.fM[0] = a.fM[0] * b.fM[0] + a.fM[1] * b.fM[3];
125         tmp.fM[1] = a.fM[0] * b.fM[1] + a.fM[1] * b.fM[4];
126         tmp.fM[2] = a.fM[0] * b.fM[2] + a.fM[1] * b.fM[5] + a.fM[2] * gRESCALE;
127 
128         tmp.fM[3] = a.fM[3] * b.fM[0] + a.fM[4] * b.fM[3];
129         tmp.fM[4] = a.fM[3] * b.fM[1] + a.fM[4] * b.fM[4];
130         tmp.fM[5] = a.fM[3] * b.fM[2] + a.fM[4] * b.fM[5] + a.fM[5] * gRESCALE;
131 
132         tmp.fM[6] = 0;
133         tmp.fM[7] = 0;
134         tmp.fM[8] = gRESCALE * gRESCALE;
135     } else {
136         tmp.fM[0] = a.fM[0] * b.fM[0] + a.fM[1] * b.fM[3] + a.fM[2] * b.fM[6];
137         tmp.fM[1] = a.fM[0] * b.fM[1] + a.fM[1] * b.fM[4] + a.fM[2] * b.fM[7];
138         tmp.fM[2] = a.fM[0] * b.fM[2] + a.fM[1] * b.fM[5] + a.fM[2] * b.fM[8];
139 
140         tmp.fM[3] = a.fM[3] * b.fM[0] + a.fM[4] * b.fM[3] + a.fM[5] * b.fM[6];
141         tmp.fM[4] = a.fM[3] * b.fM[1] + a.fM[4] * b.fM[4] + a.fM[5] * b.fM[7];
142         tmp.fM[5] = a.fM[3] * b.fM[2] + a.fM[4] * b.fM[5] + a.fM[5] * b.fM[8];
143 
144         tmp.fM[6] = a.fM[6] * b.fM[0] + a.fM[7] * b.fM[3] + a.fM[8] * b.fM[6];
145         tmp.fM[7] = a.fM[6] * b.fM[1] + a.fM[7] * b.fM[4] + a.fM[8] * b.fM[7];
146         tmp.fM[8] = a.fM[6] * b.fM[2] + a.fM[7] * b.fM[5] + a.fM[8] * b.fM[8];
147     }
148     *this = tmp;
149     this->computeTypeMask();
150 }
151 
152 void GrMatrix::preConcat(const GrMatrix& m) {
153     setConcat(*this, m);
154 }
155 
156 void GrMatrix::postConcat(const GrMatrix& m) {
157     setConcat(m, *this);
158 }
159 
160 double GrMatrix::determinant() const {
161     if (fTypeMask & kPerspective_TypeBit) {
162         return  fM[0]*((double)fM[4]*fM[8] - (double)fM[5]*fM[7]) +
163                 fM[1]*((double)fM[5]*fM[6] - (double)fM[3]*fM[8]) +
164                 fM[2]*((double)fM[3]*fM[7] - (double)fM[4]*fM[6]);
165     } else {
166         return (double)fM[0]*fM[4]*gRESCALE -
167                (double)fM[1]*fM[3]*gRESCALE;
168     }
169 }
170 
171 bool GrMatrix::invert(GrMatrix* inverted) const {
172 
173     if (isIdentity()) {
174         if (inverted != this) {
175             inverted->setIdentity();
176         }
177         return true;
178     }
179     static const double MIN_DETERMINANT_SQUARED = 1.e-16;
180 
181     // could do more optimizations based on type bits. Hopefully this call is
182     // low frequency.
183 
184     double det = determinant();
185 
186     // check if we can't be inverted
187     if (det*det <= MIN_DETERMINANT_SQUARED) {
188         return false;
189     } else if (NULL == inverted) {
190         return true;
191     }
192 
193     double t[9];
194 
195     if (fTypeMask & kPerspective_TypeBit) {
196         t[0] = ((double)fM[4]*fM[8] - (double)fM[5]*fM[7]);
197         t[1] = ((double)fM[2]*fM[7] - (double)fM[1]*fM[8]);
198         t[2] = ((double)fM[1]*fM[5] - (double)fM[2]*fM[4]);
199         t[3] = ((double)fM[5]*fM[6] - (double)fM[3]*fM[8]);
200         t[4] = ((double)fM[0]*fM[8] - (double)fM[2]*fM[6]);
201         t[5] = ((double)fM[2]*fM[3] - (double)fM[0]*fM[5]);
202         t[6] = ((double)fM[3]*fM[7] - (double)fM[4]*fM[6]);
203         t[7] = ((double)fM[1]*fM[6] - (double)fM[0]*fM[7]);
204         t[8] = ((double)fM[0]*fM[4] - (double)fM[1]*fM[3]);
205         det = 1.0 / det;
206         for (int i = 0; i < 9; ++i) {
207             inverted->fM[i] = (GrScalar)(t[i] * det);
208         }
209     } else {
210         t[0] =  (double)fM[4]*gRESCALE;
211         t[1] = -(double)fM[1]*gRESCALE;
212         t[2] =  (double)fM[1]*fM[5] - (double)fM[2]*fM[4];
213         t[3] = -(double)fM[3]*gRESCALE;
214         t[4] =  (double)fM[0]*gRESCALE;
215         t[5] =  (double)fM[2]*fM[3] - (double)fM[0]*fM[5];
216         //t[6] = 0.0;
217         //t[7] = 0.0;
218         t[8] = (double)fM[0]*fM[4] - (double)fM[1]*fM[3];
219         det = 1.0 / det;
220         for (int i = 0; i < 6; ++i) {
221             inverted->fM[i] = (GrScalar)(t[i] * det);
222         }
223         inverted->fM[6] = 0;
224         inverted->fM[7] = 0;
225         inverted->fM[8] = (GrScalar)(t[8] * det);
226     }
227     inverted->computeTypeMask();
228     return true;
229 }
230 
231 void GrMatrix::mapRect(GrRect* dst, const GrRect& src) const {
232     GrPoint srcPts[4], dstPts[4];
233     srcPts[0].set(src.fLeft, src.fTop);
234     srcPts[1].set(src.fRight, src.fTop);
235     srcPts[2].set(src.fRight, src.fBottom);
236     srcPts[3].set(src.fLeft, src.fBottom);
237     this->mapPoints(dstPts, srcPts, 4);
238     dst->setBounds(dstPts, 4);
239 }
240 
241 bool GrMatrix::hasPerspective() const {
242     GrAssert(!!(kPerspective_TypeBit & fTypeMask) ==
243              (fM[kPersp0] != 0 || fM[kPersp1] != 0 || fM[kPersp2] != gRESCALE));
244     return 0 != (kPerspective_TypeBit & fTypeMask);
245 }
246 
247 bool GrMatrix::isIdentity() const {
248     GrAssert((0 == fTypeMask) ==
249              (GR_Scalar1 == fM[kScaleX] && 0          == fM[kSkewX]  && 0          == fM[kTransX] &&
250               0          == fM[kSkewY]  && GR_Scalar1 == fM[kScaleY] && 0          == fM[kTransY] &&
251               0          == fM[kPersp0] && 0          == fM[kPersp1] && gRESCALE == fM[kPersp2]));
252     return (0 == fTypeMask);
253 }
254 
255 
256 bool GrMatrix::preservesAxisAlignment() const {
257 
258     // check if matrix is trans and scale only
259     static const int gAllowedMask1 = kScale_TypeBit | kTranslate_TypeBit;
260 
261     if (!(~gAllowedMask1 & fTypeMask)) {
262         return true;
263     }
264 
265     // check matrix is trans and skew only (0 scale)
266     static const int gAllowedMask2 = kScale_TypeBit | kSkew_TypeBit |
267                                      kTranslate_TypeBit | kZeroScale_TypeBit;
268 
269     if (!(~gAllowedMask2 & fTypeMask) && (kZeroScale_TypeBit & fTypeMask)) {
270         return true;
271     }
272 
273     return false;
274 }
275 
276 GrScalar GrMatrix::getMaxStretch() const {
277 
278     if (fTypeMask & kPerspective_TypeBit) {
279         return -GR_Scalar1;
280     }
281 
282     GrScalar stretch;
283 
284     if (isIdentity()) {
285         stretch = GR_Scalar1;
286     } else if (!(fTypeMask & kSkew_TypeBit)) {
287         stretch = GrMax(GrScalarAbs(fM[kScaleX]), GrScalarAbs(fM[kScaleY]));
288     } else if (fTypeMask & kZeroScale_TypeBit) {
289         stretch = GrMax(GrScalarAbs(fM[kSkewX]), GrScalarAbs(fM[kSkewY]));
290     } else {
291         // ignore the translation part of the matrix, just look at 2x2 portion.
292         // compute singular values, take largest abs value.
293         // [a b; b c] = A^T*A
294         GrScalar a = GrMul(fM[kScaleX], fM[kScaleX]) + GrMul(fM[kSkewY],  fM[kSkewY]);
295         GrScalar b = GrMul(fM[kScaleX], fM[kSkewX]) +  GrMul(fM[kScaleY], fM[kSkewY]);
296         GrScalar c = GrMul(fM[kSkewX],  fM[kSkewX]) +  GrMul(fM[kScaleY], fM[kScaleY]);
297         // eigenvalues of A^T*A are the squared singular values of A.
298         // characteristic equation is det((A^T*A) - l*I) = 0
299         // l^2 - (a + c)l + (ac-b^2)
300         // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
301         // and roots are guaraunteed to be pos and real).
302         GrScalar largerRoot;
303         GrScalar bSqd = GrMul(b,b);
304         // TODO: fixed point tolerance value.
305         if (bSqd < 1e-10) { // will be true if upper left 2x2 is orthogonal, which is common, so save some math
306             largerRoot = GrMax(a, c);
307         } else {
308             GrScalar aminusc = a - c;
309             GrScalar apluscdiv2 = (a + c) / 2;
310             GrScalar x = sqrtf(GrMul(aminusc,aminusc) + GrMul(4,(bSqd))) / 2;
311             largerRoot = apluscdiv2 + x;
312         }
313 
314         stretch = sqrtf(largerRoot);
315     }
316 #if GR_DEBUG && 0
317     // test a bunch of vectors. None should be scaled by more than stretch
318     // (modulo some error) and we should find a vector that is scaled by almost
319     // stretch.
320     GrPoint pt;
321     GrScalar max = 0;
322     for (int i = 0; i < 1000; ++i) {
323         GrScalar x = (float)rand() / RAND_MAX;
324         GrScalar y = sqrtf(1 - (x*x));
325         pt.fX = fM[kScaleX]*x + fM[kSkewX]*y;
326         pt.fY = fM[kSkewY]*x + fM[kScaleY]*y;
327         GrScalar d = pt.distanceToOrigin();
328         GrAssert(d <= (1.0001 * stretch));
329         max = GrMax(max, pt.distanceToOrigin());
330     }
331     GrAssert((stretch - max) < .05*stretch);
332 #endif
333     return stretch;
334 }
335 
336 bool GrMatrix::operator == (const GrMatrix& m) const {
337     if (fTypeMask != m.fTypeMask) {
338         return false;
339     }
340     if (!fTypeMask) {
341         return true;
342     }
343     for (int i = 0; i < 9; ++i) {
344         if (m.fM[i] != fM[i]) {
345             return false;
346         }
347     }
348     return true;
349 }
350 
351 bool GrMatrix::operator != (const GrMatrix& m) const {
352     return !(*this == m);
353 }
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 // Matrix transformation procs
357 //////
358 
359 void GrMatrix::mapIdentity(GrPoint* dst, const GrPoint* src, uint32_t count) const {
360     if (src != dst) {
361         for (uint32_t i = 0; i < count; ++i) {
362             dst[i] = src[i];
363         }
364     }
365 }
366 
367 void GrMatrix::mapScale(GrPoint* dst, const GrPoint* src, uint32_t count) const {
368     for (uint32_t i = 0; i < count; ++i) {
369         dst[i].fX = GrMul(src[i].fX, fM[kScaleX]);
370         dst[i].fY = GrMul(src[i].fY, fM[kScaleY]);
371     }
372 }
373 
374 
375 void GrMatrix::mapTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {
376     for (uint32_t i = 0; i < count; ++i) {
377         dst[i].fX = src[i].fX + fM[kTransX];
378         dst[i].fY = src[i].fY + fM[kTransY];
379     }
380 }
381 
382 void GrMatrix::mapScaleAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {
383     for (uint32_t i = 0; i < count; ++i) {
384         dst[i].fX = GrMul(src[i].fX, fM[kScaleX]) + fM[kTransX];
385         dst[i].fY = GrMul(src[i].fY, fM[kScaleY]) + fM[kTransY];
386     }
387 }
388 
389 void GrMatrix::mapSkew(GrPoint* dst, const GrPoint* src, uint32_t count) const {
390     if (src != dst) {
391         for (uint32_t i = 0; i < count; ++i) {
392             dst[i].fX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]);
393             dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]);
394         }
395     } else {
396         for (uint32_t i = 0; i < count; ++i) {
397             GrScalar newX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]);
398             dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]);
399             dst[i].fX = newX;
400         }
401     }
402 }
403 
404 void GrMatrix::mapScaleAndSkew(GrPoint* dst, const GrPoint* src, uint32_t count) const {
405     if (src != dst) {
406         for (uint32_t i = 0; i < count; ++i) {
407             dst[i].fX = GrMul(src[i].fX, fM[kScaleX]) + GrMul(src[i].fY, fM[kSkewX]);
408             dst[i].fY = GrMul(src[i].fY, fM[kScaleY]) + GrMul(src[i].fX, fM[kSkewY]);
409         }
410     } else {
411         for (uint32_t i = 0; i < count; ++i) {
412             GrScalar newX = GrMul(src[i].fX, fM[kScaleX]) + GrMul(src[i].fY, fM[kSkewX]);
413             dst[i].fY = GrMul(src[i].fY, fM[kScaleY]) + GrMul(src[i].fX, fM[kSkewY]);
414             dst[i].fX = newX;
415         }
416     }
417 }
418 
419 void GrMatrix::mapSkewAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {
420     if (src != dst) {
421         for (uint32_t i = 0; i < count; ++i) {
422             dst[i].fX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];
423             dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];
424         }
425     } else {
426         for (uint32_t i = 0; i < count; ++i) {
427             GrScalar newX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];
428             dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];
429             dst[i].fX = newX;
430         }
431     }
432 }
433 
434 void GrMatrix::mapNonPerspective(GrPoint* dst, const GrPoint* src, uint32_t count) const {
435     if (src != dst) {
436         for (uint32_t i = 0; i < count; ++i) {
437             dst[i].fX = GrMul(fM[kScaleX], src[i].fX) + GrMul(fM[kSkewX], src[i].fY) + fM[kTransX];
438             dst[i].fY = GrMul(fM[kSkewY], src[i].fX) + GrMul(fM[kScaleY], src[i].fY) + fM[kTransY];
439         }
440     } else {
441         for (uint32_t i = 0; i < count; ++i) {
442             GrScalar newX = GrMul(fM[kScaleX], src[i].fX) + GrMul(fM[kSkewX], src[i].fY) + fM[kTransX];
443             dst[i].fY = GrMul(fM[kSkewY], src[i].fX) + GrMul(fM[kScaleY], src[i].fY) + fM[kTransY];
444             dst[i].fX = newX;
445         }
446     }
447 }
448 
449 void GrMatrix::mapPerspective(GrPoint* dst, const GrPoint* src, uint32_t count) const {
450     for (uint32_t i = 0; i < count; ++i) {
451         GrScalar x, y, w;
452         x = GrMul(fM[kScaleX], src[i].fX) + GrMul(fM[kSkewX], src[i].fY) + fM[kTransX];
453         y = GrMul(fM[kSkewY], src[i].fX) + GrMul(fM[kScaleY], src[i].fY) + fM[kTransY];
454         w = GrMul(fM[kPersp0], src[i].fX) + GrMul(fM[kPersp1], src[i].fY) + fM[kPersp2];
455         // TODO need fixed point invert
456         if (w) {
457             w = 1 / w;
458         }
459         dst[i].fX = GrMul(x, w);
460         dst[i].fY = GrMul(y, w);
461     }
462 }
463 
464 void GrMatrix::mapInvalid(GrPoint* dst, const GrPoint* src, uint32_t count) const {
465     GrAssert(0);
466 }
467 
468 void GrMatrix::mapZero(GrPoint* dst, const GrPoint* src, uint32_t count) const {
469     memset(dst, 0, sizeof(GrPoint)*count);
470 }
471 
472 void GrMatrix::mapSetToTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {
473     for (uint32_t i = 0; i < count; ++i) {
474         dst[i].fX = fM[kTransX];
475         dst[i].fY = fM[kTransY];
476     }
477 }
478 
479 void GrMatrix::mapSwappedScale(GrPoint* dst, const GrPoint* src, uint32_t count) const {
480     if (src != dst) {
481         for (uint32_t i = 0; i < count; ++i) {
482             dst[i].fX = GrMul(src[i].fY, fM[kSkewX]);
483             dst[i].fY = GrMul(src[i].fX, fM[kSkewY]);
484         }
485     } else {
486         for (uint32_t i = 0; i < count; ++i) {
487             GrScalar newX = GrMul(src[i].fY, fM[kSkewX]);
488             dst[i].fY = GrMul(src[i].fX, fM[kSkewY]);
489             dst[i].fX = newX;
490         }
491     }
492 }
493 
494 void GrMatrix::mapSwappedScaleAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {
495     if (src != dst) {
496         for (uint32_t i = 0; i < count; ++i) {
497             dst[i].fX = GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];
498             dst[i].fY = GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];
499         }
500     } else {
501         for (uint32_t i = 0; i < count; ++i) {
502             GrScalar newX = GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];
503             dst[i].fY = GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];
504             dst[i].fX = newX;
505         }
506     }
507 }
508 
509 ///////////////////////////////////////////////////////////////////////////////
510 // Unit test
511 //////
512 
513 #include "GrRandom.h"
514 
515 #if GR_DEBUG
516 enum MatrixType {
517     kRotate_MatrixType,
518     kScaleX_MatrixType,
519     kScaleY_MatrixType,
520     kSkewX_MatrixType,
521     kSkewY_MatrixType,
522     kTranslateX_MatrixType,
523     kTranslateY_MatrixType,
524     kSwapScaleXY_MatrixType,
525     kPersp_MatrixType,
526 
527     kMatrixTypeCount
528 };
529 
530 static void create_matrix(GrMatrix* matrix, GrRandom& rand) {
531     MatrixType type = (MatrixType)(rand.nextU() % kMatrixTypeCount);
532     switch (type) {
533         case kRotate_MatrixType: {
534             float angle = rand.nextF() * 2 *3.14159265358979323846f;
535             GrScalar cosa = GrFloatToScalar(cosf(angle));
536             GrScalar sina = GrFloatToScalar(sinf(angle));
537             matrix->setAll(cosa,      -sina,           0,
538                            sina,       cosa,           0,
539                            0,          0,              GrMatrix::I()[8]);
540         } break;
541         case kScaleX_MatrixType: {
542             GrScalar scale = GrFloatToScalar(rand.nextF(-2, 2));
543             matrix->setAll(scale,      0,              0,
544                            0,          GR_Scalar1,     0,
545                            0,          0,              GrMatrix::I()[8]);
546         } break;
547         case kScaleY_MatrixType: {
548             GrScalar scale = GrFloatToScalar(rand.nextF(-2, 2));
549             matrix->setAll(GR_Scalar1, 0,              0,
550                            0,          scale,          0,
551                            0,          0,              GrMatrix::I()[8]);
552         } break;
553         case kSkewX_MatrixType: {
554             GrScalar skew = GrFloatToScalar(rand.nextF(-2, 2));
555             matrix->setAll(GR_Scalar1, skew,           0,
556                            0,          GR_Scalar1,     0,
557                            0,          0,              GrMatrix::I()[8]);
558         } break;
559         case kSkewY_MatrixType: {
560             GrScalar skew = GrFloatToScalar(rand.nextF(-2, 2));
561             matrix->setAll(GR_Scalar1, 0,              0,
562                            skew,       GR_Scalar1,     0,
563                            0,          0,              GrMatrix::I()[8]);
564         } break;
565         case kTranslateX_MatrixType: {
566             GrScalar trans = GrFloatToScalar(rand.nextF(-10, 10));
567             matrix->setAll(GR_Scalar1, 0,              trans,
568                            0,          GR_Scalar1,     0,
569                            0,          0,              GrMatrix::I()[8]);
570         } break;
571         case kTranslateY_MatrixType: {
572             GrScalar trans = GrFloatToScalar(rand.nextF(-10, 10));
573             matrix->setAll(GR_Scalar1, 0,              0,
574                            0,          GR_Scalar1,     trans,
575                            0,          0,              GrMatrix::I()[8]);
576         } break;
577         case kSwapScaleXY_MatrixType: {
578             GrScalar xy = GrFloatToScalar(rand.nextF(-2, 2));
579             GrScalar yx = GrFloatToScalar(rand.nextF(-2, 2));
580             matrix->setAll(0,          xy,             0,
581                            yx,         0,              0,
582                            0,          0,              GrMatrix::I()[8]);
583         } break;
584         case kPersp_MatrixType: {
585             GrScalar p0 = GrFloatToScalar(rand.nextF(-2, 2));
586             GrScalar p1 = GrFloatToScalar(rand.nextF(-2, 2));
587             GrScalar p2 = GrFloatToScalar(rand.nextF(-0.5f, 0.75f));
588             matrix->setAll(GR_Scalar1, 0,              0,
589                            0,          GR_Scalar1,     0,
590                            p0,         p1,             GrMul(p2,GrMatrix::I()[8]));
591         } break;
592         default:
593             GrAssert(0);
594             break;
595     }
596 }
597 #endif
598 
599 void GrMatrix::UnitTest() {
600     GrRandom rand;
601 
602     // Create a bunch of matrices and test point mapping, max stretch calc,
603     // inversion and multiply-by-inverse.
604 #if GR_DEBUG
605     for (int i = 0; i < 10000; ++i) {
606         GrMatrix a, b;
607         a.setIdentity();
608         int num = rand.nextU() % 6;
609         // force testing of I and swapXY
610         if (0 == i) {
611             num = 0;
612             GrAssert(a.isIdentity());
613         } else if (1 == i) {
614             num = 0;
615             a.setAll(0, GR_Scalar1, 0,
616                      GR_Scalar1, 0, 0,
617                      0, 0, I()[8]);
618         }
619         for (int j = 0; j < num; ++j) {
620             create_matrix(&b, rand);
621             a.preConcat(b);
622         }
623 
624         GrScalar maxStretch = a.getMaxStretch();
625         if (maxStretch > 0) {
626             maxStretch = GrMul(GR_Scalar1 + GR_Scalar1 / 100, maxStretch);
627         }
628         GrPoint origin = a.mapPoint(GrPoint::Make(0,0));
629 
630         for (int j = 0; j < 9; ++j) {
631             int mask, origMask = a.fTypeMask;
632             GrScalar old = a[j];
633 
634             a.set(j, GR_Scalar1);
635             mask = a.fTypeMask;
636             a.computeTypeMask();
637             GrAssert(mask == a.fTypeMask);
638 
639             a.set(j, 0);
640             mask = a.fTypeMask;
641             a.computeTypeMask();
642             GrAssert(mask == a.fTypeMask);
643 
644             a.set(j, 10 * GR_Scalar1);
645             mask = a.fTypeMask;
646             a.computeTypeMask();
647             GrAssert(mask == a.fTypeMask);
648 
649             a.set(j, old);
650             GrAssert(a.fTypeMask == origMask);
651         }
652 
653         for (int j = 0; j < 100; ++j) {
654             GrPoint pt;
655             pt.fX = GrFloatToScalar(rand.nextF(-10, 10));
656             pt.fY = GrFloatToScalar(rand.nextF(-10, 10));
657 
658             GrPoint t0, t1, t2;
659             t0 = a.mapPoint(pt);             // map to a new point
660             t1 = pt;
661             a.mapPoints(&t1, &t1, 1);        // in place
662             a.mapPerspective(&t2, &pt, 1);   // full mult
663             GrAssert(t0 == t1 && t1 == t2);
664             if (maxStretch >= 0.f) {
665                 GrVec vec = origin - t0;
666 //                vec.setBetween(t0, origin);
667                 GrScalar stretch = vec.length() / pt.distanceToOrigin();
668                 GrAssert(stretch <= maxStretch);
669             }
670         }
671         double det = a.determinant();
672         if (fabs(det) > 1e-3 && a.invert(&b)) {
673             GrMatrix c;
674             c.setConcat(a,b);
675             for (int i = 0; i < 9; ++i) {
676                 GrScalar diff = GrScalarAbs(c[i] - I()[i]);
677                 GrAssert(diff < (5*GR_Scalar1 / 100));
678             }
679         }
680     }
681 #endif
682 }
683 
684 ///////////////////////////////////////////////////////////////////////////////
685 #endif
686 
Gr_clz(uint32_t n)687 int Gr_clz(uint32_t n) {
688     if (0 == n) {
689         return 32;
690     }
691 
692     int count = 0;
693     if (0 == (n & 0xFFFF0000)) {
694         count += 16;
695         n <<= 16;
696     }
697     if (0 == (n & 0xFF000000)) {
698         count += 8;
699         n <<= 8;
700     }
701     if (0 == (n & 0xF0000000)) {
702         count += 4;
703         n <<= 4;
704     }
705     if (0 == (n & 0xC0000000)) {
706         count += 2;
707         n <<= 2;
708     }
709     if (0 == (n & 0x80000000)) {
710         count += 1;
711     }
712     return count;
713 }
714