Merge "Fix bug #8437358 Clean any ICU related code from TextLayout / Paint and their dependencies" into jb-mr2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
19eceaadd7
@@ -57,13 +57,6 @@ extends CharSequence
|
||||
float getTextRunAdvances(int start, int end, int contextStart, int contextEnd,
|
||||
int flags, float[] advances, int advancesIndex, Paint paint);
|
||||
|
||||
/**
|
||||
* Just like {@link Paint#getTextRunAdvances}.
|
||||
* @hide
|
||||
*/
|
||||
float getTextRunAdvances(int start, int end, int contextStart, int contextEnd,
|
||||
int flags, float[] advances, int advancesIndex, Paint paint, int reserved);
|
||||
|
||||
/**
|
||||
* Just like {@link Paint#getTextRunCursor}.
|
||||
* @hide
|
||||
|
||||
@@ -1225,35 +1225,6 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
float[] advances, int advancesPos, Paint p, int reserved) {
|
||||
|
||||
float ret;
|
||||
|
||||
int contextLen = contextEnd - contextStart;
|
||||
int len = end - start;
|
||||
|
||||
if (end <= mGapStart) {
|
||||
ret = p.getTextRunAdvances(mText, start, len, contextStart, contextLen,
|
||||
flags, advances, advancesPos, reserved);
|
||||
} else if (start >= mGapStart) {
|
||||
ret = p.getTextRunAdvances(mText, start + mGapLength, len,
|
||||
contextStart + mGapLength, contextLen, flags, advances, advancesPos, reserved);
|
||||
} else {
|
||||
char[] buf = TextUtils.obtain(contextLen);
|
||||
getChars(contextStart, contextEnd, buf, 0);
|
||||
ret = p.getTextRunAdvances(buf, start - contextStart, len,
|
||||
0, contextLen, flags, advances, advancesPos, reserved);
|
||||
TextUtils.recycle(buf);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -8881,16 +8881,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
advancesIndex);
|
||||
}
|
||||
|
||||
public float getTextRunAdvances(int start, int end, int contextStart,
|
||||
int contextEnd, int flags, float[] advances, int advancesIndex,
|
||||
Paint p, int reserved) {
|
||||
int count = end - start;
|
||||
int contextCount = contextEnd - contextStart;
|
||||
return p.getTextRunAdvances(mChars, start + mStart, count,
|
||||
contextStart + mStart, contextCount, flags, advances,
|
||||
advancesIndex, reserved);
|
||||
}
|
||||
|
||||
public int getTextRunCursor(int contextStart, int contextEnd, int flags,
|
||||
int offset, int cursorOpt, Paint p) {
|
||||
int contextCount = contextEnd - contextStart;
|
||||
|
||||
@@ -566,61 +566,23 @@ public:
|
||||
return totalAdvance;
|
||||
}
|
||||
|
||||
static jfloat doTextRunAdvancesICU(JNIEnv *env, SkPaint *paint, const jchar *text,
|
||||
jint start, jint count, jint contextCount, jint flags,
|
||||
jfloatArray advances, jint advancesIndex) {
|
||||
NPE_CHECK_RETURN_ZERO(env, paint);
|
||||
NPE_CHECK_RETURN_ZERO(env, text);
|
||||
|
||||
if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) {
|
||||
doThrowAIOOBE(env);
|
||||
return 0;
|
||||
}
|
||||
if (count == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (advances) {
|
||||
size_t advancesLength = env->GetArrayLength(advances);
|
||||
if ((size_t)count > advancesLength) {
|
||||
doThrowAIOOBE(env);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
jfloat advancesArray[count];
|
||||
jfloat totalAdvance = 0;
|
||||
|
||||
TextLayout::getTextRunAdvancesICU(paint, text, start, count, contextCount, flags,
|
||||
advancesArray, totalAdvance);
|
||||
|
||||
if (advances != NULL) {
|
||||
env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray);
|
||||
}
|
||||
return totalAdvance;
|
||||
}
|
||||
|
||||
static float getTextRunAdvances___CIIIII_FII(JNIEnv* env, jobject clazz, SkPaint* paint,
|
||||
static float getTextRunAdvances___CIIIII_FI(JNIEnv* env, jobject clazz, SkPaint* paint,
|
||||
jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
|
||||
jint flags, jfloatArray advances, jint advancesIndex, jint reserved) {
|
||||
jint flags, jfloatArray advances, jint advancesIndex) {
|
||||
jchar* textArray = env->GetCharArrayElements(text, NULL);
|
||||
jfloat result = (reserved == 0) ?
|
||||
doTextRunAdvances(env, paint, textArray + contextIndex, index - contextIndex,
|
||||
count, contextCount, flags, advances, advancesIndex) :
|
||||
doTextRunAdvancesICU(env, paint, textArray + contextIndex, index - contextIndex,
|
||||
count, contextCount, flags, advances, advancesIndex);
|
||||
jfloat result = doTextRunAdvances(env, paint, textArray + contextIndex,
|
||||
index - contextIndex, count, contextCount, flags, advances, advancesIndex);
|
||||
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
|
||||
return result;
|
||||
}
|
||||
|
||||
static float getTextRunAdvances__StringIIIII_FII(JNIEnv* env, jobject clazz, SkPaint* paint,
|
||||
static float getTextRunAdvances__StringIIIII_FI(JNIEnv* env, jobject clazz, SkPaint* paint,
|
||||
jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint flags,
|
||||
jfloatArray advances, jint advancesIndex, jint reserved) {
|
||||
jfloatArray advances, jint advancesIndex) {
|
||||
const jchar* textArray = env->GetStringChars(text, NULL);
|
||||
jfloat result = (reserved == 0) ?
|
||||
doTextRunAdvances(env, paint, textArray + contextStart, start - contextStart,
|
||||
end - start, contextEnd - contextStart, flags, advances, advancesIndex) :
|
||||
doTextRunAdvancesICU(env, paint, textArray + contextStart, start - contextStart,
|
||||
end - start, contextEnd - contextStart, flags, advances, advancesIndex);
|
||||
jfloat result = doTextRunAdvances(env, paint, textArray + contextStart,
|
||||
start - contextStart, end - start, contextEnd - contextStart, flags,
|
||||
advances, advancesIndex);
|
||||
env->ReleaseStringChars(text, textArray);
|
||||
return result;
|
||||
}
|
||||
@@ -886,10 +848,10 @@ static JNINativeMethod methods[] = {
|
||||
{"native_breakText","(Ljava/lang/String;ZF[F)I", (void*) SkPaintGlue::breakTextS},
|
||||
{"native_getTextWidths","(I[CII[F)I", (void*) SkPaintGlue::getTextWidths___CII_F},
|
||||
{"native_getTextWidths","(ILjava/lang/String;II[F)I", (void*) SkPaintGlue::getTextWidths__StringII_F},
|
||||
{"native_getTextRunAdvances","(I[CIIIII[FII)F",
|
||||
(void*) SkPaintGlue::getTextRunAdvances___CIIIII_FII},
|
||||
{"native_getTextRunAdvances","(ILjava/lang/String;IIIII[FII)F",
|
||||
(void*) SkPaintGlue::getTextRunAdvances__StringIIIII_FII},
|
||||
{"native_getTextRunAdvances","(I[CIIIII[FI)F",
|
||||
(void*) SkPaintGlue::getTextRunAdvances___CIIIII_FI},
|
||||
{"native_getTextRunAdvances","(ILjava/lang/String;IIIII[FI)F",
|
||||
(void*) SkPaintGlue::getTextRunAdvances__StringIIIII_FI},
|
||||
|
||||
|
||||
{"native_getTextGlyphs","(ILjava/lang/String;IIIII[C)I",
|
||||
|
||||
@@ -80,14 +80,6 @@ void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint sta
|
||||
}
|
||||
}
|
||||
|
||||
void TextLayout::getTextRunAdvancesICU(SkPaint* paint, const jchar* chars, jint start,
|
||||
jint count, jint contextCount, jint dirFlags,
|
||||
jfloat* resultAdvances, jfloat& resultTotalAdvance) {
|
||||
// Compute advances and return them
|
||||
computeAdvancesWithICU(paint, chars, start, count, contextCount, dirFlags,
|
||||
resultAdvances, &resultTotalAdvance);
|
||||
}
|
||||
|
||||
void TextLayout::getTextPath(SkPaint *paint, const jchar *text, jsize len,
|
||||
jint bidiFlags, jfloat x, jfloat y, SkPath *path) {
|
||||
handleText(paint, text, len, bidiFlags, x, y, path);
|
||||
@@ -111,73 +103,4 @@ void TextLayout::drawTextOnPath(SkPaint* paint, const jchar* text, int count,
|
||||
canvas->drawTextOnPathHV(value->getGlyphs(), value->getGlyphsCount() * 2, *path, h_, v_, *paint);
|
||||
}
|
||||
|
||||
void TextLayout::computeAdvancesWithICU(SkPaint* paint, const UChar* chars,
|
||||
size_t start, size_t count, size_t contextCount, int dirFlags,
|
||||
jfloat* outAdvances, jfloat* outTotalAdvance) {
|
||||
SkAutoSTMalloc<CHAR_BUFFER_SIZE, jchar> tempBuffer(contextCount);
|
||||
jchar* buffer = tempBuffer.get();
|
||||
SkScalar* scalarArray = (SkScalar*)outAdvances;
|
||||
|
||||
// this is where we'd call harfbuzz
|
||||
// for now we just use ushape.c
|
||||
size_t widths;
|
||||
const jchar* text;
|
||||
if (dirFlags & 0x1) { // rtl, call arabic shaping in case
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
// Use fixed length since we need to keep start and count valid
|
||||
u_shapeArabic(chars, contextCount, buffer, contextCount,
|
||||
U_SHAPE_LENGTH_FIXED_SPACES_NEAR |
|
||||
U_SHAPE_TEXT_DIRECTION_LOGICAL | U_SHAPE_LETTERS_SHAPE |
|
||||
U_SHAPE_X_LAMALEF_SUB_ALTERNATE, &status);
|
||||
// we shouldn't fail unless there's an out of memory condition,
|
||||
// in which case we're hosed anyway
|
||||
for (int i = start, e = i + count; i < e; ++i) {
|
||||
if (buffer[i] == UNICODE_NOT_A_CHAR) {
|
||||
buffer[i] = UNICODE_ZWSP; // zero-width-space for skia
|
||||
}
|
||||
}
|
||||
text = buffer + start;
|
||||
widths = paint->getTextWidths(text, count << 1, scalarArray);
|
||||
} else {
|
||||
text = chars + start;
|
||||
widths = paint->getTextWidths(text, count << 1, scalarArray);
|
||||
}
|
||||
|
||||
jfloat totalAdvance = 0;
|
||||
if (widths < count) {
|
||||
#if DEBUG_ADVANCES
|
||||
ALOGD("ICU -- count=%d", widths);
|
||||
#endif
|
||||
// Skia operates on code points, not code units, so surrogate pairs return only
|
||||
// one value. Expand the result so we have one value per UTF-16 code unit.
|
||||
|
||||
// Note, skia's getTextWidth gets confused if it encounters a surrogate pair,
|
||||
// leaving the remaining widths zero. Not nice.
|
||||
for (size_t i = 0, p = 0; i < widths; ++i) {
|
||||
totalAdvance += outAdvances[p++] = SkScalarToFloat(scalarArray[i]);
|
||||
if (p < count &&
|
||||
text[p] >= UNICODE_FIRST_LOW_SURROGATE &&
|
||||
text[p] < UNICODE_FIRST_PRIVATE_USE &&
|
||||
text[p-1] >= UNICODE_FIRST_HIGH_SURROGATE &&
|
||||
text[p-1] < UNICODE_FIRST_LOW_SURROGATE) {
|
||||
outAdvances[p++] = 0;
|
||||
}
|
||||
#if DEBUG_ADVANCES
|
||||
ALOGD("icu-adv = %f - total = %f", outAdvances[i], totalAdvance);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
#if DEBUG_ADVANCES
|
||||
ALOGD("ICU -- count=%d", count);
|
||||
#endif
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
totalAdvance += outAdvances[i] = SkScalarToFloat(scalarArray[i]);
|
||||
#if DEBUG_ADVANCES
|
||||
ALOGD("icu-adv = %f - total = %f", outAdvances[i], totalAdvance);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
*outTotalAdvance = totalAdvance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -66,10 +66,6 @@ public:
|
||||
jint count, jint contextCount, jint dirFlags,
|
||||
jfloat* resultAdvances, jfloat* resultTotalAdvance);
|
||||
|
||||
static void getTextRunAdvancesICU(SkPaint* paint, const jchar* chars, jint start,
|
||||
jint count, jint contextCount, jint dirFlags,
|
||||
jfloat* resultAdvances, jfloat& resultTotalAdvance);
|
||||
|
||||
static void getTextPath(SkPaint* paint, const jchar* text, jsize len,
|
||||
jint bidiFlags, jfloat x, jfloat y, SkPath* path);
|
||||
|
||||
@@ -82,9 +78,5 @@ private:
|
||||
|
||||
static void handleText(SkPaint* paint, const jchar* text, jsize len,
|
||||
int bidiFlags, jfloat x, jfloat y, SkPath* path);
|
||||
|
||||
static void computeAdvancesWithICU(SkPaint* paint, const UChar* chars,
|
||||
size_t start, size_t count, size_t contextCount, int dirFlags,
|
||||
jfloat* outAdvances, jfloat* outTotalAdvance);
|
||||
};
|
||||
} // namespace android
|
||||
|
||||
@@ -1717,20 +1717,6 @@ public class Paint {
|
||||
public float getTextRunAdvances(char[] chars, int index, int count,
|
||||
int contextIndex, int contextCount, int flags, float[] advances,
|
||||
int advancesIndex) {
|
||||
return getTextRunAdvances(chars, index, count, contextIndex, contextCount, flags,
|
||||
advances, advancesIndex, 0 /* use Harfbuzz*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience overload that takes a char array instead of a
|
||||
* String.
|
||||
*
|
||||
* @see #getTextRunAdvances(String, int, int, int, int, int, float[], int, int)
|
||||
* @hide
|
||||
*/
|
||||
public float getTextRunAdvances(char[] chars, int index, int count,
|
||||
int contextIndex, int contextCount, int flags, float[] advances,
|
||||
int advancesIndex, int reserved) {
|
||||
|
||||
if (chars == null) {
|
||||
throw new IllegalArgumentException("text cannot be null");
|
||||
@@ -1752,13 +1738,13 @@ public class Paint {
|
||||
}
|
||||
if (!mHasCompatScaling) {
|
||||
return native_getTextRunAdvances(mNativePaint, chars, index, count,
|
||||
contextIndex, contextCount, flags, advances, advancesIndex, reserved);
|
||||
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, reserved);
|
||||
contextIndex, contextCount, flags, advances, advancesIndex);
|
||||
setTextSize(oldSize);
|
||||
|
||||
if (advances != null) {
|
||||
@@ -1779,20 +1765,6 @@ public class Paint {
|
||||
public float getTextRunAdvances(CharSequence text, int start, int end,
|
||||
int contextStart, int contextEnd, int flags, float[] advances,
|
||||
int advancesIndex) {
|
||||
return getTextRunAdvances(text, start, end, contextStart, contextEnd, flags,
|
||||
advances, advancesIndex, 0 /* use Harfbuzz */);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, int reserved) {
|
||||
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text cannot be null");
|
||||
@@ -1807,12 +1779,12 @@ public class Paint {
|
||||
|
||||
if (text instanceof String) {
|
||||
return getTextRunAdvances((String) text, start, end,
|
||||
contextStart, contextEnd, flags, advances, advancesIndex, reserved);
|
||||
contextStart, contextEnd, flags, advances, advancesIndex);
|
||||
}
|
||||
if (text instanceof SpannedString ||
|
||||
text instanceof SpannableString) {
|
||||
return getTextRunAdvances(text.toString(), start, end,
|
||||
contextStart, contextEnd, flags, advances, advancesIndex, reserved);
|
||||
contextStart, contextEnd, flags, advances, advancesIndex);
|
||||
}
|
||||
if (text instanceof GraphicsOperations) {
|
||||
return ((GraphicsOperations) text).getTextRunAdvances(start, end,
|
||||
@@ -1827,7 +1799,7 @@ public class Paint {
|
||||
char[] buf = TemporaryBuffer.obtain(contextLen);
|
||||
TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
|
||||
float result = getTextRunAdvances(buf, start - contextStart, len,
|
||||
0, contextLen, flags, advances, advancesIndex, reserved);
|
||||
0, contextLen, flags, advances, advancesIndex);
|
||||
TemporaryBuffer.recycle(buf);
|
||||
return result;
|
||||
}
|
||||
@@ -1876,55 +1848,6 @@ public class Paint {
|
||||
*/
|
||||
public float getTextRunAdvances(String text, int start, int end, int contextStart,
|
||||
int contextEnd, int flags, float[] advances, int advancesIndex) {
|
||||
return getTextRunAdvances(text, start, end, contextStart, contextEnd, flags,
|
||||
advances, advancesIndex, 0 /* use Harfbuzz*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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. Cannot be null.
|
||||
* @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
|
||||
* @param reserved int reserved value
|
||||
* @return the total advance
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public float getTextRunAdvances(String text, int start, int end, int contextStart,
|
||||
int contextEnd, int flags, float[] advances, int advancesIndex, int reserved) {
|
||||
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text cannot be null");
|
||||
@@ -1946,13 +1869,13 @@ public class Paint {
|
||||
|
||||
if (!mHasCompatScaling) {
|
||||
return native_getTextRunAdvances(mNativePaint, text, start, end,
|
||||
contextStart, contextEnd, flags, advances, advancesIndex, reserved);
|
||||
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, reserved);
|
||||
contextStart, contextEnd, flags, advances, advancesIndex);
|
||||
setTextSize(oldSize);
|
||||
|
||||
if (advances != null) {
|
||||
@@ -2227,10 +2150,10 @@ public class Paint {
|
||||
|
||||
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, int reserved);
|
||||
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, int reserved);
|
||||
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);
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2011 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/canvas"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<SeekBar android:id="@+id/seekbar"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
/>
|
||||
|
||||
<view class="com.android.bidi.BiDiTestView"
|
||||
android:id="@+id/testview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#FF0000"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -101,7 +101,6 @@ public class BiDiTestActivity extends Activity {
|
||||
|
||||
addItem(result, "Basic", BiDiTestBasic.class, R.id.basic);
|
||||
|
||||
addItem(result, "Canvas", BiDiTestCanvas.class, R.id.canvas);
|
||||
addItem(result, "Canvas2", BiDiTestCanvas2.class, R.id.canvas2);
|
||||
|
||||
addItem(result, "TextView LTR", BiDiTestTextViewLtr.class, R.id.textview_ltr);
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.bidi;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
import static com.android.bidi.BiDiTestConstants.FONT_MAX_SIZE;
|
||||
import static com.android.bidi.BiDiTestConstants.FONT_MIN_SIZE;
|
||||
|
||||
public class BiDiTestCanvas extends Fragment {
|
||||
|
||||
static final int INIT_TEXT_SIZE = (FONT_MAX_SIZE - FONT_MIN_SIZE) / 2;
|
||||
|
||||
private BiDiTestView testView;
|
||||
private SeekBar textSizeSeekBar;
|
||||
private View currentView;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
currentView = inflater.inflate(R.layout.canvas, container, false);
|
||||
return currentView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
testView = (BiDiTestView) currentView.findViewById(R.id.testview);
|
||||
testView.setCurrentTextSize(INIT_TEXT_SIZE);
|
||||
|
||||
textSizeSeekBar = (SeekBar) currentView.findViewById(R.id.seekbar);
|
||||
textSizeSeekBar.setProgress(INIT_TEXT_SIZE);
|
||||
textSizeSeekBar.setMax(FONT_MAX_SIZE - FONT_MIN_SIZE);
|
||||
|
||||
textSizeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
testView.setCurrentTextSize(FONT_MIN_SIZE + progress);
|
||||
}
|
||||
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.bidi;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.text.TextPaint;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
public class BiDiTestView extends View {
|
||||
|
||||
private static final String TAG = "BiDiTestView";
|
||||
|
||||
private static final int BORDER_PADDING = 4;
|
||||
private static final int TEXT_PADDING = 16;
|
||||
private static final int TEXT_SIZE = 16;
|
||||
private static final int ORIGIN = 80;
|
||||
|
||||
private static final float DEFAULT_ITALIC_SKEW_X = -0.25f;
|
||||
|
||||
private Rect rect = new Rect();
|
||||
|
||||
private String NORMAL_TEXT;
|
||||
private String NORMAL_LONG_TEXT;
|
||||
private String NORMAL_LONG_TEXT_2;
|
||||
private String NORMAL_LONG_TEXT_3;
|
||||
private String ITALIC_TEXT;
|
||||
private String BOLD_TEXT;
|
||||
private String BOLD_ITALIC_TEXT;
|
||||
private String ARABIC_TEXT;
|
||||
private String CHINESE_TEXT;
|
||||
private String MIXED_TEXT_1;
|
||||
private String HEBREW_TEXT;
|
||||
private String RTL_TEXT;
|
||||
private String THAI_TEXT;
|
||||
|
||||
private int currentTextSize;
|
||||
|
||||
public BiDiTestView(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public BiDiTestView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public BiDiTestView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
NORMAL_TEXT = context.getString(R.string.normal_text);
|
||||
NORMAL_LONG_TEXT = context.getString(R.string.normal_long_text);
|
||||
NORMAL_LONG_TEXT_2 = context.getString(R.string.normal_long_text_2);
|
||||
NORMAL_LONG_TEXT_3 = context.getString(R.string.normal_long_text_3);
|
||||
ITALIC_TEXT = context.getString(R.string.italic_text);
|
||||
BOLD_TEXT = context.getString(R.string.bold_text);
|
||||
BOLD_ITALIC_TEXT = context.getString(R.string.bold_italic_text);
|
||||
ARABIC_TEXT = context.getString(R.string.arabic_text);
|
||||
CHINESE_TEXT = context.getString(R.string.chinese_text);
|
||||
MIXED_TEXT_1 = context.getString(R.string.mixed_text_1);
|
||||
HEBREW_TEXT = context.getString(R.string.hebrew_text);
|
||||
RTL_TEXT = context.getString(R.string.rtl);
|
||||
THAI_TEXT = context.getString(R.string.pointer_location);
|
||||
}
|
||||
|
||||
public void setCurrentTextSize(int size) {
|
||||
currentTextSize = size;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
drawInsideRect(canvas, new Paint(), Color.BLACK);
|
||||
|
||||
int deltaX = 0;
|
||||
|
||||
deltaX = testString(canvas, NORMAL_TEXT, ORIGIN, ORIGIN,
|
||||
false, false, Paint.DIRECTION_LTR, currentTextSize);
|
||||
|
||||
deltaX += testString(canvas, ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
|
||||
true, false, Paint.DIRECTION_LTR, currentTextSize);
|
||||
|
||||
deltaX += testString(canvas, BOLD_TEXT, ORIGIN + deltaX, ORIGIN,
|
||||
false, true, Paint.DIRECTION_LTR, currentTextSize);
|
||||
|
||||
deltaX += testString(canvas, BOLD_ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
|
||||
true, true, Paint.DIRECTION_LTR, currentTextSize);
|
||||
|
||||
// Test with a long string
|
||||
deltaX = testString(canvas, NORMAL_LONG_TEXT, ORIGIN, ORIGIN + 2 * currentTextSize,
|
||||
false, false, Paint.DIRECTION_LTR, currentTextSize);
|
||||
|
||||
// Test with a long string
|
||||
deltaX = testString(canvas, NORMAL_LONG_TEXT_2, ORIGIN, ORIGIN + 4 * currentTextSize,
|
||||
false, false, Paint.DIRECTION_LTR, currentTextSize);
|
||||
|
||||
// Test with a long string
|
||||
deltaX = testString(canvas, NORMAL_LONG_TEXT_3, ORIGIN, ORIGIN + 6 * currentTextSize,
|
||||
false, false, Paint.DIRECTION_LTR, currentTextSize);
|
||||
|
||||
// Test Arabic ligature
|
||||
deltaX = testString(canvas, ARABIC_TEXT, ORIGIN, ORIGIN + 8 * currentTextSize,
|
||||
false, false, Paint.DIRECTION_RTL, currentTextSize);
|
||||
|
||||
// Test Chinese
|
||||
deltaX = testString(canvas, CHINESE_TEXT, ORIGIN, ORIGIN + 10 * currentTextSize,
|
||||
false, false, Paint.DIRECTION_LTR, currentTextSize);
|
||||
|
||||
// Test Mixed (English and Arabic)
|
||||
deltaX = testString(canvas, MIXED_TEXT_1, ORIGIN, ORIGIN + 12 * currentTextSize,
|
||||
false, false, Paint.DIRECTION_LTR, currentTextSize);
|
||||
|
||||
// Test Hebrew
|
||||
deltaX = testString(canvas, RTL_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
|
||||
false, false, Paint.DIRECTION_RTL, currentTextSize);
|
||||
|
||||
// Test Thai
|
||||
deltaX = testString(canvas, THAI_TEXT, ORIGIN, ORIGIN + 16 * currentTextSize,
|
||||
false, false, Paint.DIRECTION_LTR, currentTextSize);
|
||||
}
|
||||
|
||||
private int testString(Canvas canvas, String text, int x, int y,
|
||||
boolean isItalic, boolean isBold, int dir, int textSize) {
|
||||
|
||||
TextPaint paint = new TextPaint();
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
// Set paint properties
|
||||
boolean oldFakeBold = paint.isFakeBoldText();
|
||||
paint.setFakeBoldText(isBold);
|
||||
|
||||
float oldTextSkewX = paint.getTextSkewX();
|
||||
if (isItalic) {
|
||||
paint.setTextSkewX(DEFAULT_ITALIC_SKEW_X);
|
||||
}
|
||||
|
||||
paint.setTextSize(textSize);
|
||||
paint.setColor(Color.WHITE);
|
||||
canvas.drawText(text, x, y, paint);
|
||||
|
||||
int length = text.length();
|
||||
float[] advances = new float[length];
|
||||
float textWidthHB = paint.getTextRunAdvances(text, 0, length, 0, length, dir, advances, 0);
|
||||
setPaintDir(paint, dir);
|
||||
float textWidthICU = paint.getTextRunAdvances(text, 0, length, 0, length, dir, advances, 0,
|
||||
1 /* use ICU */);
|
||||
|
||||
logAdvances(text, textWidthHB, textWidthICU, advances);
|
||||
drawMetricsAroundText(canvas, x, y, textWidthHB, textWidthICU, textSize, Color.RED, Color.GREEN);
|
||||
|
||||
// Restore old paint properties
|
||||
paint.setFakeBoldText(oldFakeBold);
|
||||
paint.setTextSkewX(oldTextSkewX);
|
||||
|
||||
return (int) Math.ceil(textWidthHB) + TEXT_PADDING;
|
||||
}
|
||||
|
||||
private void setPaintDir(Paint paint, int dir) {
|
||||
Log.v(TAG, "Setting Paint dir=" + dir);
|
||||
paint.setBidiFlags(dir);
|
||||
}
|
||||
|
||||
private void drawInsideRect(Canvas canvas, Paint paint, int color) {
|
||||
paint.setColor(color);
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
rect.set(BORDER_PADDING, BORDER_PADDING, width - BORDER_PADDING, height - BORDER_PADDING);
|
||||
canvas.drawRect(rect, paint);
|
||||
}
|
||||
|
||||
private void drawMetricsAroundText(Canvas canvas, int x, int y, float textWidthHB,
|
||||
float textWidthICU, int textSize, int color, int colorICU) {
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(color);
|
||||
canvas.drawLine(x, y - textSize, x, y + 8, paint);
|
||||
canvas.drawLine(x, y + 8, x + textWidthHB, y + 8, paint);
|
||||
canvas.drawLine(x + textWidthHB, y - textSize, x + textWidthHB, y + 8, paint);
|
||||
paint.setColor(colorICU);
|
||||
canvas.drawLine(x + textWidthICU, y - textSize, x + textWidthICU, y + 8, paint);
|
||||
}
|
||||
|
||||
private void logAdvances(String text, float textWidth, float textWidthICU, float[] advances) {
|
||||
Log.v(TAG, "Advances for text: " + text + " total= " + textWidth + " - totalICU= " + textWidthICU);
|
||||
// int length = advances.length;
|
||||
// for(int n=0; n<length; n++){
|
||||
// Log.v(TAG, "adv[" + n + "]=" + advances[n]);
|
||||
// }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user