1/* 2 * Copyright (C) 2012 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 */ 16package com.android.gallery3d.util; 17 18import android.annotation.TargetApi; 19import android.graphics.Matrix; 20import android.util.FloatMath; 21import android.view.MotionEvent; 22import android.view.MotionEvent.PointerCoords; 23 24import com.android.gallery3d.common.ApiHelper; 25 26public final class MotionEventHelper { 27 private MotionEventHelper() {} 28 29 public static MotionEvent transformEvent(MotionEvent e, Matrix m) { 30 // We try to use the new transform method if possible because it uses 31 // less memory. 32 if (ApiHelper.HAS_MOTION_EVENT_TRANSFORM) { 33 return transformEventNew(e, m); 34 } else { 35 return transformEventOld(e, m); 36 } 37 } 38 39 @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) 40 private static MotionEvent transformEventNew(MotionEvent e, Matrix m) { 41 MotionEvent newEvent = MotionEvent.obtain(e); 42 newEvent.transform(m); 43 return newEvent; 44 } 45 46 // This is copied from Input.cpp in the android framework. 47 private static MotionEvent transformEventOld(MotionEvent e, Matrix m) { 48 long downTime = e.getDownTime(); 49 long eventTime = e.getEventTime(); 50 int action = e.getAction(); 51 int pointerCount = e.getPointerCount(); 52 int[] pointerIds = getPointerIds(e); 53 PointerCoords[] pointerCoords = getPointerCoords(e); 54 int metaState = e.getMetaState(); 55 float xPrecision = e.getXPrecision(); 56 float yPrecision = e.getYPrecision(); 57 int deviceId = e.getDeviceId(); 58 int edgeFlags = e.getEdgeFlags(); 59 int source = e.getSource(); 60 int flags = e.getFlags(); 61 62 // Copy the x and y coordinates into an array, map them, and copy back. 63 float[] xy = new float[pointerCoords.length * 2]; 64 for (int i = 0; i < pointerCount;i++) { 65 xy[2 * i] = pointerCoords[i].x; 66 xy[2 * i + 1] = pointerCoords[i].y; 67 } 68 m.mapPoints(xy); 69 for (int i = 0; i < pointerCount;i++) { 70 pointerCoords[i].x = xy[2 * i]; 71 pointerCoords[i].y = xy[2 * i + 1]; 72 pointerCoords[i].orientation = transformAngle( 73 m, pointerCoords[i].orientation); 74 } 75 76 MotionEvent n = MotionEvent.obtain(downTime, eventTime, action, 77 pointerCount, pointerIds, pointerCoords, metaState, xPrecision, 78 yPrecision, deviceId, edgeFlags, source, flags); 79 80 return n; 81 } 82 83 private static int[] getPointerIds(MotionEvent e) { 84 int n = e.getPointerCount(); 85 int[] r = new int[n]; 86 for (int i = 0; i < n; i++) { 87 r[i] = e.getPointerId(i); 88 } 89 return r; 90 } 91 92 private static PointerCoords[] getPointerCoords(MotionEvent e) { 93 int n = e.getPointerCount(); 94 PointerCoords[] r = new PointerCoords[n]; 95 for (int i = 0; i < n; i++) { 96 r[i] = new PointerCoords(); 97 e.getPointerCoords(i, r[i]); 98 } 99 return r; 100 } 101 102 private static float transformAngle(Matrix m, float angleRadians) { 103 // Construct and transform a vector oriented at the specified clockwise 104 // angle from vertical. Coordinate system: down is increasing Y, right is 105 // increasing X. 106 float[] v = new float[2]; 107 v[0] = FloatMath.sin(angleRadians); 108 v[1] = -FloatMath.cos(angleRadians); 109 m.mapVectors(v); 110 111 // Derive the transformed vector's clockwise angle from vertical. 112 float result = (float) Math.atan2(v[0], -v[1]); 113 if (result < -Math.PI / 2) { 114 result += Math.PI; 115 } else if (result > Math.PI / 2) { 116 result -= Math.PI; 117 } 118 return result; 119 } 120} 121