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