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