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