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