summaryrefslogtreecommitdiffstats
path: root/tools/layoutlib
diff options
context:
space:
mode:
Diffstat (limited to 'tools/layoutlib')
-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);