summaryrefslogtreecommitdiffstats
path: root/core/java/android/gesture/GestureStroke.java
diff options
context:
space:
mode:
authorRomain Guy <romainguy@android.com>2009-05-21 16:23:21 -0700
committerRomain Guy <romainguy@android.com>2009-05-21 18:12:56 -0700
commitdb567c390bd56c05614eaa83c02dbb99f97ad9cc (patch)
tree86399406ca7a53c3d902b3863bf7a944cb7c5c3f /core/java/android/gesture/GestureStroke.java
parent384bfa270cdcb5dc3bc9ec396b783e25eb2d9b4d (diff)
downloadframeworks_base-db567c390bd56c05614eaa83c02dbb99f97ad9cc.zip
frameworks_base-db567c390bd56c05614eaa83c02dbb99f97ad9cc.tar.gz
frameworks_base-db567c390bd56c05614eaa83c02dbb99f97ad9cc.tar.bz2
Move the Gestures API to the framework in android.gesture.
Diffstat (limited to 'core/java/android/gesture/GestureStroke.java')
-rw-r--r--core/java/android/gesture/GestureStroke.java215
1 files changed, 215 insertions, 0 deletions
diff --git a/core/java/android/gesture/GestureStroke.java b/core/java/android/gesture/GestureStroke.java
new file mode 100644
index 0000000..5160a76
--- /dev/null
+++ b/core/java/android/gesture/GestureStroke.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.gesture;
+
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+
+import java.io.IOException;
+import java.io.DataOutputStream;
+import java.io.DataInputStream;
+import java.util.ArrayList;
+
+/**
+ * A gesture stroke started on a touch down and ended on a touch up.
+ */
+public class GestureStroke {
+ public final RectF boundingBox;
+
+ public final float length;
+ public final float[] points;
+
+ private final long[] timestamps;
+ private Path mCachedPath;
+
+ /**
+ * Construct a gesture stroke from a list of gesture points
+ *
+ * @param points
+ */
+ public GestureStroke(ArrayList<GesturePoint> points) {
+ final int count = points.size();
+ final float[] tmpPoints = new float[count * 2];
+ final long[] times = new long[count];
+
+ RectF bx = null;
+ float len = 0;
+ int index = 0;
+
+ for (int i = 0; i < count; i++) {
+ final GesturePoint p = points.get(i);
+ tmpPoints[i * 2] = p.x;
+ tmpPoints[i * 2 + 1] = p.y;
+ times[index] = p.timestamp;
+
+ if (bx == null) {
+ bx = new RectF();
+ bx.top = p.y;
+ bx.left = p.x;
+ bx.right = p.x;
+ bx.bottom = p.y;
+ len = 0;
+ } else {
+ len += Math.sqrt(Math.pow(p.x - tmpPoints[(i - 1) * 2], 2)
+ + Math.pow(p.y - tmpPoints[(i -1 ) * 2 + 1], 2));
+ bx.union(p.x, p.y);
+ }
+ index++;
+ }
+
+ timestamps = times;
+ this.points = tmpPoints;
+ boundingBox = bx;
+ length = len;
+ }
+
+ /**
+ * Draw the gesture with a given canvas and paint
+ *
+ * @param canvas
+ */
+ void draw(Canvas canvas, Paint paint) {
+ if (mCachedPath == null) {
+ final float[] localPoints = points;
+ final int count = localPoints.length;
+
+ Path path = null;
+
+ float mX = 0;
+ float mY = 0;
+
+ for (int i = 0; i < count; i += 2) {
+ float x = localPoints[i];
+ float y = localPoints[i + 1];
+ if (path == null) {
+ path = new Path();
+ path.moveTo(x, y);
+ mX = x;
+ mY = y;
+ } else {
+ float dx = Math.abs(x - mX);
+ float dy = Math.abs(y - mY);
+ if (dx >= 3 || dy >= 3) {
+ path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
+ mX = x;
+ mY = y;
+ }
+ }
+ }
+
+ mCachedPath = path;
+ }
+
+ canvas.drawPath(mCachedPath, paint);
+ }
+
+ /**
+ * Convert the stroke to a Path based on the number of points
+ *
+ * @param width the width of the bounding box of the target path
+ * @param height the height of the bounding box of the target path
+ * @param numSample the number of points needed
+ *
+ * @return the path
+ */
+ public Path toPath(float width, float height, int numSample) {
+ final float[] pts = GestureUtilities.temporalSampling(this, numSample);
+ final RectF rect = boundingBox;
+
+ final Matrix matrix = new Matrix();
+ matrix.setTranslate(-rect.left, -rect.top);
+ matrix.postScale(width / rect.width(), height / rect.height());
+ matrix.mapPoints(pts);
+
+ float mX = 0;
+ float mY = 0;
+
+ Path path = null;
+
+ final int count = pts.length;
+
+ for (int i = 0; i < count; i += 2) {
+ float x = pts[i];
+ float y = pts[i + 1];
+ if (path == null) {
+ path = new Path();
+ path.moveTo(x, y);
+ mX = x;
+ mY = y;
+ } else {
+ float dx = Math.abs(x - mX);
+ float dy = Math.abs(y - mY);
+ if (dx >= GestureOverlayView.TOUCH_TOLERANCE ||
+ dy >= GestureOverlayView.TOUCH_TOLERANCE) {
+ path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
+ mX = x;
+ mY = y;
+ }
+ }
+ }
+
+ return path;
+ }
+
+ void serialize(DataOutputStream out) throws IOException {
+ final float[] pts = points;
+ final long[] times = timestamps;
+ final int count = points.length;
+
+ // Write number of points
+ out.writeInt(count / 2);
+
+ for (int i = 0; i < count; i += 2) {
+ // Write X
+ out.writeFloat(pts[i]);
+ // Write Y
+ out.writeFloat(pts[i + 1]);
+ // Write timestamp
+ out.writeLong(times[i / 2]);
+ }
+ }
+
+ static GestureStroke deserialize(DataInputStream in) throws IOException {
+ // Number of points
+ final int count = in.readInt();
+
+ final ArrayList<GesturePoint> points = new ArrayList<GesturePoint>(count);
+ for (int i = 0; i < count; i++) {
+ points.add(GesturePoint.deserialize(in));
+ }
+
+ return new GestureStroke(points);
+ }
+
+ /**
+ * Invalidate the cached path that is used to render the stroke
+ */
+ public void clearPath() {
+ if (mCachedPath != null) mCachedPath.rewind();
+ }
+
+ /**
+ * Compute an oriented bounding box of the stroke
+ * @return OrientedBoundingBox
+ */
+ public OrientedBoundingBox computeOrientedBoundingBox() {
+ return GestureUtilities.computeOrientedBoundingBox(points);
+ }
+}