Transform.cpp revision edbf3b6af777b721cd2a1ef461947e51e88241e1
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 <ui/Region.h>
18
19#include <private/pixelflinger/ggl_fixed.h>
20
21#include "Transform.h"
22
23// ---------------------------------------------------------------------------
24
25#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
26#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
27
28// ---------------------------------------------------------------------------
29
30namespace android {
31
32// ---------------------------------------------------------------------------
33
34Transform::Transform()
35    : mType(0)
36{
37    mTransform.reset();
38}
39
40Transform::Transform(const Transform&  other)
41    : mTransform(other.mTransform), mType(other.mType)
42{
43}
44
45Transform::~Transform() {
46}
47
48Transform Transform::operator * (const Transform& rhs) const
49{
50    if (LIKELY(mType == 0))
51        return rhs;
52
53    Transform r(*this);
54    r.mTransform.preConcat(rhs.mTransform);
55    r.mType |= rhs.mType;
56    return r;
57}
58
59float Transform::operator [] (int i) const
60{
61    float r = 0;
62    switch(i) {
63        case 0: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleX] );  break;
64        case 1: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewX] );   break;
65        case 2: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewY] );   break;
66        case 3: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleY] );  break;
67    }
68    return r;
69}
70
71uint8_t Transform::type() const
72{
73    if (UNLIKELY(mType & 0x80000000)) {
74        mType = mTransform.getType();
75    }
76    return uint8_t(mType & 0xFF);
77}
78
79bool Transform::transformed() const {
80    return type() > SkMatrix::kTranslate_Mask;
81}
82
83int Transform::tx() const {
84    return SkScalarRound( mTransform[SkMatrix::kMTransX] );
85}
86
87int Transform::ty() const {
88    return SkScalarRound( mTransform[SkMatrix::kMTransY] );
89}
90
91void Transform::reset() {
92    mTransform.reset();
93    mType = 0;
94}
95
96void Transform::set( float xx, float xy,
97                     float yx, float yy)
98{
99    mTransform.set(SkMatrix::kMScaleX, SkFloatToScalar(xx));
100    mTransform.set(SkMatrix::kMSkewX, SkFloatToScalar(xy));
101    mTransform.set(SkMatrix::kMSkewY, SkFloatToScalar(yx));
102    mTransform.set(SkMatrix::kMScaleY, SkFloatToScalar(yy));
103    mType |= 0x80000000;
104}
105
106void Transform::set(int tx, int ty)
107{
108    if (tx | ty) {
109        mTransform.set(SkMatrix::kMTransX, SkIntToScalar(tx));
110        mTransform.set(SkMatrix::kMTransY, SkIntToScalar(ty));
111        mType |= SkMatrix::kTranslate_Mask;
112    } else {
113        mTransform.set(SkMatrix::kMTransX, 0);
114        mTransform.set(SkMatrix::kMTransY, 0);
115        mType &= ~SkMatrix::kTranslate_Mask;
116    }
117}
118
119void Transform::transform(GLfixed* point, int x, int y) const
120{
121    SkPoint s;
122    mTransform.mapXY(SkIntToScalar(x), SkIntToScalar(y), &s);
123    point[0] = SkScalarToFixed(s.fX);
124    point[1] = SkScalarToFixed(s.fY);
125}
126
127Rect Transform::makeBounds(int w, int h) const
128{
129    Rect r;
130    SkRect d, s;
131    s.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
132    mTransform.mapRect(&d, s);
133    r.left   = SkScalarRound( d.fLeft );
134    r.top    = SkScalarRound( d.fTop );
135    r.right  = SkScalarRound( d.fRight );
136    r.bottom = SkScalarRound( d.fBottom );
137    return r;
138}
139
140Rect Transform::transform(const Rect& bounds) const
141{
142    Rect r;
143    SkRect d, s;
144    s.set(  SkIntToScalar( bounds.left ),
145            SkIntToScalar( bounds.top ),
146            SkIntToScalar( bounds.right ),
147            SkIntToScalar( bounds.bottom ));
148    mTransform.mapRect(&d, s);
149    r.left   = SkScalarRound( d.fLeft );
150    r.top    = SkScalarRound( d.fTop );
151    r.right  = SkScalarRound( d.fRight );
152    r.bottom = SkScalarRound( d.fBottom );
153    return r;
154}
155
156Region Transform::transform(const Region& reg) const
157{
158    Region out;
159    if (UNLIKELY(transformed())) {
160        if (LIKELY(preserveRects())) {
161            Rect r;
162            Region::iterator iterator(reg);
163            while (iterator.iterate(&r)) {
164                out.orSelf(transform(r));
165            }
166        } else {
167            out.set(transform(reg.bounds()));
168        }
169    } else {
170        out = reg.translate(tx(), ty());
171    }
172    return out;
173}
174
175int32_t Transform::getOrientation() const
176{
177    uint32_t flags = 0;
178    if (UNLIKELY(transformed())) {
179        SkScalar a = mTransform[SkMatrix::kMScaleX];
180        SkScalar b = mTransform[SkMatrix::kMSkewX];
181        SkScalar c = mTransform[SkMatrix::kMSkewY];
182        SkScalar d = mTransform[SkMatrix::kMScaleY];
183        if (b==0 && c==0 && a && d) {
184            if (a<0)    flags |= FLIP_H;
185            if (d<0)    flags |= FLIP_V;
186        } else if (b && c && a==0 && d==0) {
187            flags |= ROT_90;
188            if (b>0)    flags |= FLIP_H;
189            if (c<0)    flags |= FLIP_V;
190        } else {
191            flags = 0x80000000;
192        }
193    }
194    return flags;
195}
196
197bool Transform::preserveRects() const
198{
199    return mTransform.rectStaysRect();
200}
201
202// ---------------------------------------------------------------------------
203
204}; // namespace android
205