From fcf2be1846935e7983ea2fe87fdd4d7af27764b6 Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Tue, 5 Apr 2011 17:02:36 -0700 Subject: [PATCH] TextLayoutCache - add glyphs caching - cache glyphs after Harfbuzz shaping - use "m" prefix for member variables - add temporary API for drawing text with glyphs - update BiDiTest app Change-Id: I619b3f313b15f010018daad21b3e5e486619b4e4 --- core/jni/android/graphics/Canvas.cpp | 69 +++++++++++- core/jni/android/graphics/RtlProperties.h | 2 + core/jni/android/graphics/TextLayout.cpp | 20 ++-- core/jni/android/graphics/TextLayout.h | 12 +- core/jni/android/graphics/TextLayoutCache.cpp | 105 +++++++++--------- core/jni/android/graphics/TextLayoutCache.h | 80 ++++++++----- graphics/java/android/graphics/Canvas.java | 95 ++++++++++++---- .../src/com/android/bidi/BiDiTestView.java | 15 ++- 8 files changed, 273 insertions(+), 125 deletions(-) diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index b4ad9e9c18def..b2caa98a98cf0 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -27,6 +27,7 @@ #include "SkTemplates.h" #include "TextLayout.h" +#include "TextLayoutCache.h" #include "unicode/ubidi.h" #include "unicode/ushape.h" @@ -755,11 +756,57 @@ public: env->ReleaseStringChars(text, textArray); } - static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, - jcharArray glyphs, int index, int count, - jfloat x, jfloat y, int flags, SkPaint* paint) { - jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); + static void drawTextWithGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, + jcharArray text, int index, int count, + jfloat x, jfloat y, int flags, SkPaint* paint) { + jchar* textArray = env->GetCharArrayElements(text, NULL); +#if RTL_USE_HARFBUZZ && USE_TEXT_LAYOUT_CACHE + sp value = gTextLayoutCache.getValue( + paint, textArray + index, 0, count, count, flags); + if (value != NULL) { +#if DEBUG_GLYPHS + LOGD("drawTextWithGlyphs -- got glyphs - count=%d", value->getGlyphsCount()); + for (size_t i = 0; i < value->getGlyphsCount(); i++) { + LOGD(" glyphs[%d]=%d", i, value->getGlyphs()[i]); + } +#endif + doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), + x, y, flags, paint); + } +#else + TextLayout::drawText(paint, textArray + index, count, flags, x, y, canvas); +#endif + env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); + } + static void drawTextWithGlyphs__StringIIFFIPaint(JNIEnv* env, jobject, + SkCanvas* canvas, jstring text, + int start, int end, + jfloat x, jfloat y, int flags, SkPaint* paint) { + + const jchar* textArray = env->GetStringChars(text, NULL); +#if RTL_USE_HARFBUZZ && USE_TEXT_LAYOUT_CACHE + size_t count = end - start; + sp value = gTextLayoutCache.getValue( + paint, textArray, start, count, count, flags); + if (value != NULL) { +#if DEBUG_GLYPHS + LOGD("drawTextWithGlyphs -- got glyphs - count=%d", value->getGlyphsCount()); + for (size_t i = 0; i < value->getGlyphsCount(); i++) { + LOGD(" glyphs[%d]=%d", i, value->getGlyphs()[i]); + } +#endif + doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), + x, y, flags, paint); + } +#else + TextLayout::drawText(paint, textArray + start, end - start, flags, x, y, canvas); +#endif + env->ReleaseStringChars(text, textArray); + } + + static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count, + jfloat x, jfloat y, int flags, SkPaint* paint) { // TODO: need to suppress this code after the GL renderer is modified for not // copying the paint @@ -768,10 +815,18 @@ public: // Define Glyph encoding paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); - TextLayout::drawText(paint, glyphArray + index, count, flags, x, y, canvas); + canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint); // Get back old encoding paint->setTextEncoding(oldEncoding); + } + + static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, + jcharArray glyphs, int index, int count, + jfloat x, jfloat y, int flags, SkPaint* paint) { + jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); + + doDrawGlyphs(canvas, glyphArray, index, count, x, y, flags, paint); env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT); } @@ -967,6 +1022,10 @@ static JNINativeMethod gCanvasMethods[] = { (void*) SkCanvasGlue::drawText___CIIFFIPaint}, {"native_drawText","(ILjava/lang/String;IIFFII)V", (void*) SkCanvasGlue::drawText__StringIIFFIPaint}, + {"native_drawTextWithGlyphs","(I[CIIFFII)V", + (void*) SkCanvasGlue::drawTextWithGlyphs___CIIFFIPaint}, + {"native_drawTextWithGlyphs","(ILjava/lang/String;IIFFII)V", + (void*) SkCanvasGlue::drawTextWithGlyphs__StringIIFFIPaint}, {"native_drawGlyphs","(I[CIIFFII)V", (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint}, {"native_drawTextRun","(I[CIIIIFFII)V", diff --git a/core/jni/android/graphics/RtlProperties.h b/core/jni/android/graphics/RtlProperties.h index f41f4a1bef74d..a41c91b0812a7 100644 --- a/core/jni/android/graphics/RtlProperties.h +++ b/core/jni/android/graphics/RtlProperties.h @@ -51,6 +51,8 @@ static RtlDebugLevel readRtlDebugLevel() { // Define if we want (1) to have Advances debug values or not (0) #define DEBUG_ADVANCES 0 +// Define if we want (1) to have Glyphs debug values or not (0) +#define DEBUG_GLYPHS 0 } // namespace android #endif // ANDROID_RTL_PROPERTIES_H diff --git a/core/jni/android/graphics/TextLayout.cpp b/core/jni/android/graphics/TextLayout.cpp index 2578ea18668d7..28906623a7c95 100644 --- a/core/jni/android/graphics/TextLayout.cpp +++ b/core/jni/android/graphics/TextLayout.cpp @@ -26,10 +26,6 @@ namespace android { -#if USE_TEXT_LAYOUT_CACHE -TextLayoutCache TextLayout::mCache; -#endif - // Returns true if we might need layout. If bidiFlags force LTR, assume no layout, if // bidiFlags indicate there probably is RTL, assume we do, otherwise scan the text // looking for a character >= the first RTL character in unicode and assume we do if @@ -260,12 +256,16 @@ void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint sta jfloat* resultAdvances, jfloat& resultTotalAdvance) { #if USE_TEXT_LAYOUT_CACHE // Return advances from the cache. Compute them if needed - mCache.getRunAdvances(paint, chars, start, count, contextCount, - dirFlags, resultAdvances, &resultTotalAdvance); + sp layout = gTextLayoutCache.getValue( + paint, chars, start, count, contextCount, dirFlags); + if (layout != NULL) { + memcpy(resultAdvances, layout->getAdvances(), layout->getAdvancesCount() * sizeof(jfloat)); + resultTotalAdvance = layout->getTotalAdvance(); + } #else // Compute advances and return them - TextLayoutCacheValue::computeAdvances(paint, chars, start, count, contextCount, dirFlags, - resultAdvances, &resultTotalAdvance); + TextLayoutCacheValue::computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, + dirFlags, resultAdvances, &resultTotalAdvance, NULL, NULL ); #endif } @@ -273,8 +273,8 @@ void TextLayout::getTextRunAdvancesHB(SkPaint* paint, const jchar* chars, jint s jint count, jint contextCount, jint dirFlags, jfloat* resultAdvances, jfloat& resultTotalAdvance) { // Compute advances and return them - TextLayoutCacheValue::computeAdvancesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, - resultAdvances, &resultTotalAdvance); + TextLayoutCacheValue::computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, + dirFlags, resultAdvances, &resultTotalAdvance, NULL, NULL); } void TextLayout::getTextRunAdvancesICU(SkPaint* paint, const jchar* chars, jint start, diff --git a/core/jni/android/graphics/TextLayout.h b/core/jni/android/graphics/TextLayout.h index 138983c19ccdd..f203b751f998e 100644 --- a/core/jni/android/graphics/TextLayout.h +++ b/core/jni/android/graphics/TextLayout.h @@ -41,6 +41,11 @@ namespace android { */ #define USE_TEXT_LAYOUT_CACHE 1 + +#if USE_TEXT_LAYOUT_CACHE + static TextLayoutCache gTextLayoutCache; +#endif + class TextLayout { public: @@ -106,10 +111,5 @@ private: UErrorCode &status); static void handleText(SkPaint* paint, const jchar* text, jsize len, int bidiFlags, jfloat x, jfloat y, SkCanvas* canvas, SkPath* path); - -#if USE_TEXT_LAYOUT_CACHE - static TextLayoutCache mCache; -#endif }; - -} +} // namespace android diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index 10e2e411ea38b..8db768c0cd4c1 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -18,15 +18,15 @@ namespace android { -TextLayoutCache::TextLayoutCache(): - mCache(GenerationCache::kUnlimitedCapacity), +TextLayoutCache::TextLayoutCache() : + mCache(GenerationCache >::kUnlimitedCapacity), mSize(0), mMaxSize(MB(DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB)), mCacheHitCount(0), mNanosecondsSaved(0) { init(); } TextLayoutCache::TextLayoutCache(uint32_t max): - mCache(GenerationCache::kUnlimitedCapacity), + mCache(GenerationCache >::kUnlimitedCapacity), mSize(0), mMaxSize(max), mCacheHitCount(0), mNanosecondsSaved(0) { init(); @@ -88,14 +88,14 @@ void TextLayoutCache::removeOldests() { /** * Callbacks */ -void TextLayoutCache::operator()(TextLayoutCacheKey& text, TextLayoutCacheValue*& desc) { - if (desc) { +void TextLayoutCache::operator()(TextLayoutCacheKey& text, sp& desc) { + if (desc != NULL) { size_t totalSizeToDelete = text.getSize() + desc->getSize(); mSize -= totalSizeToDelete; if (mDebugEnabled) { LOGD("Cache value deleted, size = %d", totalSizeToDelete); } - delete desc; + desc.clear(); } } @@ -109,29 +109,26 @@ void TextLayoutCache::clear() { /* * Caching */ -void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, - jint start, jint count, jint contextCount, jint dirFlags, - jfloat* outAdvances, jfloat* outTotalAdvance) { - +sp TextLayoutCache::getValue(SkPaint* paint, + const jchar* text, jint start, jint count, jint contextCount, jint dirFlags) { AutoMutex _l(mLock); - nsecs_t startTime = 0; if (mDebugEnabled) { startTime = systemTime(SYSTEM_TIME_MONOTONIC); } + // Create the key TextLayoutCacheKey key(paint, text, start, count, contextCount, dirFlags); - // Get entry for cache if possible - TextLayoutCacheValue* value = mCache.get(key); + // Get value from cache if possible + sp value = mCache.get(key); - // Value not found for the entry, we need to add a new value in the cache - if (!value) { + // Value not found for the key, we need to add a new value in the cache + if (value == NULL) { value = new TextLayoutCacheValue(); // Compute advances and store them - value->computeAdvances(paint, text, start, count, contextCount, dirFlags); - value->copyResult(outAdvances, outTotalAdvance); + value->computeValues(paint, text, start, count, contextCount, dirFlags); // Don't bother to add in the cache if the entry is too big size_t size = key.getSize() + value->getSize(); @@ -156,7 +153,7 @@ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, mCache.put(key, value); if (mDebugEnabled) { - // Update timing information for statistics. + // Update timing information for statistics value->setElapsedTime(systemTime(SYSTEM_TIME_MONOTONIC) - startTime); LOGD("CACHE MISS: Added entry for text='%s' with start=%d, count=%d, " @@ -174,11 +171,10 @@ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, String8(text, contextCount).string(), start, count, contextCount, size, mMaxSize - mSize, value->getElapsedTime()); } - delete value; + value.clear(); } } else { - // This is a cache hit, just copy the pre-computed results - value->copyResult(outAdvances, outTotalAdvance); + // This is a cache hit, just log timestamp and user infos if (mDebugEnabled) { nsecs_t elapsedTimeThruCacheGet = systemTime(SYSTEM_TIME_MONOTONIC) - startTime; mNanosecondsSaved += (value->getElapsedTime() - elapsedTimeThruCacheGet); @@ -199,6 +195,7 @@ void TextLayoutCache::getRunAdvances(SkPaint* paint, const jchar* text, } } } + return value; } void TextLayoutCache::dumpCacheStats() { @@ -218,7 +215,7 @@ void TextLayoutCache::dumpCacheStats() { /** * TextLayoutCacheKey */ -TextLayoutCacheKey::TextLayoutCacheKey() : text(NULL), start(0), count(0), contextCount(0), +TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), start(0), count(0), contextCount(0), dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0), hinting(SkPaint::kNo_Hinting) { } @@ -273,49 +270,46 @@ size_t TextLayoutCacheKey::getSize() { /** * TextLayoutCacheValue */ -TextLayoutCacheValue::TextLayoutCacheValue() { - advances = NULL; - totalAdvance = 0; +TextLayoutCacheValue::TextLayoutCacheValue() : + mAdvances(NULL), mTotalAdvance(0), mAdvancesCount(0), + mGlyphs(NULL), mGlyphsCount(0), mElapsedTime(0) { } TextLayoutCacheValue::~TextLayoutCacheValue() { - delete[] advances; + delete[] mAdvances; + delete[] mGlyphs; } void TextLayoutCacheValue::setElapsedTime(uint32_t time) { - elapsedTime = time; + mElapsedTime = time; } uint32_t TextLayoutCacheValue::getElapsedTime() { - return elapsedTime; + return mElapsedTime; } -void TextLayoutCacheValue::computeAdvances(SkPaint* paint, const UChar* chars, size_t start, +void TextLayoutCacheValue::computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags) { - advances = new float[count]; - this->count = count; + mAdvancesCount = count; + mAdvances = new float[count]; #if RTL_USE_HARFBUZZ - computeAdvancesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, - advances, &totalAdvance); + computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, + mAdvances, &mTotalAdvance, &mGlyphs, &mGlyphsCount); #else computeAdvancesWithICU(paint, chars, start, count, contextCount, dirFlags, - advances, &totalAdvance); + mAdvances, &mTotalAdvance); #endif #if DEBUG_ADVANCES LOGD("Advances - count=%d - countextCount=%d - totalAdvance=%f - " - "adv[0]=%f adv[1]=%f adv[2]=%f adv[3]=%f", count, contextCount, totalAdvance, - advances[0], advances[1], advances[2], advances[3]); + "adv[0]=%f adv[1]=%f adv[2]=%f adv[3]=%f", count, contextCount, mTotalAdvance, + mAdvances[0], mAdvances[1], mAdvances[2], mAdvances[3]); #endif } -void TextLayoutCacheValue::copyResult(jfloat* outAdvances, jfloat* outTotalAdvance) { - memcpy(outAdvances, advances, count * sizeof(jfloat)); - *outTotalAdvance = totalAdvance; -} - size_t TextLayoutCacheValue::getSize() { - return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * count; + return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * mAdvancesCount + + sizeof(jchar) * mGlyphsCount; } void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, @@ -387,49 +381,56 @@ void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontR } } -void TextLayoutCacheValue::computeAdvancesWithHarfbuzz(SkPaint* paint, const UChar* chars, +void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, - jfloat* outAdvances, jfloat* outTotalAdvance) { - + jfloat* outAdvances, jfloat* outTotalAdvance, + jchar** outGlyphs, size_t* outGlyphsCount) { bool isRTL = dirFlags & 0x1; + // TODO: need to run BiDi algo here to breakdown the text in several runs HB_ShaperItem shaperItem; HB_FontRec font; FontData fontData; shapeWithHarfbuzz(&shaperItem, &font, &fontData, paint, chars, start, count, contextCount, dirFlags); -#if DEBUG_ADVANCES +#if DEBUG_GLYPHS LOGD("HARFBUZZ -- num_glypth=%d - kerning_applied=%d", shaperItem.num_glyphs, shaperItem.kerning_applied); LOGD(" -- string= '%s'", String8(chars, contextCount).string()); LOGD(" -- isDevKernText=%d", paint->isDevKernText()); #endif + // Get Advances and their total jfloat totalAdvance = 0; - for (size_t i = 0; i < count; i++) { totalAdvance += outAdvances[i] = HBFixedToFloat(shaperItem.advances[i]); - #if DEBUG_ADVANCES LOGD("hb-adv = %d - rebased = %f - total = %f", shaperItem.advances[i], outAdvances[i], totalAdvance); #endif } + *outTotalAdvance = totalAdvance; + // Get Glyphs + if (outGlyphs) { + *outGlyphsCount = shaperItem.num_glyphs; + *outGlyphs = new jchar[shaperItem.num_glyphs]; + for (size_t i = 0; i < shaperItem.num_glyphs; i++) { + (*outGlyphs)[i] = (jchar) shaperItem.glyphs[i]; + } + } + + // Cleaning deleteGlyphArrays(&shaperItem); HB_FreeFace(shaperItem.face); - - *outTotalAdvance = totalAdvance; } void TextLayoutCacheValue::computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, jfloat* outAdvances, jfloat* outTotalAdvance) { - SkAutoSTMalloc tempBuffer(contextCount); jchar* buffer = tempBuffer.get(); - SkScalar* scalarArray = (SkScalar*)outAdvances; // this is where we'd call harfbuzz diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h index cd5a58d7cd632..e6ce68d75cb14 100644 --- a/core/jni/android/graphics/TextLayoutCache.h +++ b/core/jni/android/graphics/TextLayoutCache.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -101,18 +102,24 @@ private: /* * TextLayoutCacheValue is the Cache value */ -class TextLayoutCacheValue { +class TextLayoutCacheValue : public RefBase { +protected: + ~TextLayoutCacheValue(); + public: TextLayoutCacheValue(); - ~TextLayoutCacheValue(); void setElapsedTime(uint32_t time); uint32_t getElapsedTime(); - void computeAdvances(SkPaint* paint, const UChar* chars, size_t start, size_t count, + void computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags); - void copyResult(jfloat* outAdvances, jfloat* outTotalAdvance); + inline const jfloat* getAdvances() const { return mAdvances; } + inline size_t getAdvancesCount() const { return mAdvancesCount; } + inline jfloat getTotalAdvance() const { return mTotalAdvance; } + inline const jchar* getGlyphs() const { return mGlyphs; } + inline size_t getGlyphsCount() const { return mGlyphsCount; } /** * Get the size of the Cache entry @@ -127,20 +134,45 @@ public: SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags); - static void computeAdvancesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, + static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, - jfloat* outAdvances, jfloat* outTotalAdvance); + jfloat* outAdvances, jfloat* outTotalAdvance, + jchar** outGlyphs, size_t* outGlyphsCount); static void computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, jfloat* outAdvances, jfloat* outTotalAdvance); private: - jfloat* advances; - jfloat totalAdvance; - size_t count; + /** + * Advances array + */ + jfloat* mAdvances; - uint32_t elapsedTime; + /** + * Total number of advances + */ + jfloat mTotalAdvance; + + /** + * Allocated size for advances array + */ + size_t mAdvancesCount; + + /** + * Glyphs array + */ + jchar* mGlyphs; + + /** + * Total number of glyphs + */ + size_t mGlyphsCount; + + /** + * Time for computing the values (in milliseconds) + */ + uint32_t mElapsedTime; static void deleteGlyphArrays(HB_ShaperItem* shaperItem); static void createGlyphArrays(HB_ShaperItem* shaperItem, int size); @@ -148,8 +180,10 @@ private: }; // TextLayoutCacheValue - -class TextLayoutCache: public OnEntryRemoved +/** + * Cache of text layout information. + */ +class TextLayoutCache : public OnEntryRemoved > { public: TextLayoutCache(); @@ -162,17 +196,13 @@ public: } /** - * Used as a callback when an entry is removed from the cache. - * Do not invoke directly. + * Used as a callback when an entry is removed from the cache + * Do not invoke directly */ - void operator()(TextLayoutCacheKey& text, TextLayoutCacheValue*& desc); + void operator()(TextLayoutCacheKey& text, sp& desc); - /** - * Get cache entries - */ - void getRunAdvances(SkPaint* paint, const jchar* text, - jint start, jint count, jint contextCount, jint dirFlags, - jfloat* outAdvances, jfloat* outTotalAdvance); + sp getValue(SkPaint* paint, + const jchar* text, jint start, jint count, jint contextCount, jint dirFlags); /** * Clear the cache @@ -180,17 +210,17 @@ public: void clear(); /** - * Sets the maximum size of the cache in bytes. + * Sets the maximum size of the cache in bytes */ void setMaxSize(uint32_t maxSize); /** - * Returns the maximum size of the cache in bytes. + * Returns the maximum size of the cache in bytes */ uint32_t getMaxSize(); /** - * Returns the current size of the cache in bytes. + * Returns the current size of the cache in bytes */ uint32_t getSize(); @@ -198,7 +228,7 @@ private: Mutex mLock; bool mInitialized; - GenerationCache mCache; + GenerationCache > mCache; uint32_t mSize; uint32_t mMaxSize; diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index e493b18cc2d59..0b488c96b44b1 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -1329,29 +1329,6 @@ public class Canvas { paint.mNativePaint); } - /** - * Draw the glyphs, with origin at (x,y), using the specified paint. The - * origin is interpreted based on the Align setting in the paint. - * - * @param glyphs The glyphs to be drawn - * @param x The x-coordinate of the origin of the text being drawn - * @param y The y-coordinate of the origin of the text being drawn - * @param paint The paint used for the text (e.g. color, size, style) - * - * @hide - * - * Used only for BiDi / RTL Tests - */ - public void drawGlyphs(char[] glyphs, int index, int count, float x, float y, - Paint paint) { - if ((index | count | (index + count) | - (glyphs.length - index - count)) < 0) { - throw new IndexOutOfBoundsException(); - } - native_drawGlyphs(mNativeCanvas, glyphs, index, count, x, y, paint.mBidiFlags, - paint.mNativePaint); - } - /** * Draw the text, with origin at (x,y), using the specified paint. The * origin is interpreted based on the Align setting in the paint. @@ -1417,6 +1394,70 @@ public class Canvas { } } + /** + * Draw the text, with origin at (x,y), using the specified paint. The + * origin is interpreted based on the Align setting in the paint. + * + * @param text The text to be drawn + * @param x The x-coordinate of the origin of the text being drawn + * @param y The y-coordinate of the origin of the text being drawn + * @param paint The paint used for the text (e.g. color, size, style) + * + * @hide + * + * Used only for BiDi / RTL Tests + */ + public void drawTextWithGlyphs(char[] text, int index, int count, float x, float y, + Paint paint) { + if ((index | count | (index + count) | + (text.length - index - count)) < 0) { + throw new IndexOutOfBoundsException(); + } + native_drawTextWithGlyphs(mNativeCanvas, text, index, count, x, y, paint.mBidiFlags, + paint.mNativePaint); + } + + /** + * Draw the text, with origin at (x,y), using the specified paint. The + * origin is interpreted based on the Align setting in the paint. + * + * @param text The text to be drawn + * @param x The x-coordinate of the origin of the text being drawn + * @param y The y-coordinate of the origin of the text being drawn + * @param paint The paint used for the text (e.g. color, size, style) + * + * @hide + * + * Used only for BiDi / RTL Tests + */ + public void drawTextWithGlyphs(String text, float x, float y, Paint paint) { + native_drawTextWithGlyphs(mNativeCanvas, text, 0, text.length(), x, y, paint.mBidiFlags, + paint.mNativePaint); + } + + /** + * Draw the glyphs, with origin at (x,y), using the specified paint. The + * origin is interpreted based on the Align setting in the paint. + * + * @param glyphs The glyphs to be drawn + * @param x The x-coordinate of the origin of the text being drawn + * @param y The y-coordinate of the origin of the text being drawn + * @param paint The paint used for the text (e.g. color, size, style) + * + * @hide + * + * Used only for BiDi / RTL Tests + */ + public void drawGlyphs(char[] glyphs, int index, int count, float x, float y, + Paint paint) { + if ((index | count | (index + count) | + (glyphs.length - index - count)) < 0) { + throw new IndexOutOfBoundsException(); + } + native_drawGlyphs(mNativeCanvas, glyphs, index, count, x, y, paint.mBidiFlags, + paint.mNativePaint); + } + /** * Render a run of all LTR or all RTL text, with shaping. This does not run * bidi on the provided text, but renders it as a uniform right-to-left or @@ -1745,9 +1786,17 @@ public class Canvas { private static native void native_drawText(int nativeCanvas, String text, int start, int end, float x, float y, int flags, int paint); + + private static native void native_drawTextWithGlyphs(int nativeCanvas, char[] text, + int index, int count, float x, + float y, int flags, int paint); + private static native void native_drawTextWithGlyphs(int nativeCanvas, String text, + int start, int end, float x, + float y, int flags, int paint); private static native void native_drawGlyphs(int nativeCanvas, char[] glyphs, int index, int count, 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); diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java index cd415c2f320e8..f00bd06cf08ce 100644 --- a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java @@ -150,11 +150,13 @@ public class BiDiTestView extends View { drawMetricsAroundText(canvas, x, y, textWidthHB, textWidthICU, textSize, Color.RED, Color.GREEN); paint.setColor(Color.WHITE); - char[] glyphs = new char[2*length]; - int count = getGlyphs(text, glyphs, dir); - +// char[] glyphs = new char[2*length]; +// int count = getGlyphs(text, glyphs, dir); +// // logGlypths(glyphs, count); - drawTextWithDrawGlyph(canvas, glyphs, count, x, y + currentTextSize); +// drawTextWithDrawGlyph(canvas, glyphs, count, x, y + currentTextSize); + + drawTextWithGlyphs(canvas, text, x, y + currentTextSize, dir); // Restore old paint properties paint.setFakeBoldText(oldFakeBold); @@ -167,6 +169,11 @@ public class BiDiTestView extends View { canvas.drawGlyphs(glyphs, 0, count, x, y, paint); } + private void drawTextWithGlyphs(Canvas canvas, String text, int x, int y, int dir) { + paint.setBidiFlags(dir); + canvas.drawTextWithGlyphs(text, x, y, paint); + } + private void logGlypths(char[] glyphs, int count) { Log.v(TAG, "GlyphIds - count=" + count); for (int n = 0; n < count; n++) {