Fix tons of bugs and add new text rendering support.

Change-Id: I326c66b10784006f6df2f12d38e120cef94cd0d7
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 96bd884..78836fa 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -610,9 +610,13 @@
         if ((index | count | (index + count) | (text.length - index - count)) < 0) {
             throw new IndexOutOfBoundsException();
         }
+
         boolean hasModifier = setupModifiers(paint);
-        nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
-        if (hasModifier) nResetModifiers(mRenderer);
+        try {
+            nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint);
+        } finally {
+            if (hasModifier) nResetModifiers(mRenderer);
+        }
     }
     
     private native void nDrawText(int renderer, char[] text, int index, int count, float x, float y,
@@ -621,20 +625,23 @@
     @Override
     public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
         boolean hasModifier = setupModifiers(paint);
-        if (text instanceof String || text instanceof SpannedString ||
-                text instanceof SpannableString) {
-            nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
-                    paint.mNativePaint);
-        } else if (text instanceof GraphicsOperations) {
-            ((GraphicsOperations) text).drawText(this, start, end, x, y,
-                                                     paint);
-        } else {
-            char[] buf = TemporaryBuffer.obtain(end - start);
-            TextUtils.getChars(text, start, end, buf, 0);
-            nDrawText(mRenderer, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint);
-            TemporaryBuffer.recycle(buf);
+        try {
+            if (text instanceof String || text instanceof SpannedString ||
+                    text instanceof SpannableString) {
+                nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
+                        paint.mNativePaint);
+            } else if (text instanceof GraphicsOperations) {
+                ((GraphicsOperations) text).drawText(this, start, end, x, y,
+                                                         paint);
+            } else {
+                char[] buf = TemporaryBuffer.obtain(end - start);
+                TextUtils.getChars(text, start, end, buf, 0);
+                nDrawText(mRenderer, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint);
+                TemporaryBuffer.recycle(buf);
+            }
+        } finally {
+            if (hasModifier) nResetModifiers(mRenderer);
         }
-        if (hasModifier) nResetModifiers(mRenderer);
     }
 
     @Override
@@ -642,9 +649,13 @@
         if ((start | end | (end - start) | (text.length() - end)) < 0) {
             throw new IndexOutOfBoundsException();
         }
+
         boolean hasModifier = setupModifiers(paint);
-        nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
-        if (hasModifier) nResetModifiers(mRenderer);
+        try {
+            nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint);
+        } finally {
+            if (hasModifier) nResetModifiers(mRenderer);
+        }
     }
 
     private native void nDrawText(int renderer, String text, int start, int end, float x, float y,
@@ -653,8 +664,12 @@
     @Override
     public void drawText(String text, float x, float y, Paint paint) {
         boolean hasModifier = setupModifiers(paint);
-        nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags, paint.mNativePaint);
-        if (hasModifier) nResetModifiers(mRenderer);
+        try {
+            nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
+                    paint.mNativePaint);
+        } finally {
+            if (hasModifier) nResetModifiers(mRenderer);
+        }
     }
 
     @Override
@@ -671,15 +686,59 @@
     @Override
     public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
             float x, float y, int dir, Paint paint) {
-        throw new UnsupportedOperationException();
+        if ((index | count | text.length - index - count) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
+            throw new IllegalArgumentException("Unknown direction: " + dir);
+        }
+
+        boolean hasModifier = setupModifiers(paint);
+        try {
+            nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
+                    paint.mNativePaint);
+        } finally {
+            if (hasModifier) nResetModifiers(mRenderer);
+        }
     }
 
+    private native void nDrawTextRun(int renderer, char[] text, int index, int count,
+            int contextIndex, int contextCount, float x, float y, int dir, int nativePaint);
+
     @Override
     public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
             float x, float y, int dir, Paint paint) {
-        throw new UnsupportedOperationException();
+        if ((start | end | end - start | text.length() - end) < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+
+        boolean hasModifier = setupModifiers(paint);
+        try {
+            int flags = dir == 0 ? 0 : 1;
+            if (text instanceof String || text instanceof SpannedString ||
+                    text instanceof SpannableString) {
+                nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
+                        contextEnd, x, y, flags, paint.mNativePaint);
+            } else if (text instanceof GraphicsOperations) {
+                ((GraphicsOperations) text).drawTextRun(this, start, end,
+                        contextStart, contextEnd, x, y, flags, paint);
+            } else {
+                int contextLen = contextEnd - contextStart;
+                int len = end - start;
+                char[] buf = TemporaryBuffer.obtain(contextLen);
+                TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
+                nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
+                        x, y, flags, paint.mNativePaint);
+                TemporaryBuffer.recycle(buf);
+            }
+        } finally {
+            if (hasModifier) nResetModifiers(mRenderer);
+        }
     }
 
+    private native void nDrawTextRun(int renderer, String text, int start, int end,
+            int contextStart, int contextEnd, float x, float y, int flags, int nativePaint);
+
     @Override
     public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
             float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 60d495f..cd6b820 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -34,12 +34,23 @@
  * 
  * @hide
  */
-abstract class HardwareRenderer {
+public abstract class HardwareRenderer {
     private boolean mEnabled;
     private boolean mRequested = true;
     private static final String LOG_TAG = "HardwareRenderer";
 
     /**
+     * Indicates whether hardware acceleration is available under any form for
+     * the view hierarchy.
+     * 
+     * @return True if the view hierarchy can potentially be hardware accelerated,
+     *         false otherwise
+     */
+    public static boolean isAvailable() {
+        return GLES20Canvas.isAvailable();
+    }
+
+    /**
      * Destroys the hardware rendering context.
      */
     abstract void destroy();
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 2b98e89..36413d7 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -149,7 +149,9 @@
     storedBounds[2] = x1; storedBounds[3] = y1;
     jfloat* storedPositions = new jfloat[count];
     uint32_t* storedColors = new uint32_t[count];
-    memcpy(storedColors, colorValues, count);
+    for (size_t i = 0; i < count; i++) {
+        storedColors[i] = static_cast<uint32_t>(colorValues[i]);
+    }
 
     if (posArray) {
         AutoJavaFloatArray autoPos(env, posArray, count);
@@ -185,8 +187,8 @@
     storedPositions[1] = 1.0f;
 
     uint32_t* storedColors = new uint32_t[2];
-    storedColors[0] = color0;
-    storedColors[1] = color1;
+    storedColors[0] = static_cast<uint32_t>(color0);
+    storedColors[1] = static_cast<uint32_t>(color1);
 
     SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
             storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
diff --git a/core/jni/android/graphics/TextLayout.cpp b/core/jni/android/graphics/TextLayout.cpp
index 716d960..147e1fa 100644
--- a/core/jni/android/graphics/TextLayout.cpp
+++ b/core/jni/android/graphics/TextLayout.cpp
@@ -221,6 +221,18 @@
     }
 }
 
+bool TextLayout::prepareRtlTextRun(const jchar* context, jsize start, jsize& count,
+        jsize contextCount, jchar* shaped) {
+    UErrorCode status = U_ZERO_ERROR;
+    count = shapeRtlText(context, start, count, contextCount, shaped, status);
+    if (U_SUCCESS(status)) {
+        return true;
+    } else {
+        LOG(LOG_WARN, "LAYOUT", "drawTextRun error %d\n", status);
+    }
+    return false;
+}
+
 void TextLayout::drawTextRun(SkPaint* paint, const jchar* chars,
                              jint start, jint count, jint contextCount,
                              int dirFlags, jfloat x, jfloat y, SkCanvas* canvas) {
@@ -231,12 +243,8 @@
      uint8_t rtl = dirFlags & 0x1;
      if (rtl) {
          SkAutoSTMalloc<80, jchar> buffer(contextCount);
-         UErrorCode status = U_ZERO_ERROR;
-         count = shapeRtlText(chars, start, count, contextCount, buffer.get(), status);
-         if (U_SUCCESS(status)) {
+         if (prepareRtlTextRun(chars, start, count, contextCount, buffer.get())) {
              canvas->drawText(buffer.get(), count << 1, x_, y_, *paint);
-         } else {
-             LOG(LOG_WARN, "LAYOUT", "drawTextRun error %d\n", status);
          }
      } else {
          canvas->drawText(chars + start, count << 1, x_, y_, *paint);
diff --git a/core/jni/android/graphics/TextLayout.h b/core/jni/android/graphics/TextLayout.h
index 3d05e18..8f666c0 100644
--- a/core/jni/android/graphics/TextLayout.h
+++ b/core/jni/android/graphics/TextLayout.h
@@ -66,6 +66,9 @@
                                
    static bool prepareText(SkPaint *paint, const jchar* text, jsize len, jint bidiFlags,
         const jchar** outText, int32_t* outBytes, jchar** outBuffer);
+    static bool prepareRtlTextRun(const jchar* context, jsize start, jsize& count,
+        jsize contextCount, jchar* shaped);
+        
 
 private:
     static bool needsLayout(const jchar* text, jint len, jint bidiFlags);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index bb1a9e3..be29433 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -27,6 +27,7 @@
 #include <SkPaint.h>
 #include <SkRegion.h>
 #include <SkScalerContext.h>
+#include <SkTemplates.h>
 #include <SkXfermode.h>
 
 #include <OpenGLRenderer.h>
@@ -275,6 +276,23 @@
     }
 }
 
+static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
+        jint start, jint count, jint contextCount, jfloat x, jfloat y,
+        int flags, SkPaint* paint) {
+    uint8_t rtl = flags & 0x1;
+    if (rtl) {
+        SkAutoSTMalloc<80, jchar> buffer(contextCount);
+        jchar* shaped = buffer.get();
+        if (TextLayout::prepareRtlTextRun(text, start, count, contextCount, shaped)) {
+            renderer->drawText((const char*) shaped, count << 1, count, x, y, paint);
+        } else {
+            LOGW("drawTextRun error");
+        }
+    } else {
+        renderer->drawText((const char*) (text + start), count << 1, count, x, y, paint);
+    }
+}
+
 static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject canvas,
         OpenGLRenderer* renderer, jcharArray text, int index, int count,
         jfloat x, jfloat y, int flags, SkPaint* paint) {
@@ -291,6 +309,28 @@
     env->ReleaseStringChars(text, textArray);
 }
 
+static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject canvas,
+        OpenGLRenderer* renderer, jcharArray text, int index, int count,
+        int contextIndex, int contextCount, jfloat x, jfloat y, int dirFlags,
+        SkPaint* paint) {
+    jchar* textArray = env->GetCharArrayElements(text, NULL);
+    renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
+            count, contextCount, x, y, dirFlags, paint);
+    env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
+ }
+
+static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject canvas,
+        OpenGLRenderer* renderer, jstring text, int start, int end,
+        int contextStart, int contextEnd, jfloat x, jfloat y, int dirFlags,
+        SkPaint* paint) {
+    const jchar* textArray = env->GetStringChars(text, NULL);
+    jint count = end - start;
+    jint contextCount = contextEnd - contextStart;
+    renderTextRun(renderer, textArray + contextStart, start - contextStart,
+            count, contextCount, x, y, dirFlags, paint);
+    env->ReleaseStringChars(text, textArray);
+}
+
 #endif // USE_OPENGL_RENDERER
 
 // ----------------------------------------------------------------------------
@@ -312,50 +352,54 @@
 const char* const kClassPathName = "android/view/GLES20Canvas";
 
 static JNINativeMethod gMethods[] = {
-    {   "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
+    { "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
+
 #ifdef USE_OPENGL_RENDERER
+    { "nCreateRenderer",    "()I",             (void*) android_view_GLES20Canvas_createRenderer },
+    { "nDestroyRenderer",   "(I)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
+    { "nSetViewport",       "(III)V",          (void*) android_view_GLES20Canvas_setViewport },
+    { "nPrepare",           "(I)V",            (void*) android_view_GLES20Canvas_prepare },
 
-    {   "nCreateRenderer",    "()I",             (void*) android_view_GLES20Canvas_createRenderer },
-    {   "nDestroyRenderer",   "(I)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
-    {   "nSetViewport",       "(III)V",          (void*) android_view_GLES20Canvas_setViewport },
-    {   "nPrepare",           "(I)V",            (void*) android_view_GLES20Canvas_prepare },
+    { "nSave",              "(II)I",           (void*) android_view_GLES20Canvas_save },
+    { "nRestore",           "(I)V",            (void*) android_view_GLES20Canvas_restore },
+    { "nRestoreToCount",    "(II)V",           (void*) android_view_GLES20Canvas_restoreToCount },
+    { "nGetSaveCount",      "(I)I",            (void*) android_view_GLES20Canvas_getSaveCount },
 
-    {   "nSave",              "(II)I",           (void*) android_view_GLES20Canvas_save },
-    {   "nRestore",           "(I)V",            (void*) android_view_GLES20Canvas_restore },
-    {   "nRestoreToCount",    "(II)V",           (void*) android_view_GLES20Canvas_restoreToCount },
-    {   "nGetSaveCount",      "(I)I",            (void*) android_view_GLES20Canvas_getSaveCount },
+    { "nSaveLayer",         "(IFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayer },
+    { "nSaveLayerAlpha",    "(IFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
 
-    {   "nSaveLayer",         "(IFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayer },
-    {   "nSaveLayerAlpha",    "(IFFFFII)I",      (void*) android_view_GLES20Canvas_saveLayerAlpha },
+    { "nQuickReject",       "(IFFFFI)Z",       (void*) android_view_GLES20Canvas_quickReject },
+    { "nClipRect",          "(IFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
+    { "nClipRect",          "(IIIIII)Z",       (void*) android_view_GLES20Canvas_clipRect },
 
-    {   "nQuickReject",       "(IFFFFI)Z",       (void*) android_view_GLES20Canvas_quickReject },
-    {   "nClipRect",          "(IFFFFI)Z",       (void*) android_view_GLES20Canvas_clipRectF },
-    {   "nClipRect",          "(IIIIII)Z",       (void*) android_view_GLES20Canvas_clipRect },
+    { "nTranslate",         "(IFF)V",          (void*) android_view_GLES20Canvas_translate },
+    { "nRotate",            "(IF)V",           (void*) android_view_GLES20Canvas_rotate },
+    { "nScale",             "(IFF)V",          (void*) android_view_GLES20Canvas_scale },
 
-    {   "nTranslate",         "(IFF)V",          (void*) android_view_GLES20Canvas_translate },
-    {   "nRotate",            "(IF)V",           (void*) android_view_GLES20Canvas_rotate },
-    {   "nScale",             "(IFF)V",          (void*) android_view_GLES20Canvas_scale },
+    { "nSetMatrix",         "(II)V",           (void*) android_view_GLES20Canvas_setMatrix },
+    { "nGetMatrix",         "(II)V",           (void*) android_view_GLES20Canvas_getMatrix },
+    { "nConcatMatrix",      "(II)V",           (void*) android_view_GLES20Canvas_concatMatrix },
 
-    {   "nSetMatrix",         "(II)V",           (void*) android_view_GLES20Canvas_setMatrix },
-    {   "nGetMatrix",         "(II)V",           (void*) android_view_GLES20Canvas_getMatrix },
-    {   "nConcatMatrix",      "(II)V",           (void*) android_view_GLES20Canvas_concatMatrix },
+    { "nDrawBitmap",        "(IIFFI)V",        (void*) android_view_GLES20Canvas_drawBitmap },
+    { "nDrawBitmap",        "(IIFFFFFFFFI)V",  (void*) android_view_GLES20Canvas_drawBitmapRect },
+    { "nDrawBitmap",        "(IIII)V",         (void*) android_view_GLES20Canvas_drawBitmapMatrix },
+    { "nDrawPatch",         "(II[BFFFFI)V",    (void*) android_view_GLES20Canvas_drawPatch },
+    { "nDrawColor",         "(III)V",          (void*) android_view_GLES20Canvas_drawColor },
+    { "nDrawRect",          "(IFFFFI)V",       (void*) android_view_GLES20Canvas_drawRect },
+    { "nDrawPath",          "(III)V",          (void*) android_view_GLES20Canvas_drawPath },
 
-    {   "nDrawBitmap",        "(IIFFI)V",        (void*) android_view_GLES20Canvas_drawBitmap },
-    {   "nDrawBitmap",        "(IIFFFFFFFFI)V",  (void*) android_view_GLES20Canvas_drawBitmapRect },
-    {   "nDrawBitmap",        "(IIII)V",         (void*) android_view_GLES20Canvas_drawBitmapMatrix },
-    {   "nDrawPatch",         "(II[BFFFFI)V",    (void*) android_view_GLES20Canvas_drawPatch },
-    {   "nDrawColor",         "(III)V",          (void*) android_view_GLES20Canvas_drawColor },
-    {   "nDrawRect",          "(IFFFFI)V",       (void*) android_view_GLES20Canvas_drawRect },
-    {   "nDrawPath",          "(III)V",          (void*) android_view_GLES20Canvas_drawPath },
+    { "nResetModifiers",    "(I)V",            (void*) android_view_GLES20Canvas_resetModifiers },
+    { "nSetupShader",       "(II)V",           (void*) android_view_GLES20Canvas_setupShader },
+    { "nSetupColorFilter",  "(II)V",           (void*) android_view_GLES20Canvas_setupColorFilter },
 
-    {   "nResetModifiers",    "(I)V",            (void*) android_view_GLES20Canvas_resetModifiers },
-    {   "nSetupShader",       "(II)V",           (void*) android_view_GLES20Canvas_setupShader },
-    {   "nSetupColorFilter",  "(II)V",           (void*) android_view_GLES20Canvas_setupColorFilter },
-
-    {   "nDrawText",          "(I[CIIFFII)V",    (void*) android_view_GLES20Canvas_drawTextArray },
-    {   "nDrawText",          "(ILjava/lang/String;IIFFII)V",
+    { "nDrawText",          "(I[CIIFFII)V",    (void*) android_view_GLES20Canvas_drawTextArray },
+    { "nDrawText",          "(ILjava/lang/String;IIFFII)V",
             (void*) android_view_GLES20Canvas_drawText },
 
+    { "nDrawTextRun",       "(I[CIIIIFFII)V",  (void*) android_view_GLES20Canvas_drawTextRunArray },
+    { "nDrawTextRun",       "(ILjava/lang/String;IIIIFFII)V",
+            (void*) android_view_GLES20Canvas_drawTextRun },
+
     {   "nGetClipBounds",     "(ILandroid/graphics/Rect;)Z",
             (void*) android_view_GLES20Canvas_getClipBounds },
 #endif
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index cb2c6a2..8251881 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -24,6 +24,10 @@
  * text on a path.
  */
 public class Path {
+    /**
+     * @hide
+     */
+    public final int mNativePath;
 
     /**
      * Create an empty path
@@ -537,8 +541,8 @@
             super.finalize();
         }
     }
-    
-    /*package*/ final int ni() {
+
+    final int ni() {
         return mNativePath;
     }
 
@@ -592,9 +596,4 @@
                                                 int dst_path);
     private static native void native_transform(int nPath, int matrix);
     private static native void finalizer(int nPath);
-
-    /**
-     * @hide
-     */
-    public final int mNativePath;
 }
diff --git a/graphics/java/android/graphics/Region.java b/graphics/java/android/graphics/Region.java
index 489ef83..e540806 100644
--- a/graphics/java/android/graphics/Region.java
+++ b/graphics/java/android/graphics/Region.java
@@ -20,6 +20,10 @@
 import android.os.Parcelable;
 
 public class Region implements Parcelable {
+    /**
+     * @hide
+     */
+    public final int mNativeRegion;
 
     // the native values for these must match up with the enum in SkRegion.h
     public enum Op {
@@ -329,10 +333,14 @@
     }
 
     protected void finalize() throws Throwable {
-        nativeDestructor(mNativeRegion);
+        try {
+            nativeDestructor(mNativeRegion);
+        } finally {
+            super.finalize();
+        }
     }
     
-    /*package*/ Region(int ni) {
+    Region(int ni) {
         if (ni == 0) {
             throw new RuntimeException();
         }
@@ -345,7 +353,7 @@
         this(ni);
     }
 
-    /*package*/ final int ni() {
+    final int ni() {
         return mNativeRegion;
     }
 
@@ -374,6 +382,4 @@
                                                       Parcel p);
 
     private static native boolean nativeEquals(int native_r1, int native_r2);
-
-    private final int mNativeRegion;
 }
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 33ecbea..88f6d43 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -313,18 +313,16 @@
             case RECTANGLE:
                 if (st.mRadiusArray != null) {
                     mPath.reset();
-                    mPath.addRoundRect(mRect, st.mRadiusArray,
-                                       Path.Direction.CW);
+                    mPath.addRoundRect(mRect, st.mRadiusArray, Path.Direction.CW);
                     canvas.drawPath(mPath, mFillPaint);
                     if (haveStroke) {
                         canvas.drawPath(mPath, mStrokePaint);
                     }
-                }
-                else {
+                } else if (st.mRadius > 0.0f) {
                     // since the caller is only giving us 1 value, we will force
                     // it to be square if the rect is too small in one dimension
                     // to show it. If we did nothing, Skia would clamp the rad
-                    // independently along each axis, giving us a thin ellips
+                    // independently along each axis, giving us a thin ellipse
                     // if the rect were very wide but not very tall
                     float rad = st.mRadius;
                     float r = Math.min(mRect.width(), mRect.height()) * 0.5f;
@@ -335,6 +333,11 @@
                     if (haveStroke) {
                         canvas.drawRoundRect(mRect, rad, rad, mStrokePaint);
                     }
+                } else {
+                    canvas.drawRect(mRect, mFillPaint);
+                    if (haveStroke) {
+                        canvas.drawRect(mRect, mStrokePaint);
+                    }
                 }
                 break;
             case OVAL:
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 8d00e85..e807aba 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -69,16 +69,16 @@
     int width = (int) glyph->mBitmapWidth;
     int height = (int) glyph->mBitmapHeight;
 
-    if(bounds->bottom > nPenY) {
+    if (bounds->bottom > nPenY) {
         bounds->bottom = nPenY;
     }
-    if(bounds->left > nPenX) {
+    if (bounds->left > nPenX) {
         bounds->left = nPenX;
     }
-    if(bounds->right < nPenX + width) {
+    if (bounds->right < nPenX + width) {
         bounds->right = nPenX + width;
     }
-    if(bounds->top < nPenY + height) {
+    if (bounds->top < nPenY + height) {
         bounds->top = nPenY + height;
     }
 }
@@ -102,7 +102,7 @@
 }
 
 void Font::drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
-                             uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
+        uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
     int nPenX = x + glyph->mBitmapLeft;
     int nPenY = y + glyph->mBitmapTop;
 
@@ -116,7 +116,7 @@
     int32_t bX = 0, bY = 0;
     for (cacheX = glyph->mStartX, bX = nPenX; cacheX < endX; cacheX++, bX++) {
         for (cacheY = glyph->mStartY, bY = nPenY; cacheY < endY; cacheY++, bY++) {
-            if(bX < 0 || bY < 0 || bX >= (int32_t)bitmapW || bY >= (int32_t)bitmapH) {
+            if (bX < 0 || bY < 0 || bX >= (int32_t)bitmapW || bY >= (int32_t)bitmapH) {
                 LOGE("Skipping invalid index");
                 continue;
             }
@@ -143,22 +143,19 @@
 }
 
 void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-                       int numGlyphs, int x, int y,
-                       uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
-    if(bitmap != NULL && bitmapW > 0 && bitmapH > 0) {
-        renderUTF(paint, text, start, len, numGlyphs, x, y, BITMAP,
-                   bitmap, bitmapW, bitmapH, NULL);
-    }
-    else {
-        renderUTF(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER,
-                   NULL, 0, 0, NULL);
+        int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
+    if (bitmap != NULL && bitmapW > 0 && bitmapH > 0) {
+        renderUTF(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap,
+                bitmapW, bitmapH, NULL);
+    } else {
+        renderUTF(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL);
     }
 
 }
 
 void Font::measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-                       int numGlyphs, Rect *bounds) {
-    if(bounds == NULL) {
+        int numGlyphs, Rect *bounds) {
+    if (bounds == NULL) {
         LOGE("No return rectangle provided to measure text");
         return;
     }
@@ -167,9 +164,8 @@
 }
 
 void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-                       int numGlyphs, int x, int y, RenderMode mode,
-                       uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
-                       Rect *bounds) {
+        int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
+        uint32_t bitmapW, uint32_t bitmapH,Rect *bounds) {
     if (numGlyphs == 0 || text == NULL || len == 0) {
         return;
     }
@@ -185,7 +181,7 @@
     while (glyphsLeft > 0) {
         int32_t utfChar = SkUTF16_NextUnichar((const uint16_t**) &text);
 
-        // Reached the end of the string or encountered
+        // Reached the end of the string
         if (utfChar < 0) {
             break;
         }
@@ -422,7 +418,7 @@
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     // Initialize texture dimentions
     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, mCacheWidth, mCacheHeight, 0,
-                  GL_ALPHA, GL_UNSIGNED_BYTE, 0);
+            GL_ALPHA, GL_UNSIGNED_BYTE, 0);
 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -527,7 +523,6 @@
 }
 
 void FontRenderer::issueDrawCommand() {
-
     checkTextureUpdate();
 
     float* vtx = mTextMeshPtr;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 5d30b1a..ff00ba6 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -435,6 +435,7 @@
         return;
     }
 
+    glActiveTexture(GL_TEXTURE0);
     const Texture* texture = mTextureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
@@ -451,6 +452,7 @@
         return;
     }
 
+    glActiveTexture(GL_TEXTURE0);
     const Texture* texture = mTextureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
@@ -466,6 +468,7 @@
         return;
     }
 
+    glActiveTexture(GL_TEXTURE0);
     const Texture* texture = mTextureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
@@ -491,6 +494,7 @@
         return;
     }
 
+    glActiveTexture(GL_TEXTURE0);
     const Texture* texture = mTextureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 4a01ffa..9a22dc0 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -162,7 +162,8 @@
     glGenTextures(1, &texture->id);
 
     glBindTexture(GL_TEXTURE_2D, texture->id);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap.bytesPerPixel());
+    // Textures are Alpha8
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
     texture->blend = true;
     glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, bitmap.rowBytesAsPixels(), texture->height, 0,
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 8a97b4c..2449b6d 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -376,6 +376,9 @@
     }
     shader.append("    return vec2(");
     switch (wrapS) {
+        case GL_CLAMP_TO_EDGE:
+            shader.append("texCoords.x");
+            break;
         case GL_REPEAT:
             shader.append("mod(texCoords.x, 1.0)");
             break;
@@ -385,6 +388,9 @@
     }
     shader.append(", ");
     switch (wrapT) {
+        case GL_CLAMP_TO_EDGE:
+            shader.append("texCoords.y");
+            break;
         case GL_REPEAT:
             shader.append("mod(texCoords.y, 1.0)");
             break;
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 42c0621..15a4e88 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -89,7 +89,8 @@
     description.hasBitmap = true;
     // The driver does not support non-power of two mirrored/repeated
     // textures, so do it ourselves
-    if (!extensions.hasNPot() && !isPowerOfTwo(width) && !isPowerOfTwo(height)) {
+    if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
+            (mTileX != SkShader::kClamp_TileMode || mTileY != SkShader::kClamp_TileMode)) {
         description.isBitmapNpot = true;
         description.bitmapWrapS = gTileModes[mTileX];
         description.bitmapWrapT = gTileModes[mTileY];
@@ -136,6 +137,9 @@
         SkMatrix* matrix, bool blend):
         SkiaShader(kLinearGradient, key, tileMode, tileMode, matrix, blend),
         mBounds(bounds), mColors(colors), mPositions(positions), mCount(count) {
+    for (int i = 0; i < count; i++) {
+        LOGD("[GL] Gradient color %d = 0x%x", i, colors[i]);
+    }
 }
 
 SkiaLinearGradientShader::~SkiaLinearGradientShader() {
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index 924737e..a12edf2 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -39,6 +39,8 @@
 #undef CALL_GL_API
 #undef CALL_GL_API_RETURN
 
+#define DEBUG_CALL_GL_API 0
+
 #if USE_FAST_TLS_KEY
 
     #ifdef HAVE_ARM_TLS_REGISTER
@@ -73,10 +75,24 @@
 
     #define API_ENTRY(_api) _api
 
+#if DEBUG_CALL_GL_API
+
     #define CALL_GL_API(_api, ...)                                       \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
-        _c->_api(__VA_ARGS__)
-    
+        _c->_api(__VA_ARGS__); \
+        GLenum status = GL_NO_ERROR; \
+        while ((status = glGetError()) != GL_NO_ERROR) { \
+            LOGD("[" #_api "] 0x%x", status); \
+        }
+
+#else
+
+    #define CALL_GL_API(_api, ...)                                       \
+        gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
+        _c->_api(__VA_ARGS__);
+
+#endif
+
     #define CALL_GL_API_RETURN(_api, ...)                                \
         gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl;  \
         return _c->_api(__VA_ARGS__)
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 73994f7..90c82ee 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -171,5 +171,14 @@
             </intent-filter>
         </activity>
 
+        <activity
+                android:name="SimplePathsActivity"
+                android:label="_SimplePaths">
+            <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/HwAccelerationTest/src/com/google/android/test/hwui/SimplePathsActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/SimplePathsActivity.java
new file mode 100644
index 0000000..071a118
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/SimplePathsActivity.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.hwui;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class SimplePathsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        FrameLayout layout = new FrameLayout(this);
+        EditText text = new EditText(this);
+        layout.addView(text, new FrameLayout.LayoutParams(600, 350, Gravity.CENTER));
+        text.setText("This is an example of an EditText widget \n" +
+                "using simple paths to create the selection.");
+        //text.setSelection(0, text.getText().length());
+
+        setContentView(layout);
+    }
+}
\ No newline at end of file