Transform.cpp revision 0694d0f3b3d016b9eedda13c447e8e7735a4a177
1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/* 2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * 4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * you may not use this file except in compliance with the License. 6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * You may obtain a copy of the License at 7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * 8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * 10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * See the License for the specific language governing permissions and 14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project * limitations under the License. 15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project */ 16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 17eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian#include <math.h> 18edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 19eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian#include <cutils/compiler.h> 20eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian#include <utils/String8.h> 21eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian#include <ui/Region.h> 22edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "Transform.h" 24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 25edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// --------------------------------------------------------------------------- 26edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 27eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopiannamespace android { 28edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// --------------------------------------------------------------------------- 30edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 31eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopiantemplate <typename T> inline T min(T a, T b) { 32eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return a<b ? a : b; 33eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 34eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopiantemplate <typename T> inline T min(T a, T b, T c) { 35eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return min(a, min(b, c)); 36eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 37eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopiantemplate <typename T> inline T min(T a, T b, T c, T d) { 38eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return min(a, b, min(c, d)); 39eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 40eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 41eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopiantemplate <typename T> inline T max(T a, T b) { 42eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return a>b ? a : b; 43eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 44eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopiantemplate <typename T> inline T max(T a, T b, T c) { 45eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return max(a, max(b, c)); 46eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 47eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopiantemplate <typename T> inline T max(T a, T b, T c, T d) { 48eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return max(a, b, max(c, d)); 49eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 50edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 51edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// --------------------------------------------------------------------------- 52edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 53eda65400f5ae301e26c5f52287d831f063069ec2Mathias AgopianTransform::Transform() { 54eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian reset(); 55edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 56edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 57edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectTransform::Transform(const Transform& other) 58eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian : mMatrix(other.mMatrix), mType(other.mType) { 59edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 60edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 61eda65400f5ae301e26c5f52287d831f063069ec2Mathias AgopianTransform::Transform(uint32_t orientation) { 62eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian set(orientation, 0, 0); 6352e7200b6e020bba978c36e3a928493a3f2c8a92Chih-Chung Chang} 6452e7200b6e020bba978c36e3a928493a3f2c8a92Chih-Chung Chang 65edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectTransform::~Transform() { 66edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 67edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 68d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopianstatic const float EPSILON = 0.0f; 69eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 70eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianbool Transform::isZero(float f) { 71d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian return fabs(f) <= EPSILON; 72eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 73eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 74d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopianbool Transform::absIsOne(float f) { 75d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian return isZero(fabs(f) - 1.0f); 76eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 77eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 78edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectTransform Transform::operator * (const Transform& rhs) const 79edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 80eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (CC_LIKELY(mType == IDENTITY)) 81edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return rhs; 82edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 83edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Transform r(*this); 84eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (rhs.mType == IDENTITY) 85eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return r; 86eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 87eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian // TODO: we could use mType to optimize the matrix multiply 88eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& A(mMatrix); 89eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& B(rhs.mMatrix); 90eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mat33& D(r.mMatrix); 91eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian for (int i=0 ; i<3 ; i++) { 92eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float v0 = A[0][i]; 93eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float v1 = A[1][i]; 94eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float v2 = A[2][i]; 95eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian D[0][i] = v0*B[0][0] + v1*B[0][1] + v2*B[0][2]; 96eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian D[1][i] = v0*B[1][0] + v1*B[1][1] + v2*B[1][2]; 97eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian D[2][i] = v0*B[2][0] + v1*B[2][1] + v2*B[2][2]; 98eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 99edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project r.mType |= rhs.mType; 100edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 101eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian // TODO: we could recompute this value from r and rhs 102eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r.mType &= 0xFF; 103eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r.mType |= UNKNOWN_TYPE; 104edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return r; 105edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 106edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 107eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianfloat const* Transform::operator [] (int i) const { 108eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return mMatrix[i].v; 109edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 110edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 111edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectbool Transform::transformed() const { 112eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return type() > TRANSLATE; 113edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 114edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 115edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectint Transform::tx() const { 116eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return floorf(mMatrix[2][0] + 0.5f); 117edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 118edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 119edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectint Transform::ty() const { 120eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return floorf(mMatrix[2][1] + 0.5f); 121edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 122edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 123edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectvoid Transform::reset() { 124eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType = IDENTITY; 125eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian for(int i=0 ; i<3 ; i++) { 126eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec3& v(mMatrix[i]); 127eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian for (int j=0 ; j<3 ; j++) 128eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian v[j] = ((i==j) ? 1.0f : 0.0f); 129eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 130edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 131edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 132eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianvoid Transform::set(float tx, float ty) 133edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 134eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mMatrix[2][0] = tx; 135eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mMatrix[2][1] = ty; 136eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mMatrix[2][2] = 1.0f; 137eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 138eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (isZero(tx) && isZero(ty)) { 139eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType &= ~TRANSLATE; 140eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } else { 141eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= TRANSLATE; 142eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 143edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 144edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 145eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianvoid Transform::set(float a, float b, float c, float d) 1460d1318b974feba2e6ff13e36a1781343c2fce045Mathias Agopian{ 147eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mat33& M(mMatrix); 148eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian M[0][0] = a; M[1][0] = b; 149eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian M[0][1] = c; M[1][1] = d; 150eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian M[0][2] = 0; M[1][2] = 0; 151eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType = UNKNOWN_TYPE; 1520d1318b974feba2e6ff13e36a1781343c2fce045Mathias Agopian} 1530d1318b974feba2e6ff13e36a1781343c2fce045Mathias Agopian 154d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopianstatus_t Transform::set(uint32_t flags, float w, float h) 155edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 156d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (flags & ROT_INVALID) { 157d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian // that's not allowed! 158d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian reset(); 159d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian return BAD_VALUE; 160d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian } 161d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian 1620694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian Transform H, V, R; 163eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & FLIP_H) { 1640694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian H.mType = (FLIP_H << 8) | SCALE; 1650694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian H.mType |= isZero(w) ? IDENTITY : TRANSLATE; 1660694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian mat33& M(H.mMatrix); 1670694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian M[0][0] = -1; 1680694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian M[2][0] = w; 169eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 170eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 171eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & FLIP_V) { 1720694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian V.mType = (FLIP_V << 8) | SCALE; 1730694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian V.mType |= isZero(h) ? IDENTITY : TRANSLATE; 1740694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian mat33& M(V.mMatrix); 1750694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian M[1][1] = -1; 1760694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian M[2][1] = h; 177eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 178eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 1790694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian if (flags & ROT_90) { 1800694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian R.mType = (ROT_90 << 8) | ROTATE; 1810694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian R.mType |= isZero(w) ? IDENTITY : TRANSLATE; 1820694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian mat33& M(R.mMatrix); 1830694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian M[0][0] = 0; M[1][0] =-1; M[2][0] = w; 1840694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian M[0][1] = 1; M[1][1] = 0; 185eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 186eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 1870694d0f3b3d016b9eedda13c447e8e7735a4a177Mathias Agopian *this = ((H*V)*R); 188d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian return NO_ERROR; 189eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 190eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 191eda65400f5ae301e26c5f52287d831f063069ec2Mathias AgopianTransform::vec2 Transform::transform(const vec2& v) const { 192eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 r; 193eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& M(mMatrix); 194eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0]; 195eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1]; 196eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return r; 197edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 198edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 199eda65400f5ae301e26c5f52287d831f063069ec2Mathias AgopianTransform::vec3 Transform::transform(const vec3& v) const { 200eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec3 r; 201eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& M(mMatrix); 202eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0]*v[2]; 203eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1]*v[2]; 204eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r[2] = M[0][2]*v[0] + M[1][2]*v[1] + M[2][2]*v[2]; 205eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return r; 206eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 207eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 20878fd5010a87425d2be401d10a306dd68638fc1ddMathias Agopianvoid Transform::transform(float* point, int x, int y) const 209edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 210eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& M(mMatrix); 211eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 v(x, y); 212eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian v = transform(v); 21378fd5010a87425d2be401d10a306dd68638fc1ddMathias Agopian point[0] = v[0]; 21478fd5010a87425d2be401d10a306dd68638fc1ddMathias Agopian point[1] = v[1]; 215edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 216edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 217edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectRect Transform::makeBounds(int w, int h) const 218edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 219eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return transform( Rect(w, h) ); 220edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 221edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 222edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectRect Transform::transform(const Rect& bounds) const 223edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 224edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Rect r; 225eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 lt( bounds.left, bounds.top ); 226eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 rt( bounds.right, bounds.top ); 227eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 lb( bounds.left, bounds.bottom ); 228eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 rb( bounds.right, bounds.bottom ); 229eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 230eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian lt = transform(lt); 231eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian rt = transform(rt); 232eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian lb = transform(lb); 233eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian rb = transform(rb); 234eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 235eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r.left = floorf(min(lt[0], rt[0], lb[0], rb[0]) + 0.5f); 236eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r.top = floorf(min(lt[1], rt[1], lb[1], rb[1]) + 0.5f); 237eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r.right = floorf(max(lt[0], rt[0], lb[0], rb[0]) + 0.5f); 238eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r.bottom = floorf(max(lt[1], rt[1], lb[1], rb[1]) + 0.5f); 239eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 240edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return r; 241edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 242edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 243edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectRegion Transform::transform(const Region& reg) const 244edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 245edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Region out; 246eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (CC_UNLIKELY(transformed())) { 247eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (CC_LIKELY(preserveRects())) { 24820f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian Region::const_iterator it = reg.begin(); 24920f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian Region::const_iterator const end = reg.end(); 25020f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian while (it != end) { 25120f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian out.orSelf(transform(*it++)); 252edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 253edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } else { 254edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project out.set(transform(reg.bounds())); 255edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 256edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } else { 257edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project out = reg.translate(tx(), ty()); 258edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 259edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return out; 260edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 261edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 262eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianuint32_t Transform::type() const 263edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 264eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (mType & UNKNOWN_TYPE) { 265eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian // recompute what this transform is 266eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 267eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& M(mMatrix); 268eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float a = M[0][0]; 269eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float b = M[1][0]; 270eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float c = M[0][1]; 271eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float d = M[1][1]; 272eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float x = M[2][0]; 273eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float y = M[2][1]; 274eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 275eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian bool scale = false; 276eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian uint32_t flags = ROT_0; 277eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (isZero(b) && isZero(c)) { 278d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (a<0) flags |= FLIP_H; 279d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (d<0) flags |= FLIP_V; 280d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (!absIsOne(a) || !absIsOne(d)) { 281d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian scale = true; 282eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 283eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } else if (isZero(a) && isZero(d)) { 284d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian flags |= ROT_90; 285d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (b>0) flags |= FLIP_H; 286d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (c<0) flags |= FLIP_V; 287d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (!absIsOne(b) || !absIsOne(c)) { 288d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian scale = true; 289eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 290eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } else { 291eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian flags = ROT_INVALID; 292eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 293eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 294eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType = flags << 8; 295eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & ROT_INVALID) { 296eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= UNKNOWN; 297edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } else { 298eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if ((flags & ROT_90) || ((flags & ROT_180) == ROT_180)) 299eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= ROTATE; 300eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & FLIP_H) 301eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType ^= SCALE; 302eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & FLIP_V) 303eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType ^= SCALE; 304eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (scale) 305eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= SCALE; 306edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 307eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 308eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (!isZero(x) || !isZero(y)) 309eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= TRANSLATE; 310edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 311eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return mType; 312eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 313eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 314eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianuint32_t Transform::getType() const { 315eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return type() & 0xFF; 316eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 317eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 318eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianuint32_t Transform::getOrientation() const 319eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian{ 320eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return (type() >> 8) & 0xFF; 321edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 322edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 323edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectbool Transform::preserveRects() const 324edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 325eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return (type() & ROT_INVALID) ? false : true; 326eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 327eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 328eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianvoid Transform::dump(const char* name) const 329eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian{ 330eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian type(); // updates the type 331eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 332eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian String8 flags, type; 333eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& m(mMatrix); 334eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian uint32_t orient = mType >> 8; 335eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 336d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (orient&ROT_INVALID) { 337eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian flags.append("ROT_INVALID "); 338d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian } else { 339d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (orient&ROT_90) { 340d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian flags.append("ROT_90 "); 341d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian } else { 342d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian flags.append("ROT_0 "); 343d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian } 344d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (orient&FLIP_V) 345d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian flags.append("FLIP_V "); 346d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (orient&FLIP_H) 347d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian flags.append("FLIP_H "); 348d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian } 349eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 350d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (!(mType&(SCALE|ROTATE|TRANSLATE))) 351d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian type.append("IDENTITY "); 352eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (mType&SCALE) 353eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian type.append("SCALE "); 354eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (mType&ROTATE) 355eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian type.append("ROTATE "); 356eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (mType&TRANSLATE) 357eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian type.append("TRANSLATE "); 358eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 359d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian LOGD("%s 0x%08x (%s, %s)", name, mType, flags.string(), type.string()); 360d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian LOGD("%.4f %.4f %.4f", m[0][0], m[1][0], m[2][0]); 361d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian LOGD("%.4f %.4f %.4f", m[0][1], m[1][1], m[2][1]); 362d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian LOGD("%.4f %.4f %.4f", m[0][2], m[1][2], m[2][2]); 363edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 364edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 365edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// --------------------------------------------------------------------------- 366edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 367edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}; // namespace android 368