Additional loading methods for fonts and a3d files.
Cleaned up error messages.

Change-Id: Id33b7149671df23c37cc11375d844a7837dac750

Change-Id: I6663ce54f7b9bbaf285935ca658d93ba417f8179
diff --git a/graphics/java/android/renderscript/FileA3D.java b/graphics/java/android/renderscript/FileA3D.java
index c3e5faf..01a9a82 100644
--- a/graphics/java/android/renderscript/FileA3D.java
+++ b/graphics/java/android/renderscript/FileA3D.java
@@ -167,47 +167,57 @@
         return mFileEntries[index];
     }
 
-    // API cleanup stand-ins
-    // TODO: implement ermaining loading mechanisms
-    static public FileA3D createFromAsset(RenderScript rs, AssetManager mgr, String path)
-        throws IllegalArgumentException {
-        return null;
+    static public FileA3D createFromAsset(RenderScript rs, AssetManager mgr, String path) {
+        rs.validate();
+        int fileId = rs.nFileA3DCreateFromAsset(mgr, path);
+
+        if(fileId == 0) {
+            throw new RSRuntimeException("Unable to create a3d file from asset " + path);
+        }
+        FileA3D fa3d = new FileA3D(fileId, rs, null);
+        fa3d.initEntries();
+        return fa3d;
     }
 
-    static public FileA3D createFromFile(RenderScript rs, String path)
-        throws IllegalArgumentException {
-        return null;
+    static public FileA3D createFromFile(RenderScript rs, String path) {
+        int fileId = rs.nFileA3DCreateFromFile(path);
+
+        if(fileId == 0) {
+            throw new RSRuntimeException("Unable to create a3d file from " + path);
+        }
+        FileA3D fa3d = new FileA3D(fileId, rs, null);
+        fa3d.initEntries();
+        return fa3d;
     }
 
-    static public FileA3D createFromFile(RenderScript rs, File path)
-        throws IllegalArgumentException {
+    static public FileA3D createFromFile(RenderScript rs, File path) {
         return createFromFile(rs, path.getAbsolutePath());
     }
 
-    static public FileA3D createFromResource(RenderScript rs, Resources res, int id)
-        throws IllegalArgumentException {
+    static public FileA3D createFromResource(RenderScript rs, Resources res, int id) {
 
         rs.validate();
         InputStream is = null;
         try {
-            final TypedValue value = new TypedValue();
-            is = res.openRawResource(id, value);
-
-            int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
-
-            int fileId = rs.nFileA3DCreateFromAssetStream(asset);
-
-            if(fileId == 0) {
-                throw new IllegalStateException("Load failed.");
-            }
-            FileA3D fa3d = new FileA3D(fileId, rs, is);
-            fa3d.initEntries();
-            return fa3d;
-
+            is = res.openRawResource(id);
         } catch (Exception e) {
-            // Ignore
+            throw new RSRuntimeException("Unable to open resource " + id);
         }
 
-        return null;
+        int fileId = 0;
+        if (is instanceof AssetManager.AssetInputStream) {
+            int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+            fileId = rs.nFileA3DCreateFromAssetStream(asset);
+        } else {
+            throw new RSRuntimeException("Unsupported asset stream");
+        }
+
+        if(fileId == 0) {
+            throw new RSRuntimeException("Unable to create a3d file from resource " + id);
+        }
+        FileA3D fa3d = new FileA3D(fileId, rs, is);
+        fa3d.initEntries();
+        return fa3d;
+
     }
 }
diff --git a/graphics/java/android/renderscript/Font.java b/graphics/java/android/renderscript/Font.java
index 0f7c24d..ae209fa 100644
--- a/graphics/java/android/renderscript/Font.java
+++ b/graphics/java/android/renderscript/Font.java
@@ -129,41 +129,62 @@
     /**
      * Takes a specific file name as an argument
      */
-    static public Font createFromFile(RenderScript rs, Resources res, String path, float pointSize)
-        throws IllegalArgumentException {
-
+    static public Font createFromFile(RenderScript rs, Resources res, String path, float pointSize) {
         rs.validate();
-        try {
-            int dpi = res.getDisplayMetrics().densityDpi;
-            int fontId = rs.nFontCreateFromFile(path, pointSize, dpi);
+        int dpi = res.getDisplayMetrics().densityDpi;
+        int fontId = rs.nFontCreateFromFile(path, pointSize, dpi);
 
-            if(fontId == 0) {
-                throw new IllegalStateException("Failed loading a font");
-            }
-            Font rsFont = new Font(fontId, rs);
-
-            return rsFont;
-
-        } catch (Exception e) {
-            // Ignore
+        if(fontId == 0) {
+            throw new RSRuntimeException("Unable to create font from file " + path);
         }
+        Font rsFont = new Font(fontId, rs);
 
-        return null;
+        return rsFont;
     }
 
-    static public Font createFromFile(RenderScript rs, Resources res, File path, float pointSize)
-        throws IllegalArgumentException {
+    static public Font createFromFile(RenderScript rs, Resources res, File path, float pointSize) {
         return createFromFile(rs, res, path.getAbsolutePath(), pointSize);
     }
 
-    static public Font createFromAsset(RenderScript rs, Resources res, AssetManager mgr, String path, float pointSize)
-        throws IllegalArgumentException {
-        return null;
+    static public Font createFromAsset(RenderScript rs, Resources res, String path, float pointSize) {
+        rs.validate();
+        AssetManager mgr = res.getAssets();
+        int dpi = res.getDisplayMetrics().densityDpi;
+
+        int fontId = rs.nFontCreateFromAsset(mgr, path, pointSize, dpi);
+        if(fontId == 0) {
+            throw new RSRuntimeException("Unable to create font from asset " + path);
+        }
+        Font rsFont = new Font(fontId, rs);
+        return rsFont;
     }
 
-    static public Font createFromResource(RenderScript rs, Resources res, int id, float pointSize)
-        throws IllegalArgumentException {
-        return null;
+    static public Font createFromResource(RenderScript rs, Resources res, int id, float pointSize) {
+        String name = "R." + Integer.toString(id);
+
+        rs.validate();
+        InputStream is = null;
+        try {
+            is = res.openRawResource(id);
+        } catch (Exception e) {
+            throw new RSRuntimeException("Unable to open resource " + id);
+        }
+
+        int dpi = res.getDisplayMetrics().densityDpi;
+
+        int fontId = 0;
+        if (is instanceof AssetManager.AssetInputStream) {
+            int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+            fontId = rs.nFontCreateFromAssetStream(name, pointSize, dpi, asset);
+        } else {
+            throw new RSRuntimeException("Unsupported asset stream created");
+        }
+
+        if(fontId == 0) {
+            throw new RSRuntimeException("Unable to create font from resource " + id);
+        }
+        Font rsFont = new Font(fontId, rs);
+        return rsFont;
     }
 
     /**
@@ -175,8 +196,7 @@
      * "monospace" "courier" "courier new" "monaco"
      * Returns default font if no match could be found
      */
-    static public Font create(RenderScript rs, Resources res, String familyName, Style fontStyle, float pointSize)
-    throws IllegalArgumentException {
+    static public Font create(RenderScript rs, Resources res, String familyName, Style fontStyle, float pointSize) {
         String fileName = getFontFileName(familyName, fontStyle);
         String fontPath = Environment.getRootDirectory().getAbsolutePath();
         fontPath += "/fonts/" + fileName;
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 6a52810..665a893 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -19,6 +19,7 @@
 import java.lang.reflect.Field;
 
 import android.content.Context;
+import android.content.res.AssetManager;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.util.Config;
@@ -284,6 +285,14 @@
     synchronized int nFileA3DCreateFromAssetStream(int assetStream) {
         return rsnFileA3DCreateFromAssetStream(mContext, assetStream);
     }
+    native int  rsnFileA3DCreateFromFile(int con, String path);
+    synchronized int nFileA3DCreateFromFile(String path) {
+        return rsnFileA3DCreateFromFile(mContext, path);
+    }
+    native int  rsnFileA3DCreateFromAsset(int con, AssetManager mgr, String path);
+    synchronized int nFileA3DCreateFromAsset(AssetManager mgr, String path) {
+        return rsnFileA3DCreateFromAsset(mContext, mgr, path);
+    }
     native int  rsnFileA3DGetNumIndexEntries(int con, int fileA3D);
     synchronized int nFileA3DGetNumIndexEntries(int fileA3D) {
         return rsnFileA3DGetNumIndexEntries(mContext, fileA3D);
@@ -301,6 +310,14 @@
     synchronized int nFontCreateFromFile(String fileName, float size, int dpi) {
         return rsnFontCreateFromFile(mContext, fileName, size, dpi);
     }
+    native int  rsnFontCreateFromAssetStream(int con, String name, float size, int dpi, int assetStream);
+    synchronized int nFontCreateFromAssetStream(String name, float size, int dpi, int assetStream) {
+        return rsnFontCreateFromAssetStream(mContext, name, size, dpi, assetStream);
+    }
+    native int  rsnFontCreateFromAsset(int con, AssetManager mgr, String path, float size, int dpi);
+    synchronized int nFontCreateFromAsset(AssetManager mgr, String path, float size, int dpi) {
+        return rsnFontCreateFromAsset(mContext, mgr, path, size, dpi);
+    }
 
 
     native void rsnScriptBindAllocation(int con, int script, int alloc, int slot);
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index fe22269..1817a1b 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -32,12 +32,14 @@
 #include <images/SkImageDecoder.h>
 
 #include <utils/Asset.h>
+#include <utils/AssetManager.h>
 #include <utils/ResourceTypes.h>
 
 #include "jni.h"
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_view_Surface.h"
+#include "android_runtime/android_util_AssetManager.h"
 
 #include <RenderScript.h>
 #include <RenderScriptEnv.h>
@@ -47,6 +49,27 @@
 
 using namespace android;
 
+class AutoJavaStringToUTF8 {
+public:
+    AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str)
+    {
+        fCStr = env->GetStringUTFChars(str, NULL);
+        fLength = env->GetStringUTFLength(str);
+    }
+    ~AutoJavaStringToUTF8()
+    {
+        fEnv->ReleaseStringUTFChars(fJStr, fCStr);
+    }
+    const char* c_str() const { return fCStr; }
+    jsize length() const { return fLength; }
+
+private:
+    JNIEnv*     fEnv;
+    jstring     fJStr;
+    const char* fCStr;
+    jsize       fLength;
+};
+
 // ---------------------------------------------------------------------------
 
 static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
@@ -572,7 +595,34 @@
 
     Asset* asset = reinterpret_cast<Asset*>(native_asset);
 
-    jint id = (jint)rsaFileA3DCreateFromAssetStream(con, asset->getBuffer(false), asset->getLength());
+    jint id = (jint)rsaFileA3DCreateFromMemory(con, asset->getBuffer(false), asset->getLength());
+    return id;
+}
+
+static int
+nFileA3DCreateFromAsset(JNIEnv *_env, jobject _this, RsContext con, jobject _assetMgr, jstring _path)
+{
+    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
+    if (mgr == NULL) {
+        return 0;
+    }
+
+    AutoJavaStringToUTF8 str(_env, _path);
+    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    if (asset == NULL) {
+        return 0;
+    }
+
+    jint id = (jint)rsaFileA3DCreateFromAsset(con, asset);
+    return id;
+}
+
+static int
+nFileA3DCreateFromFile(JNIEnv *_env, jobject _this, RsContext con, jstring fileName)
+{
+    AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
+    jint id = (jint)rsaFileA3DCreateFromFile(con, fileNameUTF.c_str());
+
     return id;
 }
 
@@ -611,11 +661,45 @@
 // -----------------------------------
 
 static int
-nFontCreateFromFile(JNIEnv *_env, jobject _this, RsContext con, jstring fileName, jfloat fontSize, jint dpi)
+nFontCreateFromFile(JNIEnv *_env, jobject _this, RsContext con,
+                    jstring fileName, jfloat fontSize, jint dpi)
 {
-    const char* fileNameUTF = _env->GetStringUTFChars(fileName, NULL);
+    AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
+    jint id = (jint)rsFontCreateFromFile(con, fileNameUTF.c_str(), fontSize, dpi);
 
-    jint id = (jint)rsFontCreateFromFile(con, fileNameUTF, fontSize, dpi);
+    return id;
+}
+
+static int
+nFontCreateFromAssetStream(JNIEnv *_env, jobject _this, RsContext con,
+                           jstring name, jfloat fontSize, jint dpi, jint native_asset)
+{
+    Asset* asset = reinterpret_cast<Asset*>(native_asset);
+    AutoJavaStringToUTF8 nameUTF(_env, name);
+
+    jint id = (jint)rsFontCreateFromMemory(con, nameUTF.c_str(), fontSize, dpi,
+                                           asset->getBuffer(false), asset->getLength());
+    return id;
+}
+
+static int
+nFontCreateFromAsset(JNIEnv *_env, jobject _this, RsContext con, jobject _assetMgr, jstring _path,
+                     jfloat fontSize, jint dpi)
+{
+    AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr);
+    if (mgr == NULL) {
+        return 0;
+    }
+
+    AutoJavaStringToUTF8 str(_env, _path);
+    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    if (asset == NULL) {
+        return 0;
+    }
+
+    jint id = (jint)rsFontCreateFromMemory(con, str.c_str(), fontSize, dpi,
+                                           asset->getBuffer(false), asset->getLength());
+    delete asset;
     return id;
 }
 
@@ -764,13 +848,10 @@
 nScriptCCreate(JNIEnv *_env, jobject _this, RsContext con, jstring packageName, jstring resName, jstring cacheDir)
 {
     LOG_API("nScriptCCreate, con(%p)", con);
-    const char* packageNameUTF = _env->GetStringUTFChars(packageName, NULL);
-    const char* resNameUTF = _env->GetStringUTFChars(resName, NULL);
-    const char* cacheDirUTF = _env->GetStringUTFChars(cacheDir, NULL);
-    jint i = (jint)rsScriptCCreate(con, packageNameUTF, resNameUTF, cacheDirUTF);
-    _env->ReleaseStringUTFChars(packageName, packageNameUTF);
-    _env->ReleaseStringUTFChars(resName, resNameUTF);
-    _env->ReleaseStringUTFChars(cacheDir, cacheDirUTF);
+    AutoJavaStringToUTF8 packageNameUTF(_env, packageName);
+    AutoJavaStringToUTF8 resNameUTF(_env, resName);
+    AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
+    jint i = (jint)rsScriptCCreate(con, packageNameUTF.c_str(), resNameUTF.c_str(), cacheDirUTF.c_str());
     return i;
 }
 
@@ -853,15 +934,13 @@
 static jint
 nProgramFragmentCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader, jintArray params)
 {
-    const char* shaderUTF = _env->GetStringUTFChars(shader, NULL);
-    jint shaderLen = _env->GetStringUTFLength(shader);
+    AutoJavaStringToUTF8 shaderUTF(_env, shader);
     jint *paramPtr = _env->GetIntArrayElements(params, NULL);
     jint paramLen = _env->GetArrayLength(params);
 
     LOG_API("nProgramFragmentCreate, con(%p), shaderLen(%i), paramLen(%i)", con, shaderLen, paramLen);
 
-    jint ret = (jint)rsProgramFragmentCreate(con, shaderUTF, shaderLen, (uint32_t *)paramPtr, paramLen);
-    _env->ReleaseStringUTFChars(shader, shaderUTF);
+    jint ret = (jint)rsProgramFragmentCreate(con, shaderUTF.c_str(), shaderUTF.length(), (uint32_t *)paramPtr, paramLen);
     _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
     return ret;
 }
@@ -872,15 +951,13 @@
 static jint
 nProgramVertexCreate(JNIEnv *_env, jobject _this, RsContext con, jstring shader, jintArray params)
 {
-    const char* shaderUTF = _env->GetStringUTFChars(shader, NULL);
-    jint shaderLen = _env->GetStringUTFLength(shader);
+    AutoJavaStringToUTF8 shaderUTF(_env, shader);
     jint *paramPtr = _env->GetIntArrayElements(params, NULL);
     jint paramLen = _env->GetArrayLength(params);
 
     LOG_API("nProgramVertexCreate, con(%p), shaderLen(%i), paramLen(%i)", con, shaderLen, paramLen);
 
-    jint ret = (jint)rsProgramVertexCreate(con, shaderUTF, shaderLen, (uint32_t *)paramPtr, paramLen);
-    _env->ReleaseStringUTFChars(shader, shaderUTF);
+    jint ret = (jint)rsProgramVertexCreate(con, shaderUTF.c_str(), shaderUTF.length(), (uint32_t *)paramPtr, paramLen);
     _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
     return ret;
 }
@@ -1095,12 +1172,16 @@
 {"rsnGetName",                       "(II)Ljava/lang/String;",                (void*)nGetName },
 {"rsnObjDestroy",                    "(II)V",                                 (void*)nObjDestroy },
 
+{"rsnFileA3DCreateFromFile",         "(ILjava/lang/String;)I",                (void*)nFileA3DCreateFromFile },
 {"rsnFileA3DCreateFromAssetStream",  "(II)I",                                 (void*)nFileA3DCreateFromAssetStream },
+{"rsnFileA3DCreateFromAsset",        "(ILandroid/content/res/AssetManager;Ljava/lang/String;)I",            (void*)nFileA3DCreateFromAsset },
 {"rsnFileA3DGetNumIndexEntries",     "(II)I",                                 (void*)nFileA3DGetNumIndexEntries },
 {"rsnFileA3DGetIndexEntries",        "(III[I[Ljava/lang/String;)V",           (void*)nFileA3DGetIndexEntries },
 {"rsnFileA3DGetEntryByIndex",        "(III)I",                                (void*)nFileA3DGetEntryByIndex },
 
 {"rsnFontCreateFromFile",            "(ILjava/lang/String;FI)I",              (void*)nFontCreateFromFile },
+{"rsnFontCreateFromAssetStream",     "(ILjava/lang/String;FII)I",             (void*)nFontCreateFromAssetStream },
+{"rsnFontCreateFromAsset",        "(ILandroid/content/res/AssetManager;Ljava/lang/String;FI)I",            (void*)nFontCreateFromAsset },
 
 {"rsnElementCreate",                 "(IIIZI)I",                              (void*)nElementCreate },
 {"rsnElementCreate2",                "(I[I[Ljava/lang/String;[I)I",           (void*)nElementCreate2 },
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 87758e5..f160ef1 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -334,7 +334,9 @@
 // A3D loading and object update code.
 // Should only be called at object creation, not thread safe
 RsObjectBase rsaFileA3DGetEntryByIndex(RsContext, uint32_t idx, RsFile);
-RsFile rsaFileA3DCreateFromAssetStream(RsContext, const void *data, uint32_t len);
+RsFile rsaFileA3DCreateFromMemory(RsContext, const void *data, uint32_t len);
+RsFile rsaFileA3DCreateFromAsset(RsContext, void *asset);
+RsFile rsaFileA3DCreateFromFile(RsContext, const char *path);
 void rsaFileA3DGetNumIndexEntries(RsContext, int32_t *numEntries, RsFile);
 void rsaFileA3DGetIndexEntries(RsContext, RsFileIndexEntry *fileEntries,uint32_t numEntries, RsFile);
 void rsaGetName(RsContext, void * obj, const char **name);
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 3483a5d..33ac2f0 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -346,12 +346,6 @@
 	ret RsProgramVertex
 	}
 
-FileOpen {
-	ret RsFile
-	param const char *name
-	param size_t len
-	}
-
 FontCreateFromFile {
 	param const char *name
 	param float fontSize
@@ -359,6 +353,15 @@
 	ret RsFont
 	}
 
+FontCreateFromMemory {
+	param const char *name
+	param float fontSize
+	param uint32_t dpi
+    param const void *data
+    param uint32_t dataLen
+	ret RsFont
+	}
+
 MeshCreate {
 	ret RsMesh
 	param uint32_t vtxCount
diff --git a/libs/rs/rsFileA3D.cpp b/libs/rs/rsFileA3D.cpp
index 0c8692d..d34ddd6 100644
--- a/libs/rs/rsFileA3D.cpp
+++ b/libs/rs/rsFileA3D.cpp
@@ -35,6 +35,7 @@
     mData = NULL;
     mWriteStream = NULL;
     mReadStream = NULL;
+    mAsset = NULL;
 
     mMajorVersion = 0;
     mMinorVersion = 1;
@@ -57,6 +58,9 @@
     if (mAlloc) {
         free(mAlloc);
     }
+    if (mAsset) {
+        delete mAsset;
+    }
 }
 
 void FileA3D::parseHeader(IStream *headerStream) {
@@ -83,6 +87,11 @@
     }
 }
 
+bool FileA3D::load(Asset *asset) {
+    mAsset = asset;
+    return load(asset->getBuffer(false), asset->getLength());
+}
+
 bool FileA3D::load(const void *data, size_t length) {
     const uint8_t *localData = (const uint8_t *)data;
 
@@ -357,26 +366,6 @@
     mWriteStream->align(4);
 }
 
-namespace android {
-namespace renderscript {
-
-RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len) {
-    FileA3D *fa3d = new FileA3D(rsc);
-
-    FILE *f = fopen("/sdcard/test.a3d", "rb");
-    if (f) {
-        fa3d->load(f);
-        fclose(f);
-        fa3d->incUserRef();
-        return fa3d;
-    }
-    delete fa3d;
-    return NULL;
-}
-
-}
-}
-
 RsObjectBase rsaFileA3DGetEntryByIndex(RsContext con, uint32_t index, RsFile file) {
     FileA3D *fa3d = static_cast<FileA3D *>(file);
     if (!fa3d) {
@@ -422,7 +411,7 @@
     }
 }
 
-RsFile rsaFileA3DCreateFromAssetStream(RsContext con, const void *data, uint32_t len) {
+RsFile rsaFileA3DCreateFromMemory(RsContext con, const void *data, uint32_t len) {
     if (data == NULL) {
         LOGE("File load failed. Asset stream is NULL");
         return NULL;
@@ -435,3 +424,35 @@
     fa3d->load(data, len);
     return fa3d;
 }
+
+RsFile rsaFileA3DCreateFromAsset(RsContext con, void *_asset) {
+    Context *rsc = static_cast<Context *>(con);
+    Asset *asset = static_cast<Asset *>(_asset);
+    FileA3D *fa3d = new FileA3D(rsc);
+    fa3d->incUserRef();
+
+    fa3d->load(asset);
+    return fa3d;
+}
+
+RsFile rsaFileA3DCreateFromFile(RsContext con, const char *path) {
+    if (path == NULL) {
+        LOGE("File load failed. Path is NULL");
+        return NULL;
+    }
+
+    Context *rsc = static_cast<Context *>(con);
+    FileA3D *fa3d = NULL;
+
+    FILE *f = fopen(path, "rb");
+    if (f) {
+        fa3d = new FileA3D(rsc);
+        fa3d->incUserRef();
+        fa3d->load(f);
+        fclose(f);
+    } else {
+        LOGE("Could not open file %s", path);
+    }
+
+    return fa3d;
+}
diff --git a/libs/rs/rsFileA3D.h b/libs/rs/rsFileA3D.h
index 3ece4c9..056b5af 100644
--- a/libs/rs/rsFileA3D.h
+++ b/libs/rs/rsFileA3D.h
@@ -21,6 +21,7 @@
 #include "rsMesh.h"
 
 #include <utils/String8.h>
+#include <utils/Asset.h>
 #include "rsStream.h"
 #include <stdio.h>
 
@@ -59,6 +60,7 @@
     };
 
     bool load(FILE *f);
+    bool load(Asset *asset);
     bool load(const void *data, size_t length);
 
     size_t getNumIndexEntries() const;
@@ -83,6 +85,7 @@
     const uint8_t * mData;
     void * mAlloc;
     uint64_t mDataSize;
+    Asset *mAsset;
 
     OStream *mWriteStream;
     Vector<A3DIndexEntry*> mWriteIndex;
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index 3dcf743..8571c32 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -40,13 +40,19 @@
     mFace = NULL;
 }
 
-bool Font::init(const char *name, float fontSize, uint32_t dpi) {
+bool Font::init(const char *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) {
     if (mInitialized) {
         LOGE("Reinitialization of fonts not supported");
         return false;
     }
 
-    FT_Error error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace);
+    FT_Error error = 0;
+    if (data != NULL && dataLen > 0) {
+        error = FT_New_Memory_Face(mRSC->mStateFont.getLib(), (const FT_Byte*)data, dataLen, 0, &mFace);
+    } else {
+        error = FT_New_Face(mRSC->mStateFont.getLib(), name, 0, &mFace);
+    }
+
     if (error) {
         LOGE("Unable to initialize font %s", name);
         return false;
@@ -127,7 +133,8 @@
     int32_t width = (int32_t) glyph->mBitmapWidth;
     int32_t height = (int32_t) glyph->mBitmapHeight;
 
-    if (bounds->bottom > nPenY) {
+    // 0, 0 is top left, so bottom is a positive number
+    if (bounds->bottom < nPenY) {
         bounds->bottom = nPenY;
     }
     if (bounds->left > nPenX) {
@@ -136,8 +143,8 @@
     if (bounds->right < nPenX + width) {
         bounds->right = nPenX + width;
     }
-    if (bounds->top < nPenY + height) {
-        bounds->top = nPenY + height;
+    if (bounds->top > nPenY - height) {
+        bounds->top = nPenY - height;
     }
 }
 
@@ -155,7 +162,7 @@
             return;
         }
         // Reset min and max of the bounding box to something large
-        bounds->set(1e6, -1e6, -1e6, 1e6);
+        bounds->set(1e6, -1e6, 1e6, -1e6);
     }
 
     int32_t penX = x, penY = y;
@@ -273,7 +280,8 @@
     return newGlyph;
 }
 
-Font * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi) {
+Font * Font::create(Context *rsc, const char *name, float fontSize, uint32_t dpi,
+                    const void *data, uint32_t dataLen) {
     rsc->mStateFont.checkInit();
     Vector<Font*> &activeFonts = rsc->mStateFont.mActiveFonts;
 
@@ -285,7 +293,7 @@
     }
 
     Font *newFont = new Font(rsc);
-    bool isInitialized = newFont->init(name, fontSize, dpi);
+    bool isInitialized = newFont->init(name, fontSize, dpi, data, dataLen);
     if (isInitialized) {
         activeFonts.push(newFont);
         rsc->mStateFont.precacheLatin(newFont);
@@ -743,6 +751,8 @@
 
 void FontState::measureText(const char *text, uint32_t len, Font::Rect *bounds) {
     renderText(text, len, 0, 0, 0, -1, Font::MEASURE, bounds);
+    bounds->bottom = - bounds->bottom;
+    bounds->top = - bounds->top;
 }
 
 void FontState::setFontColor(float r, float g, float b, float a) {
@@ -811,5 +821,13 @@
     return newFont;
 }
 
+RsFont rsi_FontCreateFromMemory(Context *rsc, char const *name, float fontSize, uint32_t dpi, const void *data, uint32_t dataLen) {
+    Font *newFont = Font::create(rsc, name, fontSize, dpi, data, dataLen);
+    if (newFont) {
+        newFont->incUserRef();
+    }
+    return newFont;
+}
+
 } // renderscript
 } // android
diff --git a/libs/rs/rsFont.h b/libs/rs/rsFont.h
index c24c9f1..00d77c8 100644
--- a/libs/rs/rsFont.h
+++ b/libs/rs/rsFont.h
@@ -73,7 +73,8 @@
         return RS_A3D_CLASS_ID_UNKNOWN;
     }
 
-    static Font * create(Context *rsc, const char *name, float fontSize, uint32_t dpi);
+    static Font * create(Context *rsc, const char *name, float fontSize, uint32_t dpi,
+                         const void *data = NULL, uint32_t dataLen = 0);
 
 protected:
 
@@ -116,7 +117,7 @@
     uint32_t mDpi;
 
     Font(Context *rsc);
-    bool init(const char *name, float fontSize, uint32_t dpi);
+    bool init(const char *name, float fontSize, uint32_t dpi, const void *data = NULL, uint32_t dataLen = 0);
 
     FT_Face mFace;
     bool mInitialized;