Modify Canvas drawText to run bidi and shape.

Adds drawTextRun as internal API on Canvas and GraphicsOperations.
Adds implementation to implementors of GraphicsOperations.

Adds state and API on Paint to control the bidi algorithm when used
by Canvas.  This API is currently hidden.

The drawText changes are incomplete since shaping is not yet available
in the native code.

Change-Id: I4368048aef9545df0953a349381771603e04b619
This commit is contained in:
Doug Felt
2010-04-21 16:01:52 -07:00
committed by Kenny Root
parent d937420996
commit f47d7405bb
7 changed files with 481 additions and 102 deletions

View File

@@ -34,6 +34,12 @@ extends CharSequence
float x, float y, Paint p);
/**
* Just like {@link Canvas#drawTextRun}.
*/
void drawTextRun(Canvas c, int start, int end,
float x, float y, int flags, Paint p);
/**
* Just like {@link Paint#measureText}.
*/
float measureText(int start, int end, Paint p);

View File

@@ -17,8 +17,9 @@
package android.text;
import com.android.internal.util.ArrayUtils;
import android.graphics.Paint;
import android.graphics.Canvas;
import android.graphics.Paint;
import java.lang.reflect.Array;
@@ -780,7 +781,7 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
}
if (count == 0) {
return (T[]) ArrayUtils.emptyArray(kind);
return ArrayUtils.emptyArray(kind);
}
if (count == 1) {
ret = (Object[]) Array.newInstance(kind, 1);
@@ -1055,6 +1056,39 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
}
/**
* Don't call this yourself -- exists for Canvas to use internally.
* {@hide}
*/
public void drawTextRun(Canvas c, int start, int end,
float x, float y, int flags, Paint p) {
checkRange("drawTextRun", start, end);
// Assume context requires no more than 8 chars on either side.
// This is ample, only decomposed U+FDFA falls into this
// category, and no one should put a style break within it
// anyway.
int cstart = start - 8;
if (cstart < 0) {
cstart = 0;
}
int cend = end + 8;
int max = length();
if (cend > max) {
cend = max;
}
if (cend <= mGapStart) {
c.drawTextRun(mText, start, end - start, x, y, flags, p);
} else if (cstart >= mGapStart) {
c.drawTextRun(mText, start + mGapLength, end - start, x, y, flags, p);
} else {
char[] buf = TextUtils.obtain(cend - cstart);
getChars(cstart, cend, buf, 0);
c.drawTextRun(buf, start - cstart, end - start, x, y, flags, p);
TextUtils.recycle(buf);
}
}
/**
* Don't call this yourself -- exists for Paint to use internally.
* {@hide}
*/

View File

@@ -951,48 +951,11 @@ class TextLine {
private void drawTextRun(Canvas c, TextPaint wp, int start, int limit,
boolean runIsRtl, float x, int y) {
// Since currently skia only renders text left-to-right, we need to
// put the shaped characters into visual order before rendering.
// Since we might want to re-render the line again, we swap them
// back when we're done. If we left them swapped, measurement
// would be broken since it expects the characters in logical order.
if (runIsRtl) {
swapRun(start, limit);
}
int flags = runIsRtl ? Canvas.DIRECTION_RTL : Canvas.DIRECTION_LTR;
if (mCharsValid) {
c.drawText(mChars, start, limit - start, x, y, wp);
c.drawTextRun(mChars, start, limit - start, x, y, flags, wp);
} else {
c.drawText(mText, mStart + start, mStart + limit, x, y, wp);
}
if (runIsRtl) {
swapRun(start, limit);
}
}
/**
* Reverses the order of characters in the chars array between start and
* limit, used by drawTextRun.
* @param start the start of the run to reverse
* @param limit the limit of the run to reverse
*/
private void swapRun(int start, int limit) {
// First we swap all the characters one for one, then we
// do another pass looking for surrogate pairs and swapping them
// back into their logical order.
char[] chars = mChars;
for (int s = start, e = limit - 1; s < e; ++s, --e) {
char ch = chars[s]; chars[s] = chars[e]; chars[e] = ch;
}
for (int s = start, e = limit - 1; s < e; ++s) {
char c1 = chars[s];
if (c1 >= 0xdc00 && c1 < 0xe000) {
char c2 = chars[s+1];
if (c2 >= 0xd800 && c2 < 0xdc00) {
chars[s++] = c2;
chars[s] = c1;
}
}
c.drawTextRun(mText, mStart + start, mStart + limit, x, y, flags, wp);
}
}

View File

@@ -2781,6 +2781,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
c.drawText(mChars, start + mStart, end - start, x, y, p);
}
public void drawTextRun(Canvas c, int start, int end,
float x, float y, int flags, Paint p) {
c.drawTextRun(mChars, start + mStart, end - start, x, y, flags, p);
}
public float measureText(int start, int end, Paint p) {
return p.measureText(mChars, start + mStart, end - start);
}