summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDeepanshu Gupta <deepanshu@google.com>2014-06-25 17:47:16 -0700
committerDeepanshu Gupta <deepanshu@google.com>2014-07-01 12:23:59 -0700
commit84d1d431cfe3e66029380fa038f8816b06da120a (patch)
tree493379fed92ca918e8a5f6c1423585279b1bbfcf /tools
parent509d860907691a8eb7ff4c8b949fbee36db70fea (diff)
downloadframeworks_base-84d1d431cfe3e66029380fa038f8816b06da120a.zip
frameworks_base-84d1d431cfe3e66029380fa038f8816b06da120a.tar.gz
frameworks_base-84d1d431cfe3e66029380fa038f8816b06da120a.tar.bz2
Update text rendering delegates.
The flags for RTL and LTR are simplified in commit 0a1d91862a3822dcbbb412bcd6d69b0f5f079f8b. This change follows up the same in LayoutLib. This also fixes the following bug which incorrectly computed runs with 'en-dash' (\u20132) as RTL. Bug: http://b.android.com/69432 Change-Id: Iaed62d13ce31f107773576ed2ef412be6037cd04
Diffstat (limited to 'tools')
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java69
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java87
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java76
-rw-r--r--tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java11
4 files changed, 154 insertions, 89 deletions
diff --git a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
index 33813d1..88ebd1f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
@@ -28,6 +28,8 @@ import java.util.List;
import com.ibm.icu.lang.UScript;
import com.ibm.icu.lang.UScriptRun;
+import com.ibm.icu.text.Bidi;
+import com.ibm.icu.text.BidiRun;
import android.graphics.Paint_Delegate.FontInfo;
@@ -38,7 +40,7 @@ import android.graphics.Paint_Delegate.FontInfo;
@SuppressWarnings("deprecation")
public class BidiRenderer {
- /*package*/ static class ScriptRun {
+ private static class ScriptRun {
int start;
int limit;
boolean isRtl;
@@ -66,7 +68,7 @@ public class BidiRenderer {
* @param paint The Paint to use to get the fonts. Should not be null.
* @param text Unidirectional text. Should not be null.
*/
- /*package*/ BidiRenderer(Graphics2D graphics, Paint_Delegate paint, char[] text) {
+ public BidiRenderer(Graphics2D graphics, Paint_Delegate paint, char[] text) {
assert (paint != null);
mGraphics = graphics;
mPaint = paint;
@@ -75,13 +77,45 @@ public class BidiRenderer {
for (FontInfo fontInfo : paint.getFonts()) {
mFonts.add(fontInfo.mFont);
}
+ mBounds = new RectF();
}
/**
- * Render unidirectional text.
*
- * This method can also be used to measure the width of the text without actually drawing it.
+ * @param x The x-coordinate of the left edge of where the text should be drawn on the given
+ * graphics.
+ * @param y The y-coordinate at which to draw the text on the given mGraphics.
*
+ */
+ public BidiRenderer setRenderLocation(float x, float y) {
+ mBounds = new RectF(x, y, x, y);
+ mBaseline = y;
+ return this;
+ }
+
+ /**
+ * Perform Bidi Analysis on the text and then render it.
+ * <p/>
+ * To skip the analysis and render unidirectional text, see {@link
+ * #renderText(int, int, boolean, float[], int, boolean)}
+ */
+ public RectF renderText(int start, int limit, int bidiFlags, float[] advances,
+ int advancesIndex, boolean draw) {
+ Bidi bidi = new Bidi(mText, start, null, 0, limit - start, getIcuFlags(bidiFlags));
+ for (int i = 0; i < bidi.countRuns(); i++) {
+ BidiRun visualRun = bidi.getVisualRun(i);
+ boolean isRtl = visualRun.getDirection() == Bidi.RTL;
+ renderText(visualRun.getStart(), visualRun.getLimit(), isRtl, advances,
+ advancesIndex, draw);
+ }
+ return mBounds;
+ }
+
+ /**
+ * Render unidirectional text.
+ * <p/>
+ * This method can also be used to measure the width of the text without actually drawing it.
+ * <p/>
* @param start index of the first character
* @param limit index of the first character that should not be rendered.
* @param isRtl is the text right-to-left
@@ -90,17 +124,12 @@ public class BidiRenderer {
* @param advancesIndex index into advances from where the advances need to be filled.
* @param draw If true and {@code graphics} is not null, draw the rendered text on the graphics
* at the given co-ordinates
- * @param x The x-coordinate of the left edge of where the text should be drawn on the given
- * graphics.
- * @param y The y-coordinate at which to draw the text on the given mGraphics.
* @return A rectangle specifying the bounds of the text drawn.
*/
- /* package */ RectF renderText(int start, int limit, boolean isRtl, float[] advances,
- int advancesIndex, boolean draw, float x, float y) {
+ public RectF renderText(int start, int limit, boolean isRtl, float[] advances,
+ int advancesIndex, boolean draw) {
// We break the text into scripts and then select font based on it and then render each of
// the script runs.
- mBounds = new RectF(x, y, x, y);
- mBaseline = y;
for (ScriptRun run : getScriptRuns(mText, start, limit, isRtl, mFonts)) {
int flag = Font.LAYOUT_NO_LIMIT_CONTEXT | Font.LAYOUT_NO_START_CONTEXT;
flag |= isRtl ? Font.LAYOUT_RIGHT_TO_LEFT : Font.LAYOUT_LEFT_TO_RIGHT;
@@ -244,4 +273,22 @@ public class BidiRenderer {
}
run.font = fonts.get(0);
}
+
+ private static int getIcuFlags(int bidiFlag) {
+ switch (bidiFlag) {
+ case Paint.BIDI_LTR:
+ case Paint.BIDI_FORCE_LTR:
+ return Bidi.DIRECTION_LEFT_TO_RIGHT;
+ case Paint.BIDI_RTL:
+ case Paint.BIDI_FORCE_RTL:
+ return Bidi.DIRECTION_RIGHT_TO_LEFT;
+ case Paint.BIDI_DEFAULT_LTR:
+ return Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
+ case Paint.BIDI_DEFAULT_RTL:
+ return Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT;
+ default:
+ assert false;
+ return Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
+ }
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 12e4a85..7c8ef70 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -906,41 +906,10 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_drawText(long nativeCanvas,
- final char[] text, final int index, final int count,
- final float startX, final float startY, final int flags, long paint,
- final long typeface) {
-
- draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
- new GcSnapshot.Drawable() {
- @Override
- public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
- // WARNING: the logic in this method is similar to Paint_Delegate.measureText.
- // Any change to this method should be reflected in Paint.measureText
-
- // assert that the typeface passed is actually the one stored in paint.
- assert (typeface == paintDelegate.mNativeTypeface);
-
-
- // Paint.TextAlign indicates how the text is positioned relative to X.
- // LEFT is the default and there's nothing to do.
- float x = startX;
- int limit = index + count;
- boolean isRtl = flags == Canvas.DIRECTION_RTL;
- if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
- RectF bounds = paintDelegate.measureText(text, index, count, isRtl);
- float m = bounds.right - bounds.left;
- if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
- x -= m / 2;
- } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
- x -= m;
- }
- }
-
- new BidiRenderer(graphics, paintDelegate, text).renderText(
- index, limit, isRtl, null, 0, true, x, startY);
- }
- });
+ /*package*/ static void native_drawText(long nativeCanvas, char[] text, int index, int count,
+ float startX, float startY, int flags, long paint, long typeface) {
+ drawText(nativeCanvas, text, index, count, startX, startY, flags == Canvas.DIRECTION_RTL,
+ paint, typeface);
}
@LayoutlibDelegate
@@ -957,19 +926,19 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static void native_drawTextRun(long nativeCanvas, String text,
int start, int end, int contextStart, int contextEnd,
- float x, float y, int flags, long paint, long typeface) {
+ float x, float y, boolean isRtl, long paint, long typeface) {
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
- native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface);
+ drawText(nativeCanvas, buffer, 0, count, x, y, isRtl, paint, typeface);
}
@LayoutlibDelegate
/*package*/ static void native_drawTextRun(long nativeCanvas, char[] text,
int start, int count, int contextStart, int contextCount,
- float x, float y, int flags, long paint, long typeface) {
- native_drawText(nativeCanvas, text, start, count, x, y, flags, paint, typeface);
+ float x, float y, boolean isRtl, long paint, long typeface) {
+ drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
}
@LayoutlibDelegate
@@ -978,7 +947,7 @@ public final class Canvas_Delegate {
int count, long path,
float hOffset,
float vOffset, int bidiFlags,
- long paint) {
+ long paint, long typeface) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawTextOnPath is not supported.", null, null /*data*/);
@@ -989,7 +958,8 @@ public final class Canvas_Delegate {
String text, long path,
float hOffset,
float vOffset,
- int bidiFlags, long paint, long typeface) {
+ int bidiFlags, long paint,
+ long typeface) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawTextOnPath is not supported.", null, null /*data*/);
@@ -1047,6 +1017,41 @@ public final class Canvas_Delegate {
canvasDelegate.mSnapshot.draw(drawable);
}
+ private static void drawText(long nativeCanvas, final char[] text, final int index,
+ final int count, final float startX, final float startY, final boolean isRtl,
+ long paint, final long typeface) {
+
+ draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
+ new GcSnapshot.Drawable() {
+ @Override
+ public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
+ // WARNING: the logic in this method is similar to Paint_Delegate.measureText.
+ // Any change to this method should be reflected in Paint.measureText
+
+ // assert that the typeface passed is actually the one stored in paint.
+ assert (typeface == paintDelegate.mNativeTypeface);
+
+ // Paint.TextAlign indicates how the text is positioned relative to X.
+ // LEFT is the default and there's nothing to do.
+ float x = startX;
+ int limit = index + count;
+ if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
+ RectF bounds = paintDelegate.measureText(text, index, count, null, 0,
+ isRtl);
+ float m = bounds.right - bounds.left;
+ if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
+ x -= m / 2;
+ } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
+ x -= m;
+ }
+ }
+
+ new BidiRenderer(graphics, paintDelegate, text).setRenderLocation(x, startY)
+ .renderText(index, limit, isRtl, null, 0, true);
+ }
+ });
+ }
+
private Canvas_Delegate(Bitmap_Delegate bitmap) {
mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap);
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 5adf4ca..24ef189 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -602,7 +602,7 @@ public class Paint_Delegate {
return 0;
}
- RectF bounds = delegate.measureText(text, index, count, isRtl(bidiFlags));
+ RectF bounds = delegate.measureText(text, index, count, null, 0, bidiFlags);
return bounds.right - bounds.left;
}
@@ -618,11 +618,11 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
- /*package*/ static int native_breakText(Paint thisPaint, char[] text, int index, int count,
- float maxWidth, int bidiFlags, float[] measuredWidth) {
+ /*package*/ static int native_breakText(long nativePaint, long nativeTypeface, char[] text,
+ int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth) {
// get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@@ -641,7 +641,7 @@ public class Paint_Delegate {
}
// measure from start to end
- RectF bounds = delegate.measureText(text, start, end - start + 1, isRtl(bidiFlags));
+ RectF bounds = delegate.measureText(text, start, end - start + 1, null, 0, bidiFlags);
float res = bounds.right - bounds.left;
if (measuredWidth != null) {
@@ -660,10 +660,11 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
- /*package*/ static int native_breakText(Paint thisPaint, String text, boolean measureForwards,
+ /*package*/ static int native_breakText(long nativePaint, long nativeTypeface, String text,
+ boolean measureForwards,
float maxWidth, int bidiFlags, float[] measuredWidth) {
- return native_breakText(thisPaint, text.toCharArray(), 0, text.length(), maxWidth,
- bidiFlags, measuredWidth);
+ return native_breakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(),
+ maxWidth, bidiFlags, measuredWidth);
}
@LayoutlibDelegate
@@ -950,8 +951,25 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static int native_getTextWidths(long native_object, long native_typeface,
char[] text, int index, int count, int bidiFlags, float[] widths) {
- return (int) native_getTextRunAdvances(native_object, native_typeface, text, index, count,
- index, count, bidiFlags, widths, 0);
+
+ if (widths != null) {
+ for (int i = 0; i< count; i++) {
+ widths[i]=0;
+ }
+ }
+ // get the delegate from the native int.
+ Paint_Delegate delegate = sManager.getDelegate(native_object);
+ if (delegate == null) {
+ return 0;
+ }
+
+ // native_typeface is passed here since Framework's old implementation did not have the
+ // typeface object associated with the Paint. Since, we follow the new framework way,
+ // we store the typeface with the paint and use it directly.
+ assert (native_typeface == delegate.mNativeTypeface);
+
+ RectF bounds = delegate.measureText(text, index, count, widths, 0, bidiFlags);
+ return ((int) (bounds.right - bounds.left));
}
@LayoutlibDelegate
@@ -971,7 +989,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static 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) {
if (advances != null)
for (int i = advancesIndex; i< advancesIndex+count; i++)
@@ -987,25 +1005,21 @@ public class Paint_Delegate {
// we store the typeface with the paint and use it directly.
assert (native_typeface == delegate.mNativeTypeface);
- boolean isRtl = isRtl(flags);
-
- int limit = index + count;
- RectF bounds = new BidiRenderer(null, delegate, text).renderText(
- index, limit, isRtl, advances, advancesIndex, false, 0, 0);
+ RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, isRtl);
return bounds.right - bounds.left;
}
@LayoutlibDelegate
/*package*/ static 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) {
// FIXME: support contextStart and contextEnd
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
return native_getTextRunAdvances(native_object, native_typeface, buffer, 0, count,
- contextStart, contextEnd - contextStart, flags, advances, advancesIndex);
+ contextStart, contextEnd - contextStart, isRtl, advances, advancesIndex);
}
@LayoutlibDelegate
@@ -1062,7 +1076,7 @@ public class Paint_Delegate {
// assert that the typeface passed is actually the one that we had stored.
assert (native_typeface == delegate.mNativeTypeface);
- delegate.measureText(text, index, count, isRtl(bidiFlags)).roundOut(bounds);
+ delegate.measureText(text, index, count, null, 0, bidiFlags).roundOut(bounds);
}
@LayoutlibDelegate
@@ -1158,9 +1172,16 @@ public class Paint_Delegate {
}
}
- /*package*/ RectF measureText(char[] text, int index, int count, boolean isRtl) {
- return new BidiRenderer(null, this, text).renderText(
- index, index + count, isRtl, null, 0, false, 0, 0);
+ /*package*/ RectF measureText(char[] text, int index, int count, float[] advances,
+ int advancesIndex, int bidiFlags) {
+ return new BidiRenderer(null, this, text)
+ .renderText(index, index + count, bidiFlags, advances, advancesIndex, false);
+ }
+
+ /*package*/ RectF measureText(char[] text, int index, int count, float[] advances,
+ int advancesIndex, boolean isRtl) {
+ return new BidiRenderer(null, this, text)
+ .renderText(index, index + count, isRtl, advances, advancesIndex, false);
}
private float getFontMetrics(FontMetrics metrics) {
@@ -1198,15 +1219,4 @@ public class Paint_Delegate {
delegate.mFlags &= ~flagMask;
}
}
-
- private static boolean isRtl(int flag) {
- switch(flag) {
- case Paint.BIDI_RTL:
- case Paint.BIDI_FORCE_RTL:
- case Paint.BIDI_DEFAULT_RTL:
- return true;
- default:
- return false;
- }
- }
}
diff --git a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
index 973fa0e..6247dae 100644
--- a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
@@ -37,14 +37,17 @@ public class AndroidBidi_Delegate {
switch (dir) {
case 0: // Layout.DIR_REQUEST_LTR
+ dir = Bidi.LTR;
+ break;
case 1: // Layout.DIR_REQUEST_RTL
- break; // No change.
- case -1:
- dir = Bidi.LEVEL_DEFAULT_LTR;
+ dir = Bidi.RTL;
break;
- case -2:
+ case -1: // Layout.DIR_REQUEST_DEFAULT_RTL
dir = Bidi.LEVEL_DEFAULT_RTL;
break;
+ case -2: // Layout.DIR_REQUEST_DEFAULT_LTR
+ dir = Bidi.LEVEL_DEFAULT_LTR;
+ break;
default:
// Invalid code. Log error, assume LEVEL_DEFAULT_LTR and continue.
Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Invalid direction flag", null);