Transform.cpp revision 52e7200b6e020bba978c36e3a928493a3f2c8a92
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(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 56Transform::~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 117void 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 136void 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())) { 191 Region::const_iterator it = reg.begin(); 192 Region::const_iterator const end = reg.end(); 193 while (it != end) { 194 out.orSelf(transform(*it++)); 195 } 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 235