diff options
author | Romain Guy <romainguy@android.com> | 2009-05-21 15:05:50 -0700 |
---|---|---|
committer | Romain Guy <romainguy@android.com> | 2009-05-21 15:26:46 -0700 |
commit | b6d99b7d17fd1bb1326a70744bd01be5d1586487 (patch) | |
tree | d7450b579b920bf26dd559f4dc349af411727263 /tests | |
parent | aeed1816b7bbf8948c1daed48db6fe7567f338af (diff) | |
download | frameworks_base-b6d99b7d17fd1bb1326a70744bd01be5d1586487.zip frameworks_base-b6d99b7d17fd1bb1326a70744bd01be5d1586487.tar.gz frameworks_base-b6d99b7d17fd1bb1326a70744bd01be5d1586487.tar.bz2 |
Modify how GestureLibrary stores its data. The XML format is now replaced by a more efficient binary format which should speed up saving/loading. The format is very similar to the one used by the letters recognizer. The format is documented in GestureLibrary.java.
Diffstat (limited to 'tests')
10 files changed, 288 insertions, 278 deletions
diff --git a/tests/sketch/AndroidManifest.xml b/tests/sketch/AndroidManifest.xml index 1f4333c..78df234 100755 --- a/tests/sketch/AndroidManifest.xml +++ b/tests/sketch/AndroidManifest.xml @@ -14,25 +14,34 @@ limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.gesture.example" - android:versionCode="1" - android:versionName="1.0.0"> - <uses-permission android:name="android.permission.READ_CONTACTS" /> - <application android:icon="@drawable/icon" android:label="@string/app_name"> - <activity android:name="com.android.gesture.example.GestureEntry" - android:label="@string/app_name"> + package="com.android.gesture.example" + android:versionCode="1" + android:versionName="1.0.0"> + + <uses-permission android:name="android.permission.READ_CONTACTS" /> + <uses-permission android:name="android.permission.WRITE_SDCARD" /> + + <application android:icon="@drawable/icon" android:label="@string/app_name"> + + <activity + android:name="com.android.gesture.example.GestureEntry" + android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + <activity android:name="com.android.gesture.example.GestureLibViewer"/> - <activity android:name="com.android.gesture.example.ContactListGestureOverlay" - android:label="@string/overlay_name"> + + <activity + android:name="com.android.gesture.example.ContactListGestureOverlay" + android:label="@string/overlay_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> + </application> </manifest> diff --git a/tests/sketch/src/com/android/gesture/Gesture.java b/tests/sketch/src/com/android/gesture/Gesture.java index 44711ca..d5dcc65 100755 --- a/tests/sketch/src/com/android/gesture/Gesture.java +++ b/tests/sketch/src/com/android/gesture/Gesture.java @@ -23,12 +23,17 @@ import android.graphics.Path; import android.graphics.RectF; import android.os.Parcel; import android.os.Parcelable; - -import org.xmlpull.v1.XmlSerializer; +import android.util.Log; import java.io.IOException; +import java.io.DataOutputStream; +import java.io.DataInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; import java.util.ArrayList; +import static com.android.gesture.GestureConstants.LOG_TAG; + /** * A gesture can have a single or multiple strokes */ @@ -149,10 +154,12 @@ public class Gesture implements Parcelable { * @return the bitmap */ public Bitmap toBitmap(int width, int height, int edge, int numSample, int color) { - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); + final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(bitmap); + canvas.translate(edge, edge); - Paint paint = new Paint(); + + final Paint paint = new Paint(); paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS); paint.setDither(BITMAP_RENDERING_DITHER); paint.setColor(color); @@ -182,10 +189,12 @@ public class Gesture implements Parcelable { * @return the bitmap */ public Bitmap toBitmap(int width, int height, int edge, int color) { - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); + final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(bitmap); + canvas.translate(edge, edge); - Paint paint = new Paint(); + + final Paint paint = new Paint(); paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS); paint.setDither(BITMAP_RENDERING_DITHER); paint.setColor(color); @@ -193,53 +202,44 @@ public class Gesture implements Parcelable { paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStrokeWidth(BITMAP_RENDERING_WIDTH); - ArrayList<GestureStroke> strokes = mStrokes; - int count = strokes.size(); + + final ArrayList<GestureStroke> strokes = mStrokes; + final int count = strokes.size(); + for (int i = 0; i < count; i++) { - GestureStroke stroke = strokes.get(i); - stroke.draw(canvas, paint); + strokes.get(i).draw(canvas, paint); } return bitmap; } - /** - * Save the gesture as XML - * - * @param namespace - * @param serializer - * @throws IOException - */ - void toXML(String namespace, XmlSerializer serializer) throws IOException { - serializer.startTag(namespace, GestureConstants.XML_TAG_GESTURE); - serializer.attribute(namespace, GestureConstants.XML_TAG_ID, Long.toString(mGestureID)); - ArrayList<GestureStroke> strokes = mStrokes; - int count = strokes.size(); + void serialize(DataOutputStream out) throws IOException { + final ArrayList<GestureStroke> strokes = mStrokes; + final int count = strokes.size(); + + // Write gesture ID + out.writeLong(mGestureID); + // Write number of strokes + out.writeInt(count); + for (int i = 0; i < count; i++) { - GestureStroke stroke = strokes.get(i); - stroke.toXML(namespace, serializer); + strokes.get(i).serialize(out); } - serializer.endTag(namespace, GestureConstants.XML_TAG_GESTURE); } - /** - * Create the gesture from a string - * - * @param str - */ - public void createFromString(String str) { - int startIndex = 0; - int endIndex; - while ((endIndex = - str.indexOf(GestureConstants.STRING_GESTURE_DELIIMITER, startIndex + 1)) != -1) { - String token = str.substring(startIndex, endIndex); - if (startIndex > 0) { // stroke tokens - addStroke(GestureStroke.createFromString(token)); - } else { // id token - mGestureID = Long.parseLong(token); - } - startIndex = endIndex + 1; + static Gesture deserialize(DataInputStream in) throws IOException { + final Gesture gesture = new Gesture(); + + // Gesture ID + gesture.mGestureID = in.readLong(); + // Number of strokes + final int count = in.readInt(); + + for (int i = 0; i < count; i++) { + gesture.addStroke(GestureStroke.deserialize(in)); } + + return gesture; } /** @@ -247,12 +247,14 @@ public class Gesture implements Parcelable { */ @Override public String toString() { - StringBuilder str = new StringBuilder(); + final StringBuilder str = new StringBuilder(); str.append(mGestureID); - ArrayList<GestureStroke> strokes = mStrokes; - int count = strokes.size(); + + final ArrayList<GestureStroke> strokes = mStrokes; + final int count = strokes.size(); + for (int i = 0; i < count; i++) { - GestureStroke stroke = strokes.get(i); + final GestureStroke stroke = strokes.get(i); str.append(GestureConstants.STRING_GESTURE_DELIIMITER); str.append(stroke.toString()); } @@ -262,9 +264,24 @@ public class Gesture implements Parcelable { public static final Parcelable.Creator<Gesture> CREATOR = new Parcelable.Creator<Gesture>() { public Gesture createFromParcel(Parcel in) { - String str = in.readString(); - Gesture gesture = new Gesture(); - gesture.createFromString(str); + Gesture gesture = null; + final long gestureID = in.readLong(); + + final DataInputStream inStream = new DataInputStream( + new ByteArrayInputStream(in.createByteArray())); + + try { + gesture = deserialize(inStream); + } catch (IOException e) { + Log.e(LOG_TAG, "Error reading Gesture from parcel:", e); + } finally { + GestureUtilities.closeStream(inStream); + } + + if (gesture != null) { + gesture.mGestureID = gestureID; + } + return gesture; } @@ -273,35 +290,31 @@ public class Gesture implements Parcelable { } }; - /** - * Build a gesture from a byte array - * - * @param bytes - * @return the gesture - */ - static Gesture buildFromArray(byte[] bytes) { - String str = new String(bytes); - Gesture gesture = new Gesture(); - gesture.createFromString(str); - return gesture; - } - - /** - * Save a gesture to a byte array - * - * @param stroke - * @return the byte array - */ - static byte[] saveToArray(Gesture stroke) { - String str = stroke.toString(); - return str.getBytes(); - } - public void writeToParcel(Parcel out, int flags) { - out.writeString(toString()); + out.writeLong(mGestureID); + + boolean result = false; + final ByteArrayOutputStream byteStream = + new ByteArrayOutputStream(GestureConstants.IO_BUFFER_SIZE); + final DataOutputStream outStream = new DataOutputStream(byteStream); + + try { + serialize(outStream); + result = true; + } catch (IOException e) { + Log.e(LOG_TAG, "Error writing Gesture to parcel:", e); + } finally { + GestureUtilities.closeStream(outStream); + GestureUtilities.closeStream(byteStream); + } + + if (result) { + out.writeByteArray(byteStream.toByteArray()); + } } public int describeContents() { - return CONTENTS_FILE_DESCRIPTOR; + return 0; } } + diff --git a/tests/sketch/src/com/android/gesture/GestureConstants.java b/tests/sketch/src/com/android/gesture/GestureConstants.java index cb64791..c0f2f3d 100644 --- a/tests/sketch/src/com/android/gesture/GestureConstants.java +++ b/tests/sketch/src/com/android/gesture/GestureConstants.java @@ -17,16 +17,13 @@ package com.android.gesture; interface GestureConstants { - static final String XML_TAG_LIBRARY = "library"; - static final String XML_TAG_ENTRY = "entry"; - static final String XML_TAG_GESTURE = "gesture"; - static final String XML_TAG_STROKE = "stroke"; - static final String XML_TAG_ID = "id"; - static final String XML_TAG_NAME = "name"; static final String STRING_GESTURE_DELIIMITER = "#"; static final String STRING_STROKE_DELIIMITER = ","; + static final int STROKE_STRING_BUFFER_SIZE = 1024; static final int STROKE_POINT_BUFFER_SIZE = 100; // number of points - static final int IO_BUFFER_SIZE = 8 * 1024; // 8K - String LOG_TAG = "GestureLibrary"; + + static final int IO_BUFFER_SIZE = 32 * 1024; // 32K + + static final String LOG_TAG = "Gestures"; } diff --git a/tests/sketch/src/com/android/gesture/GestureLibrary.java b/tests/sketch/src/com/android/gesture/GestureLibrary.java index 915b840..eba6069 100644 --- a/tests/sketch/src/com/android/gesture/GestureLibrary.java +++ b/tests/sketch/src/com/android/gesture/GestureLibrary.java @@ -16,16 +16,8 @@ package com.android.gesture; -import android.util.Config; import android.util.Log; -import android.util.Xml; -import android.util.Xml.Encoding; - -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xmlpull.v1.XmlSerializer; +import android.os.SystemClock; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -33,10 +25,12 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.io.PrintWriter; +import java.io.DataOutputStream; +import java.io.DataInputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Set; +import java.util.Map; import static com.android.gesture.GestureConstants.LOG_TAG; @@ -44,10 +38,28 @@ import static com.android.gesture.GestureConstants.LOG_TAG; * GestureLibrary maintains gesture examples and makes predictions on a new * gesture */ +// +// File format for GestureLibrary: +// +// Nb. bytes Java type Description +// ----------------------------------- +// Header +// 2 bytes short File format version number +// 4 bytes int Number of entries +// Entry +// X bytes UTF String Entry name +// 4 bytes int Number of gestures +// Gesture +// 8 bytes long Gesture ID +// 4 bytes int Number of strokes +// Stroke +// 4 bytes int Number of points +// Point +// 4 bytes float X coordinate of the point +// 4 bytes float Y coordinate of the point +// 8 bytes long Time stamp +// public class GestureLibrary { - - private static final String NAMESPACE = ""; - public static final int SEQUENCE_INVARIANT = 1; // when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed public static final int SEQUENCE_SENSITIVE = 2; @@ -56,12 +68,16 @@ public class GestureLibrary { public static final int ORIENTATION_INVARIANT = 1; public static final int ORIENTATION_SENSITIVE = 2; + private static final short FILE_FORMAT_VERSION = 1; + + private static final boolean PROFILE_LOADING_SAVING = false; + private int mSequenceType = SEQUENCE_SENSITIVE; private int mOrientationStyle = ORIENTATION_SENSITIVE; private final String mGestureFileName; - private final HashMap<String, ArrayList<Gesture>> mEntryName2gestures = + private final HashMap<String, ArrayList<Gesture>> mNamedGestures = new HashMap<String, ArrayList<Gesture>>(); private Learner mClassifier; @@ -104,7 +120,7 @@ public class GestureLibrary { * @return a set of strings */ public Set<String> getGestureEntries() { - return mEntryName2gestures.keySet(); + return mNamedGestures.keySet(); } /** @@ -128,10 +144,10 @@ public class GestureLibrary { if (entryName == null || entryName.length() == 0) { return; } - ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName); + ArrayList<Gesture> gestures = mNamedGestures.get(entryName); if (gestures == null) { gestures = new ArrayList<Gesture>(); - mEntryName2gestures.put(entryName, gestures); + mNamedGestures.put(entryName, gestures); } gestures.add(gesture); mClassifier.addInstance(Instance.createInstance(mSequenceType, gesture, entryName)); @@ -146,7 +162,7 @@ public class GestureLibrary { * @param gesture */ public void removeGesture(String entryName, Gesture gesture) { - ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName); + ArrayList<Gesture> gestures = mNamedGestures.get(entryName); if (gestures == null) { return; } @@ -155,7 +171,7 @@ public class GestureLibrary { // if there are no more samples, remove the entry automatically if (gestures.isEmpty()) { - mEntryName2gestures.remove(entryName); + mNamedGestures.remove(entryName); } mClassifier.removeInstance(gesture.getID()); @@ -169,7 +185,7 @@ public class GestureLibrary { * @param entryName the entry name */ public void removeEntireEntry(String entryName) { - mEntryName2gestures.remove(entryName); + mNamedGestures.remove(entryName); mClassifier.removeInstances(entryName); mChanged = true; } @@ -181,7 +197,7 @@ public class GestureLibrary { * @return the list of gestures that is under this name */ public ArrayList<Gesture> getGestures(String entryName) { - ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName); + ArrayList<Gesture> gestures = mNamedGestures.get(entryName); if (gestures != null) { return new ArrayList<Gesture>(gestures); } else { @@ -197,8 +213,8 @@ public class GestureLibrary { return true; } - boolean result= false; - PrintWriter writer = null; + boolean result = false; + DataOutputStream out = null; try { File file = new File(mGestureFileName); @@ -208,40 +224,48 @@ public class GestureLibrary { } } - writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream( - mGestureFileName), GestureConstants.IO_BUFFER_SIZE)); + long start; + if (PROFILE_LOADING_SAVING) { + start = SystemClock.elapsedRealtime(); + } + + final HashMap<String, ArrayList<Gesture>> maps = mNamedGestures; + + out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file), + GestureConstants.IO_BUFFER_SIZE)); + // Write version number + out.writeShort(FILE_FORMAT_VERSION); + // Write number of entries + out.writeInt(maps.size()); - final XmlSerializer serializer = Xml.newSerializer(); - serializer.setOutput(writer); - serializer.startDocument(Encoding.ISO_8859_1.name(), null); - serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY); + for (Map.Entry<String, ArrayList<Gesture>> entry : maps.entrySet()) { + final String key = entry.getKey(); + final ArrayList<Gesture> examples = entry.getValue(); + final int count = examples.size(); - final HashMap<String, ArrayList<Gesture>> maps = mEntryName2gestures; + // Write entry name + out.writeUTF(key); + // Write number of examples for this entry + out.writeInt(count); - for (String key : maps.keySet()) { - ArrayList<Gesture> examples = maps.get(key); - // save an entry - serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY); - serializer.attribute(NAMESPACE, GestureConstants.XML_TAG_NAME, key); - int count = examples.size(); for (int i = 0; i < count; i++) { - Gesture gesture = examples.get(i); - // save each gesture in the entry - gesture.toXML(NAMESPACE, serializer); + examples.get(i).serialize(out); } - serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY); } - serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY); - serializer.endDocument(); - serializer.flush(); + out.flush(); + + if (PROFILE_LOADING_SAVING) { + long end = SystemClock.elapsedRealtime(); + Log.d(LOG_TAG, "Saving gestures library = " + (end - start) + " ms"); + } mChanged = false; result = true; } catch (IOException ex) { Log.d(LOG_TAG, "Failed to save gestures:", ex); } finally { - GestureUtilities.closeStream(writer); + GestureUtilities.closeStream(out); } return result; @@ -255,17 +279,30 @@ public class GestureLibrary { final File file = new File(mGestureFileName); if (file.exists()) { - BufferedInputStream in = null; + DataInputStream in = null; try { - if (Config.DEBUG) { - Log.v(LOG_TAG, "Load from " + mGestureFileName); + in = new DataInputStream(new BufferedInputStream( + new FileInputStream(mGestureFileName), GestureConstants.IO_BUFFER_SIZE)); + + long start; + if (PROFILE_LOADING_SAVING) { + start = SystemClock.elapsedRealtime(); + } + + // Read file format version number + final short versionNumber = in.readShort(); + switch (versionNumber) { + case 1: + readFormatV1(in); + break; } - in = new BufferedInputStream(new FileInputStream( - mGestureFileName), GestureConstants.IO_BUFFER_SIZE); - Xml.parse(in, Encoding.ISO_8859_1, new CompactInkHandler()); + + if (PROFILE_LOADING_SAVING) { + long end = SystemClock.elapsedRealtime(); + Log.d(LOG_TAG, "Loading gestures library = " + (end - start) + " ms"); + } + result = true; - } catch (SAXException ex) { - Log.d(LOG_TAG, "Failed to load gestures:", ex); } catch (IOException ex) { Log.d(LOG_TAG, "Failed to load gestures:", ex); } finally { @@ -276,69 +313,28 @@ public class GestureLibrary { return result; } - private class CompactInkHandler implements ContentHandler { - final StringBuilder mBuffer = new StringBuilder(GestureConstants.STROKE_STRING_BUFFER_SIZE); - - String mEntryName; - - Gesture mCurrentGesture = null; - ArrayList<Gesture> mGestures; - - CompactInkHandler() { - } - - public void characters(char[] ch, int start, int length) { - mBuffer.append(ch, start, length); - } - - public void endDocument() { - } - - public void endElement(String uri, String localName, String qName) { - if (localName.equals(GestureConstants.XML_TAG_ENTRY)) { - mEntryName2gestures.put(mEntryName, mGestures); - mGestures = null; - } else if (localName.equals(GestureConstants.XML_TAG_GESTURE)) { - mGestures.add(mCurrentGesture); - mClassifier.addInstance(Instance.createInstance(mSequenceType, - mCurrentGesture, mEntryName)); - mCurrentGesture = null; - } else if (localName.equals(GestureConstants.XML_TAG_STROKE)) { - mCurrentGesture.addStroke(GestureStroke.createFromString(mBuffer.toString())); - mBuffer.setLength(0); + private void readFormatV1(DataInputStream in) throws IOException { + final Learner classifier = mClassifier; + final HashMap<String, ArrayList<Gesture>> namedGestures = mNamedGestures; + namedGestures.clear(); + + // Number of entries in the library + final int entriesCount = in.readInt(); + + for (int i = 0; i < entriesCount; i++) { + // Entry name + final String name = in.readUTF(); + // Number of gestures + final int gestureCount = in.readInt(); + + final ArrayList<Gesture> gestures = new ArrayList<Gesture>(gestureCount); + for (int j = 0; j < gestureCount; j++) { + final Gesture gesture = Gesture.deserialize(in); + gestures.add(gesture); + classifier.addInstance(Instance.createInstance(mSequenceType, gesture, name)); } - } - - public void endPrefixMapping(String prefix) { - } - - public void ignorableWhitespace(char[] ch, int start, int length) { - } - - public void processingInstruction(String target, String data) { - } - - public void setDocumentLocator(Locator locator) { - } - - public void skippedEntity(String name) { - } - - public void startDocument() { - } - - public void startElement(String uri, String localName, String qName, Attributes attributes) { - if (localName.equals(GestureConstants.XML_TAG_ENTRY)) { - mGestures = new ArrayList<Gesture>(); - mEntryName = attributes.getValue(NAMESPACE, GestureConstants.XML_TAG_NAME); - } else if (localName.equals(GestureConstants.XML_TAG_GESTURE)) { - mCurrentGesture = new Gesture(); - mCurrentGesture.setID(Long.parseLong(attributes.getValue(NAMESPACE, - GestureConstants.XML_TAG_ID))); - } - } - public void startPrefixMapping(String prefix, String uri) { + namedGestures.put(name, gestures); } } } diff --git a/tests/sketch/src/com/android/gesture/GesturePoint.java b/tests/sketch/src/com/android/gesture/GesturePoint.java index 81e59a4..560f893 100644 --- a/tests/sketch/src/com/android/gesture/GesturePoint.java +++ b/tests/sketch/src/com/android/gesture/GesturePoint.java @@ -16,6 +16,9 @@ package com.android.gesture; +import java.io.DataInputStream; +import java.io.IOException; + /** * A timed point of a gesture stroke */ @@ -31,4 +34,13 @@ public class GesturePoint { this.y = y; timestamp = t; } + + static GesturePoint deserialize(DataInputStream in) throws IOException { + // Read X and Y + final float x = in.readFloat(); + final float y = in.readFloat(); + // Read timestamp + final long timeStamp = in.readLong(); + return new GesturePoint(x, y, timeStamp); + } } diff --git a/tests/sketch/src/com/android/gesture/GestureStroke.java b/tests/sketch/src/com/android/gesture/GestureStroke.java index c2ebc17..79b42fe 100644 --- a/tests/sketch/src/com/android/gesture/GestureStroke.java +++ b/tests/sketch/src/com/android/gesture/GestureStroke.java @@ -22,9 +22,9 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; -import org.xmlpull.v1.XmlSerializer; - import java.io.IOException; +import java.io.DataOutputStream; +import java.io.DataInputStream; import java.util.ArrayList; /** @@ -167,57 +167,35 @@ public class GestureStroke { return path; } - /** - * Save the gesture stroke as XML - * - * @param namespace - * @param serializer - * @throws IOException - */ - void toXML(String namespace, XmlSerializer serializer) throws IOException { - serializer.startTag(namespace, GestureConstants.XML_TAG_STROKE); - serializer.text(toString()); - serializer.endTag(namespace, GestureConstants.XML_TAG_STROKE); + 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]); + } } - /** - * Create a gesture stroke from a string - * - * @param str - * @return the gesture stroke - */ - public static GestureStroke createFromString(String str) { - final ArrayList<GesturePoint> points = new ArrayList<GesturePoint>( - GestureConstants.STROKE_POINT_BUFFER_SIZE); - - int endIndex; - int startIndex = 0; - - while ((endIndex = - str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1)) != -1) { - - // parse x - String token = str.substring(startIndex, endIndex); - float x = Float.parseFloat(token); - startIndex = endIndex + 1; - - // parse y - endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1); - token = str.substring(startIndex, endIndex); - float y = Float.parseFloat(token); - startIndex = endIndex + 1; - - // parse t - endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1); - token = str.substring(startIndex, endIndex); - long time = Long.parseLong(token); - startIndex = endIndex + 1; - - points.add(new GesturePoint(x, y, time)); + 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); - } + } /** * Convert the stroke to string diff --git a/tests/sketch/src/com/android/gesture/GestureUtilities.java b/tests/sketch/src/com/android/gesture/GestureUtilities.java index 92de987..6d73c2d 100755 --- a/tests/sketch/src/com/android/gesture/GestureUtilities.java +++ b/tests/sketch/src/com/android/gesture/GestureUtilities.java @@ -18,6 +18,7 @@ package com.android.gesture; import android.graphics.RectF; import android.graphics.Matrix; +import android.util.Log; import java.util.ArrayList; import java.util.Arrays; @@ -42,7 +43,7 @@ final class GestureUtilities { try { stream.close(); } catch (IOException e) { - android.util.Log.e(LOG_TAG, "Could not close stream", e); + Log.e(LOG_TAG, "Could not close stream", e); } } } @@ -56,24 +57,25 @@ final class GestureUtilities { float sx = targetPatchSize / rect.width(); float sy = targetPatchSize / rect.height(); float scale = sx < sy ? sx : sy; - android.graphics.Matrix trans = new android.graphics.Matrix(); + + Matrix trans = new Matrix(); trans.setScale(scale, scale); - android.graphics.Matrix translate1 = new android.graphics.Matrix(); - translate1.setTranslate(-rect.centerX(), -rect.centerY()); - trans.preConcat(translate1); - android.graphics.Matrix translate2 = new android.graphics.Matrix(); - translate2.setTranslate(targetPatchSize / 2, targetPatchSize / 2); - trans.postConcat(translate2); - - ArrayList<GestureStroke> strokes = gesture.getStrokes(); - int count = strokes.size(); + trans.preTranslate(-rect.centerX(), -rect.centerY()); + trans.postTranslate(targetPatchSize / 2, targetPatchSize / 2); + + final ArrayList<GestureStroke> strokes = gesture.getStrokes(); + final int count = strokes.size(); + int size; float xpos; float ypos; + for (int index = 0; index < count; index++) { - GestureStroke stroke = strokes.get(index); + final GestureStroke stroke = strokes.get(index); size = stroke.points.length; - float[] pts = new float[size]; + + final float[] pts = new float[size]; + trans.mapPoints(pts, 0, stroke.points, 0, size / 2); float segmentEndX = -1; float segmentEndY = -1; diff --git a/tests/sketch/src/com/android/gesture/Instance.java b/tests/sketch/src/com/android/gesture/Instance.java index b2e030e..502a0fa 100755 --- a/tests/sketch/src/com/android/gesture/Instance.java +++ b/tests/sketch/src/com/android/gesture/Instance.java @@ -16,6 +16,8 @@ package com.android.gesture; +import android.graphics.Matrix; + /** * An instance represents a sample if the label is available or a query if the * label is null. @@ -47,10 +49,12 @@ class Instance { private void normalize() { float[] sample = vector; float sum = 0; + int size = sample.length; for (int i = 0; i < size; i++) { sum += sample[i] * sample[i]; } + float magnitude = (float) Math.sqrt(sum); for (int i = 0; i < size; i++) { sample[i] /= magnitude; @@ -100,12 +104,11 @@ class Instance { } } - android.graphics.Matrix m = new android.graphics.Matrix(); + Matrix m = new Matrix(); m.setTranslate(-center[0], -center[1]); - android.graphics.Matrix rotation = new android.graphics.Matrix(); - rotation.setRotate(adjustment); - m.postConcat(rotation); + m.postRotate(adjustment); m.mapPoints(pts); + return pts; } diff --git a/tests/sketch/src/com/android/gesture/LetterRecognizer.java b/tests/sketch/src/com/android/gesture/LetterRecognizer.java index 086aedf..981c416 100644 --- a/tests/sketch/src/com/android/gesture/LetterRecognizer.java +++ b/tests/sketch/src/com/android/gesture/LetterRecognizer.java @@ -21,7 +21,6 @@ import android.content.res.Resources; import android.util.Log; import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; @@ -29,9 +28,9 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -public class LetterRecognizer { - private static final String LOG_TAG = "LetterRecognizer"; +import static com.android.gesture.GestureConstants.LOG_TAG; +public class LetterRecognizer { public final static int LATIN_LOWERCASE = 0; private SigmoidUnit[] mHiddenLayer; @@ -41,7 +40,7 @@ public class LetterRecognizer { private final int mPatchSize; - static final String GESTURE_FILE_NAME = "letters.xml"; + static final String GESTURE_FILE_NAME = "letters.gestures"; private GestureLibrary mGestureLibrary; private final static int ADJUST_RANGE = 3; @@ -151,7 +150,8 @@ public class LetterRecognizer { LetterRecognizer classifier = null; try { - in = new DataInputStream(new BufferedInputStream(resources.openRawResource(resourceID))); + in = new DataInputStream(new BufferedInputStream(resources.openRawResource(resourceID), + GestureConstants.IO_BUFFER_SIZE)); final int iCount = in.readInt(); final int hCount = in.readInt(); diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntry.java b/tests/sketch/src/com/android/gesture/example/GestureEntry.java index 03a26da..53ba481 100644 --- a/tests/sketch/src/com/android/gesture/example/GestureEntry.java +++ b/tests/sketch/src/com/android/gesture/example/GestureEntry.java @@ -49,7 +49,7 @@ public class GestureEntry extends Activity { private static final String PARCEL_KEY = "gesture"; static final String GESTURE_FILE_NAME = Environment.getExternalStorageDirectory().getAbsolutePath() - + File.separator + "gestureEntry.xml"; + + File.separator + "demo_library.gestures"; private static final int DIALOG_NEW_ENTRY = 1; |