Transform.cpp revision d12965934712ed0b9c1a264a6934dc0dad839ffd
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 162eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType = flags << 8; 163eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian float sx = (flags & FLIP_H) ? -1 : 1; 164eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian float sy = (flags & FLIP_V) ? -1 : 1; 165eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian float a=0, b=0, c=0, d=0, x=0, y=0; 166eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian int xmask = 0; 167eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 168eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian // computation of x,y 169eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian // x y 170eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian // 0 0 0 171eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian // w 0 ROT90 172eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian // w h FLIPH|FLIPV 173eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian // 0 h FLIPH|FLIPV|ROT90 174eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 175eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & ROT_90) { 176eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= ROTATE; 177eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian b = -sy; 178eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian c = sx; 179eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian xmask = 1; 180edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } else { 181eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian a = sx; 182eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian d = sy; 183edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 184eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 185eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & FLIP_H) { 186eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType ^= SCALE; 187eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian xmask ^= 1; 188eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 189eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 190eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & FLIP_V) { 191eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType ^= SCALE; 192eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian y = h; 193eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 194eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 195eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if ((flags & ROT_180) == ROT_180) { 196eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= ROTATE; 197eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 198eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 199eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (xmask) { 200eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian x = w; 201eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 202eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 203eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (!isZero(x) || !isZero(y)) { 204eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= TRANSLATE; 205eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 206eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 207eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mat33& M(mMatrix); 208eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian M[0][0] = a; M[1][0] = b; M[2][0] = x; 209eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian M[0][1] = c; M[1][1] = d; M[2][1] = y; 210eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian M[0][2] = 0; M[1][2] = 0; M[2][2] = 1; 211d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian 212d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian return NO_ERROR; 213eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 214eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 215eda65400f5ae301e26c5f52287d831f063069ec2Mathias AgopianTransform::vec2 Transform::transform(const vec2& v) const { 216eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 r; 217eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& M(mMatrix); 218eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0]; 219eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1]; 220eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return r; 221edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 222edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 223eda65400f5ae301e26c5f52287d831f063069ec2Mathias AgopianTransform::vec3 Transform::transform(const vec3& v) const { 224eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec3 r; 225eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& M(mMatrix); 226eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r[0] = M[0][0]*v[0] + M[1][0]*v[1] + M[2][0]*v[2]; 227eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r[1] = M[0][1]*v[0] + M[1][1]*v[1] + M[2][1]*v[2]; 228eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r[2] = M[0][2]*v[0] + M[1][2]*v[1] + M[2][2]*v[2]; 229eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return r; 230eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 231eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 232eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianvoid Transform::transform(fixed1616* point, int x, int y) const 233edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 234eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float toFixed = 65536.0f; 235eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& M(mMatrix); 236eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 v(x, y); 237eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian v = transform(v); 238eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian point[0] = v[0] * toFixed; 239eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian point[1] = v[1] * toFixed; 240edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 241edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 242edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectRect Transform::makeBounds(int w, int h) const 243edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 244eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return transform( Rect(w, h) ); 245edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 246edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 247edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectRect Transform::transform(const Rect& bounds) const 248edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 249edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Rect r; 250eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 lt( bounds.left, bounds.top ); 251eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 rt( bounds.right, bounds.top ); 252eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 lb( bounds.left, bounds.bottom ); 253eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian vec2 rb( bounds.right, bounds.bottom ); 254eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 255eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian lt = transform(lt); 256eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian rt = transform(rt); 257eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian lb = transform(lb); 258eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian rb = transform(rb); 259eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 260eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r.left = floorf(min(lt[0], rt[0], lb[0], rb[0]) + 0.5f); 261eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r.top = floorf(min(lt[1], rt[1], lb[1], rb[1]) + 0.5f); 262eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r.right = floorf(max(lt[0], rt[0], lb[0], rb[0]) + 0.5f); 263eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian r.bottom = floorf(max(lt[1], rt[1], lb[1], rb[1]) + 0.5f); 264eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 265edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return r; 266edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 267edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 268edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source ProjectRegion Transform::transform(const Region& reg) const 269edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 270edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project Region out; 271eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (CC_UNLIKELY(transformed())) { 272eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (CC_LIKELY(preserveRects())) { 27320f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian Region::const_iterator it = reg.begin(); 27420f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian Region::const_iterator const end = reg.end(); 27520f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian while (it != end) { 27620f68782a4ea71c6a977d7f87d8288d3daa265ecMathias Agopian out.orSelf(transform(*it++)); 277edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 278edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } else { 279edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project out.set(transform(reg.bounds())); 280edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 281edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } else { 282edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project out = reg.translate(tx(), ty()); 283edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 284edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return out; 285edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 286edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 287eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianuint32_t Transform::type() const 288edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 289eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (mType & UNKNOWN_TYPE) { 290eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian // recompute what this transform is 291eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 292eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& M(mMatrix); 293eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float a = M[0][0]; 294eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float b = M[1][0]; 295eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float c = M[0][1]; 296eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float d = M[1][1]; 297eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float x = M[2][0]; 298eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const float y = M[2][1]; 299eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 300eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian bool scale = false; 301eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian uint32_t flags = ROT_0; 302eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (isZero(b) && isZero(c)) { 303d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (a<0) flags |= FLIP_H; 304d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (d<0) flags |= FLIP_V; 305d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (!absIsOne(a) || !absIsOne(d)) { 306d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian scale = true; 307eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 308eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } else if (isZero(a) && isZero(d)) { 309d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian flags |= ROT_90; 310d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (b>0) flags |= FLIP_H; 311d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (c<0) flags |= FLIP_V; 312d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (!absIsOne(b) || !absIsOne(c)) { 313d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian scale = true; 314eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 315eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } else { 316eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian flags = ROT_INVALID; 317eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian } 318eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 319eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType = flags << 8; 320eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & ROT_INVALID) { 321eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= UNKNOWN; 322edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } else { 323eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if ((flags & ROT_90) || ((flags & ROT_180) == ROT_180)) 324eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= ROTATE; 325eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & FLIP_H) 326eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType ^= SCALE; 327eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (flags & FLIP_V) 328eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType ^= SCALE; 329eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (scale) 330eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= SCALE; 331edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 332eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 333eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (!isZero(x) || !isZero(y)) 334eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian mType |= TRANSLATE; 335edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 336eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return mType; 337eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 338eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 339eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianuint32_t Transform::getType() const { 340eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return type() & 0xFF; 341eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 342eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 343eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianuint32_t Transform::getOrientation() const 344eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian{ 345eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return (type() >> 8) & 0xFF; 346edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 347edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 348edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectbool Transform::preserveRects() const 349edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 350eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian return (type() & ROT_INVALID) ? false : true; 351eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian} 352eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 353eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopianvoid Transform::dump(const char* name) const 354eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian{ 355eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian type(); // updates the type 356eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 357eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian String8 flags, type; 358eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian const mat33& m(mMatrix); 359eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian uint32_t orient = mType >> 8; 360eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 361d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (orient&ROT_INVALID) { 362eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian flags.append("ROT_INVALID "); 363d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian } else { 364d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (orient&ROT_90) { 365d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian flags.append("ROT_90 "); 366d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian } else { 367d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian flags.append("ROT_0 "); 368d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian } 369d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (orient&FLIP_V) 370d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian flags.append("FLIP_V "); 371d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (orient&FLIP_H) 372d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian flags.append("FLIP_H "); 373d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian } 374eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 375d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian if (!(mType&(SCALE|ROTATE|TRANSLATE))) 376d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian type.append("IDENTITY "); 377eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (mType&SCALE) 378eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian type.append("SCALE "); 379eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (mType&ROTATE) 380eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian type.append("ROTATE "); 381eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian if (mType&TRANSLATE) 382eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian type.append("TRANSLATE "); 383eda65400f5ae301e26c5f52287d831f063069ec2Mathias Agopian 384d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian LOGD("%s 0x%08x (%s, %s)", name, mType, flags.string(), type.string()); 385d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian LOGD("%.4f %.4f %.4f", m[0][0], m[1][0], m[2][0]); 386d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian LOGD("%.4f %.4f %.4f", m[0][1], m[1][1], m[2][1]); 387d12965934712ed0b9c1a264a6934dc0dad839ffdMathias Agopian LOGD("%.4f %.4f %.4f", m[0][2], m[1][2], m[2][2]); 388edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 389edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 390edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// --------------------------------------------------------------------------- 391edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 392edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}; // namespace android 393