SkMatrix.cpp
Upload User: micun2005
Upload Date: 2020-11-27
Package Size: 11738k
Code Size: 54k
Development Platform:

Visual C++

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