Clean up dirFlags / bidiFlags confusion

The dirFlags and bidiFlags enums are distinct, and have different
meanings. The former is a determined direction for a run of text, while
the latter is a request for the bidi algorithm. They have been used
interchangeably, and this has caused some problems, notably running the
bidi algorithm needlessly when the direction for a run is already
determined.

This patch cleans up the confusion, by always naming each occurrence
explicitly "boolean isRtl" or "int bidiFlags" (the previous code often
just used "int flags", which added to the confusion), and converts
between the meanings when a function takes an isRtl argument but passes
it to another function expecting bidiFlags.

Fixes b/15089607 Clean up bidi flag mess

Change-Id: I410b6604376e853dd12c255e7f5a9d2b9a310dd9
diff --git a/core/java/android/text/GraphicsOperations.java b/core/java/android/text/GraphicsOperations.java
index d426d124..8674c66 100644
--- a/core/java/android/text/GraphicsOperations.java
+++ b/core/java/android/text/GraphicsOperations.java
@@ -38,7 +38,7 @@
      * {@hide}
      */
     void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd,
-            float x, float y, int flags, Paint p);
+            float x, float y, boolean isRtl, Paint p);
 
    /**
      * Just like {@link Paint#measureText}.
@@ -55,12 +55,12 @@
      * @hide
      */
     float getTextRunAdvances(int start, int end, int contextStart, int contextEnd,
-            int flags, float[] advances, int advancesIndex, Paint paint);
+            boolean isRtl, float[] advances, int advancesIndex, Paint paint);
 
     /**
      * Just like {@link Paint#getTextRunCursor}.
      * @hide
      */
-    int getTextRunCursor(int contextStart, int contextEnd, int flags, int offset,
+    int getTextRunCursor(int contextStart, int contextEnd, int dir, int offset,
             int cursorOpt, Paint p);
 }
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index f8e3c83..2415b11 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -159,18 +159,17 @@
         mPos = p + len;
 
         if (mEasy) {
-            int flags = mDir == Layout.DIR_LEFT_TO_RIGHT
-                ? Canvas.DIRECTION_LTR : Canvas.DIRECTION_RTL;
-            return paint.getTextRunAdvances(mChars, p, len, p, len, flags, mWidths, p);
+            boolean isRtl = mDir != Layout.DIR_LEFT_TO_RIGHT;
+            return paint.getTextRunAdvances(mChars, p, len, p, len, isRtl, mWidths, p);
         }
 
         float totalAdvance = 0;
         int level = mLevels[p];
         for (int q = p, i = p + 1, e = p + len;; ++i) {
             if (i == e || mLevels[i] != level) {
-                int flags = (level & 0x1) == 0 ? Canvas.DIRECTION_LTR : Canvas.DIRECTION_RTL;
+                boolean isRtl = (level & 0x1) != 0;
                 totalAdvance +=
-                        paint.getTextRunAdvances(mChars, q, i - q, q, i - q, flags, mWidths, q);
+                        paint.getTextRunAdvances(mChars, q, i - q, q, i - q, isRtl, mWidths, q);
                 if (i == e) {
                     break;
                 }
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 1d9aa05..6b984d6 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -503,7 +503,7 @@
         // Span watchers need to be called after text watchers, which may update the layout
         sendToSpanWatchers(start, end, newLen - origLen);
 
-        return this; 
+        return this;
     }
 
     private static boolean hasNonExclusiveExclusiveSpanAt(CharSequence text, int offset) {
@@ -745,7 +745,7 @@
             }
         }
 
-        return 0; 
+        return 0;
     }
 
     /**
@@ -1117,20 +1117,20 @@
      * {@hide}
      */
     public void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd,
-            float x, float y, int flags, Paint p) {
+            float x, float y, boolean isRtl, Paint p) {
         checkRange("drawTextRun", start, end);
 
         int contextLen = contextEnd - contextStart;
         int len = end - start;
         if (contextEnd <= mGapStart) {
-            c.drawTextRun(mText, start, len, contextStart, contextLen, x, y, flags, p);
+            c.drawTextRun(mText, start, len, contextStart, contextLen, x, y, isRtl, p);
         } else if (contextStart >= mGapStart) {
             c.drawTextRun(mText, start + mGapLength, len, contextStart + mGapLength,
-                    contextLen, x, y, flags, p);
+                    contextLen, x, y, isRtl, p);
         } else {
             char[] buf = TextUtils.obtain(contextLen);
             getChars(contextStart, contextEnd, buf, 0);
-            c.drawTextRun(buf, start - contextStart, len, 0, contextLen, x, y, flags, p);
+            c.drawTextRun(buf, start - contextStart, len, 0, contextLen, x, y, isRtl, p);
             TextUtils.recycle(buf);
         }
     }
@@ -1187,7 +1187,7 @@
      * Don't call this yourself -- exists for Paint to use internally.
      * {@hide}
      */
-    public float getTextRunAdvances(int start, int end, int contextStart, int contextEnd, int flags,
+    public float getTextRunAdvances(int start, int end, int contextStart, int contextEnd, boolean isRtl,
             float[] advances, int advancesPos, Paint p) {
 
         float ret;
@@ -1197,15 +1197,15 @@
 
         if (end <= mGapStart) {
             ret = p.getTextRunAdvances(mText, start, len, contextStart, contextLen,
-                    flags, advances, advancesPos);
+                    isRtl, advances, advancesPos);
         } else if (start >= mGapStart) {
             ret = p.getTextRunAdvances(mText, start + mGapLength, len,
-                    contextStart + mGapLength, contextLen, flags, advances, advancesPos);
+                    contextStart + mGapLength, contextLen, isRtl, advances, advancesPos);
         } else {
             char[] buf = TextUtils.obtain(contextLen);
             getChars(contextStart, contextEnd, buf, 0);
             ret = p.getTextRunAdvances(buf, start - contextStart, len,
-                    0, contextLen, flags, advances, advancesPos);
+                    0, contextLen, isRtl, advances, advancesPos);
             TextUtils.recycle(buf);
         }
 
@@ -1228,7 +1228,7 @@
      *
      * @param contextStart the start index of the context
      * @param contextEnd the (non-inclusive) end index of the context
-     * @param flags either DIRECTION_RTL or DIRECTION_LTR
+     * @param dir either DIRECTION_RTL or DIRECTION_LTR
      * @param offset the cursor position to move from
      * @param cursorOpt how to move the cursor, one of CURSOR_AFTER,
      * CURSOR_AT_OR_AFTER, CURSOR_BEFORE,
@@ -1238,7 +1238,7 @@
      * @deprecated This is an internal method, refrain from using it in your code
      */
     @Deprecated
-    public int getTextRunCursor(int contextStart, int contextEnd, int flags, int offset,
+    public int getTextRunCursor(int contextStart, int contextEnd, int dir, int offset,
             int cursorOpt, Paint p) {
 
         int ret;
@@ -1246,15 +1246,15 @@
         int contextLen = contextEnd - contextStart;
         if (contextEnd <= mGapStart) {
             ret = p.getTextRunCursor(mText, contextStart, contextLen,
-                    flags, offset, cursorOpt);
+                    dir, offset, cursorOpt);
         } else if (contextStart >= mGapStart) {
             ret = p.getTextRunCursor(mText, contextStart + mGapLength, contextLen,
-                    flags, offset + mGapLength, cursorOpt) - mGapLength;
+                    dir, offset + mGapLength, cursorOpt) - mGapLength;
         } else {
             char[] buf = TextUtils.obtain(contextLen);
             getChars(contextStart, contextEnd, buf, 0);
             ret = p.getTextRunCursor(buf, 0, contextLen,
-                    flags, offset - contextStart, cursorOpt) + contextStart;
+                    dir, offset - contextStart, cursorOpt) + contextStart;
             TextUtils.recycle(buf);
         }
 
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index d892f19..c19cf32 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -664,14 +664,14 @@
             }
         }
 
-        int flags = runIsRtl ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR;
+        int dir = runIsRtl ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR;
         int cursorOpt = after ? Paint.CURSOR_AFTER : Paint.CURSOR_BEFORE;
         if (mCharsValid) {
             return wp.getTextRunCursor(mChars, spanStart, spanLimit - spanStart,
-                    flags, offset, cursorOpt);
+                    dir, offset, cursorOpt);
         } else {
             return wp.getTextRunCursor(mText, mStart + spanStart,
-                    mStart + spanLimit, flags, mStart + offset, cursorOpt) - mStart;
+                    mStart + spanLimit, dir, mStart + offset, cursorOpt) - mStart;
         }
     }
 
@@ -738,15 +738,14 @@
 
         int contextLen = contextEnd - contextStart;
         if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineColor != 0 || runIsRtl))) {
-            int flags = runIsRtl ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR;
             if (mCharsValid) {
                 ret = wp.getTextRunAdvances(mChars, start, runLen,
-                        contextStart, contextLen, flags, null, 0);
+                        contextStart, contextLen, runIsRtl, null, 0);
             } else {
                 int delta = mStart;
                 ret = wp.getTextRunAdvances(mText, delta + start,
                         delta + end, delta + contextStart, delta + contextEnd,
-                        flags, null, 0);
+                        runIsRtl, null, 0);
             }
         }
 
@@ -977,16 +976,15 @@
     private void drawTextRun(Canvas c, TextPaint wp, int start, int end,
             int contextStart, int contextEnd, boolean runIsRtl, float x, int y) {
 
-        int flags = runIsRtl ? Canvas.DIRECTION_RTL : Canvas.DIRECTION_LTR;
         if (mCharsValid) {
             int count = end - start;
             int contextCount = contextEnd - contextStart;
             c.drawTextRun(mChars, start, count, contextStart, contextCount,
-                    x, y, flags, wp);
+                    x, y, runIsRtl, wp);
         } else {
             int delta = mStart;
             c.drawTextRun(mText, delta + start, delta + end,
-                    delta + contextStart, delta + contextEnd, x, y, flags, wp);
+                    delta + contextStart, delta + contextEnd, x, y, runIsRtl, wp);
         }
     }
 
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 5056097..832d67a 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -51,10 +51,10 @@
 
     private int mWidth;
     private int mHeight;
-    
+
     private float[] mPoint;
     private float[] mLine;
-    
+
     private Rect mClipBounds;
     private RectF mPathBounds;
 
@@ -167,7 +167,7 @@
 
         nSetViewport(mRenderer, width, height);
     }
-    
+
     private static native void nSetViewport(long renderer, int width, int height);
 
     @Override
@@ -208,22 +208,22 @@
 
     /**
      * Must match Caches::FlushMode values
-     * 
-     * @see #flushCaches(int) 
+     *
+     * @see #flushCaches(int)
      */
     static final int FLUSH_CACHES_LAYERS = 0;
-    
+
     /**
      * Must match Caches::FlushMode values
-     * 
-     * @see #flushCaches(int) 
+     *
+     * @see #flushCaches(int)
      */
     static final int FLUSH_CACHES_MODERATE = 1;
 
     /**
      * Must match Caches::FlushMode values
-     * 
-     * @see #flushCaches(int) 
+     *
+     * @see #flushCaches(int)
      */
     static final int FLUSH_CACHES_FULL = 2;
 
@@ -245,7 +245,7 @@
     ///////////////////////////////////////////////////////////////////////////
     // Hardware layer
     ///////////////////////////////////////////////////////////////////////////
-    
+
     void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
         layer.setLayerPaint(paint);
         nDrawLayer(mRenderer, layer.getLayer(), x, y);
@@ -298,7 +298,7 @@
     public boolean clipRect(float left, float top, float right, float bottom) {
         return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
     }
-    
+
     private static native boolean nClipRect(long renderer, float left, float top,
             float right, float bottom, int op);
 
@@ -311,14 +311,14 @@
     public boolean clipRect(int left, int top, int right, int bottom) {
         return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
     }
-    
+
     private static native boolean nClipRect(long renderer, int left, int top,
             int right, int bottom, int op);
 
     @Override
     public boolean clipRect(Rect rect) {
         return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
-                Region.Op.INTERSECT.nativeInt);        
+                Region.Op.INTERSECT.nativeInt);
     }
 
     @Override
@@ -360,7 +360,7 @@
     public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
         return nQuickReject(mRenderer, left, top, right, bottom);
     }
-    
+
     private static native boolean nQuickReject(long renderer, float left, float top,
             float right, float bottom);
 
@@ -385,7 +385,7 @@
     public void translate(float dx, float dy) {
         if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
     }
-    
+
     private static native void nTranslate(long renderer, float dx, float dy);
 
     @Override
@@ -399,21 +399,21 @@
     public void rotate(float degrees) {
         nRotate(mRenderer, degrees);
     }
-    
+
     private static native void nRotate(long renderer, float degrees);
 
     @Override
     public void scale(float sx, float sy) {
         nScale(mRenderer, sx, sy);
     }
-    
+
     private static native void nScale(long renderer, float sx, float sy);
 
     @Override
     public void setMatrix(Matrix matrix) {
         nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance);
     }
-    
+
     private static native void nSetMatrix(long renderer, long matrix);
 
     @SuppressWarnings("deprecation")
@@ -421,16 +421,16 @@
     public void getMatrix(Matrix matrix) {
         nGetMatrix(mRenderer, matrix.native_instance);
     }
-    
+
     private static native void nGetMatrix(long renderer, long matrix);
 
     @Override
     public void concat(Matrix matrix) {
         if (matrix != null) nConcatMatrix(mRenderer, matrix.native_instance);
     }
-    
+
     private static native void nConcatMatrix(long renderer, long matrix);
-    
+
     ///////////////////////////////////////////////////////////////////////////
     // State management
     ///////////////////////////////////////////////////////////////////////////
@@ -439,14 +439,14 @@
     public int save() {
         return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
     }
-    
+
     @Override
     public int save(int saveFlags) {
         return nSave(mRenderer, saveFlags);
     }
 
     private static native int nSave(long renderer, int flags);
-    
+
     @Override
     public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
         if (bounds != null) {
@@ -494,12 +494,12 @@
 
     private static native int nSaveLayerAlpha(long renderer, float left, float top, float right,
             float bottom, int alpha, int saveFlags);
-    
+
     @Override
     public void restore() {
         nRestore(mRenderer);
     }
-    
+
     private static native void nRestore(long renderer);
 
     @Override
@@ -508,12 +508,12 @@
     }
 
     private static native void nRestoreToCount(long renderer, int saveCount);
-    
+
     @Override
     public int getSaveCount() {
         return nGetSaveCount(mRenderer);
     }
-    
+
     private static native int nGetSaveCount(long renderer);
 
     ///////////////////////////////////////////////////////////////////////////
@@ -739,7 +739,7 @@
     public void drawColor(int color, PorterDuff.Mode mode) {
         nDrawColor(mRenderer, color, mode.nativeInt);
     }
-    
+
     private static native void nDrawColor(long renderer, int color, int mode);
 
     @Override
@@ -930,7 +930,7 @@
         nDrawText(mRenderer, text, index, count, x, y,
                 paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
     }
-    
+
     private static native void nDrawText(long renderer, char[] text, int index, int count,
             float x, float y, int bidiFlags, long paint, long typeface);
 
@@ -997,49 +997,45 @@
 
     @Override
     public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
-            float x, float y, int dir, Paint paint) {
+            float x, float y, boolean isRtl, Paint paint) {
         if ((index | count | text.length - index - count) < 0) {
             throw new IndexOutOfBoundsException();
         }
-        if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
-            throw new IllegalArgumentException("Unknown direction: " + dir);
-        }
 
-        nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
+        nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, isRtl,
                 paint.mNativePaint, paint.mNativeTypeface);
     }
 
     private static native void nDrawTextRun(long renderer, char[] text, int index, int count,
-            int contextIndex, int contextCount, float x, float y, int dir, long nativePaint, long nativeTypeface);
+            int contextIndex, int contextCount, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
 
     @Override
     public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
-            float x, float y, int dir, Paint paint) {
+            float x, float y, boolean isRtl, Paint paint) {
         if ((start | end | end - start | text.length() - end) < 0) {
             throw new IndexOutOfBoundsException();
         }
 
-        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, paint.mNativeTypeface);
+                    contextEnd, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
         } else if (text instanceof GraphicsOperations) {
             ((GraphicsOperations) text).drawTextRun(this, start, end,
-                    contextStart, contextEnd, x, y, flags, paint);
+                    contextStart, contextEnd, x, y, isRtl, 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, paint.mNativeTypeface);
+                    x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
             TemporaryBuffer.recycle(buf);
         }
     }
 
     private static native void nDrawTextRun(long renderer, String text, int start, int end,
-            int contextStart, int contextEnd, float x, float y, int flags, long nativePaint, long nativeTypeface);
+            int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
 
     @Override
     public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 22f5e23..45039fc 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9062,11 +9062,11 @@
         }
 
         public void drawTextRun(Canvas c, int start, int end,
-                int contextStart, int contextEnd, float x, float y, int flags, Paint p) {
+                int contextStart, int contextEnd, float x, float y, boolean isRtl, Paint p) {
             int count = end - start;
             int contextCount = contextEnd - contextStart;
             c.drawTextRun(mChars, start + mStart, count, contextStart + mStart,
-                    contextCount, x, y, flags, p);
+                    contextCount, x, y, isRtl, p);
         }
 
         public float measureText(int start, int end, Paint p) {
@@ -9078,20 +9078,20 @@
         }
 
         public float getTextRunAdvances(int start, int end, int contextStart,
-                int contextEnd, int flags, float[] advances, int advancesIndex,
+                int contextEnd, boolean isRtl, float[] advances, int advancesIndex,
                 Paint p) {
             int count = end - start;
             int contextCount = contextEnd - contextStart;
             return p.getTextRunAdvances(mChars, start + mStart, count,
-                    contextStart + mStart, contextCount, flags, advances,
+                    contextStart + mStart, contextCount, isRtl, advances,
                     advancesIndex);
         }
 
-        public int getTextRunCursor(int contextStart, int contextEnd, int flags,
+        public int getTextRunCursor(int contextStart, int contextEnd, int dir,
                 int offset, int cursorOpt, Paint p) {
             int contextCount = contextEnd - contextStart;
             return p.getTextRunCursor(mChars, contextStart + mStart,
-                    contextCount, flags, offset + mStart, cursorOpt);
+                    contextCount, dir, offset + mStart, cursorOpt);
         }
     }
 
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 6de3b9e..a5964c8 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -882,26 +882,26 @@
 
     static void drawText___CIIFFIPaintTypeface(JNIEnv* env, jobject, jlong canvasHandle,
                                                jcharArray text, jint index, jint count,
-                                               jfloat x, jfloat y, jint flags,
+                                               jfloat x, jfloat y, jint bidiFlags,
                                                jlong paintHandle, jlong typefaceHandle) {
         SkCanvas* canvas = getNativeCanvas(canvasHandle);
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         jchar* textArray = env->GetCharArrayElements(text, NULL);
-        drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint, typeface);
+        drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, bidiFlags, paint, typeface);
         env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
     }
 
     static void drawText__StringIIFFIPaintTypeface(JNIEnv* env, jobject,
                                                    jlong canvasHandle, jstring text,
                                                    jint start, jint end,
-                                                   jfloat x, jfloat y, jint flags,
+                                                   jfloat x, jfloat y, jint bidiFlags,
                                                    jlong paintHandle, jlong typefaceHandle) {
         SkCanvas* canvas = getNativeCanvas(canvasHandle);
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         const jchar* textArray = env->GetStringChars(text, NULL);
-        drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint, typeface);
+        drawTextWithGlyphs(canvas, textArray, start, end, x, y, bidiFlags, paint, typeface);
         env->ReleaseStringChars(text, textArray);
     }
 
@@ -951,24 +951,25 @@
 
     static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
             int start, int end,
-            jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
+            jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
 
         jint count = end - start;
-        drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint, typeface);
+        drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, bidiFlags, paint,
+                typeface);
     }
 
     static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
             int start, int count, int contextCount,
-            jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
+            jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
 
 #ifdef USE_MINIKIN
         Layout layout;
-        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
         layout.doLayout(textArray, start, count, contextCount, css);
         drawGlyphsToSkia(canvas, paint, layout, x, y);
 #else
         sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
-                textArray, start, count, contextCount, flags);
+                textArray, start, count, contextCount, bidiFlags);
         if (value == NULL) {
             return;
         }
@@ -979,7 +980,8 @@
             x -= value->getTotalAdvance();
         }
         paint->setTextAlign(SkPaint::kLeft_Align);
-        doDrawGlyphsPos(canvas, value->getGlyphs(), value->getPos(), 0, value->getGlyphsCount(), x, y, flags, paint);
+        doDrawGlyphsPos(canvas, value->getGlyphs(), value->getPos(), 0, value->getGlyphsCount(),
+                x, y, paint);
         doDrawTextDecorations(canvas, x, y, value->getTotalAdvance(), paint);
         paint->setTextAlign(align);
 #endif
@@ -990,42 +992,37 @@
 #define kStdUnderline_Offset    (1.0f / 9.0f)
 #define kStdUnderline_Thickness (1.0f / 18.0f)
 
-static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length, SkPaint* paint) {
-    uint32_t flags;
-    SkDrawFilter* drawFilter = canvas->getDrawFilter();
-    if (drawFilter) {
-        SkPaint paintCopy(*paint);
-        drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
-        flags = paintCopy.getFlags();
-    } else {
-        flags = paint->getFlags();
-    }
-    if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
-        SkScalar left = x;
-        SkScalar right = x + length;
-        float textSize = paint->getTextSize();
-        float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
-        if (flags & SkPaint::kUnderlineText_Flag) {
-            SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
-            SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
-            canvas->drawRectCoords(left, top, right, bottom, *paint);
+    static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length,
+            SkPaint* paint) {
+        uint32_t flags;
+        SkDrawFilter* drawFilter = canvas->getDrawFilter();
+        if (drawFilter) {
+            SkPaint paintCopy(*paint);
+            drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
+            flags = paintCopy.getFlags();
+        } else {
+            flags = paint->getFlags();
         }
-        if (flags & SkPaint::kStrikeThruText_Flag) {
-            SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
-            SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
-            canvas->drawRectCoords(left, top, right, bottom, *paint);
+        if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+            SkScalar left = x;
+            SkScalar right = x + length;
+            float textSize = paint->getTextSize();
+            float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
+            if (flags & SkPaint::kUnderlineText_Flag) {
+                SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
+                SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
+                canvas->drawRectCoords(left, top, right, bottom, *paint);
+            }
+            if (flags & SkPaint::kStrikeThruText_Flag) {
+                SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
+                SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
+                canvas->drawRectCoords(left, top, right, bottom, *paint);
+            }
         }
     }
-}
-
-    static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
-            jfloat x, jfloat y, int flags, SkPaint* paint) {
-        // Beware: this needs Glyph encoding (already done on the Paint constructor)
-        canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint);
-    }
 
     static void doDrawGlyphsPos(SkCanvas* canvas, const jchar* glyphArray, const jfloat* posArray,
-            int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) {
+            int index, int count, jfloat x, jfloat y, SkPaint* paint) {
         SkPoint* posPtr = new SkPoint[count];
         for (int indx = 0; indx < count; indx++) {
             posPtr[indx].fX = x + posArray[indx * 2];
@@ -1035,33 +1032,35 @@
         delete[] posPtr;
     }
 
-    static void drawTextRun___CIIIIFFIPaintTypeface(
+    static void drawTextRun___CIIIIFFZPaintTypeface(
             JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
             jint count, jint contextIndex, jint contextCount,
-            jfloat x, jfloat y, jint dirFlags, jlong paintHandle, jlong typefaceHandle) {
+            jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
         SkCanvas* canvas = getNativeCanvas(canvasHandle);
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
 
+        int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
         jchar* chars = env->GetCharArrayElements(text, NULL);
         drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex,
-                count, contextCount, x, y, dirFlags, paint, typeface);
+                count, contextCount, x, y, bidiFlags, paint, typeface);
         env->ReleaseCharArrayElements(text, chars, JNI_ABORT);
     }
 
-    static void drawTextRun__StringIIIIFFIPaintTypeface(
+    static void drawTextRun__StringIIIIFFZPaintTypeface(
             JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, jint start,
             jint end, jint contextStart, jint contextEnd,
-            jfloat x, jfloat y, jint dirFlags, jlong paintHandle, jlong typefaceHandle) {
+            jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
         SkCanvas* canvas = getNativeCanvas(canvasHandle);
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
 
+        int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
         jint count = end - start;
         jint contextCount = contextEnd - contextStart;
         const jchar* chars = env->GetStringChars(text, NULL);
         drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart,
-                count, contextCount, x, y, dirFlags, paint, typeface);
+                count, contextCount, x, y, bidiFlags, paint, typeface);
         env->ReleaseStringChars(text, chars);
     }
 
@@ -1268,10 +1267,10 @@
         (void*) SkCanvasGlue::drawText___CIIFFIPaintTypeface},
     {"native_drawText","(JLjava/lang/String;IIFFIJJ)V",
         (void*) SkCanvasGlue::drawText__StringIIFFIPaintTypeface},
-    {"native_drawTextRun","(J[CIIIIFFIJJ)V",
-        (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaintTypeface},
-    {"native_drawTextRun","(JLjava/lang/String;IIIIFFIJJ)V",
-        (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaintTypeface},
+    {"native_drawTextRun","(J[CIIIIFFZJJ)V",
+        (void*) SkCanvasGlue::drawTextRun___CIIIIFFZPaintTypeface},
+    {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V",
+        (void*) SkCanvasGlue::drawTextRun__StringIIIIFFZPaintTypeface},
     {"native_drawPosText","(J[CII[FJ)V",
         (void*) SkCanvasGlue::drawPosText___CII_FPaint},
     {"native_drawPosText","(JLjava/lang/String;[FJ)V",
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 8b11d31..1e40d94 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -707,7 +707,7 @@
     }
 
     static jfloat doTextRunAdvances(JNIEnv *env, SkPaint *paint, TypefaceImpl* typeface, const jchar *text,
-                                    jint start, jint count, jint contextCount, jint flags,
+                                    jint start, jint count, jint contextCount, jboolean isRtl,
                                     jfloatArray advances, jint advancesIndex) {
         NPE_CHECK_RETURN_ZERO(env, paint);
         NPE_CHECK_RETURN_ZERO(env, text);
@@ -729,14 +729,16 @@
         jfloat* advancesArray = new jfloat[count];
         jfloat totalAdvance = 0;
 
+        int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
+
 #ifdef USE_MINIKIN
         Layout layout;
-        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+        std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
         layout.doLayout(text, start, count, contextCount, css);
         layout.getAdvances(advancesArray);
         totalAdvance = layout.getAdvance();
 #else
-        TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags,
+        TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, bidiFlags,
                                        advancesArray, &totalAdvance);
 #endif
 
@@ -747,28 +749,28 @@
         return totalAdvance;
     }
 
-    static jfloat getTextRunAdvances___CIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
+    static jfloat getTextRunAdvances___CIIIIZ_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
             jlong typefaceHandle,
             jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
-            jint flags, jfloatArray advances, jint advancesIndex) {
+            jboolean isRtl, jfloatArray advances, jint advancesIndex) {
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         jchar* textArray = env->GetCharArrayElements(text, NULL);
         jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextIndex,
-                index - contextIndex, count, contextCount, flags, advances, advancesIndex);
+                index - contextIndex, count, contextCount, isRtl, advances, advancesIndex);
         env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
         return result;
     }
 
-    static jfloat getTextRunAdvances__StringIIIII_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
+    static jfloat getTextRunAdvances__StringIIIIZ_FI(JNIEnv* env, jobject clazz, jlong paintHandle,
             jlong typefaceHandle,
-            jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags,
+            jstring text, jint start, jint end, jint contextStart, jint contextEnd, jboolean isRtl,
             jfloatArray advances, jint advancesIndex) {
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
         TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
         const jchar* textArray = env->GetStringChars(text, NULL);
         jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextStart,
-                start - contextStart, end - start, contextEnd - contextStart, flags,
+                start - contextStart, end - start, contextEnd - contextStart, isRtl,
                 advances, advancesIndex);
         env->ReleaseStringChars(text, textArray);
         return result;
@@ -819,21 +821,21 @@
     }
 
     static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text,
-            jint contextStart, jint contextCount, jint flags, jint offset, jint cursorOpt) {
+            jint contextStart, jint contextCount, jint dir, jint offset, jint cursorOpt) {
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
         jchar* textArray = env->GetCharArrayElements(text, NULL);
-        jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, flags,
+        jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, dir,
                 offset, cursorOpt);
         env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
         return result;
     }
 
     static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, jlong paintHandle, jstring text,
-            jint contextStart, jint contextEnd, jint flags, jint offset, jint cursorOpt) {
+            jint contextStart, jint contextEnd, jint dir, jint offset, jint cursorOpt) {
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
         const jchar* textArray = env->GetStringChars(text, NULL);
         jint result = doTextRunCursor(env, paint, textArray, contextStart,
-                contextEnd - contextStart, flags, offset, cursorOpt);
+                contextEnd - contextStart, dir, offset, cursorOpt);
         env->ReleaseStringChars(text, textArray);
         return result;
     }
@@ -1110,10 +1112,10 @@
     {"native_breakText","(Ljava/lang/String;ZFI[F)I", (void*) SkPaintGlue::breakTextS},
     {"native_getTextWidths","(JJ[CIII[F)I", (void*) SkPaintGlue::getTextWidths___CIII_F},
     {"native_getTextWidths","(JJLjava/lang/String;III[F)I", (void*) SkPaintGlue::getTextWidths__StringIII_F},
-    {"native_getTextRunAdvances","(JJ[CIIIII[FI)F",
-        (void*) SkPaintGlue::getTextRunAdvances___CIIIII_FI},
-    {"native_getTextRunAdvances","(JJLjava/lang/String;IIIII[FI)F",
-        (void*) SkPaintGlue::getTextRunAdvances__StringIIIII_FI},
+    {"native_getTextRunAdvances","(JJ[CIIIIZ[FI)F",
+        (void*) SkPaintGlue::getTextRunAdvances___CIIIIZ_FI},
+    {"native_getTextRunAdvances","(JJLjava/lang/String;IIIIZ[FI)F",
+        (void*) SkPaintGlue::getTextRunAdvances__StringIIIIZ_FI},
 
 
     {"native_getTextGlyphs","(JLjava/lang/String;IIIII[C)I",
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 9fa5ec9..4a6e117 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -641,16 +641,16 @@
 #endif
 
 static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
-        jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
+        jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
 #ifdef USE_MINIKIN
     Layout layout;
-    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
     layout.doLayout(text, 0, count, count, css);
     x += xOffsetForTextAlign(paint, layout.getAdvance());
     renderTextLayout(renderer, &layout, x, y, paint);
 #else
     sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
-            text, 0, count, count, flags);
+            text, 0, count, count, bidiFlags);
     if (value == NULL) {
         return;
     }
@@ -670,9 +670,9 @@
 }
 
 static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
-        SkPath* path, jfloat hOffset, jfloat vOffset, int flags, SkPaint* paint) {
+        SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, SkPaint* paint) {
     sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
-            text, 0, count, count, flags);
+            text, 0, count, count, bidiFlags);
     if (value == NULL) {
         return;
     }
@@ -685,16 +685,16 @@
 
 static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
         jint start, jint count, jint contextCount, jfloat x, jfloat y,
-        int flags, SkPaint* paint, TypefaceImpl* typeface) {
+        int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
 #ifdef USE_MINIKIN
     Layout layout;
-    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, flags, typeface);
+    std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
     layout.doLayout(text, start, count, contextCount, css);
     x += xOffsetForTextAlign(paint, layout.getAdvance());
     renderTextLayout(renderer, &layout, x, y, paint);
 #else
     sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
-            text, start, count, contextCount, flags);
+            text, start, count, contextCount, bidiFlags);
     if (value == NULL) {
         return;
     }
@@ -715,71 +715,72 @@
 
 static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jcharArray text, jint index, jint count,
-        jfloat x, jfloat y, jint flags, jlong paintPtr, jlong typefacePtr) {
+        jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
     jchar* textArray = env->GetCharArrayElements(text, NULL);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
 
-    renderText(renderer, textArray + index, count, x, y, flags, paint, typeface);
+    renderText(renderer, textArray + index, count, x, y, bidiFlags, paint, typeface);
     env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
 }
 
 static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jstring text, jint start, jint end,
-        jfloat x, jfloat y, jint flags, jlong paintPtr, jlong typefacePtr) {
+        jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
     const jchar* textArray = env->GetStringChars(text, NULL);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
 
-    renderText(renderer, textArray + start, end - start, x, y, flags, paint, typeface);
+    renderText(renderer, textArray + start, end - start, x, y, bidiFlags, paint, typeface);
     env->ReleaseStringChars(text, textArray);
 }
 
 static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jcharArray text, jint index, jint count,
-        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint flags, jlong paintPtr) {
+        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
     jchar* textArray = env->GetCharArrayElements(text, NULL);
     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
 
     renderTextOnPath(renderer, textArray + index, count, path,
-            hOffset, vOffset, flags, paint);
+            hOffset, vOffset, bidiFlags, paint);
     env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
 }
 
 static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jstring text, jint start, jint end,
-        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint flags, jlong paintPtr) {
+        jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
     const jchar* textArray = env->GetStringChars(text, NULL);
     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
 
     renderTextOnPath(renderer, textArray + start, end - start, path,
-            hOffset, vOffset, flags, paint);
+            hOffset, vOffset, bidiFlags, paint);
     env->ReleaseStringChars(text, textArray);
 }
 
 static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jcharArray text, jint index, jint count,
-        jint contextIndex, jint contextCount, jfloat x, jfloat y, jint dirFlags,
+        jint contextIndex, jint contextCount, jfloat x, jfloat y, jboolean isRtl,
         jlong paintPtr, jlong typefacePtr) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
     jchar* textArray = env->GetCharArrayElements(text, NULL);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
 
+    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
     renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
-            count, contextCount, x, y, dirFlags, paint, typeface);
+            count, contextCount, x, y, bidiFlags, paint, typeface);
     env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
  }
 
 static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jstring text, jint start, jint end,
-        jint contextStart, int contextEnd, jfloat x, jfloat y, jint dirFlags,
+        jint contextStart, int contextEnd, jfloat x, jfloat y, jboolean isRtl,
         jlong paintPtr, jlong typefacePtr) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
     const jchar* textArray = env->GetStringChars(text, NULL);
@@ -788,15 +789,16 @@
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
 
+    int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
     renderTextRun(renderer, textArray + contextStart, start - contextStart,
-            count, contextCount, x, y, dirFlags, paint, typeface);
+            count, contextCount, x, y, bidiFlags, paint, typeface);
     env->ReleaseStringChars(text, textArray);
 }
 
 static void renderPosText(OpenGLRenderer* renderer, const jchar* text, int count,
-        const jfloat* positions, jint dirFlags, SkPaint* paint) {
+        const jfloat* positions, jint bidiFlags, SkPaint* paint) {
     sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
-            text, 0, count, count, dirFlags);
+            text, 0, count, count, bidiFlags);
     if (value == NULL) {
         return;
     }
@@ -988,8 +990,8 @@
     { "nDrawTextOnPath",    "(JLjava/lang/String;IIJFFIJ)V",
             (void*) android_view_GLES20Canvas_drawTextOnPath },
 
-    { "nDrawTextRun",       "(J[CIIIIFFIJJ)V",  (void*) android_view_GLES20Canvas_drawTextRunArray },
-    { "nDrawTextRun",       "(JLjava/lang/String;IIIIFFIJJ)V",
+    { "nDrawTextRun",       "(J[CIIIIFFZJJ)V",  (void*) android_view_GLES20Canvas_drawTextRunArray },
+    { "nDrawTextRun",       "(JLjava/lang/String;IIIIFFZJJ)V",
             (void*) android_view_GLES20Canvas_drawTextRun },
 
     { "nDrawPosText",       "(J[CII[FJ)V",     (void*) android_view_GLES20Canvas_drawPosTextArray },
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 13789ca..2b36016 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -65,11 +65,11 @@
 
     /**
      * Used to determine when compatibility scaling is in effect.
-     * 
+     *
      * @hide
      */
     protected int mScreenDensity = Bitmap.DENSITY_NONE;
-    
+
     // Used by native code
     @SuppressWarnings("UnusedDeclaration")
     private int mSurfaceFormat;
@@ -79,7 +79,7 @@
      * @hide
      */
     public static final int DIRECTION_LTR = 0;
-    
+
     /**
      * Flag for drawTextRun indicating right-to-left run direction.
      * @hide
@@ -136,7 +136,7 @@
     /**
      * Construct a canvas with the specified bitmap to draw into. The bitmap
      * must be mutable.
-     * 
+     *
      * <p>The initial target density of the canvas is the same as the given
      * bitmap's density.
      *
@@ -177,10 +177,10 @@
 
     /**
      * Indicates whether this Canvas uses hardware acceleration.
-     * 
+     *
      * Note that this method does not define what type of hardware acceleration
      * may or may not be used.
-     * 
+     *
      * @return True if drawing operations are hardware accelerated,
      *         false otherwise.
      */
@@ -189,7 +189,7 @@
     }
 
     /**
-     * Specify a bitmap for the canvas to draw into. All canvas state such as 
+     * Specify a bitmap for the canvas to draw into. All canvas state such as
      * layers, filters, and the save/restore stack are reset with the exception
      * of the current matrix and clip stack. Additionally, as a side-effect
      * the canvas' target density is updated to match that of the bitmap.
@@ -279,7 +279,7 @@
      * to determine the scaling factor when drawing a bitmap into it.
      *
      * @see #setDensity(int)
-     * @see Bitmap#getDensity() 
+     * @see Bitmap#getDensity()
      */
     public int getDensity() {
         return mDensity;
@@ -295,7 +295,7 @@
      * {@link Bitmap#DENSITY_NONE} to disable bitmap scaling.
      *
      * @see #getDensity()
-     * @see Bitmap#setDensity(int) 
+     * @see Bitmap#setDensity(int)
      */
     public void setDensity(int density) {
         if (mBitmap != null) {
@@ -313,19 +313,19 @@
      * Returns the maximum allowed width for bitmaps drawn with this canvas.
      * Attempting to draw with a bitmap wider than this value will result
      * in an error.
-     * 
-     * @see #getMaximumBitmapHeight() 
+     *
+     * @see #getMaximumBitmapHeight()
      */
     public int getMaximumBitmapWidth() {
         return MAXMIMUM_BITMAP_SIZE;
     }
-    
+
     /**
      * Returns the maximum allowed height for bitmaps drawn with this canvas.
      * Attempting to draw with a bitmap taller than this value will result
      * in an error.
-     * 
-     * @see #getMaximumBitmapWidth() 
+     *
+     * @see #getMaximumBitmapWidth()
      */
     public int getMaximumBitmapHeight() {
         return MAXMIMUM_BITMAP_SIZE;
@@ -357,8 +357,8 @@
     /** clip against the layer's bounds */
     public static final int CLIP_TO_LAYER_SAVE_FLAG = 0x10;
     /** restore everything when restore() is called */
-    public static final int ALL_SAVE_FLAG = 0x1F; 
-    
+    public static final int ALL_SAVE_FLAG = 0x1F;
+
     /**
      * Saves the current matrix and clip onto a private stack. Subsequent
      * calls to translate,scale,rotate,skew,concat or clipRect,clipPath
@@ -371,7 +371,7 @@
     public int save() {
         return native_save(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
     }
-    
+
     /**
      * Based on saveFlags, can save the current matrix and clip onto a private
      * stack. Subsequent calls to translate,scale,rotate,skew,concat or
@@ -589,25 +589,25 @@
     public void concat(@Nullable Matrix matrix) {
         if (matrix != null) native_concat(mNativeCanvasWrapper, matrix.native_instance);
     }
-    
+
     /**
      * Completely replace the current matrix with the specified matrix. If the
      * matrix parameter is null, then the current matrix is reset to identity.
-     * 
+     *
      * <strong>Note:</strong> it is recommended to use {@link #concat(Matrix)},
      * {@link #scale(float, float)}, {@link #translate(float, float)} and
      * {@link #rotate(float)} instead of this method.
      *
      * @param matrix The matrix to replace the current matrix with. If it is
      *               null, set the current matrix to identity.
-     *               
-     * @see #concat(Matrix) 
+     *
+     * @see #concat(Matrix)
      */
     public void setMatrix(@Nullable Matrix matrix) {
         native_setMatrix(mNativeCanvasWrapper,
                          matrix == null ? 0 : matrix.native_instance);
     }
-    
+
     /**
      * Return, in ctm, the current transformation matrix. This does not alter
      * the matrix in the canvas, but just returns a copy of it.
@@ -628,7 +628,7 @@
         getMatrix(m);
         return m;
     }
-    
+
     /**
      * Modify the current clip with the specified rectangle.
      *
@@ -677,7 +677,7 @@
         return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
                 Region.Op.INTERSECT.nativeInt);
     }
-    
+
     /**
      * Modify the current clip with the specified rectangle, which is
      * expressed in local coordinates.
@@ -744,7 +744,7 @@
     public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) {
         return native_clipPath(mNativeCanvasWrapper, path.ni(), op.nativeInt);
     }
-    
+
     /**
      * Intersect the current clip with the specified path.
      *
@@ -754,7 +754,7 @@
     public boolean clipPath(@NonNull Path path) {
         return clipPath(path, Region.Op.INTERSECT);
     }
-    
+
     /**
      * Modify the current clip with the specified region. Note that unlike
      * clipRect() and clipPath() which transform their arguments by the
@@ -789,11 +789,11 @@
     public boolean clipRegion(@NonNull Region region) {
         return clipRegion(region, Region.Op.INTERSECT);
     }
-    
+
     public @Nullable DrawFilter getDrawFilter() {
         return mDrawFilter;
     }
-    
+
     public void setDrawFilter(@Nullable DrawFilter filter) {
         long nativeFilter = 0;
         if (filter != null) {
@@ -814,7 +814,7 @@
          * Antialiased: Treat edges by rounding-out, since they may be antialiased
          */
         AA(1);
-        
+
         EdgeType(int nativeInt) {
             this.nativeInt = nativeInt;
         }
@@ -900,7 +900,7 @@
     public boolean getClipBounds(@Nullable Rect bounds) {
         return native_getClipBounds(mNativeCanvasWrapper, bounds);
     }
-    
+
     /**
      * Retrieve the bounds of the current clip (in local coordinates).
      *
@@ -911,7 +911,7 @@
         getClipBounds(r);
         return r;
     }
-    
+
     /**
      * Fill the entire canvas' bitmap (restricted to the current clip) with the
      * specified RGB color, using srcover porterduff mode.
@@ -968,7 +968,7 @@
     public void drawPaint(@NonNull Paint paint) {
         native_drawPaint(mNativeCanvasWrapper, paint.mNativePaint);
     }
-    
+
     /**
      * Draw a series of points. Each point is centered at the coordinate
      * specified by pts[], and its diameter is specified by the paint's stroke
@@ -1065,7 +1065,7 @@
     public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
         drawRect(r.left, r.top, r.right, r.bottom, paint);
     }
-    
+
 
     /**
      * Draw the specified Rect using the specified paint. The rectangle will
@@ -1111,15 +1111,15 @@
     /**
      * <p>Draw the specified arc, which will be scaled to fit inside the
      * specified oval.</p>
-     * 
+     *
      * <p>If the start angle is negative or >= 360, the start angle is treated
      * as start angle modulo 360.</p>
-     * 
+     *
      * <p>If the sweep angle is >= 360, then the oval is drawn
      * completely. Note that this differs slightly from SkPath::arcTo, which
      * treats the sweep angle modulo 360. If the sweep angle is negative,
      * the sweep angle is treated as sweep angle modulo 360</p>
-     * 
+     *
      * <p>The arc is drawn clockwise. An angle of 0 degrees correspond to the
      * geometric angle of 0 degrees (3 o'clock on a watch.)</p>
      *
@@ -1197,7 +1197,7 @@
      * @param patch The ninepatch object to render
      * @param dst The destination rectangle.
      * @param paint The paint to draw the bitmap with. may be null
-     * 
+     *
      * @hide
      */
     public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
@@ -1220,7 +1220,7 @@
     /**
      * Draw the specified bitmap, with its top/left corner at (x,y), using
      * the specified paint, transformed by the current matrix.
-     * 
+     *
      * <p>Note: if the paint contains a maskfilter that generates a mask which
      * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
      * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
@@ -1230,7 +1230,7 @@
      * <p>If the bitmap and canvas have different densities, this function
      * will take care of automatically scaling the bitmap to draw at the
      * same density as the canvas.
-     * 
+     *
      * @param bitmap The bitmap to be drawn
      * @param left   The position of the left side of the bitmap being drawn
      * @param top    The position of the top side of the bitmap being drawn
@@ -1246,7 +1246,7 @@
      * Draw the specified bitmap, scaling/translating automatically to fill
      * the destination rectangle. If the source rectangle is not null, it
      * specifies the subset of the bitmap to draw.
-     * 
+     *
      * <p>Note: if the paint contains a maskfilter that generates a mask which
      * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
      * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
@@ -1257,7 +1257,7 @@
      * This is because the source and destination rectangle coordinate
      * spaces are in their respective densities, so must already have the
      * appropriate scaling factor applied.
-     * 
+     *
      * @param bitmap The bitmap to be drawn
      * @param src    May be null. The subset of the bitmap to be drawn
      * @param dst    The rectangle that the bitmap will be scaled/translated
@@ -1278,7 +1278,7 @@
      * Draw the specified bitmap, scaling/translating automatically to fill
      * the destination rectangle. If the source rectangle is not null, it
      * specifies the subset of the bitmap to draw.
-     * 
+     *
      * <p>Note: if the paint contains a maskfilter that generates a mask which
      * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
      * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
@@ -1289,7 +1289,7 @@
      * This is because the source and destination rectangle coordinate
      * spaces are in their respective densities, so must already have the
      * appropriate scaling factor applied.
-     * 
+     *
      * @param bitmap The bitmap to be drawn
      * @param src    May be null. The subset of the bitmap to be drawn
      * @param dst    The rectangle that the bitmap will be scaled/translated
@@ -1305,7 +1305,7 @@
         native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), src, dst,
                 paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
     }
-    
+
     /**
      * Treat the specified array of colors as a bitmap, and draw it. This gives
      * the same result as first creating a bitmap from the array, and then
@@ -1394,7 +1394,7 @@
             throw new ArrayIndexOutOfBoundsException();
         }
     }
-    
+
     /**
      * Draw the bitmap through the mesh, where mesh vertices are evenly
      * distributed across the bitmap. There are meshWidth+1 vertices across, and
@@ -1446,7 +1446,7 @@
         TRIANGLES(0),
         TRIANGLE_STRIP(1),
         TRIANGLE_FAN(2);
-        
+
         VertexMode(int nativeInt) {
             this.nativeInt = nativeInt;
         }
@@ -1456,7 +1456,7 @@
          */
         public final int nativeInt;
     }
-    
+
     /**
      * Draw the array of vertices, interpreted as triangles (based on mode). The
      * verts array is required, and specifies the x,y pairs for each vertex. If
@@ -1485,7 +1485,7 @@
      * @param indices If not null, array of indices to reference into the
      *      vertex (texs, colors) array.
      * @param indexCount number of entries in the indices array (if not null).
-     * @param paint Specifies the shader to use if the texs array is non-null. 
+     * @param paint Specifies the shader to use if the texs array is non-null.
      */
     public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
             int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
@@ -1595,7 +1595,7 @@
      * bidi on the provided text, but renders it as a uniform right-to-left or
      * left-to-right run, as indicated by dir. Alignment of the text is as
      * determined by the Paint's TextAlign value.
-     * 
+     *
      * @param text the text to render
      * @param index the start of the text to render
      * @param count the count of chars to render
@@ -1606,13 +1606,12 @@
      *         + count.
      * @param x the x position at which to draw the text
      * @param y the y position at which to draw the text
-     * @param dir the run direction, either {@link #DIRECTION_LTR} or
-     *         {@link #DIRECTION_RTL}.
+     * @param isRtl whether the run is in RTL direction
      * @param paint the paint
      * @hide
      */
     public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
-            int contextCount, float x, float y, int dir, @NonNull Paint paint) {
+            int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
 
         if (text == null) {
             throw new NullPointerException("text is null");
@@ -1623,12 +1622,9 @@
         if ((index | count | text.length - index - count) < 0) {
             throw new IndexOutOfBoundsException();
         }
-        if (dir != DIRECTION_LTR && dir != DIRECTION_RTL) {
-            throw new IllegalArgumentException("unknown dir: " + dir);
-        }
 
         native_drawTextRun(mNativeCanvasWrapper, text, index, count,
-                contextIndex, contextCount, x, y, dir, paint.mNativePaint, paint.mNativeTypeface);
+                contextIndex, contextCount, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
     }
 
     /**
@@ -1644,12 +1640,12 @@
      *            position can be used for shaping context.
      * @param x the x position at which to draw the text
      * @param y the y position at which to draw the text
-     * @param dir the run direction, either 0 for LTR or 1 for RTL.
+     * @param isRtl whether the run is in RTL direction
      * @param paint the paint
      * @hide
      */
     public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
-            int contextEnd, float x, float y, int dir, @NonNull Paint paint) {
+            int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
 
         if (text == null) {
             throw new NullPointerException("text is null");
@@ -1661,22 +1657,20 @@
             throw new IndexOutOfBoundsException();
         }
 
-        int flags = dir == 0 ? 0 : 1;
-
         if (text instanceof String || text instanceof SpannedString ||
                 text instanceof SpannableString) {
             native_drawTextRun(mNativeCanvasWrapper, text.toString(), start, end,
-                    contextStart, contextEnd, x, y, flags, paint.mNativePaint, paint.mNativeTypeface);
+                    contextStart, contextEnd, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
         } else if (text instanceof GraphicsOperations) {
             ((GraphicsOperations) text).drawTextRun(this, start, end,
-                    contextStart, contextEnd, x, y, flags, paint);
+                    contextStart, contextEnd, x, y, isRtl, paint);
         } else {
             int contextLen = contextEnd - contextStart;
             int len = end - start;
             char[] buf = TemporaryBuffer.obtain(contextLen);
             TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
             native_drawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
-                    0, contextLen, x, y, flags, paint.mNativePaint, paint.mNativeTypeface);
+                    0, contextLen, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
             TemporaryBuffer.recycle(buf);
         }
     }
@@ -1684,7 +1678,7 @@
     /**
      * Draw the text in the array, with each character's origin specified by
      * the pos array.
-     * 
+     *
      * This method does not support glyph composition and decomposition and
      * should therefore not be used to render complex scripts.
      *
@@ -1708,7 +1702,7 @@
     /**
      * Draw the text in the array, with each character's origin specified by
      * the pos array.
-     * 
+     *
      * This method does not support glyph composition and decomposition and
      * should therefore not be used to render complex scripts.
      *
@@ -1776,7 +1770,7 @@
      * <p>
      * <strong>Note:</strong> This forces the picture to internally call
      * {@link Picture#endRecording} in order to prepare for playback.
-     * 
+     *
      * @param picture  The picture to be drawn
      */
     public void drawPicture(@NonNull Picture picture) {
@@ -1785,7 +1779,7 @@
         picture.draw(this);
         restoreToCount(restoreCount);
     }
-    
+
     /**
      * Draw the picture, stretched to fit into the dst rectangle.
      */
@@ -1798,7 +1792,7 @@
         drawPicture(picture);
         restore();
     }
-    
+
     /**
      * Draw the picture, stretched to fit into the dst rectangle.
      */
@@ -1977,11 +1971,11 @@
 
     private static native void native_drawTextRun(long nativeCanvas, String text,
             int start, int end, int contextStart, int contextEnd,
-            float x, float y, int flags, long nativePaint, long nativeTypeface);
+            float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
 
     private static native void native_drawTextRun(long nativeCanvas, char[] text,
             int start, int count, int contextStart, int contextCount,
-            float x, float y, int flags, long nativePaint, long nativeTypeface);
+            float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
 
     private static native void native_drawPosText(long nativeCanvas,
                                                   char[] text, int index,
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 4268a24..8837955 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -56,7 +56,7 @@
      * @hide
      */
     public  int         mBidiFlags = BIDI_DEFAULT_LTR;
-    
+
     static final Style[] sStyleArray = {
         Style.FILL, Style.STROKE, Style.FILL_AND_STROKE
     };
@@ -202,14 +202,14 @@
 
     /**
      * Bidi flag to set LTR paragraph direction.
-     * 
+     *
      * @hide
      */
     public static final int BIDI_LTR = 0x0;
 
     /**
      * Bidi flag to set RTL paragraph direction.
-     * 
+     *
      * @hide
      */
     public static final int BIDI_RTL = 0x1;
@@ -217,7 +217,7 @@
     /**
      * Bidi flag to detect paragraph direction via heuristics, defaulting to
      * LTR.
-     * 
+     *
      * @hide
      */
     public static final int BIDI_DEFAULT_LTR = 0x2;
@@ -225,21 +225,21 @@
     /**
      * Bidi flag to detect paragraph direction via heuristics, defaulting to
      * RTL.
-     * 
+     *
      * @hide
      */
     public static final int BIDI_DEFAULT_RTL = 0x3;
 
     /**
      * Bidi flag to override direction to all LTR (ignore bidi).
-     * 
+     *
      * @hide
      */
     public static final int BIDI_FORCE_LTR = 0x4;
 
     /**
      * Bidi flag to override direction to all RTL (ignore bidi).
-     * 
+     *
      * @hide
      */
     public static final int BIDI_FORCE_RTL = 0x5;
@@ -331,7 +331,7 @@
          * either FILL or STROKE.
          */
         FILL_AND_STROKE (2);
-        
+
         Style(int nativeInt) {
             this.nativeInt = nativeInt;
         }
@@ -357,7 +357,7 @@
          * of the path.
          */
         SQUARE  (2);
-        
+
         private Cap(int nativeInt) {
             this.nativeInt = nativeInt;
         }
@@ -381,7 +381,7 @@
          * The outer edges of a join meet with a straight line
          */
         BEVEL   (2);
-        
+
         private Join(int nativeInt) {
             this.nativeInt = nativeInt;
         }
@@ -405,7 +405,7 @@
          * The text is drawn to the left of the x,y origin
          */
         RIGHT   (2);
-        
+
         private Align(int nativeInt) {
             this.nativeInt = nativeInt;
         }
@@ -418,7 +418,7 @@
     public Paint() {
         this(0);
     }
-    
+
     /**
      * Create a new paint with the specified flags. Use setFlags() to change
      * these after the paint is created.
@@ -475,7 +475,7 @@
         setTextLocale(Locale.getDefault());
         setElegantTextHeight(false);
     }
-    
+
     /**
      * Copy the fields from src into this paint. This is equivalent to calling
      * get() on all of the src fields, and calling the corresponding set()
@@ -529,7 +529,7 @@
 
     /**
      * Return the bidi flags on the paint.
-     * 
+     *
      * @return the bidi flags on the paint
      * @hide
      */
@@ -552,7 +552,7 @@
 
     /**
      * Return the paint's flags. Use the Flag enum to test flag values.
-     * 
+     *
      * @return the paint's flags (see enums ending in _Flag for bit masks)
      */
     public native int getFlags();
@@ -587,7 +587,7 @@
     public final boolean isAntiAlias() {
         return (getFlags() & ANTI_ALIAS_FLAG) != 0;
     }
-    
+
     /**
      * Helper for setFlags(), setting or clearing the ANTI_ALIAS_FLAG bit
      * AntiAliasing smooths out the edges of what is being drawn, but is has
@@ -597,7 +597,7 @@
      * @param aa true to set the antialias bit in the flags, false to clear it
      */
     public native void setAntiAlias(boolean aa);
-    
+
     /**
      * Helper for getFlags(), returning true if DITHER_FLAG bit is set
      * Dithering affects how colors that are higher precision than the device
@@ -611,7 +611,7 @@
     public final boolean isDither() {
         return (getFlags() & DITHER_FLAG) != 0;
     }
-    
+
     /**
      * Helper for setFlags(), setting or clearing the DITHER_FLAG bit
      * Dithering affects how colors that are higher precision than the device
@@ -623,7 +623,7 @@
      * @param dither true to set the dithering bit in flags, false to clear it
      */
     public native void setDither(boolean dither);
-    
+
     /**
      * Helper for getFlags(), returning true if LINEAR_TEXT_FLAG bit is set
      *
@@ -649,7 +649,7 @@
     public final boolean isSubpixelText() {
         return (getFlags() & SUBPIXEL_TEXT_FLAG) != 0;
     }
-    
+
     /**
      * Helper for setFlags(), setting or clearing the SUBPIXEL_TEXT_FLAG bit
      *
@@ -657,7 +657,7 @@
      *                     flags, false to clear it.
      */
     public native void setSubpixelText(boolean subpixelText);
-    
+
     /**
      * Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set
      *
@@ -708,7 +708,7 @@
      *                     flags, false to clear it.
      */
     public native void setFakeBoldText(boolean fakeBoldText);
-    
+
     /**
      * Whether or not the bitmap filter is activated.
      * Filtering affects the sampling of bitmaps when they are transformed.
@@ -720,13 +720,13 @@
     public final boolean isFilterBitmap() {
         return (getFlags() & FILTER_BITMAP_FLAG) != 0;
     }
-    
+
     /**
      * Helper for setFlags(), setting or clearing the FILTER_BITMAP_FLAG bit.
      * Filtering affects the sampling of bitmaps when they are transformed.
      * Filtering does not affect how the colors in the bitmap are converted into
      * device pixels. That is dependent on dithering and xfermodes.
-     * 
+     *
      * @param filter true to set the FILTER_BITMAP_FLAG bit in the paint's
      *               flags, false to clear it.
      */
@@ -773,7 +773,7 @@
      * @param color The new color (including alpha) to set in the paint.
      */
     public native void setColor(int color);
-    
+
     /**
      * Helper to getColor() that just returns the color's alpha value. This is
      * the same as calling getColor() >>> 24. It always returns a value between
@@ -1285,7 +1285,7 @@
      */
     public static class FontMetrics {
         /**
-         * The maximum distance above the baseline for the tallest glyph in 
+         * The maximum distance above the baseline for the tallest glyph in
          * the font at a given text size.
          */
         public float   top;
@@ -1298,7 +1298,7 @@
          */
         public float   descent;
         /**
-         * The maximum distance below the baseline for the lowest glyph in 
+         * The maximum distance below the baseline for the lowest glyph in
          * the font at a given text size.
          */
         public float   bottom;
@@ -1307,7 +1307,7 @@
          */
         public float   leading;
     }
-    
+
     /**
      * Return the font's recommended interline spacing, given the Paint's
      * settings for typeface, textSize, etc. If metrics is not null, return the
@@ -1318,7 +1318,7 @@
      * @return the font's recommended interline spacing.
      */
     public native float getFontMetrics(FontMetrics metrics);
-    
+
     /**
      * Allocates a new FontMetrics object, and then calls getFontMetrics(fm)
      * with it, returning the object.
@@ -1328,7 +1328,7 @@
         getFontMetrics(fm);
         return fm;
     }
-    
+
     /**
      * Convenience method for callers that want to have FontMetrics values as
      * integers.
@@ -1339,7 +1339,7 @@
         public int   descent;
         public int   bottom;
         public int   leading;
-        
+
         @Override public String toString() {
             return "FontMetricsInt: top=" + top + " ascent=" + ascent +
                     " descent=" + descent + " bottom=" + bottom +
@@ -1364,7 +1364,7 @@
         getFontMetricsInt(fm);
         return fm;
     }
-    
+
     /**
      * Return the recommend line spacing based on the current typeface and
      * text size.
@@ -1407,7 +1407,7 @@
     }
 
     private native float native_measureText(char[] text, int index, int count, int bidiFlags);
-    
+
     /**
      * Return the width of the text.
      *
@@ -1439,7 +1439,7 @@
     }
 
     private native float native_measureText(String text, int start, int end, int bidiFlags);
-    
+
     /**
      * Return the width of the text.
      *
@@ -1466,7 +1466,7 @@
     }
 
     private native float native_measureText(String text, int bidiFlags);
-    
+
     /**
      * Return the width of the text.
      *
@@ -1503,7 +1503,7 @@
         TemporaryBuffer.recycle(buf);
         return result;
     }
-    
+
     /**
      * Measure the text, stopping early if the measured width exceeds maxWidth.
      * Return the number of chars that were measured, and if measuredWidth is
@@ -1738,7 +1738,7 @@
         if (end - start > widths.length) {
             throw new ArrayIndexOutOfBoundsException();
         }
-        
+
         if (text.length() == 0 || start == end) {
             return 0;
         }
@@ -1755,7 +1755,7 @@
         }
         return res;
     }
-    
+
     /**
      * Return the advance widths for the characters in the string.
      *
@@ -1816,15 +1816,12 @@
      * @hide
      */
     public float getTextRunAdvances(char[] chars, int index, int count,
-            int contextIndex, int contextCount, int flags, float[] advances,
+            int contextIndex, int contextCount, boolean isRtl, float[] advances,
             int advancesIndex) {
 
         if (chars == null) {
             throw new IllegalArgumentException("text cannot be null");
         }
-        if (flags != DIRECTION_LTR && flags != DIRECTION_RTL) {
-            throw new IllegalArgumentException("unknown flags value: " + flags);
-        }
         if ((index | count | contextIndex | contextCount | advancesIndex
                 | (index - contextIndex) | (contextCount - count)
                 | ((contextIndex + contextCount) - (index + count))
@@ -1839,13 +1836,13 @@
         }
         if (!mHasCompatScaling) {
             return native_getTextRunAdvances(mNativePaint, mNativeTypeface, chars, index, count,
-                    contextIndex, contextCount, flags, advances, advancesIndex);
+                    contextIndex, contextCount, isRtl, advances, advancesIndex);
         }
 
         final float oldSize = getTextSize();
         setTextSize(oldSize * mCompatScaling);
         float res = native_getTextRunAdvances(mNativePaint, mNativeTypeface, chars, index, count,
-                contextIndex, contextCount, flags, advances, advancesIndex);
+                contextIndex, contextCount, isRtl, advances, advancesIndex);
         setTextSize(oldSize);
 
         if (advances != null) {
@@ -1864,7 +1861,7 @@
      * @hide
      */
     public float getTextRunAdvances(CharSequence text, int start, int end,
-            int contextStart, int contextEnd, int flags, float[] advances,
+            int contextStart, int contextEnd, boolean isRtl, float[] advances,
             int advancesIndex) {
 
         if (text == null) {
@@ -1880,16 +1877,16 @@
 
         if (text instanceof String) {
             return getTextRunAdvances((String) text, start, end,
-                    contextStart, contextEnd, flags, advances, advancesIndex);
+                    contextStart, contextEnd, isRtl, advances, advancesIndex);
         }
         if (text instanceof SpannedString ||
             text instanceof SpannableString) {
             return getTextRunAdvances(text.toString(), start, end,
-                    contextStart, contextEnd, flags, advances, advancesIndex);
+                    contextStart, contextEnd, isRtl, advances, advancesIndex);
         }
         if (text instanceof GraphicsOperations) {
             return ((GraphicsOperations) text).getTextRunAdvances(start, end,
-                    contextStart, contextEnd, flags, advances, advancesIndex, this);
+                    contextStart, contextEnd, isRtl, advances, advancesIndex, this);
         }
         if (text.length() == 0 || end == start) {
             return 0f;
@@ -1900,7 +1897,7 @@
         char[] buf = TemporaryBuffer.obtain(contextLen);
         TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
         float result = getTextRunAdvances(buf, start - contextStart, len,
-                0, contextLen, flags, advances, advancesIndex);
+                0, contextLen, isRtl, advances, advancesIndex);
         TemporaryBuffer.recycle(buf);
         return result;
     }
@@ -1937,8 +1934,7 @@
      * must be <= start
      * @param contextEnd the index past the last character to use for shaping context,
      * must be >= end
-     * @param flags the flags to control the advances, either {@link #DIRECTION_LTR}
-     * or {@link #DIRECTION_RTL}
+     * @param isRtl whether the run is in RTL direction
      * @param advances array to receive the advances, must have room for all advances,
      * can be null if only total advance is needed
      * @param advancesIndex the position in advances at which to put the
@@ -1948,14 +1944,11 @@
      * @hide
      */
     public float getTextRunAdvances(String text, int start, int end, int contextStart,
-            int contextEnd, int flags, float[] advances, int advancesIndex) {
+            int contextEnd, boolean isRtl, float[] advances, int advancesIndex) {
 
         if (text == null) {
             throw new IllegalArgumentException("text cannot be null");
         }
-        if (flags != DIRECTION_LTR && flags != DIRECTION_RTL) {
-            throw new IllegalArgumentException("unknown flags value: " + flags);
-        }
         if ((start | end | contextStart | contextEnd | advancesIndex | (end - start)
                 | (start - contextStart) | (contextEnd - end)
                 | (text.length() - contextEnd)
@@ -1970,13 +1963,13 @@
 
         if (!mHasCompatScaling) {
             return native_getTextRunAdvances(mNativePaint, mNativeTypeface, text, start, end,
-                    contextStart, contextEnd, flags, advances, advancesIndex);
+                    contextStart, contextEnd, isRtl, advances, advancesIndex);
         }
 
         final float oldSize = getTextSize();
         setTextSize(oldSize * mCompatScaling);
         float totalAdvance = native_getTextRunAdvances(mNativePaint, mNativeTypeface, text, start, end,
-                contextStart, contextEnd, flags, advances, advancesIndex);
+                contextStart, contextEnd, isRtl, advances, advancesIndex);
         setTextSize(oldSize);
 
         if (advances != null) {
@@ -2005,7 +1998,7 @@
      * @param text the text
      * @param contextStart the start of the context
      * @param contextLength the length of the context
-     * @param flags either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
+     * @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
      * @param offset the cursor position to move from
      * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
      * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
@@ -2014,7 +2007,7 @@
      * @hide
      */
     public int getTextRunCursor(char[] text, int contextStart, int contextLength,
-            int flags, int offset, int cursorOpt) {
+            int dir, int offset, int cursorOpt) {
         int contextEnd = contextStart + contextLength;
         if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
                 | (offset - contextStart) | (contextEnd - offset)
@@ -2024,7 +2017,7 @@
         }
 
         return native_getTextRunCursor(mNativePaint, text,
-                contextStart, contextLength, flags, offset, cursorOpt);
+                contextStart, contextLength, dir, offset, cursorOpt);
     }
 
     /**
@@ -2045,7 +2038,7 @@
      * @param text the text
      * @param contextStart the start of the context
      * @param contextEnd the end of the context
-     * @param flags either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
+     * @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
      * @param offset the cursor position to move from
      * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
      * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
@@ -2054,22 +2047,22 @@
      * @hide
      */
     public int getTextRunCursor(CharSequence text, int contextStart,
-           int contextEnd, int flags, int offset, int cursorOpt) {
+           int contextEnd, int dir, int offset, int cursorOpt) {
 
         if (text instanceof String || text instanceof SpannedString ||
                 text instanceof SpannableString) {
             return getTextRunCursor(text.toString(), contextStart, contextEnd,
-                    flags, offset, cursorOpt);
+                    dir, offset, cursorOpt);
         }
         if (text instanceof GraphicsOperations) {
             return ((GraphicsOperations) text).getTextRunCursor(
-                    contextStart, contextEnd, flags, offset, cursorOpt, this);
+                    contextStart, contextEnd, dir, offset, cursorOpt, this);
         }
 
         int contextLen = contextEnd - contextStart;
         char[] buf = TemporaryBuffer.obtain(contextLen);
         TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
-        int result = getTextRunCursor(buf, 0, contextLen, flags, offset - contextStart, cursorOpt);
+        int result = getTextRunCursor(buf, 0, contextLen, dir, offset - contextStart, cursorOpt);
         TemporaryBuffer.recycle(buf);
         return result;
     }
@@ -2092,7 +2085,7 @@
      * @param text the text
      * @param contextStart the start of the context
      * @param contextEnd the end of the context
-     * @param flags either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
+     * @param dir either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
      * @param offset the cursor position to move from
      * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
      * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
@@ -2101,7 +2094,7 @@
      * @hide
      */
     public int getTextRunCursor(String text, int contextStart, int contextEnd,
-            int flags, int offset, int cursorOpt) {
+            int dir, int offset, int cursorOpt) {
         if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
                 | (offset - contextStart) | (contextEnd - offset)
                 | (text.length() - contextEnd) | cursorOpt) < 0)
@@ -2110,7 +2103,7 @@
         }
 
         return native_getTextRunCursor(mNativePaint, text,
-                contextStart, contextEnd, flags, offset, cursorOpt);
+                contextStart, contextEnd, dir, offset, cursorOpt);
     }
 
     /**
@@ -2156,7 +2149,7 @@
         native_getTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, start, end, x, y,
                 path.ni());
     }
-    
+
     /**
      * Return in bounds (allocated by the caller) the smallest rectangle that
      * encloses all of the characters, with an implied origin at (0,0).
@@ -2176,7 +2169,7 @@
         }
         nativeGetStringBounds(mNativePaint, mNativeTypeface, text, start, end, mBidiFlags, bounds);
     }
-    
+
     /**
      * Return in bounds (allocated by the caller) the smallest rectangle that
      * encloses all of the characters, with an implied origin at (0,0).
@@ -2197,7 +2190,7 @@
         nativeGetCharArrayBounds(mNativePaint, mNativeTypeface, text, index, count, mBidiFlags,
             bounds);
     }
-    
+
     @Override
     protected void finalize() throws Throwable {
         try {
@@ -2252,15 +2245,15 @@
 
     private static native float native_getTextRunAdvances(long native_object, long native_typeface,
             char[] text, int index, int count, int contextIndex, int contextCount,
-            int flags, float[] advances, int advancesIndex);
+            boolean isRtl, float[] advances, int advancesIndex);
     private static native float native_getTextRunAdvances(long native_object, long native_typeface,
             String text, int start, int end, int contextStart, int contextEnd,
-            int flags, float[] advances, int advancesIndex);
+            boolean isRtl, float[] advances, int advancesIndex);
 
     private native int native_getTextRunCursor(long native_object, char[] text,
-            int contextStart, int contextLength, int flags, int offset, int cursorOpt);
+            int contextStart, int contextLength, int dir, int offset, int cursorOpt);
     private native int native_getTextRunCursor(long native_object, String text,
-            int contextStart, int contextEnd, int flags, int offset, int cursorOpt);
+            int contextStart, int contextEnd, int dir, int offset, int cursorOpt);
 
     private static native void native_getTextPath(long native_object, long native_typeface,
             int bidiFlags, char[] text, int index, int count, float x, float y, long path);