Home | History | Annotate | Download | only in surfaceflinger
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <math.h>
     18 
     19 #include <cutils/compiler.h>
     20 #include <utils/String8.h>
     21 #include <ui/Region.h>
     22 
     23 #include "Transform.h"
     24 
     25 // ---------------------------------------------------------------------------
     26 
     27 namespace android {
     28 
     29 // ---------------------------------------------------------------------------
     30 
     31 template <typename T> inline T min(T a, T b) {
     32     return a<b ? a : b;
     33 }
     34 template <typename T> inline T min(T a, T b, T c) {
     35     return min(a, min(b, c));
     36 }
     37 template <typename T> inline T min(T a, T b, T c, T d) {
     38     return min(a, b, min(c, d));
     39 }
     40 
     41 template <typename T> inline T max(T a, T b) {
     42     return a>b ? a : b;
     43 }
     44 template <typename T> inline T max(T a, T b, T c) {
     45     return max(a, max(b, c));
     46 }
     47 template <typename T> inline T max(T a, T b, T c, T d) {
     48     return max(a, b, max(c, d));
     49 }
     50 
     51 // ---------------------------------------------------------------------------
     52 
     53 Transform::Transform() {
     54     reset();
     55 }
     56 
     57 Transform::Transform(const Transform&  other)
     58     : mMatrix(other.mMatrix), mType(other.mType) {
     59 }
     60 
     61 Transform::Transform(uint32_t orientation) {
     62     set(orientation, 0, 0);
     63 }
     64 
     65 Transform::~Transform() {
     66 }
     67 
     68 static const float EPSILON = 0.0f;
     69 
     70 bool Transform::isZero(float f) {
     71     return fabs(f) <= EPSILON;
     72 }
     73 
     74 bool Transform::absIsOne(float f) {
     75     return isZero(fabs(f) - 1.0f);
     76 }
     77 
     78 Transform Transform::operator * (const Transform& rhs) const
     79 {
     80     if (CC_LIKELY(mType == IDENTITY))
     81         return rhs;
     82 
     83     Transform r(*this);
     84     if (rhs.mType == IDENTITY)
     85         return r;
     86 
     87     // TODO: we could use mType to optimize the matrix multiply
     88     const mat33& A(mMatrix);
     89     const mat33& B(rhs.mMatrix);
     90           mat33& D(r.mMatrix);
     91     for (int i=0 ; i<3 ; i++) {
     92         const float v0 = A[0][i];
     93         const float v1 = A[1][i];
     94         const float v2 = A[2][i];
     95         D[0][i] = v0*B[0][0] + v1*B[0][1] + v2*B[0][2];
     96         D[1][i] = v0*B[1][0] + v1*B[1][1] + v2*B[1][2];
     97         D[2][i] = v0*B[2][0] + v1*B[2][1] + v2*B[2][2];
     98     }
     99     r.mType |= rhs.mType;
    100 
    101     // TODO: we could recompute this value from r and rhs
    102     r.mType &= 0xFF;
    103     r.mType |= UNKNOWN_TYPE;
    104     return r;
    105 }
    106 
    107 float const* Transform::operator [] (int i) const {
    108     return mMatrix[i].v;
    109 }
    110 
    111 bool Transform::transformed() const {
    112     return type() > TRANSLATE;
    113 }
    114 
    115 int Transform::tx() const {
    116     return floorf(mMatrix[2][0] + 0.5f);
    117 }
    118 
    119 int Transform::ty() const {
    120     return floorf(mMatrix[2][1] + 0.5f);
    121 }
    122 
    123 void Transform::reset() {
    124     mType = IDENTITY;
    125     for(int i=0 ; i<3 ; i++) {
    126         vec3& v(mMatrix[i]);
    127         for (int j=0 ; j<3 ; j++)
    128             v[j] = ((i==j) ? 1.0f : 0.0f);
    129     }
    130 }
    131 
    132 void Transform::set(float tx, float ty)
    133 {
    134     mMatrix[2][0] = tx;
    135     mMatrix[2][1] = ty;
    136     mMatrix[2][2] = 1.0f;
    137 
    138     if (isZero(tx) && isZero(ty)) {
    139         mType &= ~TRANSLATE;
    140     } else {
    141         mType |= TRANSLATE;
    142     }
    143 }
    144 
    145 void Transform::set(float a, float b, float c, float d)
    146 {
    147     mat33& M(mMatrix);
    148     M[0][0] = a;    M[1][0] = b;
    149     M[0][1] = c;    M[1][1] = d;
    150     M[0][2] = 0;    M[1][2] = 0;
    151     mType = UNKNOWN_TYPE;
    152 }
    153 
    154 status_t Transform::set(uint32_t flags, float w, float h)
    155 {
    156     if (flags & ROT_INVALID) {
    157         // that's not allowed!
    158         reset();
    159         return BAD_VALUE;
    160     }
    161 
    162     mType = flags << 8;
    163     float sx = (flags & FLIP_H) ? -1 : 1;
    164     float sy = (flags & FLIP_V) ? -1 : 1;
    165     float a=0, b=0, c=0, d=0, x=0, y=0;
    166     int xmask = 0;
    167 
    168     // computation of x,y
    169     // x y
    170     // 0 0  0
    171     // w 0  ROT90
    172     // w h  FLIPH|FLIPV
    173     // 0 h  FLIPH|FLIPV|ROT90
    174 
    175     if (flags & ROT_90) {
    176         mType |= ROTATE;
    177         b = -sy;
    178         c = sx;
    179         xmask = 1;
    180     } else {
    181         a = sx;
    182         d = sy;
    183     }
    184 
    185     if (flags & FLIP_H) {
    186         mType ^= SCALE;
    187         xmask ^= 1;
    188     }
    189 
    190     if (flags & FLIP_V) {
    191         mType ^= SCALE;
    192         y = h;
    193     }
    194 
    195     if ((flags & ROT_180) == ROT_180) {
    196         mType |= ROTATE;
    197     }
    198 
    199     if (xmask) {
    200         x = w;
    201     }
    202 
    203     if (!isZero(x) || !isZero(y)) {
    204         mType |= TRANSLATE;
    205     }
    206 
    207     mat33& M(mMatrix);
    208     M[0][0] = a;    M[1][0] = b;    M[2][0] = x;
    209     M[0][1] = c;    M[1][1] = d;    M[2][1] = y;
    210     M[0][2] = 0;    M[1][2] = 0;    M[2][2] = 1;
    211 
    212     return NO_ERROR;
    213 }
    214 
    215 Transform::vec2 Transform::transform(const vec2& v) const {
    216     vec2 r;
    217     const mat33& M(mMatrix);
    218     r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0];
    219     r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1];
    220     return r;
    221 }
    222 
    223 Transform::vec3 Transform::transform(const vec3& v) const {
    224     vec3 r;
    225     const mat33& M(mMatrix);
    226     r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0]*v[2];
    227     r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1]*v[2];
    228     r[2] = M[0][2]*v[0] + M[1][2]*v[1] + M[2][2]*v[2];
    229     return r;
    230 }
    231 
    232 void Transform::transform(fixed1616* point, int x, int y) const
    233 {
    234     const float toFixed = 65536.0f;
    235     const mat33& M(mMatrix);
    236     vec2 v(x, y);
    237     v = transform(v);
    238     point[0] = v[0] * toFixed;
    239     point[1] = v[1] * toFixed;
    240 }
    241 
    242 Rect Transform::makeBounds(int w, int h) const
    243 {
    244     return transform( Rect(w, h) );
    245 }
    246 
    247 Rect Transform::transform(const Rect& bounds) const
    248 {
    249     Rect r;
    250     vec2 lt( bounds.left,  bounds.top    );
    251     vec2 rt( bounds.right, bounds.top    );
    252     vec2 lb( bounds.left,  bounds.bottom );
    253     vec2 rb( bounds.right, bounds.bottom );
    254 
    255     lt = transform(lt);
    256     rt = transform(rt);
    257     lb = transform(lb);
    258     rb = transform(rb);
    259 
    260     r.left   = floorf(min(lt[0], rt[0], lb[0], rb[0]) + 0.5f);
    261     r.top    = floorf(min(lt[1], rt[1], lb[1], rb[1]) + 0.5f);
    262     r.right  = floorf(max(lt[0], rt[0], lb[0], rb[0]) + 0.5f);
    263     r.bottom = floorf(max(lt[1], rt[1], lb[1], rb[1]) + 0.5f);
    264 
    265     return r;
    266 }
    267 
    268 Region Transform::transform(const Region& reg) const
    269 {
    270     Region out;
    271     if (CC_UNLIKELY(transformed())) {
    272         if (CC_LIKELY(preserveRects())) {
    273             Region::const_iterator it = reg.begin();
    274             Region::const_iterator const end = reg.end();
    275             while (it != end) {
    276                 out.orSelf(transform(*it++));
    277             }
    278         } else {
    279             out.set(transform(reg.bounds()));
    280         }
    281     } else {
    282         out = reg.translate(tx(), ty());
    283     }
    284     return out;
    285 }
    286 
    287 uint32_t Transform::type() const
    288 {
    289     if (mType & UNKNOWN_TYPE) {
    290         // recompute what this transform is
    291 
    292         const mat33& M(mMatrix);
    293         const float a = M[0][0];
    294         const float b = M[1][0];
    295         const float c = M[0][1];
    296         const float d = M[1][1];
    297         const float x = M[2][0];
    298         const float y = M[2][1];
    299 
    300         bool scale = false;
    301         uint32_t flags = ROT_0;
    302         if (isZero(b) && isZero(c)) {
    303             if (a<0)    flags |= FLIP_H;
    304             if (d<0)    flags |= FLIP_V;
    305             if (!absIsOne(a) || !absIsOne(d)) {
    306                 scale = true;
    307             }
    308         } else if (isZero(a) && isZero(d)) {
    309             flags |= ROT_90;
    310             if (b>0)    flags |= FLIP_H;
    311             if (c<0)    flags |= FLIP_V;
    312             if (!absIsOne(b) || !absIsOne(c)) {
    313                 scale = true;
    314             }
    315         } else {
    316             flags = ROT_INVALID;
    317         }
    318 
    319         mType = flags << 8;
    320         if (flags & ROT_INVALID) {
    321             mType |= UNKNOWN;
    322         } else {
    323             if ((flags & ROT_90) || ((flags & ROT_180) == ROT_180))
    324                 mType |= ROTATE;
    325             if (flags & FLIP_H)
    326                 mType ^= SCALE;
    327             if (flags & FLIP_V)
    328                 mType ^= SCALE;
    329             if (scale)
    330                 mType |= SCALE;
    331         }
    332 
    333         if (!isZero(x) || !isZero(y))
    334             mType |= TRANSLATE;
    335     }
    336     return mType;
    337 }
    338 
    339 uint32_t Transform::getType() const {
    340     return type() & 0xFF;
    341 }
    342 
    343 uint32_t Transform::getOrientation() const
    344 {
    345     return (type() >> 8) & 0xFF;
    346 }
    347 
    348 bool Transform::preserveRects() const
    349 {
    350     return (type() & ROT_INVALID) ? false : true;
    351 }
    352 
    353 void Transform::dump(const char* name) const
    354 {
    355     type(); // updates the type
    356 
    357     String8 flags, type;
    358     const mat33& m(mMatrix);
    359     uint32_t orient = mType >> 8;
    360 
    361     if (orient&ROT_INVALID) {
    362         flags.append("ROT_INVALID ");
    363     } else {
    364         if (orient&ROT_90) {
    365             flags.append("ROT_90 ");
    366         } else {
    367             flags.append("ROT_0 ");
    368         }
    369         if (orient&FLIP_V)
    370             flags.append("FLIP_V ");
    371         if (orient&FLIP_H)
    372             flags.append("FLIP_H ");
    373     }
    374 
    375     if (!(mType&(SCALE|ROTATE|TRANSLATE)))
    376         type.append("IDENTITY ");
    377     if (mType&SCALE)
    378         type.append("SCALE ");
    379     if (mType&ROTATE)
    380         type.append("ROTATE ");
    381     if (mType&TRANSLATE)
    382         type.append("TRANSLATE ");
    383 
    384     LOGD("%s 0x%08x (%s, %s)", name, mType, flags.string(), type.string());
    385     LOGD("%.4f  %.4f  %.4f", m[0][0], m[1][0], m[2][0]);
    386     LOGD("%.4f  %.4f  %.4f", m[0][1], m[1][1], m[2][1]);
    387     LOGD("%.4f  %.4f  %.4f", m[0][2], m[1][2], m[2][2]);
    388 }
    389 
    390 // ---------------------------------------------------------------------------
    391 
    392 }; // namespace android
    393