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
This commit is contained in:
@@ -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<TextLayoutCacheValue> 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<TextLayoutCacheValue> 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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<TextLayoutCacheValue> 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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
TextLayoutCache::TextLayoutCache():
|
||||
mCache(GenerationCache<TextLayoutCacheKey, TextLayoutCacheValue*>::kUnlimitedCapacity),
|
||||
TextLayoutCache::TextLayoutCache() :
|
||||
mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> >::kUnlimitedCapacity),
|
||||
mSize(0), mMaxSize(MB(DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB)),
|
||||
mCacheHitCount(0), mNanosecondsSaved(0) {
|
||||
init();
|
||||
}
|
||||
|
||||
TextLayoutCache::TextLayoutCache(uint32_t max):
|
||||
mCache(GenerationCache<TextLayoutCacheKey, TextLayoutCacheValue*>::kUnlimitedCapacity),
|
||||
mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> >::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<TextLayoutCacheValue>& 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<TextLayoutCacheValue> 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<TextLayoutCacheValue> 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<CHAR_BUFFER_SIZE, jchar> tempBuffer(contextCount);
|
||||
jchar* buffer = tempBuffer.get();
|
||||
|
||||
SkScalar* scalarArray = (SkScalar*)outAdvances;
|
||||
|
||||
// this is where we'd call harfbuzz
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <utils/String16.h>
|
||||
#include <utils/GenerationCache.h>
|
||||
#include <utils/Compare.h>
|
||||
#include <utils/RefBase.h>
|
||||
|
||||
#include <SkPaint.h>
|
||||
#include <SkTemplates.h>
|
||||
@@ -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<TextLayoutCacheKey, TextLayoutCacheValue*>
|
||||
/**
|
||||
* Cache of text layout information.
|
||||
*/
|
||||
class TextLayoutCache : public OnEntryRemoved<TextLayoutCacheKey, sp<TextLayoutCacheValue> >
|
||||
{
|
||||
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<TextLayoutCacheValue>& desc);
|
||||
|
||||
/**
|
||||
* Get cache entries
|
||||
*/
|
||||
void getRunAdvances(SkPaint* paint, const jchar* text,
|
||||
jint start, jint count, jint contextCount, jint dirFlags,
|
||||
jfloat* outAdvances, jfloat* outTotalAdvance);
|
||||
sp<TextLayoutCacheValue> 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<TextLayoutCacheKey, TextLayoutCacheValue*> mCache;
|
||||
GenerationCache<TextLayoutCacheKey, sp<TextLayoutCacheValue> > mCache;
|
||||
|
||||
uint32_t mSize;
|
||||
uint32_t mMaxSize;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
Reference in New Issue
Block a user