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