summaryrefslogtreecommitdiffstats
path: root/graphics/java/android
diff options
context:
space:
mode:
authorDoug Felt <dougfelt@google.com>2010-05-14 10:55:42 -0700
committerKenny Root <kroot@google.com>2010-06-10 14:03:22 -0700
commit0c702b88c5d0d4380930b920f5be6e66dd95a0d8 (patch)
tree69bce2976a8f21b6a13c6dfd53941326166dbef9 /graphics/java/android
parenta9aaf8ffcecf294c8da9785b5c5e1f055ee4d245 (diff)
downloadframeworks_base-0c702b88c5d0d4380930b920f5be6e66dd95a0d8.zip
frameworks_base-0c702b88c5d0d4380930b920f5be6e66dd95a0d8.tar.gz
frameworks_base-0c702b88c5d0d4380930b920f5be6e66dd95a0d8.tar.bz2
Move shaping to native.
Add internal API (getTextRunAdvances) to Paint, use when measuring. Add internal API (getTextRunCursor) to Paint, use when determining valid cursor positions. Remove java-level shaping code. Remove 'prep' code in TextLine (except for replacement text) since shaping now is done on the fly as needed in native. Provide explicit shaping context bounds to internal text measuring, cursor movement, and rendering APIs. Update for to changes in external API in ushape.h. Change-Id: I146958b624802ce8553125e5c3c6c03031bc9608
Diffstat (limited to 'graphics/java/android')
-rw-r--r--graphics/java/android/graphics/Canvas.java58
-rw-r--r--graphics/java/android/graphics/Paint.java354
2 files changed, 382 insertions, 30 deletions
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index e2634d1..e556350 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1354,18 +1354,22 @@ public class Canvas {
* determined by the Paint's TextAlign value.
*
* @param text the text to render
- * @param index the start of the text to render. Data before this position
- * can be used for shaping context.
- * @param length the length of the text to render. Data at or after this
- * position (start + length) can be used for shaping context.
+ * @param index the start of the text to render
+ * @param count the count of chars to render
+ * @param contextIndex the start of the context for shaping. Must be
+ * no greater than index.
+ * @param contextCount the number of characters in the context for shaping.
+ * ContexIndex + contextCount must be no less than index
+ * + 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 dir the run direction, either {@link #DIRECTION_LTR} or
+ * {@link #DIRECTION_RTL}.
* @param paint the paint
* @hide
*/
- public void drawTextRun(char[] text, int index, int length, float x, float y, int dir,
+ public void drawTextRun(char[] text, int index, int count,
+ int contextIndex, int contextCount, float x, float y, int dir,
Paint paint) {
if (text == null) {
@@ -1374,14 +1378,15 @@ public class Canvas {
if (paint == null) {
throw new NullPointerException("paint is null");
}
- if ((index | length | text.length - index - length) < 0) {
+ 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(mNativeCanvas, text, index, length, x, y, dir, paint.mNativePaint);
+ native_drawTextRun(mNativeCanvas, text, index, count,
+ contextIndex, contextCount, x, y, dir, paint.mNativePaint);
}
/**
@@ -1389,7 +1394,7 @@ public class Canvas {
* 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 start the start of the text to render. Data before this position
* can be used for shaping context.
@@ -1401,8 +1406,9 @@ public class Canvas {
* @param paint the paint
* @hide
*/
- public void drawTextRun(CharSequence text, int start, int end, float x,
- float y, int dir, Paint paint) {
+ public void drawTextRun(CharSequence text, int start, int end,
+ int contextStart, int contextEnd, float x, float y, int dir,
+ Paint paint) {
if (text == null) {
throw new NullPointerException("text is null");
@@ -1418,16 +1424,18 @@ public class Canvas {
if (text instanceof String || text instanceof SpannedString ||
text instanceof SpannableString) {
- native_drawTextRun(mNativeCanvas, text.toString(), start, end, x, y,
- flags, paint.mNativePaint);
+ native_drawTextRun(mNativeCanvas, text.toString(), start, end,
+ contextStart, contextEnd, x, y, flags, paint.mNativePaint);
} else if (text instanceof GraphicsOperations) {
- ((GraphicsOperations) text).drawTextRun(this, start, end, x, y, flags,
- paint);
+ ((GraphicsOperations) text).drawTextRun(this, start, end,
+ contextStart, contextEnd, x, y, flags, paint);
} else {
- char[] buf = TemporaryBuffer.obtain(end - start);
- TextUtils.getChars(text, start, end, buf, 0);
- native_drawTextRun(mNativeCanvas, buf, 0, end - start, x, y,
- flags, paint.mNativePaint);
+ int contextLen = contextEnd - contextStart;
+ int len = end - start;
+ char[] buf = TemporaryBuffer.obtain(contextLen);
+ TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
+ native_drawTextRun(mNativeCanvas, buf, start - contextStart, len,
+ 0, contextLen, x, y, flags, paint.mNativePaint);
TemporaryBuffer.recycle(buf);
}
}
@@ -1679,11 +1687,13 @@ public class Canvas {
int start, int end, float x,
float y, int flags, int paint);
- private static native void native_drawTextRun(int nativeCanvas, String
- text, int start, int end, float x, float y, int flags, int paint);
+ private static native void native_drawTextRun(int nativeCanvas, String text,
+ int start, int end, int contextStart, int contextEnd,
+ float x, float y, int flags, int paint);
- private static native void native_drawTextRun(int nativeCanvas, char[]
- text, int start, int len, float x, float y, int flags, int paint);
+ private static native void native_drawTextRun(int nativeCanvas, char[] text,
+ int start, int count, int contextStart, int contextCount,
+ float x, float y, int flags, int paint);
private static native void native_drawPosText(int nativeCanvas,
char[] text, int index,
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index b564929..862a2ec 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -125,13 +125,65 @@ public class Paint {
* @hide
*/
private static final int BIDI_MAX_FLAG_VALUE = BIDI_FORCE_RTL;
-
+
/**
* Mask for bidi flags.
* @hide
*/
private static final int BIDI_FLAG_MASK = 0x7;
-
+
+ /**
+ * Flag for getTextRunAdvances indicating left-to-right run direction.
+ * @hide
+ */
+ public static final int DIRECTION_LTR = 0;
+
+ /**
+ * Flag for getTextRunAdvances indicating right-to-left run direction.
+ * @hide
+ */
+ public static final int DIRECTION_RTL = 1;
+
+ /**
+ * Option for getTextRunCursor to compute the valid cursor after
+ * offset or the limit of the context, whichever is less.
+ * @hide
+ */
+ public static final int CURSOR_AFTER = 0;
+
+ /**
+ * Option for getTextRunCursor to compute the valid cursor at or after
+ * the offset or the limit of the context, whichever is less.
+ * @hide
+ */
+ public static final int CURSOR_AT_OR_AFTER = 1;
+
+ /**
+ * Option for getTextRunCursor to compute the valid cursor before
+ * offset or the start of the context, whichever is greater.
+ * @hide
+ */
+ public static final int CURSOR_BEFORE = 2;
+
+ /**
+ * Option for getTextRunCursor to compute the valid cursor at or before
+ * offset or the start of the context, whichever is greater.
+ * @hide
+ */
+ public static final int CURSOR_AT_OR_BEFORE = 3;
+
+ /**
+ * Option for getTextRunCursor to return offset if the cursor at offset
+ * is valid, or -1 if it isn't.
+ * @hide
+ */
+ public static final int CURSOR_AT = 4;
+
+ /**
+ * Maximum cursor option value.
+ */
+ private static final int CURSOR_OPT_MAX_VALUE = CURSOR_AT;
+
/**
* The Style specifies if the primitive being drawn is filled, stroked, or
* both (in the same color). The default is FILL.
@@ -1317,10 +1369,10 @@ public class Paint {
}
char[] buf = TemporaryBuffer.obtain(end - start);
- TextUtils.getChars(text, start, end, buf, 0);
- int result = getTextWidths(buf, 0, end - start, widths);
+ TextUtils.getChars(text, start, end, buf, 0);
+ int result = getTextWidths(buf, 0, end - start, widths);
TemporaryBuffer.recycle(buf);
- return result;
+ return result;
}
/**
@@ -1367,6 +1419,284 @@ public class Paint {
}
/**
+ * Convenience overload that takes a char array instead of a
+ * String.
+ *
+ * @see #getTextRunAdvances(String, int, int, int, int, int, float[], int)
+ * @hide
+ */
+ public float getTextRunAdvances(char[] chars, int index, int count,
+ int contextIndex, int contextCount, int flags, float[] advances,
+ int advancesIndex) {
+
+ if ((index | count | contextIndex | contextCount | advancesIndex
+ | (index - contextIndex)
+ | ((contextIndex + contextCount) - (index + count))
+ | (chars.length - (contextIndex + contextCount))
+ | (advances == null ? 0 :
+ (advances.length - (advancesIndex + count)))) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (flags != DIRECTION_LTR && flags != DIRECTION_RTL) {
+ throw new IllegalArgumentException("unknown flags value: " + flags);
+ }
+
+ if (!mHasCompatScaling) {
+ return native_getTextRunAdvances(mNativePaint, chars, index, count,
+ contextIndex, contextCount, flags, advances, advancesIndex);
+ }
+
+ final float oldSize = getTextSize();
+ setTextSize(oldSize * mCompatScaling);
+ float res = native_getTextRunAdvances(mNativePaint, chars, index, count,
+ contextIndex, contextCount, flags, advances, advancesIndex);
+ setTextSize(oldSize);
+
+ if (advances != null) {
+ for (int i = advancesIndex, e = i + count; i < e; i++) {
+ advances[i] *= mInvCompatScaling;
+ }
+ }
+ return res * mInvCompatScaling; // assume errors are not significant
+ }
+
+ /**
+ * Convenience overload that takes a CharSequence instead of a
+ * String.
+ *
+ * @see #getTextRunAdvances(String, int, int, int, int, int, float[], int)
+ * @hide
+ */
+ public float getTextRunAdvances(CharSequence text, int start, int end,
+ int contextStart, int contextEnd, int flags, float[] advances,
+ int advancesIndex) {
+
+ if (text instanceof String) {
+ return getTextRunAdvances((String) text, start, end,
+ contextStart, contextEnd, flags, advances, advancesIndex);
+ }
+ if (text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ return getTextRunAdvances(text.toString(), start, end,
+ contextStart, contextEnd, flags, advances, advancesIndex);
+ }
+ if (text instanceof GraphicsOperations) {
+ return ((GraphicsOperations) text).getTextRunAdvances(start, end,
+ contextStart, contextEnd, flags, advances, advancesIndex, this);
+ }
+
+ int contextLen = contextEnd - contextStart;
+ int len = end - start;
+ char[] buf = TemporaryBuffer.obtain(contextLen);
+ TextUtils.getChars(text, start, end, buf, 0);
+ float result = getTextRunAdvances(buf, start - contextStart, len,
+ 0, contextLen, flags, advances, advancesIndex);
+ TemporaryBuffer.recycle(buf);
+ return result;
+ }
+
+ /**
+ * Returns the total advance width for the characters in the run
+ * between start and end, and if advances is not null, the advance
+ * assigned to each of these characters (java chars).
+ *
+ * <p>The trailing surrogate in a valid surrogate pair is assigned
+ * an advance of 0. Thus the number of returned advances is
+ * always equal to count, not to the number of unicode codepoints
+ * represented by the run.
+ *
+ * <p>In the case of conjuncts or combining marks, the total
+ * advance is assigned to the first logical character, and the
+ * following characters are assigned an advance of 0.
+ *
+ * <p>This generates the sum of the advances of glyphs for
+ * characters in a reordered cluster as the width of the first
+ * logical character in the cluster, and 0 for the widths of all
+ * other characters in the cluster. In effect, such clusters are
+ * treated like conjuncts.
+ *
+ * <p>The shaping bounds limit the amount of context available
+ * outside start and end that can be used for shaping analysis.
+ * These bounds typically reflect changes in bidi level or font
+ * metrics across which shaping does not occur.
+ *
+ * @param text the text to measure
+ * @param start the index of the first character to measure
+ * @param end the index past the last character to measure
+ * @param contextStart the index of the first character to use for shaping context,
+ * 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 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
+ * advance corresponding to the character at start
+ * @return the total advance
+ *
+ * @hide
+ */
+ public float getTextRunAdvances(String text, int start, int end, int contextStart,
+ int contextEnd, int flags, float[] advances, int advancesIndex) {
+
+ if ((start | end | contextStart | contextEnd | advancesIndex | (end - start)
+ | (start - contextStart) | (contextEnd - end)
+ | (text.length() - contextEnd)
+ | (advances == null ? 0 :
+ (advances.length - advancesIndex - (end - start)))) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (flags != DIRECTION_LTR && flags != DIRECTION_RTL) {
+ throw new IllegalArgumentException("unknown flags value: " + flags);
+ }
+
+ if (!mHasCompatScaling) {
+ return native_getTextRunAdvances(mNativePaint, text, start, end,
+ contextStart, contextEnd, flags, advances, advancesIndex);
+ }
+
+ final float oldSize = getTextSize();
+ setTextSize(oldSize * mCompatScaling);
+ float totalAdvance = native_getTextRunAdvances(mNativePaint, text, start, end,
+ contextStart, contextEnd, flags, advances, advancesIndex);
+ setTextSize(oldSize);
+
+ if (advances != null) {
+ for (int i = advancesIndex, e = i + (end - start); i < e; i++) {
+ advances[i] *= mInvCompatScaling;
+ }
+ }
+ return totalAdvance * mInvCompatScaling; // assume errors are insignificant
+ }
+
+ /**
+ * Returns the next cursor position in the run. This avoids placing the
+ * cursor between surrogates, between characters that form conjuncts,
+ * between base characters and combining marks, or within a reordering
+ * cluster.
+ *
+ * <p>ContextStart and offset are relative to the start of text.
+ * The context is the shaping context for cursor movement, generally
+ * the bounds of the metric span enclosing the cursor in the direction of
+ * movement.
+ *
+ * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
+ * cursor position, this returns -1. Otherwise this will never return a
+ * value before contextStart or after contextStart + contextLength.
+ *
+ * @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 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},
+ * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
+ * @return the offset of the next position, or -1
+ * @hide
+ */
+ public int getTextRunCursor(char[] text, int contextStart, int contextLength,
+ int flags, int offset, int cursorOpt) {
+ int contextEnd = contextStart + contextLength;
+ if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
+ | (offset - contextStart) | (contextEnd - offset)
+ | (text.length - contextEnd) | cursorOpt) < 0)
+ || cursorOpt > CURSOR_OPT_MAX_VALUE) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ return native_getTextRunCursor(mNativePaint, text,
+ contextStart, contextLength, flags, offset, cursorOpt);
+ }
+
+ /**
+ * Returns the next cursor position in the run. This avoids placing the
+ * cursor between surrogates, between characters that form conjuncts,
+ * between base characters and combining marks, or within a reordering
+ * cluster.
+ *
+ * <p>ContextStart, contextEnd, and offset are relative to the start of
+ * text. The context is the shaping context for cursor movement, generally
+ * the bounds of the metric span enclosing the cursor in the direction of
+ * movement.
+ *
+ * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
+ * cursor position, this returns -1. Otherwise this will never return a
+ * value before contextStart or after contextEnd.
+ *
+ * @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 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},
+ * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
+ * @return the offset of the next position, or -1
+ * @hide
+ */
+ public int getTextRunCursor(CharSequence text, int contextStart,
+ int contextEnd, int flags, int offset, int cursorOpt) {
+
+ if (text instanceof String || text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ return getTextRunCursor(text.toString(), contextStart, contextEnd,
+ flags, offset, cursorOpt);
+ }
+ if (text instanceof GraphicsOperations) {
+ return ((GraphicsOperations) text).getTextRunCursor(
+ contextStart, contextEnd, flags, 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, cursorOpt);
+ TemporaryBuffer.recycle(buf);
+ return result;
+ }
+
+ /**
+ * Returns the next cursor position in the run. This avoids placing the
+ * cursor between surrogates, between characters that form conjuncts,
+ * between base characters and combining marks, or within a reordering
+ * cluster.
+ *
+ * <p>ContextStart, contextEnd, and offset are relative to the start of
+ * text. The context is the shaping context for cursor movement, generally
+ * the bounds of the metric span enclosing the cursor in the direction of
+ * movement.
+ *
+ * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
+ * cursor position, this returns -1. Otherwise this will never return a
+ * value before contextStart or after contextEnd.
+ *
+ * @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 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},
+ * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
+ * @return the offset of the next position, or -1
+ * @hide
+ */
+ public int getTextRunCursor(String text, int contextStart, int contextEnd,
+ int flags, int offset, int cursorOpt) {
+ if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
+ | (offset - contextStart) | (contextEnd - offset)
+ | (text.length() - contextEnd) | cursorOpt) < 0)
+ || cursorOpt > CURSOR_OPT_MAX_VALUE) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ return native_getTextRunCursor(mNativePaint, text,
+ contextStart, contextEnd, flags, offset, cursorOpt);
+ }
+
+ /**
* Return the path (outline) for the specified text.
* Note: just like Canvas.drawText, this will respect the Align setting in
* the paint.
@@ -1489,6 +1819,19 @@ public class Paint {
char[] text, int index, int count, float[] widths);
private static native int native_getTextWidths(int native_object,
String text, int start, int end, float[] widths);
+
+ private static native float native_getTextRunAdvances(int native_object,
+ char[] text, int index, int count, int contextIndex, int contextCount,
+ int flags, float[] advances, int advancesIndex);
+ private static native float native_getTextRunAdvances(int native_object,
+ String text, int start, int end, int contextStart, int contextEnd,
+ int flags, float[] advances, int advancesIndex);
+
+ private native int native_getTextRunCursor(int native_object, char[] text,
+ int contextStart, int contextLength, int flags, int offset, int cursorOpt);
+ private native int native_getTextRunCursor(int native_object, String text,
+ int contextStart, int contextEnd, int flags, int offset, int cursorOpt);
+
private static native void native_getTextPath(int native_object,
char[] text, int index, int count, float x, float y, int path);
private static native void native_getTextPath(int native_object,
@@ -1499,4 +1842,3 @@ public class Paint {
char[] text, int index, int count, Rect bounds);
private static native void finalizer(int nativePaint);
}
-