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
30 namespace android {
31
32 // ---------------------------------------------------------------------------
33
Transform()34 Transform::Transform()
35 : mType(0)
36 {
37 mTransform.reset();
38 }
39
Transform(const Transform & other)40 Transform::Transform(const Transform& other)
41 : mTransform(other.mTransform), mType(other.mType)
42 {
43 }
44
~Transform()45 Transform::~Transform() {
46 }
47
operator *(const Transform & rhs) const48 Transform 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
operator [](int i) const59 float 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
type() const71 uint8_t Transform::type() const
72 {
73 if (UNLIKELY(mType & 0x80000000)) {
74 mType = mTransform.getType();
75 }
76 return uint8_t(mType & 0xFF);
77 }
78
transformed() const79 bool Transform::transformed() const {
80 return type() > SkMatrix::kTranslate_Mask;
81 }
82
tx() const83 int Transform::tx() const {
84 return SkScalarRound( mTransform[SkMatrix::kMTransX] );
85 }
86
ty() const87 int Transform::ty() const {
88 return SkScalarRound( mTransform[SkMatrix::kMTransY] );
89 }
90
reset()91 void Transform::reset() {
92 mTransform.reset();
93 mType = 0;
94 }
95
set(float xx,float xy,float yx,float yy)96 void 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
set(float radian,float x,float y)106 void Transform::set(float radian, float x, float y)
107 {
108 float r00 = cosf(radian); float r01 = -sinf(radian);
109 float r10 = sinf(radian); float r11 = cosf(radian);
110 mTransform.set(SkMatrix::kMScaleX, SkFloatToScalar(r00));
111 mTransform.set(SkMatrix::kMSkewX, SkFloatToScalar(r01));
112 mTransform.set(SkMatrix::kMSkewY, SkFloatToScalar(r10));
113 mTransform.set(SkMatrix::kMScaleY, SkFloatToScalar(r11));
114 mTransform.set(SkMatrix::kMTransX, SkIntToScalar(x - r00*x - r01*y));
115 mTransform.set(SkMatrix::kMTransY, SkIntToScalar(y - r10*x - r11*y));
116 mType |= 0x80000000 | SkMatrix::kTranslate_Mask;
117 }
118
scale(float s,float x,float y)119 void Transform::scale(float s, float x, float y)
120 {
121 mTransform.postScale(s, s, x, y);
122 mType |= 0x80000000;
123 }
124
set(int tx,int ty)125 void Transform::set(int tx, int ty)
126 {
127 if (tx | ty) {
128 mTransform.set(SkMatrix::kMTransX, SkIntToScalar(tx));
129 mTransform.set(SkMatrix::kMTransY, SkIntToScalar(ty));
130 mType |= SkMatrix::kTranslate_Mask;
131 } else {
132 mTransform.set(SkMatrix::kMTransX, 0);
133 mTransform.set(SkMatrix::kMTransY, 0);
134 mType &= ~SkMatrix::kTranslate_Mask;
135 }
136 }
137
transform(GLfixed * point,int x,int y) const138 void Transform::transform(GLfixed* point, int x, int y) const
139 {
140 SkPoint s;
141 mTransform.mapXY(SkIntToScalar(x), SkIntToScalar(y), &s);
142 point[0] = SkScalarToFixed(s.fX);
143 point[1] = SkScalarToFixed(s.fY);
144 }
145
makeBounds(int w,int h) const146 Rect Transform::makeBounds(int w, int h) const
147 {
148 Rect r;
149 SkRect d, s;
150 s.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
151 mTransform.mapRect(&d, s);
152 r.left = SkScalarRound( d.fLeft );
153 r.top = SkScalarRound( d.fTop );
154 r.right = SkScalarRound( d.fRight );
155 r.bottom = SkScalarRound( d.fBottom );
156 return r;
157 }
158
transform(const Rect & bounds) const159 Rect Transform::transform(const Rect& bounds) const
160 {
161 Rect r;
162 SkRect d, s;
163 s.set( SkIntToScalar( bounds.left ),
164 SkIntToScalar( bounds.top ),
165 SkIntToScalar( bounds.right ),
166 SkIntToScalar( bounds.bottom ));
167 mTransform.mapRect(&d, s);
168 r.left = SkScalarRound( d.fLeft );
169 r.top = SkScalarRound( d.fTop );
170 r.right = SkScalarRound( d.fRight );
171 r.bottom = SkScalarRound( d.fBottom );
172 return r;
173 }
174
transform(const Region & reg) const175 Region Transform::transform(const Region& reg) const
176 {
177 Region out;
178 if (UNLIKELY(transformed())) {
179 if (LIKELY(preserveRects())) {
180 Region::const_iterator it = reg.begin();
181 Region::const_iterator const end = reg.end();
182 while (it != end) {
183 out.orSelf(transform(*it++));
184 }
185 } else {
186 out.set(transform(reg.bounds()));
187 }
188 } else {
189 out = reg.translate(tx(), ty());
190 }
191 return out;
192 }
193
getOrientation() const194 int32_t Transform::getOrientation() const
195 {
196 uint32_t flags = 0;
197 if (UNLIKELY(transformed())) {
198 SkScalar a = mTransform[SkMatrix::kMScaleX];
199 SkScalar b = mTransform[SkMatrix::kMSkewX];
200 SkScalar c = mTransform[SkMatrix::kMSkewY];
201 SkScalar d = mTransform[SkMatrix::kMScaleY];
202 if (b==0 && c==0 && a && d) {
203 if (a<0) flags |= FLIP_H;
204 if (d<0) flags |= FLIP_V;
205 } else if (b && c && a==0 && d==0) {
206 flags |= ROT_90;
207 if (b>0) flags |= FLIP_H;
208 if (c<0) flags |= FLIP_V;
209 } else {
210 flags = 0x80000000;
211 }
212 }
213 return flags;
214 }
215
preserveRects() const216 bool Transform::preserveRects() const
217 {
218 return mTransform.rectStaysRect();
219 }
220
221 // ---------------------------------------------------------------------------
222
223 }; // namespace android
224