• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/corecg/SkMatrix.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "SkMatrix.h"
19 #include "Sk64.h"
20 #include "SkFloatBits.h"
21 #include "SkScalarCompare.h"
22 #include "SkString.h"
23 
24 #ifdef SK_SCALAR_IS_FLOAT
25     #define kMatrix22Elem   SK_Scalar1
26 
SkDoubleToFloat(double x)27     static inline float SkDoubleToFloat(double x) {
28         return static_cast<float>(x);
29     }
30 #else
31     #define kMatrix22Elem   SK_Fract1
32 #endif
33 
34 /*      [scale-x    skew-x      trans-x]   [X]   [X']
35         [skew-y     scale-y     trans-y] * [Y] = [Y']
36         [persp-0    persp-1     persp-2]   [1]   [1 ]
37 */
38 
reset()39 void SkMatrix::reset() {
40     fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1;
41     fMat[kMSkewX]  = fMat[kMSkewY] =
42     fMat[kMTransX] = fMat[kMTransY] =
43     fMat[kMPersp0] = fMat[kMPersp1] = 0;
44     fMat[kMPersp2] = kMatrix22Elem;
45 
46     this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask);
47 }
48 
49 // this guy aligns with the masks, so we can compute a mask from a varaible 0/1
50 enum {
51     kTranslate_Shift,
52     kScale_Shift,
53     kAffine_Shift,
54     kPerspective_Shift,
55     kRectStaysRect_Shift
56 };
57 
58 #ifdef SK_SCALAR_IS_FLOAT
59     static const int32_t kScalar1Int = 0x3f800000;
60     static const int32_t kPersp1Int  = 0x3f800000;
61 #else
62     #define scalarAsInt(x)  (x)
63     static const int32_t kScalar1Int = (1 << 16);
64     static const int32_t kPersp1Int  = (1 << 30);
65 #endif
66 
computeTypeMask() const67 uint8_t SkMatrix::computeTypeMask() const {
68     unsigned mask = 0;
69 
70 #ifdef SK_SCALAR_SLOW_COMPARES
71     if (SkScalarAs2sCompliment(fMat[kMPersp0]) |
72             SkScalarAs2sCompliment(fMat[kMPersp1]) |
73             (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) {
74         mask |= kPerspective_Mask;
75     }
76 
77     if (SkScalarAs2sCompliment(fMat[kMTransX]) |
78             SkScalarAs2sCompliment(fMat[kMTransY])) {
79         mask |= kTranslate_Mask;
80     }
81 #else
82     // Benchmarking suggests that replacing this set of SkScalarAs2sCompliment
83     // is a win, but replacing those below is not. We don't yet understand
84     // that result.
85     if (fMat[kMPersp0] != 0 || fMat[kMPersp1] != 0 ||
86         fMat[kMPersp2] != kMatrix22Elem) {
87         mask |= kPerspective_Mask;
88     }
89 
90     if (fMat[kMTransX] != 0 || fMat[kMTransY] != 0) {
91         mask |= kTranslate_Mask;
92     }
93 #endif
94 
95     int m00 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleX]);
96     int m01 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewX]);
97     int m10 = SkScalarAs2sCompliment(fMat[SkMatrix::kMSkewY]);
98     int m11 = SkScalarAs2sCompliment(fMat[SkMatrix::kMScaleY]);
99 
100     if (m01 | m10) {
101         mask |= kAffine_Mask;
102     }
103 
104     if ((m00 - kScalar1Int) | (m11 - kScalar1Int)) {
105         mask |= kScale_Mask;
106     }
107 
108     if ((mask & kPerspective_Mask) == 0) {
109         // map non-zero to 1
110         m00 = m00 != 0;
111         m01 = m01 != 0;
112         m10 = m10 != 0;
113         m11 = m11 != 0;
114 
115         // record if the (p)rimary and (s)econdary diagonals are all 0 or
116         // all non-zero (answer is 0 or 1)
117         int dp0 = (m00 | m11) ^ 1;  // true if both are 0
118         int dp1 = m00 & m11;        // true if both are 1
119         int ds0 = (m01 | m10) ^ 1;  // true if both are 0
120         int ds1 = m01 & m10;        // true if both are 1
121 
122         // return 1 if primary is 1 and secondary is 0 or
123         // primary is 0 and secondary is 1
124         mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
125     }
126 
127     return SkToU8(mask);
128 }
129 
130 ///////////////////////////////////////////////////////////////////////////////
131 
132 #ifdef SK_SCALAR_IS_FLOAT
133 
operator ==(const SkMatrix & a,const SkMatrix & b)134 bool operator==(const SkMatrix& a, const SkMatrix& b) {
135     const SkScalar* SK_RESTRICT ma = a.fMat;
136     const SkScalar* SK_RESTRICT mb = b.fMat;
137 
138     return  ma[0] == mb[0] && ma[1] == mb[1] && ma[2] == mb[2] &&
139             ma[3] == mb[3] && ma[4] == mb[4] && ma[5] == mb[5] &&
140             ma[6] == mb[6] && ma[7] == mb[7] && ma[8] == mb[8];
141 }
142 
143 #endif
144 
145 ///////////////////////////////////////////////////////////////////////////////
146 
setTranslate(SkScalar dx,SkScalar dy)147 void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
148     if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
149         fMat[kMTransX] = dx;
150         fMat[kMTransY] = dy;
151 
152         fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1;
153         fMat[kMSkewX]  = fMat[kMSkewY] =
154         fMat[kMPersp0] = fMat[kMPersp1] = 0;
155         fMat[kMPersp2] = kMatrix22Elem;
156 
157         this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
158     } else {
159         this->reset();
160     }
161 }
162 
preTranslate(SkScalar dx,SkScalar dy)163 bool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
164     if (this->hasPerspective()) {
165         SkMatrix    m;
166         m.setTranslate(dx, dy);
167         return this->preConcat(m);
168     }
169 
170     if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
171         fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) +
172                           SkScalarMul(fMat[kMSkewX], dy);
173         fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) +
174                           SkScalarMul(fMat[kMScaleY], dy);
175 
176         this->setTypeMask(kUnknown_Mask);
177     }
178     return true;
179 }
180 
postTranslate(SkScalar dx,SkScalar dy)181 bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
182     if (this->hasPerspective()) {
183         SkMatrix    m;
184         m.setTranslate(dx, dy);
185         return this->postConcat(m);
186     }
187 
188     if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
189         fMat[kMTransX] += dx;
190         fMat[kMTransY] += dy;
191         this->setTypeMask(kUnknown_Mask);
192     }
193     return true;
194 }
195 
196 ///////////////////////////////////////////////////////////////////////////////
197 
setScale(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)198 void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
199     fMat[kMScaleX] = sx;
200     fMat[kMScaleY] = sy;
201     fMat[kMTransX] = px - SkScalarMul(sx, px);
202     fMat[kMTransY] = py - SkScalarMul(sy, py);
203     fMat[kMPersp2] = kMatrix22Elem;
204 
205     fMat[kMSkewX]  = fMat[kMSkewY] =
206     fMat[kMPersp0] = fMat[kMPersp1] = 0;
207 
208     this->setTypeMask(kScale_Mask | kTranslate_Mask | kRectStaysRect_Mask);
209 }
210 
setScale(SkScalar sx,SkScalar sy)211 void SkMatrix::setScale(SkScalar sx, SkScalar sy) {
212     fMat[kMScaleX] = sx;
213     fMat[kMScaleY] = sy;
214     fMat[kMPersp2] = kMatrix22Elem;
215 
216     fMat[kMTransX] = fMat[kMTransY] =
217     fMat[kMSkewX]  = fMat[kMSkewY] =
218     fMat[kMPersp0] = fMat[kMPersp1] = 0;
219 
220     this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
221 }
222 
preScale(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)223 bool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
224     SkMatrix    m;
225     m.setScale(sx, sy, px, py);
226     return this->preConcat(m);
227 }
228 
preScale(SkScalar sx,SkScalar sy)229 bool SkMatrix::preScale(SkScalar sx, SkScalar sy) {
230 #ifdef SK_SCALAR_IS_FIXED
231     SkMatrix    m;
232     m.setScale(sx, sy);
233     return this->preConcat(m);
234 #else
235     // the assumption is that these multiplies are very cheap, and that
236     // a full concat and/or just computing the matrix type is more expensive.
237     // Also, the fixed-point case checks for overflow, but the float doesn't,
238     // so we can get away with these blind multiplies.
239 
240     fMat[kMScaleX] = SkScalarMul(fMat[kMScaleX], sx);
241     fMat[kMSkewY] = SkScalarMul(fMat[kMSkewY],   sx);
242     fMat[kMPersp0] = SkScalarMul(fMat[kMPersp0], sx);
243 
244     fMat[kMSkewX] = SkScalarMul(fMat[kMSkewX],   sy);
245     fMat[kMScaleY] = SkScalarMul(fMat[kMScaleY], sy);
246     fMat[kMPersp1] = SkScalarMul(fMat[kMPersp1], sy);
247 
248     this->orTypeMask(kScale_Mask);
249     return true;
250 #endif
251 }
252 
postScale(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)253 bool SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
254     SkMatrix    m;
255     m.setScale(sx, sy, px, py);
256     return this->postConcat(m);
257 }
258 
postScale(SkScalar sx,SkScalar sy)259 bool SkMatrix::postScale(SkScalar sx, SkScalar sy) {
260     SkMatrix    m;
261     m.setScale(sx, sy);
262     return this->postConcat(m);
263 }
264 
265 #ifdef SK_SCALAR_IS_FIXED
roundidiv(SkFixed numer,int denom)266     static inline SkFixed roundidiv(SkFixed numer, int denom) {
267         int ns = numer >> 31;
268         int ds = denom >> 31;
269         numer = (numer ^ ns) - ns;
270         denom = (denom ^ ds) - ds;
271 
272         SkFixed answer = (numer + (denom >> 1)) / denom;
273         int as = ns ^ ds;
274         return (answer ^ as) - as;
275     }
276 #endif
277 
278 // this guy perhaps can go away, if we have a fract/high-precision way to
279 // scale matrices
postIDiv(int divx,int divy)280 bool SkMatrix::postIDiv(int divx, int divy) {
281     if (divx == 0 || divy == 0) {
282         return false;
283     }
284 
285 #ifdef SK_SCALAR_IS_FIXED
286     fMat[kMScaleX] = roundidiv(fMat[kMScaleX], divx);
287     fMat[kMSkewX]  = roundidiv(fMat[kMSkewX],  divx);
288     fMat[kMTransX] = roundidiv(fMat[kMTransX], divx);
289 
290     fMat[kMScaleY] = roundidiv(fMat[kMScaleY], divy);
291     fMat[kMSkewY]  = roundidiv(fMat[kMSkewY],  divy);
292     fMat[kMTransY] = roundidiv(fMat[kMTransY], divy);
293 #else
294     const float invX = 1.f / divx;
295     const float invY = 1.f / divy;
296 
297     fMat[kMScaleX] *= invX;
298     fMat[kMSkewX]  *= invX;
299     fMat[kMTransX] *= invX;
300 
301     fMat[kMScaleY] *= invY;
302     fMat[kMSkewY]  *= invY;
303     fMat[kMTransY] *= invY;
304 #endif
305 
306     this->setTypeMask(kUnknown_Mask);
307     return true;
308 }
309 
310 ////////////////////////////////////////////////////////////////////////////////////
311 
setSinCos(SkScalar sinV,SkScalar cosV,SkScalar px,SkScalar py)312 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV,
313                          SkScalar px, SkScalar py) {
314     const SkScalar oneMinusCosV = SK_Scalar1 - cosV;
315 
316     fMat[kMScaleX]  = cosV;
317     fMat[kMSkewX]   = -sinV;
318     fMat[kMTransX]  = SkScalarMul(sinV, py) + SkScalarMul(oneMinusCosV, px);
319 
320     fMat[kMSkewY]   = sinV;
321     fMat[kMScaleY]  = cosV;
322     fMat[kMTransY]  = SkScalarMul(-sinV, px) + SkScalarMul(oneMinusCosV, py);
323 
324     fMat[kMPersp0] = fMat[kMPersp1] = 0;
325     fMat[kMPersp2] = kMatrix22Elem;
326 
327     this->setTypeMask(kUnknown_Mask);
328 }
329 
setSinCos(SkScalar sinV,SkScalar cosV)330 void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {
331     fMat[kMScaleX]  = cosV;
332     fMat[kMSkewX]   = -sinV;
333     fMat[kMTransX]  = 0;
334 
335     fMat[kMSkewY]   = sinV;
336     fMat[kMScaleY]  = cosV;
337     fMat[kMTransY]  = 0;
338 
339     fMat[kMPersp0] = fMat[kMPersp1] = 0;
340     fMat[kMPersp2] = kMatrix22Elem;
341 
342     this->setTypeMask(kUnknown_Mask);
343 }
344 
setRotate(SkScalar degrees,SkScalar px,SkScalar py)345 void SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) {
346     SkScalar sinV, cosV;
347     sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
348     this->setSinCos(sinV, cosV, px, py);
349 }
350 
setRotate(SkScalar degrees)351 void SkMatrix::setRotate(SkScalar degrees) {
352     SkScalar sinV, cosV;
353     sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
354     this->setSinCos(sinV, cosV);
355 }
356 
preRotate(SkScalar degrees,SkScalar px,SkScalar py)357 bool SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) {
358     SkMatrix    m;
359     m.setRotate(degrees, px, py);
360     return this->preConcat(m);
361 }
362 
preRotate(SkScalar degrees)363 bool SkMatrix::preRotate(SkScalar degrees) {
364     SkMatrix    m;
365     m.setRotate(degrees);
366     return this->preConcat(m);
367 }
368 
postRotate(SkScalar degrees,SkScalar px,SkScalar py)369 bool SkMatrix::postRotate(SkScalar degrees, SkScalar px, SkScalar py) {
370     SkMatrix    m;
371     m.setRotate(degrees, px, py);
372     return this->postConcat(m);
373 }
374 
postRotate(SkScalar degrees)375 bool SkMatrix::postRotate(SkScalar degrees) {
376     SkMatrix    m;
377     m.setRotate(degrees);
378     return this->postConcat(m);
379 }
380 
381 ////////////////////////////////////////////////////////////////////////////////////
382 
setSkew(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)383 void SkMatrix::setSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
384     fMat[kMScaleX]  = SK_Scalar1;
385     fMat[kMSkewX]   = sx;
386     fMat[kMTransX]  = SkScalarMul(-sx, py);
387 
388     fMat[kMSkewY]   = sy;
389     fMat[kMScaleY]  = SK_Scalar1;
390     fMat[kMTransY]  = SkScalarMul(-sy, px);
391 
392     fMat[kMPersp0] = fMat[kMPersp1] = 0;
393     fMat[kMPersp2] = kMatrix22Elem;
394 
395     this->setTypeMask(kUnknown_Mask);
396 }
397 
setSkew(SkScalar sx,SkScalar sy)398 void SkMatrix::setSkew(SkScalar sx, SkScalar sy) {
399     fMat[kMScaleX]  = SK_Scalar1;
400     fMat[kMSkewX]   = sx;
401     fMat[kMTransX]  = 0;
402 
403     fMat[kMSkewY]   = sy;
404     fMat[kMScaleY]  = SK_Scalar1;
405     fMat[kMTransY]  = 0;
406 
407     fMat[kMPersp0] = fMat[kMPersp1] = 0;
408     fMat[kMPersp2] = kMatrix22Elem;
409 
410     this->setTypeMask(kUnknown_Mask);
411 }
412 
preSkew(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)413 bool SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
414     SkMatrix    m;
415     m.setSkew(sx, sy, px, py);
416     return this->preConcat(m);
417 }
418 
preSkew(SkScalar sx,SkScalar sy)419 bool SkMatrix::preSkew(SkScalar sx, SkScalar sy) {
420     SkMatrix    m;
421     m.setSkew(sx, sy);
422     return this->preConcat(m);
423 }
424 
postSkew(SkScalar sx,SkScalar sy,SkScalar px,SkScalar py)425 bool SkMatrix::postSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
426     SkMatrix    m;
427     m.setSkew(sx, sy, px, py);
428     return this->postConcat(m);
429 }
430 
postSkew(SkScalar sx,SkScalar sy)431 bool SkMatrix::postSkew(SkScalar sx, SkScalar sy) {
432     SkMatrix    m;
433     m.setSkew(sx, sy);
434     return this->postConcat(m);
435 }
436 
437 ///////////////////////////////////////////////////////////////////////////////
438 
setRectToRect(const SkRect & src,const SkRect & dst,ScaleToFit align)439 bool SkMatrix::setRectToRect(const SkRect& src, const SkRect& dst,
440                              ScaleToFit align)
441 {
442     if (src.isEmpty()) {
443         this->reset();
444         return false;
445     }
446 
447     if (dst.isEmpty()) {
448         sk_bzero(fMat, 8 * sizeof(SkScalar));
449         this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
450     } else {
451         SkScalar    tx, sx = SkScalarDiv(dst.width(), src.width());
452         SkScalar    ty, sy = SkScalarDiv(dst.height(), src.height());
453         bool        xLarger = false;
454 
455         if (align != kFill_ScaleToFit) {
456             if (sx > sy) {
457                 xLarger = true;
458                 sx = sy;
459             } else {
460                 sy = sx;
461             }
462         }
463 
464         tx = dst.fLeft - SkScalarMul(src.fLeft, sx);
465         ty = dst.fTop - SkScalarMul(src.fTop, sy);
466         if (align == kCenter_ScaleToFit || align == kEnd_ScaleToFit) {
467             SkScalar diff;
468 
469             if (xLarger) {
470                 diff = dst.width() - SkScalarMul(src.width(), sy);
471             } else {
472                 diff = dst.height() - SkScalarMul(src.height(), sy);
473             }
474 
475             if (align == kCenter_ScaleToFit) {
476                 diff = SkScalarHalf(diff);
477             }
478 
479             if (xLarger) {
480                 tx += diff;
481             } else {
482                 ty += diff;
483             }
484         }
485 
486         fMat[kMScaleX] = sx;
487         fMat[kMScaleY] = sy;
488         fMat[kMTransX] = tx;
489         fMat[kMTransY] = ty;
490         fMat[kMSkewX]  = fMat[kMSkewY] =
491         fMat[kMPersp0] = fMat[kMPersp1] = 0;
492 
493         this->setTypeMask(kScale_Mask | kTranslate_Mask | kRectStaysRect_Mask);
494     }
495     // shared cleanup
496     fMat[kMPersp2] = kMatrix22Elem;
497     return true;
498 }
499 
500 ///////////////////////////////////////////////////////////////////////////////
501 
502 #ifdef SK_SCALAR_IS_FLOAT
fixmuladdmul(float a,float b,float c,float d,float * result)503     static inline int fixmuladdmul(float a, float b, float c, float d,
504                                    float* result) {
505         *result = SkDoubleToFloat((double)a * b + (double)c * d);
506         return true;
507     }
508 
rowcol3(const float row[],const float col[],float * result)509     static inline bool rowcol3(const float row[], const float col[],
510                                float* result) {
511         *result = row[0] * col[0] + row[1] * col[3] + row[2] * col[6];
512         return true;
513     }
514 
negifaddoverflows(float & result,float a,float b)515     static inline int negifaddoverflows(float& result, float a, float b) {
516         result = a + b;
517         return 0;
518     }
519 #else
fixmuladdmul(SkFixed a,SkFixed b,SkFixed c,SkFixed d,SkFixed * result)520     static inline bool fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d,
521                                     SkFixed* result) {
522         Sk64    tmp1, tmp2;
523         tmp1.setMul(a, b);
524         tmp2.setMul(c, d);
525         tmp1.add(tmp2);
526         if (tmp1.isFixed()) {
527             *result = tmp1.getFixed();
528             return true;
529         }
530         return false;
531     }
532 
fracmuladdmul(SkFixed a,SkFract b,SkFixed c,SkFract d)533     static inline SkFixed fracmuladdmul(SkFixed a, SkFract b, SkFixed c,
534                                         SkFract d) {
535         Sk64 tmp1, tmp2;
536         tmp1.setMul(a, b);
537         tmp2.setMul(c, d);
538         tmp1.add(tmp2);
539         return tmp1.getFract();
540     }
541 
rowcol3(const SkFixed row[],const SkFixed col[],SkFixed * result)542     static inline bool rowcol3(const SkFixed row[], const SkFixed col[],
543                                SkFixed* result) {
544         Sk64 tmp1, tmp2;
545 
546         tmp1.setMul(row[0], col[0]);    // N * fixed
547         tmp2.setMul(row[1], col[3]);    // N * fixed
548         tmp1.add(tmp2);
549 
550         tmp2.setMul(row[2], col[6]);    // N * fract
551         tmp2.roundRight(14);            // make it fixed
552         tmp1.add(tmp2);
553 
554         if (tmp1.isFixed()) {
555             *result = tmp1.getFixed();
556             return true;
557         }
558         return false;
559     }
560 
negifaddoverflows(SkFixed & result,SkFixed a,SkFixed b)561     static inline int negifaddoverflows(SkFixed& result, SkFixed a, SkFixed b) {
562         SkFixed c = a + b;
563         result = c;
564         return (c ^ a) & (c ^ b);
565     }
566 #endif
567 
normalize_perspective(SkScalar mat[9])568 static void normalize_perspective(SkScalar mat[9]) {
569     if (SkScalarAbs(mat[SkMatrix::kMPersp2]) > kMatrix22Elem) {
570         for (int i = 0; i < 9; i++)
571             mat[i] = SkScalarHalf(mat[i]);
572     }
573 }
574 
setConcat(const SkMatrix & a,const SkMatrix & b)575 bool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
576     TypeMask aType = a.getType();
577     TypeMask bType = b.getType();
578 
579     if (0 == aType) {
580         *this = b;
581     } else if (0 == bType) {
582         *this = a;
583     } else {
584         SkMatrix tmp;
585 
586         if ((aType | bType) & kPerspective_Mask) {
587             if (!rowcol3(&a.fMat[0], &b.fMat[0], &tmp.fMat[kMScaleX])) {
588                 return false;
589             }
590             if (!rowcol3(&a.fMat[0], &b.fMat[1], &tmp.fMat[kMSkewX])) {
591                 return false;
592             }
593             if (!rowcol3(&a.fMat[0], &b.fMat[2], &tmp.fMat[kMTransX])) {
594                 return false;
595             }
596 
597             if (!rowcol3(&a.fMat[3], &b.fMat[0], &tmp.fMat[kMSkewY])) {
598                 return false;
599             }
600             if (!rowcol3(&a.fMat[3], &b.fMat[1], &tmp.fMat[kMScaleY])) {
601                 return false;
602             }
603             if (!rowcol3(&a.fMat[3], &b.fMat[2], &tmp.fMat[kMTransY])) {
604                 return false;
605             }
606 
607             if (!rowcol3(&a.fMat[6], &b.fMat[0], &tmp.fMat[kMPersp0])) {
608                 return false;
609             }
610             if (!rowcol3(&a.fMat[6], &b.fMat[1], &tmp.fMat[kMPersp1])) {
611                 return false;
612             }
613             if (!rowcol3(&a.fMat[6], &b.fMat[2], &tmp.fMat[kMPersp2])) {
614                 return false;
615             }
616 
617             normalize_perspective(tmp.fMat);
618         } else {    // not perspective
619             if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMScaleX],
620                     a.fMat[kMSkewX], b.fMat[kMSkewY], &tmp.fMat[kMScaleX])) {
621                 return false;
622             }
623             if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMSkewX],
624                       a.fMat[kMSkewX], b.fMat[kMScaleY], &tmp.fMat[kMSkewX])) {
625                 return false;
626             }
627             if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMTransX],
628                       a.fMat[kMSkewX], b.fMat[kMTransY], &tmp.fMat[kMTransX])) {
629                 return false;
630             }
631             if (negifaddoverflows(tmp.fMat[kMTransX], tmp.fMat[kMTransX],
632                                   a.fMat[kMTransX]) < 0) {
633                 return false;
634             }
635 
636             if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMScaleX],
637                       a.fMat[kMScaleY], b.fMat[kMSkewY], &tmp.fMat[kMSkewY])) {
638                 return false;
639             }
640             if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMSkewX],
641                     a.fMat[kMScaleY], b.fMat[kMScaleY], &tmp.fMat[kMScaleY])) {
642                 return false;
643             }
644             if (!fixmuladdmul(a.fMat[kMSkewY], b.fMat[kMTransX],
645                      a.fMat[kMScaleY], b.fMat[kMTransY], &tmp.fMat[kMTransY])) {
646                 return false;
647             }
648             if (negifaddoverflows(tmp.fMat[kMTransY], tmp.fMat[kMTransY],
649                                   a.fMat[kMTransY]) < 0) {
650                 return false;
651             }
652 
653             tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0;
654             tmp.fMat[kMPersp2] = kMatrix22Elem;
655         }
656         *this = tmp;
657     }
658     this->setTypeMask(kUnknown_Mask);
659     return true;
660 }
661 
preConcat(const SkMatrix & mat)662 bool SkMatrix::preConcat(const SkMatrix& mat) {
663     // check for identity first, so we don't do a needless copy of ourselves
664     // to ourselves inside setConcat()
665     return mat.isIdentity() || this->setConcat(*this, mat);
666 }
667 
postConcat(const SkMatrix & mat)668 bool SkMatrix::postConcat(const SkMatrix& mat) {
669     // check for identity first, so we don't do a needless copy of ourselves
670     // to ourselves inside setConcat()
671     return mat.isIdentity() || this->setConcat(mat, *this);
672 }
673 
674 ///////////////////////////////////////////////////////////////////////////////
675 
676 /*  Matrix inversion is very expensive, but also the place where keeping
677     precision may be most important (here and matrix concat). Hence to avoid
678     bitmap blitting artifacts when walking the inverse, we use doubles for
679     the intermediate math, even though we know that is more expensive.
680     The fixed counter part is us using Sk64 for temp calculations.
681  */
682 
683 #ifdef SK_SCALAR_IS_FLOAT
684     typedef double SkDetScalar;
685     #define SkPerspMul(a, b)            SkScalarMul(a, b)
686     #define SkScalarMulShift(a, b, s)   SkDoubleToFloat((a) * (b))
sk_inv_determinant(const float mat[9],int isPerspective,int *)687     static double sk_inv_determinant(const float mat[9], int isPerspective,
688                                     int* /* (only used in Fixed case) */) {
689         double det;
690 
691         if (isPerspective) {
692             det =   mat[SkMatrix::kMScaleX] * ((double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp2] - (double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp1]) +
693                     mat[SkMatrix::kMSkewX] * ((double)mat[SkMatrix::kMTransY] * mat[SkMatrix::kMPersp0] - (double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp2]) +
694                     mat[SkMatrix::kMTransX] * ((double)mat[SkMatrix::kMSkewY] * mat[SkMatrix::kMPersp1] - (double)mat[SkMatrix::kMScaleY] * mat[SkMatrix::kMPersp0]);
695         } else {
696             det =   (double)mat[SkMatrix::kMScaleX] * mat[SkMatrix::kMScaleY] - (double)mat[SkMatrix::kMSkewX] * mat[SkMatrix::kMSkewY];
697         }
698 
699         // Since the determinant is on the order of the cube of the matrix members,
700         // compare to the cube of the default nearly-zero constant (although an
701         // estimate of the condition number would be better if it wasn't so expensive).
702         if (SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZero * SK_ScalarNearlyZero)) {
703             return 0;
704         }
705         return 1.0 / det;
706     }
707     // we declar a,b,c,d to all be doubles, because we want to perform
708     // double-precision muls and subtract, even though the original values are
709     // from the matrix, which are floats.
mul_diff_scale(double a,double b,double c,double d,double scale)710     static float inline mul_diff_scale(double a, double b, double c, double d,
711                                        double scale) {
712         return SkDoubleToFloat((a * b - c * d) * scale);
713     }
714 #else
715     typedef SkFixed SkDetScalar;
716     #define SkPerspMul(a, b)            SkFractMul(a, b)
717     #define SkScalarMulShift(a, b, s)   SkMulShift(a, b, s)
set_muladdmul(Sk64 * dst,int32_t a,int32_t b,int32_t c,int32_t d)718     static void set_muladdmul(Sk64* dst, int32_t a, int32_t b, int32_t c,
719                               int32_t d) {
720         Sk64 tmp;
721         dst->setMul(a, b);
722         tmp.setMul(c, d);
723         dst->add(tmp);
724     }
725 
sk_inv_determinant(const SkFixed mat[9],int isPerspective,int * shift)726     static SkFixed sk_inv_determinant(const SkFixed mat[9], int isPerspective,
727                                       int* shift) {
728         Sk64    tmp1, tmp2;
729 
730         if (isPerspective) {
731             tmp1.setMul(mat[SkMatrix::kMScaleX], fracmuladdmul(mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp2], -mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp1]));
732             tmp2.setMul(mat[SkMatrix::kMSkewX], fracmuladdmul(mat[SkMatrix::kMTransY], mat[SkMatrix::kMPersp0], -mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp2]));
733             tmp1.add(tmp2);
734             tmp2.setMul(mat[SkMatrix::kMTransX], fracmuladdmul(mat[SkMatrix::kMSkewY], mat[SkMatrix::kMPersp1], -mat[SkMatrix::kMScaleY], mat[SkMatrix::kMPersp0]));
735             tmp1.add(tmp2);
736         } else {
737             tmp1.setMul(mat[SkMatrix::kMScaleX], mat[SkMatrix::kMScaleY]);
738             tmp2.setMul(mat[SkMatrix::kMSkewX], mat[SkMatrix::kMSkewY]);
739             tmp1.sub(tmp2);
740         }
741 
742         int s = tmp1.getClzAbs();
743         *shift = s;
744 
745         SkFixed denom;
746         if (s <= 32) {
747             denom = tmp1.getShiftRight(33 - s);
748         } else {
749             denom = (int32_t)tmp1.fLo << (s - 33);
750         }
751 
752         if (denom == 0) {
753             return 0;
754         }
755         /** This could perhaps be a special fractdiv function, since both of its
756             arguments are known to have bit 31 clear and bit 30 set (when they
757             are made positive), thus eliminating the need for calling clz()
758         */
759         return SkFractDiv(SK_Fract1, denom);
760     }
761 #endif
762 
pdfTransform(SkScalar transform[6]) const763 bool SkMatrix::pdfTransform(SkScalar transform[6]) const {
764     SkMatrix identity;
765     const SkMatrix* use = this;
766     bool ret = true;
767     if (this->hasPerspective()) {
768         identity.reset();
769         use = &identity;
770         ret = false;
771     }
772     transform[0] = use->fMat[kMScaleX];
773     transform[1] = use->fMat[kMSkewY];
774     transform[2] = use->fMat[kMSkewX];
775     transform[3] = use->fMat[kMScaleY];
776     transform[4] = use->fMat[kMTransX];
777     transform[5] = use->fMat[kMTransY];
778     return true;
779 }
780 
invert(SkMatrix * inv) const781 bool SkMatrix::invert(SkMatrix* inv) const {
782     int         isPersp = this->hasPerspective();
783     int         shift;
784     SkDetScalar scale = sk_inv_determinant(fMat, isPersp, &shift);
785 
786     if (scale == 0) { // underflow
787         return false;
788     }
789 
790     if (inv) {
791         SkMatrix tmp;
792         if (inv == this)
793             inv = &tmp;
794 
795         if (isPersp) {
796             shift = 61 - shift;
797             inv->fMat[kMScaleX] = SkScalarMulShift(SkPerspMul(fMat[kMScaleY], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransY], fMat[kMPersp1]), scale, shift);
798             inv->fMat[kMSkewX]  = SkScalarMulShift(SkPerspMul(fMat[kMTransX], fMat[kMPersp1]) - SkPerspMul(fMat[kMSkewX],  fMat[kMPersp2]), scale, shift);
799             inv->fMat[kMTransX] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMTransY]) - SkScalarMul(fMat[kMTransX], fMat[kMScaleY]), scale, shift);
800 
801             inv->fMat[kMSkewY]  = SkScalarMulShift(SkPerspMul(fMat[kMTransY], fMat[kMPersp0]) - SkPerspMul(fMat[kMSkewY],   fMat[kMPersp2]), scale, shift);
802             inv->fMat[kMScaleY] = SkScalarMulShift(SkPerspMul(fMat[kMScaleX], fMat[kMPersp2]) - SkPerspMul(fMat[kMTransX],  fMat[kMPersp0]), scale, shift);
803             inv->fMat[kMTransY] = SkScalarMulShift(SkScalarMul(fMat[kMTransX], fMat[kMSkewY]) - SkScalarMul(fMat[kMScaleX], fMat[kMTransY]), scale, shift);
804 
805             inv->fMat[kMPersp0] = SkScalarMulShift(SkScalarMul(fMat[kMSkewY], fMat[kMPersp1]) - SkScalarMul(fMat[kMScaleY], fMat[kMPersp0]), scale, shift);
806             inv->fMat[kMPersp1] = SkScalarMulShift(SkScalarMul(fMat[kMSkewX], fMat[kMPersp0]) - SkScalarMul(fMat[kMScaleX], fMat[kMPersp1]), scale, shift);
807             inv->fMat[kMPersp2] = SkScalarMulShift(SkScalarMul(fMat[kMScaleX], fMat[kMScaleY]) - SkScalarMul(fMat[kMSkewX], fMat[kMSkewY]), scale, shift);
808 #ifdef SK_SCALAR_IS_FIXED
809             if (SkAbs32(inv->fMat[kMPersp2]) > SK_Fixed1) {
810                 Sk64    tmp;
811 
812                 tmp.set(SK_Fract1);
813                 tmp.shiftLeft(16);
814                 tmp.div(inv->fMat[kMPersp2], Sk64::kRound_DivOption);
815 
816                 SkFract scale = tmp.get32();
817 
818                 for (int i = 0; i < 9; i++) {
819                     inv->fMat[i] = SkFractMul(inv->fMat[i], scale);
820                 }
821             }
822             inv->fMat[kMPersp2] = SkFixedToFract(inv->fMat[kMPersp2]);
823 #endif
824         } else {   // not perspective
825 #ifdef SK_SCALAR_IS_FIXED
826             Sk64    tx, ty;
827             int     clzNumer;
828 
829             // check the 2x2 for overflow
830             {
831                 int32_t value = SkAbs32(fMat[kMScaleY]);
832                 value |= SkAbs32(fMat[kMSkewX]);
833                 value |= SkAbs32(fMat[kMScaleX]);
834                 value |= SkAbs32(fMat[kMSkewY]);
835                 clzNumer = SkCLZ(value);
836                 if (shift - clzNumer > 31)
837                     return false;   // overflow
838             }
839 
840             set_muladdmul(&tx, fMat[kMSkewX], fMat[kMTransY], -fMat[kMScaleY], fMat[kMTransX]);
841             set_muladdmul(&ty, fMat[kMSkewY], fMat[kMTransX], -fMat[kMScaleX], fMat[kMTransY]);
842             // check tx,ty for overflow
843             clzNumer = SkCLZ(SkAbs32(tx.fHi) | SkAbs32(ty.fHi));
844             if (shift - clzNumer > 14) {
845                 return false;   // overflow
846             }
847 
848             int fixedShift = 61 - shift;
849             int sk64shift = 44 - shift + clzNumer;
850 
851             inv->fMat[kMScaleX] = SkMulShift(fMat[kMScaleY], scale, fixedShift);
852             inv->fMat[kMSkewX]  = SkMulShift(-fMat[kMSkewX], scale, fixedShift);
853             inv->fMat[kMTransX] = SkMulShift(tx.getShiftRight(33 - clzNumer), scale, sk64shift);
854 
855             inv->fMat[kMSkewY]  = SkMulShift(-fMat[kMSkewY], scale, fixedShift);
856             inv->fMat[kMScaleY] = SkMulShift(fMat[kMScaleX], scale, fixedShift);
857             inv->fMat[kMTransY] = SkMulShift(ty.getShiftRight(33 - clzNumer), scale, sk64shift);
858 #else
859             inv->fMat[kMScaleX] = SkDoubleToFloat(fMat[kMScaleY] * scale);
860             inv->fMat[kMSkewX] = SkDoubleToFloat(-fMat[kMSkewX] * scale);
861             inv->fMat[kMTransX] = mul_diff_scale(fMat[kMSkewX], fMat[kMTransY],
862                                      fMat[kMScaleY], fMat[kMTransX], scale);
863 
864             inv->fMat[kMSkewY] = SkDoubleToFloat(-fMat[kMSkewY] * scale);
865             inv->fMat[kMScaleY] = SkDoubleToFloat(fMat[kMScaleX] * scale);
866             inv->fMat[kMTransY] = mul_diff_scale(fMat[kMSkewY], fMat[kMTransX],
867                                         fMat[kMScaleX], fMat[kMTransY], scale);
868 #endif
869             inv->fMat[kMPersp0] = 0;
870             inv->fMat[kMPersp1] = 0;
871             inv->fMat[kMPersp2] = kMatrix22Elem;
872         }
873 
874         if (inv == &tmp) {
875             *(SkMatrix*)this = tmp;
876         }
877         inv->setTypeMask(kUnknown_Mask);
878     }
879     return true;
880 }
881 
882 ///////////////////////////////////////////////////////////////////////////////
883 
Identity_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)884 void SkMatrix::Identity_pts(const SkMatrix& m, SkPoint dst[],
885                             const SkPoint src[], int count) {
886     SkASSERT(m.getType() == 0);
887 
888     if (dst != src && count > 0)
889         memcpy(dst, src, count * sizeof(SkPoint));
890 }
891 
Trans_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)892 void SkMatrix::Trans_pts(const SkMatrix& m, SkPoint dst[],
893                          const SkPoint src[], int count) {
894     SkASSERT(m.getType() == kTranslate_Mask);
895 
896     if (count > 0) {
897         SkScalar tx = m.fMat[kMTransX];
898         SkScalar ty = m.fMat[kMTransY];
899         do {
900             dst->fY = src->fY + ty;
901             dst->fX = src->fX + tx;
902             src += 1;
903             dst += 1;
904         } while (--count);
905     }
906 }
907 
Scale_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)908 void SkMatrix::Scale_pts(const SkMatrix& m, SkPoint dst[],
909                          const SkPoint src[], int count) {
910     SkASSERT(m.getType() == kScale_Mask);
911 
912     if (count > 0) {
913         SkScalar mx = m.fMat[kMScaleX];
914         SkScalar my = m.fMat[kMScaleY];
915         do {
916             dst->fY = SkScalarMul(src->fY, my);
917             dst->fX = SkScalarMul(src->fX, mx);
918             src += 1;
919             dst += 1;
920         } while (--count);
921     }
922 }
923 
ScaleTrans_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)924 void SkMatrix::ScaleTrans_pts(const SkMatrix& m, SkPoint dst[],
925                               const SkPoint src[], int count) {
926     SkASSERT(m.getType() == (kScale_Mask | kTranslate_Mask));
927 
928     if (count > 0) {
929         SkScalar mx = m.fMat[kMScaleX];
930         SkScalar my = m.fMat[kMScaleY];
931         SkScalar tx = m.fMat[kMTransX];
932         SkScalar ty = m.fMat[kMTransY];
933         do {
934             dst->fY = SkScalarMulAdd(src->fY, my, ty);
935             dst->fX = SkScalarMulAdd(src->fX, mx, tx);
936             src += 1;
937             dst += 1;
938         } while (--count);
939     }
940 }
941 
Rot_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)942 void SkMatrix::Rot_pts(const SkMatrix& m, SkPoint dst[],
943                        const SkPoint src[], int count) {
944     SkASSERT((m.getType() & (kPerspective_Mask | kTranslate_Mask)) == 0);
945 
946     if (count > 0) {
947         SkScalar mx = m.fMat[kMScaleX];
948         SkScalar my = m.fMat[kMScaleY];
949         SkScalar kx = m.fMat[kMSkewX];
950         SkScalar ky = m.fMat[kMSkewY];
951         do {
952             SkScalar sy = src->fY;
953             SkScalar sx = src->fX;
954             src += 1;
955             dst->fY = SkScalarMul(sx, ky) + SkScalarMul(sy, my);
956             dst->fX = SkScalarMul(sx, mx) + SkScalarMul(sy, kx);
957             dst += 1;
958         } while (--count);
959     }
960 }
961 
RotTrans_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)962 void SkMatrix::RotTrans_pts(const SkMatrix& m, SkPoint dst[],
963                             const SkPoint src[], int count) {
964     SkASSERT(!m.hasPerspective());
965 
966     if (count > 0) {
967         SkScalar mx = m.fMat[kMScaleX];
968         SkScalar my = m.fMat[kMScaleY];
969         SkScalar kx = m.fMat[kMSkewX];
970         SkScalar ky = m.fMat[kMSkewY];
971         SkScalar tx = m.fMat[kMTransX];
972         SkScalar ty = m.fMat[kMTransY];
973         do {
974             SkScalar sy = src->fY;
975             SkScalar sx = src->fX;
976             src += 1;
977             dst->fY = SkScalarMul(sx, ky) + SkScalarMulAdd(sy, my, ty);
978             dst->fX = SkScalarMul(sx, mx) + SkScalarMulAdd(sy, kx, tx);
979             dst += 1;
980         } while (--count);
981     }
982 }
983 
Persp_pts(const SkMatrix & m,SkPoint dst[],const SkPoint src[],int count)984 void SkMatrix::Persp_pts(const SkMatrix& m, SkPoint dst[],
985                          const SkPoint src[], int count) {
986     SkASSERT(m.hasPerspective());
987 
988 #ifdef SK_SCALAR_IS_FIXED
989     SkFixed persp2 = SkFractToFixed(m.fMat[kMPersp2]);
990 #endif
991 
992     if (count > 0) {
993         do {
994             SkScalar sy = src->fY;
995             SkScalar sx = src->fX;
996             src += 1;
997 
998             SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) +
999                          SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
1000             SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) +
1001                          SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
1002 #ifdef SK_SCALAR_IS_FIXED
1003             SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) +
1004                         SkFractMul(sy, m.fMat[kMPersp1]) + persp2;
1005 #else
1006             float z = SkScalarMul(sx, m.fMat[kMPersp0]) +
1007                       SkScalarMulAdd(sy, m.fMat[kMPersp1], m.fMat[kMPersp2]);
1008 #endif
1009             if (z) {
1010                 z = SkScalarFastInvert(z);
1011             }
1012 
1013             dst->fY = SkScalarMul(y, z);
1014             dst->fX = SkScalarMul(x, z);
1015             dst += 1;
1016         } while (--count);
1017     }
1018 }
1019 
1020 const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = {
1021     SkMatrix::Identity_pts, SkMatrix::Trans_pts,
1022     SkMatrix::Scale_pts,    SkMatrix::ScaleTrans_pts,
1023     SkMatrix::Rot_pts,      SkMatrix::RotTrans_pts,
1024     SkMatrix::Rot_pts,      SkMatrix::RotTrans_pts,
1025     // repeat the persp proc 8 times
1026     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
1027     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
1028     SkMatrix::Persp_pts,    SkMatrix::Persp_pts,
1029     SkMatrix::Persp_pts,    SkMatrix::Persp_pts
1030 };
1031 
mapPoints(SkPoint dst[],const SkPoint src[],int count) const1032 void SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
1033     SkASSERT((dst && src && count > 0) || count == 0);
1034     // no partial overlap
1035     SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= count);
1036 
1037     this->getMapPtsProc()(*this, dst, src, count);
1038 }
1039 
1040 ///////////////////////////////////////////////////////////////////////////////
1041 
mapVectors(SkPoint dst[],const SkPoint src[],int count) const1042 void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {
1043     if (this->hasPerspective()) {
1044         SkPoint origin;
1045 
1046         MapXYProc proc = this->getMapXYProc();
1047         proc(*this, 0, 0, &origin);
1048 
1049         for (int i = count - 1; i >= 0; --i) {
1050             SkPoint tmp;
1051 
1052             proc(*this, src[i].fX, src[i].fY, &tmp);
1053             dst[i].set(tmp.fX - origin.fX, tmp.fY - origin.fY);
1054         }
1055     } else {
1056         SkMatrix tmp = *this;
1057 
1058         tmp.fMat[kMTransX] = tmp.fMat[kMTransY] = 0;
1059         tmp.clearTypeMask(kTranslate_Mask);
1060         tmp.mapPoints(dst, src, count);
1061     }
1062 }
1063 
mapRect(SkRect * dst,const SkRect & src) const1064 bool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const {
1065     SkASSERT(dst && &src);
1066 
1067     if (this->rectStaysRect()) {
1068         this->mapPoints((SkPoint*)dst, (const SkPoint*)&src, 2);
1069         dst->sort();
1070         return true;
1071     } else {
1072         SkPoint quad[4];
1073 
1074         src.toQuad(quad);
1075         this->mapPoints(quad, quad, 4);
1076         dst->set(quad, 4);
1077         return false;
1078     }
1079 }
1080 
mapRadius(SkScalar radius) const1081 SkScalar SkMatrix::mapRadius(SkScalar radius) const {
1082     SkVector    vec[2];
1083 
1084     vec[0].set(radius, 0);
1085     vec[1].set(0, radius);
1086     this->mapVectors(vec, 2);
1087 
1088     SkScalar d0 = vec[0].length();
1089     SkScalar d1 = vec[1].length();
1090 
1091     return SkScalarMean(d0, d1);
1092 }
1093 
1094 ///////////////////////////////////////////////////////////////////////////////
1095 
Persp_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1096 void SkMatrix::Persp_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1097                         SkPoint* pt) {
1098     SkASSERT(m.hasPerspective());
1099 
1100     SkScalar x = SkScalarMul(sx, m.fMat[kMScaleX]) +
1101                  SkScalarMul(sy, m.fMat[kMSkewX]) + m.fMat[kMTransX];
1102     SkScalar y = SkScalarMul(sx, m.fMat[kMSkewY]) +
1103                  SkScalarMul(sy, m.fMat[kMScaleY]) + m.fMat[kMTransY];
1104 #ifdef SK_SCALAR_IS_FIXED
1105     SkFixed z = SkFractMul(sx, m.fMat[kMPersp0]) +
1106                 SkFractMul(sy, m.fMat[kMPersp1]) +
1107                 SkFractToFixed(m.fMat[kMPersp2]);
1108 #else
1109     float z = SkScalarMul(sx, m.fMat[kMPersp0]) +
1110               SkScalarMul(sy, m.fMat[kMPersp1]) + m.fMat[kMPersp2];
1111 #endif
1112     if (z) {
1113         z = SkScalarFastInvert(z);
1114     }
1115     pt->fX = SkScalarMul(x, z);
1116     pt->fY = SkScalarMul(y, z);
1117 }
1118 
1119 #ifdef SK_SCALAR_IS_FIXED
fixmuladdmul(SkFixed a,SkFixed b,SkFixed c,SkFixed d)1120 static SkFixed fixmuladdmul(SkFixed a, SkFixed b, SkFixed c, SkFixed d) {
1121     Sk64    tmp, tmp1;
1122 
1123     tmp.setMul(a, b);
1124     tmp1.setMul(c, d);
1125     return tmp.addGetFixed(tmp1);
1126 //  tmp.add(tmp1);
1127 //  return tmp.getFixed();
1128 }
1129 #endif
1130 
RotTrans_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1131 void SkMatrix::RotTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1132                            SkPoint* pt) {
1133     SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask)) == kAffine_Mask);
1134 
1135 #ifdef SK_SCALAR_IS_FIXED
1136     pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]) +
1137              m.fMat[kMTransX];
1138     pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]) +
1139              m.fMat[kMTransY];
1140 #else
1141     pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) +
1142              SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]);
1143     pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) +
1144              SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
1145 #endif
1146 }
1147 
Rot_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1148 void SkMatrix::Rot_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1149                       SkPoint* pt) {
1150     SkASSERT((m.getType() & (kAffine_Mask | kPerspective_Mask))== kAffine_Mask);
1151     SkASSERT(0 == m.fMat[kMTransX]);
1152     SkASSERT(0 == m.fMat[kMTransY]);
1153 
1154 #ifdef SK_SCALAR_IS_FIXED
1155     pt->fX = fixmuladdmul(sx, m.fMat[kMScaleX], sy, m.fMat[kMSkewX]);
1156     pt->fY = fixmuladdmul(sx, m.fMat[kMSkewY], sy, m.fMat[kMScaleY]);
1157 #else
1158     pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]) +
1159              SkScalarMulAdd(sy, m.fMat[kMSkewX], m.fMat[kMTransX]);
1160     pt->fY = SkScalarMul(sx, m.fMat[kMSkewY]) +
1161              SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
1162 #endif
1163 }
1164 
ScaleTrans_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1165 void SkMatrix::ScaleTrans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1166                              SkPoint* pt) {
1167     SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
1168              == kScale_Mask);
1169 
1170     pt->fX = SkScalarMulAdd(sx, m.fMat[kMScaleX], m.fMat[kMTransX]);
1171     pt->fY = SkScalarMulAdd(sy, m.fMat[kMScaleY], m.fMat[kMTransY]);
1172 }
1173 
Scale_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1174 void SkMatrix::Scale_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1175                         SkPoint* pt) {
1176     SkASSERT((m.getType() & (kScale_Mask | kAffine_Mask | kPerspective_Mask))
1177              == kScale_Mask);
1178     SkASSERT(0 == m.fMat[kMTransX]);
1179     SkASSERT(0 == m.fMat[kMTransY]);
1180 
1181     pt->fX = SkScalarMul(sx, m.fMat[kMScaleX]);
1182     pt->fY = SkScalarMul(sy, m.fMat[kMScaleY]);
1183 }
1184 
Trans_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1185 void SkMatrix::Trans_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1186                         SkPoint* pt) {
1187     SkASSERT(m.getType() == kTranslate_Mask);
1188 
1189     pt->fX = sx + m.fMat[kMTransX];
1190     pt->fY = sy + m.fMat[kMTransY];
1191 }
1192 
Identity_xy(const SkMatrix & m,SkScalar sx,SkScalar sy,SkPoint * pt)1193 void SkMatrix::Identity_xy(const SkMatrix& m, SkScalar sx, SkScalar sy,
1194                            SkPoint* pt) {
1195     SkASSERT(0 == m.getType());
1196 
1197     pt->fX = sx;
1198     pt->fY = sy;
1199 }
1200 
1201 const SkMatrix::MapXYProc SkMatrix::gMapXYProcs[] = {
1202     SkMatrix::Identity_xy, SkMatrix::Trans_xy,
1203     SkMatrix::Scale_xy,    SkMatrix::ScaleTrans_xy,
1204     SkMatrix::Rot_xy,      SkMatrix::RotTrans_xy,
1205     SkMatrix::Rot_xy,      SkMatrix::RotTrans_xy,
1206     // repeat the persp proc 8 times
1207     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
1208     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
1209     SkMatrix::Persp_xy,    SkMatrix::Persp_xy,
1210     SkMatrix::Persp_xy,    SkMatrix::Persp_xy
1211 };
1212 
1213 ///////////////////////////////////////////////////////////////////////////////
1214 
1215 // if its nearly zero (just made up 26, perhaps it should be bigger or smaller)
1216 #ifdef SK_SCALAR_IS_FIXED
1217     typedef SkFract             SkPerspElemType;
1218     #define PerspNearlyZero(x)  (SkAbs32(x) < (SK_Fract1 >> 26))
1219 #else
1220     typedef float               SkPerspElemType;
1221     #define PerspNearlyZero(x)  SkScalarNearlyZero(x, (1.0f / (1 << 26)))
1222 #endif
1223 
fixedStepInX(SkScalar y,SkFixed * stepX,SkFixed * stepY) const1224 bool SkMatrix::fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const {
1225     if (PerspNearlyZero(fMat[kMPersp0])) {
1226         if (stepX || stepY) {
1227             if (PerspNearlyZero(fMat[kMPersp1]) &&
1228                     PerspNearlyZero(fMat[kMPersp2] - kMatrix22Elem)) {
1229                 if (stepX) {
1230                     *stepX = SkScalarToFixed(fMat[kMScaleX]);
1231                 }
1232                 if (stepY) {
1233                     *stepY = SkScalarToFixed(fMat[kMSkewY]);
1234                 }
1235             } else {
1236 #ifdef SK_SCALAR_IS_FIXED
1237                 SkFixed z = SkFractMul(y, fMat[kMPersp1]) +
1238                             SkFractToFixed(fMat[kMPersp2]);
1239 #else
1240                 float z = y * fMat[kMPersp1] + fMat[kMPersp2];
1241 #endif
1242                 if (stepX) {
1243                     *stepX = SkScalarToFixed(SkScalarDiv(fMat[kMScaleX], z));
1244                 }
1245                 if (stepY) {
1246                     *stepY = SkScalarToFixed(SkScalarDiv(fMat[kMSkewY], z));
1247                 }
1248             }
1249         }
1250         return true;
1251     }
1252     return false;
1253 }
1254 
1255 ///////////////////////////////////////////////////////////////////////////////
1256 
1257 #include "SkPerspIter.h"
1258 
SkPerspIter(const SkMatrix & m,SkScalar x0,SkScalar y0,int count)1259 SkPerspIter::SkPerspIter(const SkMatrix& m, SkScalar x0, SkScalar y0, int count)
1260         : fMatrix(m), fSX(x0), fSY(y0), fCount(count) {
1261     SkPoint pt;
1262 
1263     SkMatrix::Persp_xy(m, x0, y0, &pt);
1264     fX = SkScalarToFixed(pt.fX);
1265     fY = SkScalarToFixed(pt.fY);
1266 }
1267 
next()1268 int SkPerspIter::next() {
1269     int n = fCount;
1270 
1271     if (0 == n) {
1272         return 0;
1273     }
1274     SkPoint pt;
1275     SkFixed x = fX;
1276     SkFixed y = fY;
1277     SkFixed dx, dy;
1278 
1279     if (n >= kCount) {
1280         n = kCount;
1281         fSX += SkIntToScalar(kCount);
1282         SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
1283         fX = SkScalarToFixed(pt.fX);
1284         fY = SkScalarToFixed(pt.fY);
1285         dx = (fX - x) >> kShift;
1286         dy = (fY - y) >> kShift;
1287     } else {
1288         fSX += SkIntToScalar(n);
1289         SkMatrix::Persp_xy(fMatrix, fSX, fSY, &pt);
1290         fX = SkScalarToFixed(pt.fX);
1291         fY = SkScalarToFixed(pt.fY);
1292         dx = (fX - x) / n;
1293         dy = (fY - y) / n;
1294     }
1295 
1296     SkFixed* p = fStorage;
1297     for (int i = 0; i < n; i++) {
1298         *p++ = x; x += dx;
1299         *p++ = y; y += dy;
1300     }
1301 
1302     fCount -= n;
1303     return n;
1304 }
1305 
1306 ///////////////////////////////////////////////////////////////////////////////
1307 
1308 #ifdef SK_SCALAR_IS_FIXED
1309 
poly_to_point(SkPoint * pt,const SkPoint poly[],int count)1310 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
1311     SkFixed x = SK_Fixed1, y = SK_Fixed1;
1312     SkPoint pt1, pt2;
1313     Sk64    w1, w2;
1314 
1315     if (count > 1) {
1316         pt1.fX = poly[1].fX - poly[0].fX;
1317         pt1.fY = poly[1].fY - poly[0].fY;
1318         y = SkPoint::Length(pt1.fX, pt1.fY);
1319         if (y == 0) {
1320             return false;
1321         }
1322         switch (count) {
1323             case 2:
1324                 break;
1325             case 3:
1326                 pt2.fX = poly[0].fY - poly[2].fY;
1327                 pt2.fY = poly[2].fX - poly[0].fX;
1328                 goto CALC_X;
1329             default:
1330                 pt2.fX = poly[0].fY - poly[3].fY;
1331                 pt2.fY = poly[3].fX - poly[0].fX;
1332             CALC_X:
1333                 w1.setMul(pt1.fX, pt2.fX);
1334                 w2.setMul(pt1.fY, pt2.fY);
1335                 w1.add(w2);
1336                 w1.div(y, Sk64::kRound_DivOption);
1337                 if (!w1.is32()) {
1338                     return false;
1339                 }
1340                 x = w1.get32();
1341                 break;
1342         }
1343     }
1344     pt->set(x, y);
1345     return true;
1346 }
1347 
Poly2Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scalePt)1348 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
1349                          const SkPoint& scalePt) {
1350     // need to check if SkFixedDiv overflows...
1351 
1352     const SkFixed scale = scalePt.fY;
1353     dst->fMat[kMScaleX] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale);
1354     dst->fMat[kMSkewY]  = SkFixedDiv(srcPt[0].fX - srcPt[1].fX, scale);
1355     dst->fMat[kMPersp0] = 0;
1356     dst->fMat[kMSkewX]  = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale);
1357     dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale);
1358     dst->fMat[kMPersp1] = 0;
1359     dst->fMat[kMTransX] = srcPt[0].fX;
1360     dst->fMat[kMTransY] = srcPt[0].fY;
1361     dst->fMat[kMPersp2] = SK_Fract1;
1362     dst->setTypeMask(kUnknown_Mask);
1363     return true;
1364 }
1365 
Poly3Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1366 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
1367                          const SkPoint& scale) {
1368     // really, need to check if SkFixedDiv overflow'd
1369 
1370     dst->fMat[kMScaleX] = SkFixedDiv(srcPt[2].fX - srcPt[0].fX, scale.fX);
1371     dst->fMat[kMSkewY]  = SkFixedDiv(srcPt[2].fY - srcPt[0].fY, scale.fX);
1372     dst->fMat[kMPersp0] = 0;
1373     dst->fMat[kMSkewX]  = SkFixedDiv(srcPt[1].fX - srcPt[0].fX, scale.fY);
1374     dst->fMat[kMScaleY] = SkFixedDiv(srcPt[1].fY - srcPt[0].fY, scale.fY);
1375     dst->fMat[kMPersp1] = 0;
1376     dst->fMat[kMTransX] = srcPt[0].fX;
1377     dst->fMat[kMTransY] = srcPt[0].fY;
1378     dst->fMat[kMPersp2] = SK_Fract1;
1379     dst->setTypeMask(kUnknown_Mask);
1380     return true;
1381 }
1382 
Poly4Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1383 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
1384                          const SkPoint& scale) {
1385     SkFract a1, a2;
1386     SkFixed x0, y0, x1, y1, x2, y2;
1387 
1388     x0 = srcPt[2].fX - srcPt[0].fX;
1389     y0 = srcPt[2].fY - srcPt[0].fY;
1390     x1 = srcPt[2].fX - srcPt[1].fX;
1391     y1 = srcPt[2].fY - srcPt[1].fY;
1392     x2 = srcPt[2].fX - srcPt[3].fX;
1393     y2 = srcPt[2].fY - srcPt[3].fY;
1394 
1395     /* check if abs(x2) > abs(y2) */
1396     if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
1397         SkFixed denom = SkMulDiv(x1, y2, x2) - y1;
1398         if (0 == denom) {
1399             return false;
1400         }
1401         a1 = SkFractDiv(SkMulDiv(x0 - x1, y2, x2) - y0 + y1, denom);
1402     } else {
1403         SkFixed denom = x1 - SkMulDiv(y1, x2, y2);
1404         if (0 == denom) {
1405             return false;
1406         }
1407         a1 = SkFractDiv(x0 - x1 - SkMulDiv(y0 - y1, x2, y2), denom);
1408     }
1409 
1410     /* check if abs(x1) > abs(y1) */
1411     if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
1412         SkFixed denom = y2 - SkMulDiv(x2, y1, x1);
1413         if (0 == denom) {
1414             return false;
1415         }
1416         a2 = SkFractDiv(y0 - y2 - SkMulDiv(x0 - x2, y1, x1), denom);
1417     } else {
1418         SkFixed denom = SkMulDiv(y2, x1, y1) - x2;
1419         if (0 == denom) {
1420             return false;
1421         }
1422         a2 = SkFractDiv(SkMulDiv(y0 - y2, x1, y1) - x0 + x2, denom);
1423     }
1424 
1425     // need to check if SkFixedDiv overflows...
1426     dst->fMat[kMScaleX] = SkFixedDiv(SkFractMul(a2, srcPt[3].fX) +
1427                                      srcPt[3].fX - srcPt[0].fX, scale.fX);
1428     dst->fMat[kMSkewY]  = SkFixedDiv(SkFractMul(a2, srcPt[3].fY) +
1429                                      srcPt[3].fY - srcPt[0].fY, scale.fX);
1430     dst->fMat[kMPersp0] = SkFixedDiv(a2, scale.fX);
1431     dst->fMat[kMSkewX]  = SkFixedDiv(SkFractMul(a1, srcPt[1].fX) +
1432                                      srcPt[1].fX - srcPt[0].fX, scale.fY);
1433     dst->fMat[kMScaleY] = SkFixedDiv(SkFractMul(a1, srcPt[1].fY) +
1434                                      srcPt[1].fY - srcPt[0].fY, scale.fY);
1435     dst->fMat[kMPersp1] = SkFixedDiv(a1, scale.fY);
1436     dst->fMat[kMTransX] = srcPt[0].fX;
1437     dst->fMat[kMTransY] = srcPt[0].fY;
1438     dst->fMat[kMPersp2] = SK_Fract1;
1439     dst->setTypeMask(kUnknown_Mask);
1440     return true;
1441 }
1442 
1443 #else   /* Scalar is float */
1444 
checkForZero(float x)1445 static inline bool checkForZero(float x) {
1446     return x*x == 0;
1447 }
1448 
poly_to_point(SkPoint * pt,const SkPoint poly[],int count)1449 static inline bool poly_to_point(SkPoint* pt, const SkPoint poly[], int count) {
1450     float   x = 1, y = 1;
1451     SkPoint pt1, pt2;
1452 
1453     if (count > 1) {
1454         pt1.fX = poly[1].fX - poly[0].fX;
1455         pt1.fY = poly[1].fY - poly[0].fY;
1456         y = SkPoint::Length(pt1.fX, pt1.fY);
1457         if (checkForZero(y)) {
1458             return false;
1459         }
1460         switch (count) {
1461             case 2:
1462                 break;
1463             case 3:
1464                 pt2.fX = poly[0].fY - poly[2].fY;
1465                 pt2.fY = poly[2].fX - poly[0].fX;
1466                 goto CALC_X;
1467             default:
1468                 pt2.fX = poly[0].fY - poly[3].fY;
1469                 pt2.fY = poly[3].fX - poly[0].fX;
1470             CALC_X:
1471                 x = SkScalarDiv(SkScalarMul(pt1.fX, pt2.fX) +
1472                                 SkScalarMul(pt1.fY, pt2.fY), y);
1473                 break;
1474         }
1475     }
1476     pt->set(x, y);
1477     return true;
1478 }
1479 
Poly2Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1480 bool SkMatrix::Poly2Proc(const SkPoint srcPt[], SkMatrix* dst,
1481                          const SkPoint& scale) {
1482     float invScale = 1 / scale.fY;
1483 
1484     dst->fMat[kMScaleX] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1485     dst->fMat[kMSkewY] = (srcPt[0].fX - srcPt[1].fX) * invScale;
1486     dst->fMat[kMPersp0] = 0;
1487     dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
1488     dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1489     dst->fMat[kMPersp1] = 0;
1490     dst->fMat[kMTransX] = srcPt[0].fX;
1491     dst->fMat[kMTransY] = srcPt[0].fY;
1492     dst->fMat[kMPersp2] = 1;
1493     dst->setTypeMask(kUnknown_Mask);
1494     return true;
1495 }
1496 
Poly3Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1497 bool SkMatrix::Poly3Proc(const SkPoint srcPt[], SkMatrix* dst,
1498                          const SkPoint& scale) {
1499     float invScale = 1 / scale.fX;
1500     dst->fMat[kMScaleX] = (srcPt[2].fX - srcPt[0].fX) * invScale;
1501     dst->fMat[kMSkewY] = (srcPt[2].fY - srcPt[0].fY) * invScale;
1502     dst->fMat[kMPersp0] = 0;
1503 
1504     invScale = 1 / scale.fY;
1505     dst->fMat[kMSkewX] = (srcPt[1].fX - srcPt[0].fX) * invScale;
1506     dst->fMat[kMScaleY] = (srcPt[1].fY - srcPt[0].fY) * invScale;
1507     dst->fMat[kMPersp1] = 0;
1508 
1509     dst->fMat[kMTransX] = srcPt[0].fX;
1510     dst->fMat[kMTransY] = srcPt[0].fY;
1511     dst->fMat[kMPersp2] = 1;
1512     dst->setTypeMask(kUnknown_Mask);
1513     return true;
1514 }
1515 
Poly4Proc(const SkPoint srcPt[],SkMatrix * dst,const SkPoint & scale)1516 bool SkMatrix::Poly4Proc(const SkPoint srcPt[], SkMatrix* dst,
1517                          const SkPoint& scale) {
1518     float   a1, a2;
1519     float   x0, y0, x1, y1, x2, y2;
1520 
1521     x0 = srcPt[2].fX - srcPt[0].fX;
1522     y0 = srcPt[2].fY - srcPt[0].fY;
1523     x1 = srcPt[2].fX - srcPt[1].fX;
1524     y1 = srcPt[2].fY - srcPt[1].fY;
1525     x2 = srcPt[2].fX - srcPt[3].fX;
1526     y2 = srcPt[2].fY - srcPt[3].fY;
1527 
1528     /* check if abs(x2) > abs(y2) */
1529     if ( x2 > 0 ? y2 > 0 ? x2 > y2 : x2 > -y2 : y2 > 0 ? -x2 > y2 : x2 < y2) {
1530         float denom = SkScalarMulDiv(x1, y2, x2) - y1;
1531         if (checkForZero(denom)) {
1532             return false;
1533         }
1534         a1 = SkScalarDiv(SkScalarMulDiv(x0 - x1, y2, x2) - y0 + y1, denom);
1535     } else {
1536         float denom = x1 - SkScalarMulDiv(y1, x2, y2);
1537         if (checkForZero(denom)) {
1538             return false;
1539         }
1540         a1 = SkScalarDiv(x0 - x1 - SkScalarMulDiv(y0 - y1, x2, y2), denom);
1541     }
1542 
1543     /* check if abs(x1) > abs(y1) */
1544     if ( x1 > 0 ? y1 > 0 ? x1 > y1 : x1 > -y1 : y1 > 0 ? -x1 > y1 : x1 < y1) {
1545         float denom = y2 - SkScalarMulDiv(x2, y1, x1);
1546         if (checkForZero(denom)) {
1547             return false;
1548         }
1549         a2 = SkScalarDiv(y0 - y2 - SkScalarMulDiv(x0 - x2, y1, x1), denom);
1550     } else {
1551         float denom = SkScalarMulDiv(y2, x1, y1) - x2;
1552         if (checkForZero(denom)) {
1553             return false;
1554         }
1555         a2 = SkScalarDiv(SkScalarMulDiv(y0 - y2, x1, y1) - x0 + x2, denom);
1556     }
1557 
1558     float invScale = 1 / scale.fX;
1559     dst->fMat[kMScaleX] = SkScalarMul(SkScalarMul(a2, srcPt[3].fX) +
1560                                       srcPt[3].fX - srcPt[0].fX, invScale);
1561     dst->fMat[kMSkewY] = SkScalarMul(SkScalarMul(a2, srcPt[3].fY) +
1562                                      srcPt[3].fY - srcPt[0].fY, invScale);
1563     dst->fMat[kMPersp0] = SkScalarMul(a2, invScale);
1564     invScale = 1 / scale.fY;
1565     dst->fMat[kMSkewX] = SkScalarMul(SkScalarMul(a1, srcPt[1].fX) +
1566                                      srcPt[1].fX - srcPt[0].fX, invScale);
1567     dst->fMat[kMScaleY] = SkScalarMul(SkScalarMul(a1, srcPt[1].fY) +
1568                                       srcPt[1].fY - srcPt[0].fY, invScale);
1569     dst->fMat[kMPersp1] = SkScalarMul(a1, invScale);
1570     dst->fMat[kMTransX] = srcPt[0].fX;
1571     dst->fMat[kMTransY] = srcPt[0].fY;
1572     dst->fMat[kMPersp2] = 1;
1573     dst->setTypeMask(kUnknown_Mask);
1574     return true;
1575 }
1576 
1577 #endif
1578 
1579 typedef bool (*PolyMapProc)(const SkPoint[], SkMatrix*, const SkPoint&);
1580 
1581 /*  Taken from Rob Johnson's original sample code in QuickDraw GX
1582 */
setPolyToPoly(const SkPoint src[],const SkPoint dst[],int count)1583 bool SkMatrix::setPolyToPoly(const SkPoint src[], const SkPoint dst[],
1584                              int count) {
1585     if ((unsigned)count > 4) {
1586         SkDebugf("--- SkMatrix::setPolyToPoly count out of range %d\n", count);
1587         return false;
1588     }
1589 
1590     if (0 == count) {
1591         this->reset();
1592         return true;
1593     }
1594     if (1 == count) {
1595         this->setTranslate(dst[0].fX - src[0].fX, dst[0].fY - src[0].fY);
1596         return true;
1597     }
1598 
1599     SkPoint scale;
1600     if (!poly_to_point(&scale, src, count) ||
1601             SkScalarNearlyZero(scale.fX) ||
1602             SkScalarNearlyZero(scale.fY)) {
1603         return false;
1604     }
1605 
1606     static const PolyMapProc gPolyMapProcs[] = {
1607         SkMatrix::Poly2Proc, SkMatrix::Poly3Proc, SkMatrix::Poly4Proc
1608     };
1609     PolyMapProc proc = gPolyMapProcs[count - 2];
1610 
1611     SkMatrix tempMap, result;
1612     tempMap.setTypeMask(kUnknown_Mask);
1613 
1614     if (!proc(src, &tempMap, scale)) {
1615         return false;
1616     }
1617     if (!tempMap.invert(&result)) {
1618         return false;
1619     }
1620     if (!proc(dst, &tempMap, scale)) {
1621         return false;
1622     }
1623     if (!result.setConcat(tempMap, result)) {
1624         return false;
1625     }
1626     *this = result;
1627     return true;
1628 }
1629 
1630 ///////////////////////////////////////////////////////////////////////////////
1631 
getMaxStretch() const1632 SkScalar SkMatrix::getMaxStretch() const {
1633     TypeMask mask = this->getType();
1634 
1635     if (mask & kPerspective_Mask) {
1636         return -SK_Scalar1;
1637     }
1638 
1639     SkScalar stretch;
1640 
1641     if (this->isIdentity()) {
1642         stretch = SK_Scalar1;
1643     } else if (!(mask & kAffine_Mask)) {
1644         stretch = SkMaxScalar(SkScalarAbs(fMat[kMScaleX]), SkScalarAbs(fMat[kMScaleY]));
1645 #if 0   // don't have this bit
1646     } else if (mask & kZeroScale_TypeBit) {
1647         stretch = SkMaxScalar(SkScalarAbs(fM[kSkewX]), SkScalarAbs(fM[kSkewY]));
1648 #endif
1649     } else {
1650         // ignore the translation part of the matrix, just look at 2x2 portion.
1651         // compute singular values, take largest abs value.
1652         // [a b; b c] = A^T*A
1653         SkScalar a = SkScalarMul(fMat[kMScaleX], fMat[kMScaleX]) + SkScalarMul(fMat[kMSkewY],  fMat[kMSkewY]);
1654         SkScalar b = SkScalarMul(fMat[kMScaleX], fMat[kMSkewX]) +  SkScalarMul(fMat[kMScaleY], fMat[kMSkewY]);
1655         SkScalar c = SkScalarMul(fMat[kMSkewX],  fMat[kMSkewX]) +  SkScalarMul(fMat[kMScaleY], fMat[kMScaleY]);
1656         // eigenvalues of A^T*A are the squared singular values of A.
1657         // characteristic equation is det((A^T*A) - l*I) = 0
1658         // l^2 - (a + c)l + (ac-b^2)
1659         // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
1660         // and roots are guaraunteed to be pos and real).
1661         SkScalar largerRoot;
1662         SkScalar bSqd = SkScalarMul(b,b);
1663         if (bSqd <= SkFloatToScalar(1e-10)) { // will be true if upper left 2x2 is orthogonal, which is common, so save some math
1664             largerRoot = SkMaxScalar(a, c);
1665         } else {
1666             SkScalar aminusc = a - c;
1667             SkScalar apluscdiv2 = (a + c) / 2;
1668             SkScalar x = SkScalarSqrt(SkScalarMul(aminusc, aminusc) + 4 * bSqd) / 2;
1669             largerRoot = apluscdiv2 + x;
1670         }
1671 
1672         stretch = SkScalarSqrt(largerRoot);
1673     }
1674 #if defined(SK_DEBUG) && 0
1675     // test a bunch of vectors. None should be scaled by more than stretch
1676     // (modulo some error) and we should find a vector that is scaled by almost
1677     // stretch.
1678     SkPoint pt;
1679     SkScalar max = 0;
1680     for (int i = 0; i < 1000; ++i) {
1681         SkScalar x = (float)rand() / RAND_MAX;
1682         SkScalar y = sqrtf(1 - (x*x));
1683         pt.fX = fMat[kMScaleX]*x + fMat[kMSkewX]*y;
1684         pt.fY = fMat[kMSkewY]*x + fMat[kMScaleY]*y;
1685         SkScalar d = pt.distanceToOrigin();
1686         SkASSERT(d <= (1.0001 * stretch));
1687         if (max < pt.distanceToOrigin()) {
1688             max = pt.distanceToOrigin();
1689         }
1690     }
1691     SkASSERT((stretch - max) < .05*stretch);
1692 #endif
1693     return stretch;
1694 }
1695 
I()1696 const SkMatrix& SkMatrix::I() {
1697     static SkMatrix gIdentity;
1698     static bool gOnce;
1699     if (!gOnce) {
1700         gIdentity.reset();
1701         gOnce = true;
1702     }
1703     return gIdentity;
1704 };
1705 
InvalidMatrix()1706 const SkMatrix& SkMatrix::InvalidMatrix() {
1707     static SkMatrix gInvalid;
1708     static bool gOnce;
1709     if (!gOnce) {
1710         gInvalid.setAll(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
1711                         SK_ScalarMax, SK_ScalarMax, SK_ScalarMax,
1712                         SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
1713         gInvalid.getType(); // force the type to be computed
1714         gOnce = true;
1715     }
1716     return gInvalid;
1717 }
1718 
1719 ///////////////////////////////////////////////////////////////////////////////
1720 
flatten(void * buffer) const1721 uint32_t SkMatrix::flatten(void* buffer) const {
1722     // TODO write less for simple matrices
1723     if (buffer) {
1724         memcpy(buffer, fMat, 9 * sizeof(SkScalar));
1725     }
1726     return 9 * sizeof(SkScalar);
1727 }
1728 
unflatten(const void * buffer)1729 uint32_t SkMatrix::unflatten(const void* buffer) {
1730     if (buffer) {
1731         memcpy(fMat, buffer, 9 * sizeof(SkScalar));
1732         this->setTypeMask(kUnknown_Mask);
1733     }
1734     return 9 * sizeof(SkScalar);
1735 }
1736 
dump() const1737 void SkMatrix::dump() const {
1738     SkString str;
1739     this->toDumpString(&str);
1740     SkDebugf("%s\n", str.c_str());
1741 }
1742 
toDumpString(SkString * str) const1743 void SkMatrix::toDumpString(SkString* str) const {
1744 #ifdef SK_CAN_USE_FLOAT
1745     str->printf("[%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f][%8.4f %8.4f %8.4f]",
1746 #ifdef SK_SCALAR_IS_FLOAT
1747              fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5],
1748              fMat[6], fMat[7], fMat[8]);
1749 #else
1750     SkFixedToFloat(fMat[0]), SkFixedToFloat(fMat[1]), SkFixedToFloat(fMat[2]),
1751     SkFixedToFloat(fMat[3]), SkFixedToFloat(fMat[4]), SkFixedToFloat(fMat[5]),
1752     SkFractToFloat(fMat[6]), SkFractToFloat(fMat[7]), SkFractToFloat(fMat[8]));
1753 #endif
1754 #else   // can't use float
1755     str->printf("[%x %x %x][%x %x %x][%x %x %x]",
1756                 fMat[0], fMat[1], fMat[2], fMat[3], fMat[4], fMat[5],
1757                 fMat[6], fMat[7], fMat[8]);
1758 #endif
1759 }
1760