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.
This commit is contained in:
@@ -14,25 +14,34 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.android.gesture.example"
|
package="com.android.gesture.example"
|
||||||
android:versionCode="1"
|
android:versionCode="1"
|
||||||
android:versionName="1.0.0">
|
android:versionName="1.0.0">
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
|
||||||
<application android:icon="@drawable/icon" android:label="@string/app_name">
|
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||||
<activity android:name="com.android.gesture.example.GestureEntry"
|
<uses-permission android:name="android.permission.WRITE_SDCARD" />
|
||||||
android:label="@string/app_name">
|
|
||||||
|
<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>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name="com.android.gesture.example.GestureLibViewer"/>
|
<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>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -23,12 +23,17 @@ import android.graphics.Path;
|
|||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.util.Log;
|
||||||
import org.xmlpull.v1.XmlSerializer;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
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 java.util.ArrayList;
|
||||||
|
|
||||||
|
import static com.android.gesture.GestureConstants.LOG_TAG;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A gesture can have a single or multiple strokes
|
* A gesture can have a single or multiple strokes
|
||||||
*/
|
*/
|
||||||
@@ -149,10 +154,12 @@ public class Gesture implements Parcelable {
|
|||||||
* @return the bitmap
|
* @return the bitmap
|
||||||
*/
|
*/
|
||||||
public Bitmap toBitmap(int width, int height, int edge, int numSample, int color) {
|
public Bitmap toBitmap(int width, int height, int edge, int numSample, int color) {
|
||||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
Canvas canvas = new Canvas(bitmap);
|
final Canvas canvas = new Canvas(bitmap);
|
||||||
|
|
||||||
canvas.translate(edge, edge);
|
canvas.translate(edge, edge);
|
||||||
Paint paint = new Paint();
|
|
||||||
|
final Paint paint = new Paint();
|
||||||
paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
|
paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
|
||||||
paint.setDither(BITMAP_RENDERING_DITHER);
|
paint.setDither(BITMAP_RENDERING_DITHER);
|
||||||
paint.setColor(color);
|
paint.setColor(color);
|
||||||
@@ -182,10 +189,12 @@ public class Gesture implements Parcelable {
|
|||||||
* @return the bitmap
|
* @return the bitmap
|
||||||
*/
|
*/
|
||||||
public Bitmap toBitmap(int width, int height, int edge, int color) {
|
public Bitmap toBitmap(int width, int height, int edge, int color) {
|
||||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
Canvas canvas = new Canvas(bitmap);
|
final Canvas canvas = new Canvas(bitmap);
|
||||||
|
|
||||||
canvas.translate(edge, edge);
|
canvas.translate(edge, edge);
|
||||||
Paint paint = new Paint();
|
|
||||||
|
final Paint paint = new Paint();
|
||||||
paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
|
paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
|
||||||
paint.setDither(BITMAP_RENDERING_DITHER);
|
paint.setDither(BITMAP_RENDERING_DITHER);
|
||||||
paint.setColor(color);
|
paint.setColor(color);
|
||||||
@@ -193,53 +202,44 @@ public class Gesture implements Parcelable {
|
|||||||
paint.setStrokeJoin(Paint.Join.ROUND);
|
paint.setStrokeJoin(Paint.Join.ROUND);
|
||||||
paint.setStrokeCap(Paint.Cap.ROUND);
|
paint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
paint.setStrokeWidth(BITMAP_RENDERING_WIDTH);
|
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++) {
|
for (int i = 0; i < count; i++) {
|
||||||
GestureStroke stroke = strokes.get(i);
|
strokes.get(i).draw(canvas, paint);
|
||||||
stroke.draw(canvas, paint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void serialize(DataOutputStream out) throws IOException {
|
||||||
* Save the gesture as XML
|
final ArrayList<GestureStroke> strokes = mStrokes;
|
||||||
*
|
final int count = strokes.size();
|
||||||
* @param namespace
|
|
||||||
* @param serializer
|
// Write gesture ID
|
||||||
* @throws IOException
|
out.writeLong(mGestureID);
|
||||||
*/
|
// Write number of strokes
|
||||||
void toXML(String namespace, XmlSerializer serializer) throws IOException {
|
out.writeInt(count);
|
||||||
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();
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
GestureStroke stroke = strokes.get(i);
|
strokes.get(i).serialize(out);
|
||||||
stroke.toXML(namespace, serializer);
|
|
||||||
}
|
}
|
||||||
serializer.endTag(namespace, GestureConstants.XML_TAG_GESTURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static Gesture deserialize(DataInputStream in) throws IOException {
|
||||||
* Create the gesture from a string
|
final Gesture gesture = new Gesture();
|
||||||
*
|
|
||||||
* @param str
|
// Gesture ID
|
||||||
*/
|
gesture.mGestureID = in.readLong();
|
||||||
public void createFromString(String str) {
|
// Number of strokes
|
||||||
int startIndex = 0;
|
final int count = in.readInt();
|
||||||
int endIndex;
|
|
||||||
while ((endIndex =
|
for (int i = 0; i < count; i++) {
|
||||||
str.indexOf(GestureConstants.STRING_GESTURE_DELIIMITER, startIndex + 1)) != -1) {
|
gesture.addStroke(GestureStroke.deserialize(in));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return gesture;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -247,12 +247,14 @@ public class Gesture implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder str = new StringBuilder();
|
final StringBuilder str = new StringBuilder();
|
||||||
str.append(mGestureID);
|
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++) {
|
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(GestureConstants.STRING_GESTURE_DELIIMITER);
|
||||||
str.append(stroke.toString());
|
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 static final Parcelable.Creator<Gesture> CREATOR = new Parcelable.Creator<Gesture>() {
|
||||||
public Gesture createFromParcel(Parcel in) {
|
public Gesture createFromParcel(Parcel in) {
|
||||||
String str = in.readString();
|
Gesture gesture = null;
|
||||||
Gesture gesture = new Gesture();
|
final long gestureID = in.readLong();
|
||||||
gesture.createFromString(str);
|
|
||||||
|
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;
|
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) {
|
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() {
|
public int describeContents() {
|
||||||
return CONTENTS_FILE_DESCRIPTOR;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,16 +17,13 @@
|
|||||||
package com.android.gesture;
|
package com.android.gesture;
|
||||||
|
|
||||||
interface GestureConstants {
|
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_GESTURE_DELIIMITER = "#";
|
||||||
static final String STRING_STROKE_DELIIMITER = ",";
|
static final String STRING_STROKE_DELIIMITER = ",";
|
||||||
|
|
||||||
static final int STROKE_STRING_BUFFER_SIZE = 1024;
|
static final int STROKE_STRING_BUFFER_SIZE = 1024;
|
||||||
static final int STROKE_POINT_BUFFER_SIZE = 100; // number of points
|
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";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,8 @@
|
|||||||
|
|
||||||
package com.android.gesture;
|
package com.android.gesture;
|
||||||
|
|
||||||
import android.util.Config;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Xml;
|
import android.os.SystemClock;
|
||||||
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 java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@@ -33,10 +25,12 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static com.android.gesture.GestureConstants.LOG_TAG;
|
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
|
* GestureLibrary maintains gesture examples and makes predictions on a new
|
||||||
* gesture
|
* 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 {
|
public class GestureLibrary {
|
||||||
|
|
||||||
private static final String NAMESPACE = "";
|
|
||||||
|
|
||||||
public static final int SEQUENCE_INVARIANT = 1;
|
public static final int SEQUENCE_INVARIANT = 1;
|
||||||
// when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed
|
// when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed
|
||||||
public static final int SEQUENCE_SENSITIVE = 2;
|
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_INVARIANT = 1;
|
||||||
public static final int ORIENTATION_SENSITIVE = 2;
|
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 mSequenceType = SEQUENCE_SENSITIVE;
|
||||||
private int mOrientationStyle = ORIENTATION_SENSITIVE;
|
private int mOrientationStyle = ORIENTATION_SENSITIVE;
|
||||||
|
|
||||||
private final String mGestureFileName;
|
private final String mGestureFileName;
|
||||||
|
|
||||||
private final HashMap<String, ArrayList<Gesture>> mEntryName2gestures =
|
private final HashMap<String, ArrayList<Gesture>> mNamedGestures =
|
||||||
new HashMap<String, ArrayList<Gesture>>();
|
new HashMap<String, ArrayList<Gesture>>();
|
||||||
|
|
||||||
private Learner mClassifier;
|
private Learner mClassifier;
|
||||||
@@ -104,7 +120,7 @@ public class GestureLibrary {
|
|||||||
* @return a set of strings
|
* @return a set of strings
|
||||||
*/
|
*/
|
||||||
public Set<String> getGestureEntries() {
|
public Set<String> getGestureEntries() {
|
||||||
return mEntryName2gestures.keySet();
|
return mNamedGestures.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,10 +144,10 @@ public class GestureLibrary {
|
|||||||
if (entryName == null || entryName.length() == 0) {
|
if (entryName == null || entryName.length() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
|
ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
|
||||||
if (gestures == null) {
|
if (gestures == null) {
|
||||||
gestures = new ArrayList<Gesture>();
|
gestures = new ArrayList<Gesture>();
|
||||||
mEntryName2gestures.put(entryName, gestures);
|
mNamedGestures.put(entryName, gestures);
|
||||||
}
|
}
|
||||||
gestures.add(gesture);
|
gestures.add(gesture);
|
||||||
mClassifier.addInstance(Instance.createInstance(mSequenceType, gesture, entryName));
|
mClassifier.addInstance(Instance.createInstance(mSequenceType, gesture, entryName));
|
||||||
@@ -146,7 +162,7 @@ public class GestureLibrary {
|
|||||||
* @param gesture
|
* @param gesture
|
||||||
*/
|
*/
|
||||||
public void removeGesture(String entryName, Gesture gesture) {
|
public void removeGesture(String entryName, Gesture gesture) {
|
||||||
ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
|
ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
|
||||||
if (gestures == null) {
|
if (gestures == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -155,7 +171,7 @@ public class GestureLibrary {
|
|||||||
|
|
||||||
// if there are no more samples, remove the entry automatically
|
// if there are no more samples, remove the entry automatically
|
||||||
if (gestures.isEmpty()) {
|
if (gestures.isEmpty()) {
|
||||||
mEntryName2gestures.remove(entryName);
|
mNamedGestures.remove(entryName);
|
||||||
}
|
}
|
||||||
|
|
||||||
mClassifier.removeInstance(gesture.getID());
|
mClassifier.removeInstance(gesture.getID());
|
||||||
@@ -169,7 +185,7 @@ public class GestureLibrary {
|
|||||||
* @param entryName the entry name
|
* @param entryName the entry name
|
||||||
*/
|
*/
|
||||||
public void removeEntireEntry(String entryName) {
|
public void removeEntireEntry(String entryName) {
|
||||||
mEntryName2gestures.remove(entryName);
|
mNamedGestures.remove(entryName);
|
||||||
mClassifier.removeInstances(entryName);
|
mClassifier.removeInstances(entryName);
|
||||||
mChanged = true;
|
mChanged = true;
|
||||||
}
|
}
|
||||||
@@ -181,7 +197,7 @@ public class GestureLibrary {
|
|||||||
* @return the list of gestures that is under this name
|
* @return the list of gestures that is under this name
|
||||||
*/
|
*/
|
||||||
public ArrayList<Gesture> getGestures(String entryName) {
|
public ArrayList<Gesture> getGestures(String entryName) {
|
||||||
ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
|
ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
|
||||||
if (gestures != null) {
|
if (gestures != null) {
|
||||||
return new ArrayList<Gesture>(gestures);
|
return new ArrayList<Gesture>(gestures);
|
||||||
} else {
|
} else {
|
||||||
@@ -197,8 +213,8 @@ public class GestureLibrary {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean result= false;
|
boolean result = false;
|
||||||
PrintWriter writer = null;
|
DataOutputStream out = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
File file = new File(mGestureFileName);
|
File file = new File(mGestureFileName);
|
||||||
@@ -208,40 +224,48 @@ public class GestureLibrary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(
|
long start;
|
||||||
mGestureFileName), GestureConstants.IO_BUFFER_SIZE));
|
if (PROFILE_LOADING_SAVING) {
|
||||||
|
start = SystemClock.elapsedRealtime();
|
||||||
final XmlSerializer serializer = Xml.newSerializer();
|
|
||||||
serializer.setOutput(writer);
|
|
||||||
serializer.startDocument(Encoding.ISO_8859_1.name(), null);
|
|
||||||
serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY);
|
|
||||||
|
|
||||||
final HashMap<String, ArrayList<Gesture>> maps = mEntryName2gestures;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY);
|
final HashMap<String, ArrayList<Gesture>> maps = mNamedGestures;
|
||||||
serializer.endDocument();
|
|
||||||
serializer.flush();
|
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());
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
// Write entry name
|
||||||
|
out.writeUTF(key);
|
||||||
|
// Write number of examples for this entry
|
||||||
|
out.writeInt(count);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
examples.get(i).serialize(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.flush();
|
||||||
|
|
||||||
|
if (PROFILE_LOADING_SAVING) {
|
||||||
|
long end = SystemClock.elapsedRealtime();
|
||||||
|
Log.d(LOG_TAG, "Saving gestures library = " + (end - start) + " ms");
|
||||||
|
}
|
||||||
|
|
||||||
mChanged = false;
|
mChanged = false;
|
||||||
result = true;
|
result = true;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Log.d(LOG_TAG, "Failed to save gestures:", ex);
|
Log.d(LOG_TAG, "Failed to save gestures:", ex);
|
||||||
} finally {
|
} finally {
|
||||||
GestureUtilities.closeStream(writer);
|
GestureUtilities.closeStream(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -255,17 +279,30 @@ public class GestureLibrary {
|
|||||||
|
|
||||||
final File file = new File(mGestureFileName);
|
final File file = new File(mGestureFileName);
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
BufferedInputStream in = null;
|
DataInputStream in = null;
|
||||||
try {
|
try {
|
||||||
if (Config.DEBUG) {
|
in = new DataInputStream(new BufferedInputStream(
|
||||||
Log.v(LOG_TAG, "Load from " + mGestureFileName);
|
new FileInputStream(mGestureFileName), GestureConstants.IO_BUFFER_SIZE));
|
||||||
|
|
||||||
|
long start;
|
||||||
|
if (PROFILE_LOADING_SAVING) {
|
||||||
|
start = SystemClock.elapsedRealtime();
|
||||||
}
|
}
|
||||||
in = new BufferedInputStream(new FileInputStream(
|
|
||||||
mGestureFileName), GestureConstants.IO_BUFFER_SIZE);
|
// Read file format version number
|
||||||
Xml.parse(in, Encoding.ISO_8859_1, new CompactInkHandler());
|
final short versionNumber = in.readShort();
|
||||||
|
switch (versionNumber) {
|
||||||
|
case 1:
|
||||||
|
readFormatV1(in);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PROFILE_LOADING_SAVING) {
|
||||||
|
long end = SystemClock.elapsedRealtime();
|
||||||
|
Log.d(LOG_TAG, "Loading gestures library = " + (end - start) + " ms");
|
||||||
|
}
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
} catch (SAXException ex) {
|
|
||||||
Log.d(LOG_TAG, "Failed to load gestures:", ex);
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Log.d(LOG_TAG, "Failed to load gestures:", ex);
|
Log.d(LOG_TAG, "Failed to load gestures:", ex);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -276,69 +313,28 @@ public class GestureLibrary {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CompactInkHandler implements ContentHandler {
|
private void readFormatV1(DataInputStream in) throws IOException {
|
||||||
final StringBuilder mBuffer = new StringBuilder(GestureConstants.STROKE_STRING_BUFFER_SIZE);
|
final Learner classifier = mClassifier;
|
||||||
|
final HashMap<String, ArrayList<Gesture>> namedGestures = mNamedGestures;
|
||||||
|
namedGestures.clear();
|
||||||
|
|
||||||
String mEntryName;
|
// Number of entries in the library
|
||||||
|
final int entriesCount = in.readInt();
|
||||||
|
|
||||||
Gesture mCurrentGesture = null;
|
for (int i = 0; i < entriesCount; i++) {
|
||||||
ArrayList<Gesture> mGestures;
|
// Entry name
|
||||||
|
final String name = in.readUTF();
|
||||||
|
// Number of gestures
|
||||||
|
final int gestureCount = in.readInt();
|
||||||
|
|
||||||
CompactInkHandler() {
|
final ArrayList<Gesture> gestures = new ArrayList<Gesture>(gestureCount);
|
||||||
}
|
for (int j = 0; j < gestureCount; j++) {
|
||||||
|
final Gesture gesture = Gesture.deserialize(in);
|
||||||
public void characters(char[] ch, int start, int length) {
|
gestures.add(gesture);
|
||||||
mBuffer.append(ch, start, length);
|
classifier.addInstance(Instance.createInstance(mSequenceType, gesture, name));
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void endPrefixMapping(String prefix) {
|
namedGestures.put(name, gestures);
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package com.android.gesture;
|
package com.android.gesture;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A timed point of a gesture stroke
|
* A timed point of a gesture stroke
|
||||||
*/
|
*/
|
||||||
@@ -31,4 +34,13 @@ public class GesturePoint {
|
|||||||
this.y = y;
|
this.y = y;
|
||||||
timestamp = t;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ import android.graphics.Paint;
|
|||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlSerializer;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -167,57 +167,35 @@ public class GestureStroke {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void serialize(DataOutputStream out) throws IOException {
|
||||||
* Save the gesture stroke as XML
|
final float[] pts = points;
|
||||||
*
|
final long[] times = timestamps;
|
||||||
* @param namespace
|
final int count = points.length;
|
||||||
* @param serializer
|
|
||||||
* @throws IOException
|
// Write number of points
|
||||||
*/
|
out.writeInt(count / 2);
|
||||||
void toXML(String namespace, XmlSerializer serializer) throws IOException {
|
|
||||||
serializer.startTag(namespace, GestureConstants.XML_TAG_STROKE);
|
for (int i = 0; i < count; i += 2) {
|
||||||
serializer.text(toString());
|
// Write X
|
||||||
serializer.endTag(namespace, GestureConstants.XML_TAG_STROKE);
|
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 {
|
||||||
* Create a gesture stroke from a string
|
// Number of points
|
||||||
*
|
final int count = in.readInt();
|
||||||
* @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;
|
final ArrayList<GesturePoint> points = new ArrayList<GesturePoint>(count);
|
||||||
int startIndex = 0;
|
for (int i = 0; i < count; i++) {
|
||||||
|
points.add(GesturePoint.deserialize(in));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GestureStroke(points);
|
return new GestureStroke(points);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the stroke to string
|
* Convert the stroke to string
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.gesture;
|
|||||||
|
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -42,7 +43,7 @@ final class GestureUtilities {
|
|||||||
try {
|
try {
|
||||||
stream.close();
|
stream.close();
|
||||||
} catch (IOException e) {
|
} 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 sx = targetPatchSize / rect.width();
|
||||||
float sy = targetPatchSize / rect.height();
|
float sy = targetPatchSize / rect.height();
|
||||||
float scale = sx < sy ? sx : sy;
|
float scale = sx < sy ? sx : sy;
|
||||||
android.graphics.Matrix trans = new android.graphics.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();
|
Matrix trans = new Matrix();
|
||||||
int count = strokes.size();
|
trans.setScale(scale, scale);
|
||||||
|
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;
|
int size;
|
||||||
float xpos;
|
float xpos;
|
||||||
float ypos;
|
float ypos;
|
||||||
|
|
||||||
for (int index = 0; index < count; index++) {
|
for (int index = 0; index < count; index++) {
|
||||||
GestureStroke stroke = strokes.get(index);
|
final GestureStroke stroke = strokes.get(index);
|
||||||
size = stroke.points.length;
|
size = stroke.points.length;
|
||||||
float[] pts = new float[size];
|
|
||||||
|
final float[] pts = new float[size];
|
||||||
|
|
||||||
trans.mapPoints(pts, 0, stroke.points, 0, size / 2);
|
trans.mapPoints(pts, 0, stroke.points, 0, size / 2);
|
||||||
float segmentEndX = -1;
|
float segmentEndX = -1;
|
||||||
float segmentEndY = -1;
|
float segmentEndY = -1;
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.gesture;
|
package com.android.gesture;
|
||||||
|
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instance represents a sample if the label is available or a query if the
|
* An instance represents a sample if the label is available or a query if the
|
||||||
* label is null.
|
* label is null.
|
||||||
@@ -47,10 +49,12 @@ class Instance {
|
|||||||
private void normalize() {
|
private void normalize() {
|
||||||
float[] sample = vector;
|
float[] sample = vector;
|
||||||
float sum = 0;
|
float sum = 0;
|
||||||
|
|
||||||
int size = sample.length;
|
int size = sample.length;
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
sum += sample[i] * sample[i];
|
sum += sample[i] * sample[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
float magnitude = (float) Math.sqrt(sum);
|
float magnitude = (float) Math.sqrt(sum);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
sample[i] /= magnitude;
|
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]);
|
m.setTranslate(-center[0], -center[1]);
|
||||||
android.graphics.Matrix rotation = new android.graphics.Matrix();
|
m.postRotate(adjustment);
|
||||||
rotation.setRotate(adjustment);
|
|
||||||
m.postConcat(rotation);
|
|
||||||
m.mapPoints(pts);
|
m.mapPoints(pts);
|
||||||
|
|
||||||
return pts;
|
return pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import android.content.res.Resources;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -29,9 +28,9 @@ import java.util.Collections;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class LetterRecognizer {
|
import static com.android.gesture.GestureConstants.LOG_TAG;
|
||||||
private static final String LOG_TAG = "LetterRecognizer";
|
|
||||||
|
|
||||||
|
public class LetterRecognizer {
|
||||||
public final static int LATIN_LOWERCASE = 0;
|
public final static int LATIN_LOWERCASE = 0;
|
||||||
|
|
||||||
private SigmoidUnit[] mHiddenLayer;
|
private SigmoidUnit[] mHiddenLayer;
|
||||||
@@ -41,7 +40,7 @@ public class LetterRecognizer {
|
|||||||
|
|
||||||
private final int mPatchSize;
|
private final int mPatchSize;
|
||||||
|
|
||||||
static final String GESTURE_FILE_NAME = "letters.xml";
|
static final String GESTURE_FILE_NAME = "letters.gestures";
|
||||||
|
|
||||||
private GestureLibrary mGestureLibrary;
|
private GestureLibrary mGestureLibrary;
|
||||||
private final static int ADJUST_RANGE = 3;
|
private final static int ADJUST_RANGE = 3;
|
||||||
@@ -151,7 +150,8 @@ public class LetterRecognizer {
|
|||||||
LetterRecognizer classifier = null;
|
LetterRecognizer classifier = null;
|
||||||
|
|
||||||
try {
|
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 iCount = in.readInt();
|
||||||
final int hCount = in.readInt();
|
final int hCount = in.readInt();
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class GestureEntry extends Activity {
|
|||||||
private static final String PARCEL_KEY = "gesture";
|
private static final String PARCEL_KEY = "gesture";
|
||||||
|
|
||||||
static final String GESTURE_FILE_NAME = Environment.getExternalStorageDirectory().getAbsolutePath()
|
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;
|
private static final int DIALOG_NEW_ENTRY = 1;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user