blob: ab6f7badc2a13dd03783b9ff3f5aedda115182a4 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
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
Chih-Chung Chang52e72002010-01-21 17:31:06 -080045Transform::Transform(int32_t flags) {
46 mTransform.reset();
47 int sx = (flags & FLIP_H) ? -1 : 1;
48 int sy = (flags & FLIP_V) ? -1 : 1;
49 if (flags & ROT_90) {
50 this->set(0, -sy, sx, 0);
51 } else {
52 this->set(sx, 0, 0, sy);
53 }
54}
55
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080056Transform::~Transform() {
57}
58
59Transform Transform::operator * (const Transform& rhs) const
60{
61 if (LIKELY(mType == 0))
62 return rhs;
63
64 Transform r(*this);
65 r.mTransform.preConcat(rhs.mTransform);
66 r.mType |= rhs.mType;
67 return r;
68}
69
70float Transform::operator [] (int i) const
71{
72 float r = 0;
73 switch(i) {
74 case 0: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleX] ); break;
75 case 1: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewX] ); break;
76 case 2: r = SkScalarToFloat( mTransform[SkMatrix::kMSkewY] ); break;
77 case 3: r = SkScalarToFloat( mTransform[SkMatrix::kMScaleY] ); break;
78 }
79 return r;
80}
81
82uint8_t Transform::type() const
83{
84 if (UNLIKELY(mType & 0x80000000)) {
85 mType = mTransform.getType();
86 }
87 return uint8_t(mType & 0xFF);
88}
89
90bool Transform::transformed() const {
91 return type() > SkMatrix::kTranslate_Mask;
92}
93
94int Transform::tx() const {
95 return SkScalarRound( mTransform[SkMatrix::kMTransX] );
96}
97
98int Transform::ty() const {
99 return SkScalarRound( mTransform[SkMatrix::kMTransY] );
100}
101
102void Transform::reset() {
103 mTransform.reset();
104 mType = 0;
105}
106
107void Transform::set( float xx, float xy,
108 float yx, float yy)
109{
110 mTransform.set(SkMatrix::kMScaleX, SkFloatToScalar(xx));
111 mTransform.set(SkMatrix::kMSkewX, SkFloatToScalar(xy));
112 mTransform.set(SkMatrix::kMSkewY, SkFloatToScalar(yx));
113 mTransform.set(SkMatrix::kMScaleY, SkFloatToScalar(yy));
114 mType |= 0x80000000;
115}
116
Mathias Agopian0d1318b2009-03-27 17:58:20 -0700117void Transform::set(float radian, float x, float y)
118{
119 float r00 = cosf(radian); float r01 = -sinf(radian);
120 float r10 = sinf(radian); float r11 = cosf(radian);
121 mTransform.set(SkMatrix::kMScaleX, SkFloatToScalar(r00));
122 mTransform.set(SkMatrix::kMSkewX, SkFloatToScalar(r01));
123 mTransform.set(SkMatrix::kMSkewY, SkFloatToScalar(r10));
124 mTransform.set(SkMatrix::kMScaleY, SkFloatToScalar(r11));
125 mTransform.set(SkMatrix::kMTransX, SkIntToScalar(x - r00*x - r01*y));
126 mTransform.set(SkMatrix::kMTransY, SkIntToScalar(y - r10*x - r11*y));
127 mType |= 0x80000000 | SkMatrix::kTranslate_Mask;
128}
129
130void Transform::scale(float s, float x, float y)
131{
132 mTransform.postScale(s, s, x, y);
133 mType |= 0x80000000;
134}
135
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800136void Transform::set(int tx, int ty)
137{
138 if (tx | ty) {
139 mTransform.set(SkMatrix::kMTransX, SkIntToScalar(tx));
140 mTransform.set(SkMatrix::kMTransY, SkIntToScalar(ty));
141 mType |= SkMatrix::kTranslate_Mask;
142 } else {
143 mTransform.set(SkMatrix::kMTransX, 0);
144 mTransform.set(SkMatrix::kMTransY, 0);
145 mType &= ~SkMatrix::kTranslate_Mask;
146 }
147}
148
149void Transform::transform(GLfixed* point, int x, int y) const
150{
151 SkPoint s;
152 mTransform.mapXY(SkIntToScalar(x), SkIntToScalar(y), &s);
153 point[0] = SkScalarToFixed(s.fX);
154 point[1] = SkScalarToFixed(s.fY);
155}
156
157Rect Transform::makeBounds(int w, int h) const
158{
159 Rect r;
160 SkRect d, s;
161 s.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));
162 mTransform.mapRect(&d, s);
163 r.left = SkScalarRound( d.fLeft );
164 r.top = SkScalarRound( d.fTop );
165 r.right = SkScalarRound( d.fRight );
166 r.bottom = SkScalarRound( d.fBottom );
167 return r;
168}
169
170Rect Transform::transform(const Rect& bounds) const
171{
172 Rect r;
173 SkRect d, s;
174 s.set( SkIntToScalar( bounds.left ),
175 SkIntToScalar( bounds.top ),
176 SkIntToScalar( bounds.right ),
177 SkIntToScalar( bounds.bottom ));
178 mTransform.mapRect(&d, s);
179 r.left = SkScalarRound( d.fLeft );
180 r.top = SkScalarRound( d.fTop );
181 r.right = SkScalarRound( d.fRight );
182 r.bottom = SkScalarRound( d.fBottom );
183 return r;
184}
185
186Region Transform::transform(const Region& reg) const
187{
188 Region out;
189 if (UNLIKELY(transformed())) {
190 if (LIKELY(preserveRects())) {
Mathias Agopian20f68782009-05-11 00:03:41 -0700191 Region::const_iterator it = reg.begin();
192 Region::const_iterator const end = reg.end();
193 while (it != end) {
194 out.orSelf(transform(*it++));
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800195 }
196 } else {
197 out.set(transform(reg.bounds()));
198 }
199 } else {
200 out = reg.translate(tx(), ty());
201 }
202 return out;
203}
204
205int32_t Transform::getOrientation() const
206{
207 uint32_t flags = 0;
208 if (UNLIKELY(transformed())) {
209 SkScalar a = mTransform[SkMatrix::kMScaleX];
210 SkScalar b = mTransform[SkMatrix::kMSkewX];
211 SkScalar c = mTransform[SkMatrix::kMSkewY];
212 SkScalar d = mTransform[SkMatrix::kMScaleY];
213 if (b==0 && c==0 && a && d) {
214 if (a<0) flags |= FLIP_H;
215 if (d<0) flags |= FLIP_V;
216 } else if (b && c && a==0 && d==0) {
217 flags |= ROT_90;
218 if (b>0) flags |= FLIP_H;
219 if (c<0) flags |= FLIP_V;
220 } else {
221 flags = 0x80000000;
222 }
223 }
224 return flags;
225}
226
227bool Transform::preserveRects() const
228{
229 return mTransform.rectStaysRect();
230}
231
232// ---------------------------------------------------------------------------
233
234}; // namespace android