Revert "Revert "Bug fixes and performance improvements""

This reverts commit 436466d75edb5f6fd848504d998f244426ea5a09.
diff --git a/core/java/android/gesture/GestureLibrary.java b/core/java/android/gesture/GestureLibrary.java
index 1cf192e..9020d2b 100644
--- a/core/java/android/gesture/GestureLibrary.java
+++ b/core/java/android/gesture/GestureLibrary.java
@@ -136,7 +136,7 @@
      * @return a list of predictions of possible entries for a given gesture
      */
     public ArrayList<Prediction> recognize(Gesture gesture) {
-        Instance instance = Instance.createInstance(mSequenceType, gesture, null);
+        Instance instance = Instance.createInstance(mSequenceType, mOrientationStyle, gesture, null);
         return mClassifier.classify(mSequenceType, instance.vector);
     }
 
@@ -156,7 +156,7 @@
             mNamedGestures.put(entryName, gestures);
         }
         gestures.add(gesture);
-        mClassifier.addInstance(Instance.createInstance(mSequenceType, gesture, entryName));
+        mClassifier.addInstance(Instance.createInstance(mSequenceType, mOrientationStyle, gesture, entryName));
         mChanged = true;
     }
 
@@ -337,10 +337,14 @@
             for (int j = 0; j < gestureCount; j++) {
                 final Gesture gesture = Gesture.deserialize(in);
                 gestures.add(gesture);
-                classifier.addInstance(Instance.createInstance(mSequenceType, gesture, name));
+                classifier.addInstance(Instance.createInstance(mSequenceType, mOrientationStyle, gesture, name));
             }
 
             namedGestures.put(name, gestures);
         }
     }
+    
+    Learner getLearner() {
+        return mClassifier;
+    }
 }
diff --git a/core/java/android/gesture/GestureStroke.java b/core/java/android/gesture/GestureStroke.java
index 0d7bc2d0..90faaed 100644
--- a/core/java/android/gesture/GestureStroke.java
+++ b/core/java/android/gesture/GestureStroke.java
@@ -17,7 +17,6 @@
 package android.gesture;
 
 import android.graphics.Canvas;
-import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.RectF;
@@ -147,10 +146,12 @@
         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);
+        GestureUtilities.translate(pts, -rect.left, -rect.top);
+        
+        float sx = width / rect.width();
+        float sy = height / rect.height();
+        float scale = sx > sy ? sy : sx;
+        GestureUtilities.scale(pts, scale, scale);
 
         float mX = 0;
         float mY = 0;
diff --git a/core/java/android/gesture/GestureUtilities.java b/core/java/android/gesture/GestureUtilities.java
index 4a3144c2..3e8a3c8 100755
--- a/core/java/android/gesture/GestureUtilities.java
+++ b/core/java/android/gesture/GestureUtilities.java
@@ -17,7 +17,6 @@
 package android.gesture;
 
 import android.graphics.RectF;
-import android.graphics.Matrix;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -380,22 +379,17 @@
     }
 
     static OrientedBoundingBox computeOrientedBoundingBox(float[] points, float[] centroid) {
-        Matrix tr = new Matrix();
-        tr.setTranslate(-centroid[0], -centroid[1]);
-        tr.mapPoints(points);
+        translate(points, -centroid[0], -centroid[1]);
 
         double[][] array = computeCoVariance(points);
         double[] targetVector = computeOrientation(array);
 
         float angle;
         if (targetVector[0] == 0 && targetVector[1] == 0) {
-            angle = -90;
+            angle = (float) -Math.PI/2;
         } else { // -PI<alpha<PI
             angle = (float) Math.atan2(targetVector[1], targetVector[0]);
-            angle = (float) (180 * angle / Math.PI);
-            Matrix trans = new Matrix();
-            trans.setRotate(-angle);
-            trans.mapPoints(points);
+            rotate(points, -angle);
         }
 
         float minx = Float.MAX_VALUE;
@@ -446,4 +440,36 @@
         }
         return targetVector;
     }
+    
+    
+    static float[] rotate(float[] points, double angle) {
+        double cos = Math.cos(angle);
+        double sin = Math.sin(angle);
+        int size = points.length;
+        for (int i = 0; i < size; i += 2) {
+            float x = (float) (points[i] * cos - points[i + 1] * sin);
+            float y = (float) (points[i] * sin + points[i + 1] * cos);
+            points[i] = x;
+            points[i + 1] = y;
+        }
+        return points;
+    }
+    
+    static float[] translate(float[] points, float dx, float dy) {
+        int size = points.length;
+        for (int i = 0; i < size; i += 2) {
+            points[i] += dx;
+            points[i + 1] += dy;
+        }
+        return points;
+    }
+    
+    static float[] scale(float[] points, float sx, float sy) {
+        int size = points.length;
+        for (int i = 0; i < size; i += 2) {
+            points[i] *= sx;
+            points[i + 1] *= sy;
+        }
+        return points;
+    }
 }
diff --git a/core/java/android/gesture/Instance.java b/core/java/android/gesture/Instance.java
index 7922fab..9ac0a96 100755
--- a/core/java/android/gesture/Instance.java
+++ b/core/java/android/gesture/Instance.java
@@ -16,7 +16,6 @@
 
 package android.gesture;
 
-import android.graphics.Matrix;
 
 /**
  * An instance represents a sample if the label is available or a query if the
@@ -28,7 +27,9 @@
     private static final int PATCH_SAMPLE_SIZE = 16;
 
     private final static float[] ORIENTATIONS = {
-            0, 45, 90, 135, 180, -0, -45, -90, -135, -180
+            0, (float) (Math.PI / 4), (float) (Math.PI / 2), (float) (Math.PI * 3 / 4),
+            (float) Math.PI, -0, (float) (-Math.PI / 4), (float) (-Math.PI / 2),
+            (float) (-Math.PI * 3 / 4), (float) -Math.PI
     };
 
     // the feature vector
@@ -39,13 +40,13 @@
 
     // the id of the instance
     final long id;
-    
+
     private Instance(long id, float[] sample, String sampleName) {
         this.id = id;
         vector = sample;
         label = sampleName;
     }
-    
+
     private void normalize() {
         float[] sample = vector;
         float sum = 0;
@@ -55,7 +56,7 @@
             sum += sample[i] * sample[i];
         }
 
-        float magnitude = (float) Math.sqrt(sum);
+        float magnitude = (float)Math.sqrt(sum);
         for (int i = 0; i < size; i++) {
             sample[i] /= magnitude;
         }
@@ -68,11 +69,11 @@
      * @param label
      * @return the instance
      */
-    static Instance createInstance(int samplingType, Gesture gesture, String label) {
+    static Instance createInstance(int sequenceType, int orientationType, Gesture gesture, String label) {
         float[] pts;
         Instance instance;
-        if (samplingType == GestureLibrary.SEQUENCE_SENSITIVE) {
-            pts = temporalSampler(samplingType, gesture);
+        if (sequenceType == GestureLibrary.SEQUENCE_SENSITIVE) {
+            pts = temporalSampler(orientationType, gesture);
             instance = new Instance(gesture.getID(), pts, label);
             instance.normalize();
         } else {
@@ -81,20 +82,19 @@
         }
         return instance;
     }
-    
+
     private static float[] spatialSampler(Gesture gesture) {
         return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE);
     }
 
-    private static float[] temporalSampler(int samplingType, Gesture gesture) {
+    private static float[] temporalSampler(int orientationType, Gesture gesture) {
         float[] pts = GestureUtilities.temporalSampling(gesture.getStrokes().get(0),
                 SEQUENCE_SAMPLE_SIZE);
         float[] center = GestureUtilities.computeCentroid(pts);
-        float orientation = (float) Math.atan2(pts[1] - center[1], pts[0] - center[0]);
-        orientation *= 180 / Math.PI;
+        float orientation = (float)Math.atan2(pts[1] - center[1], pts[0] - center[0]);
 
         float adjustment = -orientation;
-        if (samplingType == GestureLibrary.ORIENTATION_SENSITIVE) {
+        if (orientationType == GestureLibrary.ORIENTATION_SENSITIVE) {
             int count = ORIENTATIONS.length;
             for (int i = 0; i < count; i++) {
                 float delta = ORIENTATIONS[i] - orientation;
@@ -104,10 +104,8 @@
             }
         }
 
-        Matrix m = new Matrix();
-        m.setTranslate(-center[0], -center[1]);
-        m.postRotate(adjustment);
-        m.mapPoints(pts);
+        GestureUtilities.translate(pts, -center[0], -center[1]);
+        GestureUtilities.rotate(pts, adjustment);
 
         return pts;
     }
diff --git a/core/java/android/gesture/InstanceLearner.java b/core/java/android/gesture/InstanceLearner.java
index 1739cdc..b6feb64 100644
--- a/core/java/android/gesture/InstanceLearner.java
+++ b/core/java/android/gesture/InstanceLearner.java
@@ -16,14 +16,9 @@
 
 package android.gesture;
 
-import android.util.Config;
-import android.util.Log;
-import static android.gesture.GestureConstants.*;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Iterator;
 import java.util.TreeMap;
 
 /**
@@ -32,7 +27,7 @@
 
 class InstanceLearner extends Learner {
     @Override
-    ArrayList<Prediction> classify(int gestureType, float[] vector) {
+    ArrayList<Prediction> classify(int sequenceType, float[] vector) {
         ArrayList<Prediction> predictions = new ArrayList<Prediction>();
         ArrayList<Instance> instances = getInstances();
         int count = instances.size();
@@ -43,7 +38,7 @@
                 continue;
             }
             double distance;
-            if (gestureType == GestureLibrary.SEQUENCE_SENSITIVE) {
+            if (sequenceType == GestureLibrary.SEQUENCE_SENSITIVE) {
                 distance = GestureUtilities.cosineDistance(sample.vector, vector);
             } else {
                 distance = GestureUtilities.squaredEuclideanDistance(sample.vector, vector);