Merge "Fix bug #5332081 TextLayoutCache needs to be able to have more cache hits"
This commit is contained in:
committed by
Android (Google) Code Review
commit
651e46679b
@@ -758,21 +758,7 @@ public:
|
|||||||
jfloat x, jfloat y, int flags, SkPaint* paint) {
|
jfloat x, jfloat y, int flags, SkPaint* paint) {
|
||||||
|
|
||||||
jint count = end - start;
|
jint count = end - start;
|
||||||
sp<TextLayoutCacheValue> value;
|
drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint);
|
||||||
#if USE_TEXT_LAYOUT_CACHE
|
|
||||||
value = TextLayoutCache::getInstance().getValue(paint, textArray, start, count,
|
|
||||||
end, flags);
|
|
||||||
if (value == NULL) {
|
|
||||||
LOGE("Cannot get TextLayoutCache value");
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
value = new TextLayoutCacheValue();
|
|
||||||
value->computeValues(paint, textArray, start, count, end, flags);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(),
|
|
||||||
x, y, flags, paint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
|
static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
|
||||||
@@ -781,19 +767,20 @@ public:
|
|||||||
|
|
||||||
sp<TextLayoutCacheValue> value;
|
sp<TextLayoutCacheValue> value;
|
||||||
#if USE_TEXT_LAYOUT_CACHE
|
#if USE_TEXT_LAYOUT_CACHE
|
||||||
value = TextLayoutCache::getInstance().getValue(paint, textArray, start, count,
|
value = TextLayoutCache::getInstance().getValue(paint, textArray, contextCount, flags);
|
||||||
contextCount, flags);
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
LOGE("Cannot get TextLayoutCache value");
|
LOGE("Cannot get TextLayoutCache value");
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
value = new TextLayoutCacheValue();
|
value = new TextLayoutCacheValue();
|
||||||
value->computeValues(paint, textArray, start, count, contextCount, flags);
|
value->computeValues(paint, textArray, contextCount, flags);
|
||||||
#endif
|
#endif
|
||||||
|
size_t startIndex = 0;
|
||||||
doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(),
|
size_t glyphsCount = 0;
|
||||||
x, y, flags, paint);
|
value->getGlyphsIndexAndCount(start, count, &startIndex, &glyphsCount);
|
||||||
|
const jchar* glyphs = value->getGlyphs(startIndex, glyphsCount);
|
||||||
|
doDrawGlyphs(canvas, glyphs, 0, glyphsCount, x, y, flags, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
|
static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ public:
|
|||||||
jfloat result = 0;
|
jfloat result = 0;
|
||||||
#if RTL_USE_HARFBUZZ
|
#if RTL_USE_HARFBUZZ
|
||||||
TextLayout::getTextRunAdvances(paint, textArray, index, count, textLength,
|
TextLayout::getTextRunAdvances(paint, textArray, index, count, textLength,
|
||||||
paint->getFlags(), NULL /* dont need all advances */, result);
|
paint->getFlags(), NULL /* dont need all advances */, &result);
|
||||||
#else
|
#else
|
||||||
// we double count, since measureText wants a byteLength
|
// we double count, since measureText wants a byteLength
|
||||||
SkScalar width = paint->measureText(textArray + index, count << 1);
|
SkScalar width = paint->measureText(textArray + index, count << 1);
|
||||||
@@ -382,7 +382,7 @@ public:
|
|||||||
|
|
||||||
#if RTL_USE_HARFBUZZ
|
#if RTL_USE_HARFBUZZ
|
||||||
TextLayout::getTextRunAdvances(paint, textArray, start, count, textLength,
|
TextLayout::getTextRunAdvances(paint, textArray, start, count, textLength,
|
||||||
paint->getFlags(), NULL /* dont need all advances */, width);
|
paint->getFlags(), NULL /* dont need all advances */, &width);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
width = SkScalarToFloat(paint->measureText(textArray + start, count << 1));
|
width = SkScalarToFloat(paint->measureText(textArray + start, count << 1));
|
||||||
@@ -406,7 +406,7 @@ public:
|
|||||||
|
|
||||||
#if RTL_USE_HARFBUZZ
|
#if RTL_USE_HARFBUZZ
|
||||||
TextLayout::getTextRunAdvances(paint, textArray, 0, textLength, textLength,
|
TextLayout::getTextRunAdvances(paint, textArray, 0, textLength, textLength,
|
||||||
paint->getFlags(), NULL /* dont need all advances */, width);
|
paint->getFlags(), NULL /* dont need all advances */, &width);
|
||||||
#else
|
#else
|
||||||
width = SkScalarToFloat(paint->measureText(textArray, textLength << 1));
|
width = SkScalarToFloat(paint->measureText(textArray, textLength << 1));
|
||||||
#endif
|
#endif
|
||||||
@@ -435,10 +435,8 @@ public:
|
|||||||
jfloat* widthsArray = autoWidths.ptr();
|
jfloat* widthsArray = autoWidths.ptr();
|
||||||
|
|
||||||
#if RTL_USE_HARFBUZZ
|
#if RTL_USE_HARFBUZZ
|
||||||
jfloat totalAdvance;
|
|
||||||
|
|
||||||
TextLayout::getTextRunAdvances(paint, text, 0, count, count,
|
TextLayout::getTextRunAdvances(paint, text, 0, count, count,
|
||||||
paint->getFlags(), widthsArray, totalAdvance);
|
paint->getFlags(), widthsArray, NULL /* dont need totalAdvance */);
|
||||||
#else
|
#else
|
||||||
SkScalar* scalarArray = (SkScalar*)widthsArray;
|
SkScalar* scalarArray = (SkScalar*)widthsArray;
|
||||||
|
|
||||||
@@ -533,7 +531,7 @@ public:
|
|||||||
jfloat totalAdvance = 0;
|
jfloat totalAdvance = 0;
|
||||||
|
|
||||||
TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags,
|
TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags,
|
||||||
advancesArray, totalAdvance);
|
advancesArray, &totalAdvance);
|
||||||
|
|
||||||
if (advances != NULL) {
|
if (advances != NULL) {
|
||||||
env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray);
|
env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray);
|
||||||
@@ -604,10 +602,9 @@ public:
|
|||||||
jint count, jint flags, jint offset, jint opt) {
|
jint count, jint flags, jint offset, jint opt) {
|
||||||
#if RTL_USE_HARFBUZZ
|
#if RTL_USE_HARFBUZZ
|
||||||
jfloat scalarArray[count];
|
jfloat scalarArray[count];
|
||||||
jfloat totalAdvance = 0;
|
|
||||||
|
|
||||||
TextLayout::getTextRunAdvances(paint, text, start, count, count, flags,
|
TextLayout::getTextRunAdvances(paint, text, start, count, count, flags,
|
||||||
scalarArray, totalAdvance);
|
scalarArray, NULL /* dont need totalAdvance */);
|
||||||
#else
|
#else
|
||||||
SkScalar scalarArray[count];
|
SkScalar scalarArray[count];
|
||||||
jchar buffer[count];
|
jchar buffer[count];
|
||||||
|
|||||||
@@ -253,21 +253,22 @@ void TextLayout::drawTextRun(SkPaint* paint, const jchar* chars,
|
|||||||
|
|
||||||
void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start,
|
void TextLayout::getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start,
|
||||||
jint count, jint contextCount, jint dirFlags,
|
jint count, jint contextCount, jint dirFlags,
|
||||||
jfloat* resultAdvances, jfloat& resultTotalAdvance) {
|
jfloat* resultAdvances, jfloat* resultTotalAdvance) {
|
||||||
sp<TextLayoutCacheValue> value;
|
sp<TextLayoutCacheValue> value;
|
||||||
#if USE_TEXT_LAYOUT_CACHE
|
#if USE_TEXT_LAYOUT_CACHE
|
||||||
// Return advances from the cache. Compute them if needed
|
// Return advances from the cache. Compute them if needed
|
||||||
value = TextLayoutCache::getInstance().getValue(
|
value = TextLayoutCache::getInstance().getValue(paint, chars, contextCount, dirFlags);
|
||||||
paint, chars, start, count, contextCount, dirFlags);
|
|
||||||
#else
|
#else
|
||||||
value = new TextLayoutCacheValue();
|
value = new TextLayoutCacheValue();
|
||||||
value->computeValues(paint, chars, start, count, contextCount, dirFlags);
|
value->computeValues(paint, chars, contextCount, dirFlags);
|
||||||
#endif
|
#endif
|
||||||
if (value != NULL) {
|
if (value != NULL) {
|
||||||
if (resultAdvances != NULL) {
|
if (resultAdvances != NULL) {
|
||||||
memcpy(resultAdvances, value->getAdvances(), value->getAdvancesCount() * sizeof(jfloat));
|
value->getAdvances(start, count, resultAdvances);
|
||||||
|
}
|
||||||
|
if (resultTotalAdvance) {
|
||||||
|
*resultTotalAdvance = value->getTotalAdvance(start, count);
|
||||||
}
|
}
|
||||||
resultTotalAdvance = value->getTotalAdvance();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public:
|
|||||||
|
|
||||||
static void getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start,
|
static void getTextRunAdvances(SkPaint* paint, const jchar* chars, jint start,
|
||||||
jint count, jint contextCount, jint dirFlags,
|
jint count, jint contextCount, jint dirFlags,
|
||||||
jfloat* resultAdvances, jfloat& resultTotalAdvance);
|
jfloat* resultAdvances, jfloat* resultTotalAdvance);
|
||||||
|
|
||||||
static void getTextRunAdvancesICU(SkPaint* paint, const jchar* chars, jint start,
|
static void getTextRunAdvancesICU(SkPaint* paint, const jchar* chars, jint start,
|
||||||
jint count, jint contextCount, jint dirFlags,
|
jint count, jint contextCount, jint dirFlags,
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ void TextLayoutCache::clear() {
|
|||||||
* Caching
|
* Caching
|
||||||
*/
|
*/
|
||||||
sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint,
|
sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint,
|
||||||
const jchar* text, jint start, jint count, jint contextCount, jint dirFlags) {
|
const jchar* text, jint count, jint dirFlags) {
|
||||||
AutoMutex _l(mLock);
|
AutoMutex _l(mLock);
|
||||||
nsecs_t startTime = 0;
|
nsecs_t startTime = 0;
|
||||||
if (mDebugEnabled) {
|
if (mDebugEnabled) {
|
||||||
@@ -114,7 +114,7 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the key
|
// Create the key
|
||||||
TextLayoutCacheKey key(paint, text, start, count, contextCount, dirFlags);
|
TextLayoutCacheKey key(paint, text, count, dirFlags);
|
||||||
|
|
||||||
// Get value from cache if possible
|
// Get value from cache if possible
|
||||||
sp<TextLayoutCacheValue> value = mCache.get(key);
|
sp<TextLayoutCacheValue> value = mCache.get(key);
|
||||||
@@ -128,7 +128,7 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint,
|
|||||||
value = new TextLayoutCacheValue();
|
value = new TextLayoutCacheValue();
|
||||||
|
|
||||||
// Compute advances and store them
|
// Compute advances and store them
|
||||||
value->computeValues(paint, text, start, count, contextCount, dirFlags);
|
value->computeValues(paint, text, count, dirFlags);
|
||||||
|
|
||||||
nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC);
|
nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||||
|
|
||||||
@@ -157,20 +157,20 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint,
|
|||||||
// Update timing information for statistics
|
// Update timing information for statistics
|
||||||
value->setElapsedTime(endTime - startTime);
|
value->setElapsedTime(endTime - startTime);
|
||||||
|
|
||||||
LOGD("CACHE MISS: Added entry with start=%d, count=%d, "
|
LOGD("CACHE MISS: Added entry with "
|
||||||
"contextCount=%d, entry size %d bytes, remaining space %d bytes"
|
"count=%d, entry size %d bytes, remaining space %d bytes"
|
||||||
" - Compute time in nanos: %d - Text='%s' ",
|
" - Compute time in nanos: %d - Text='%s' ",
|
||||||
start, count, contextCount, size, mMaxSize - mSize, value->getElapsedTime(),
|
count, size, mMaxSize - mSize, value->getElapsedTime(),
|
||||||
String8(text, contextCount).string());
|
String8(text, count).string());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (mDebugEnabled) {
|
if (mDebugEnabled) {
|
||||||
LOGD("CACHE MISS: Calculated but not storing entry because it is too big "
|
LOGD("CACHE MISS: Calculated but not storing entry because it is too big "
|
||||||
"with start=%d, count=%d, contextCount=%d, "
|
"with count=%d, "
|
||||||
"entry size %d bytes, remaining space %d bytes"
|
"entry size %d bytes, remaining space %d bytes"
|
||||||
" - Compute time in nanos: %lld - Text='%s'",
|
" - Compute time in nanos: %lld - Text='%s'",
|
||||||
start, count, contextCount, size, mMaxSize - mSize, endTime,
|
count, size, mMaxSize - mSize, endTime,
|
||||||
String8(text, contextCount).string());
|
String8(text, count).string());
|
||||||
}
|
}
|
||||||
value.clear();
|
value.clear();
|
||||||
}
|
}
|
||||||
@@ -184,12 +184,12 @@ sp<TextLayoutCacheValue> TextLayoutCache::getValue(SkPaint* paint,
|
|||||||
if (value->getElapsedTime() > 0) {
|
if (value->getElapsedTime() > 0) {
|
||||||
float deltaPercent = 100 * ((value->getElapsedTime() - elapsedTimeThruCacheGet)
|
float deltaPercent = 100 * ((value->getElapsedTime() - elapsedTimeThruCacheGet)
|
||||||
/ ((float)value->getElapsedTime()));
|
/ ((float)value->getElapsedTime()));
|
||||||
LOGD("CACHE HIT #%d with start=%d, count=%d, contextCount=%d "
|
LOGD("CACHE HIT #%d with count=%d "
|
||||||
"- Compute time in nanos: %d - "
|
"- Compute time in nanos: %d - "
|
||||||
"Cache get time in nanos: %lld - Gain in percent: %2.2f - Text='%s' ",
|
"Cache get time in nanos: %lld - Gain in percent: %2.2f - Text='%s' ",
|
||||||
mCacheHitCount, start, count, contextCount,
|
mCacheHitCount, count,
|
||||||
value->getElapsedTime(), elapsedTimeThruCacheGet, deltaPercent,
|
value->getElapsedTime(), elapsedTimeThruCacheGet, deltaPercent,
|
||||||
String8(text, contextCount).string());
|
String8(text, count).string());
|
||||||
}
|
}
|
||||||
if (mCacheHitCount % DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL == 0) {
|
if (mCacheHitCount % DEFAULT_DUMP_STATS_CACHE_HIT_INTERVAL == 0) {
|
||||||
dumpCacheStats();
|
dumpCacheStats();
|
||||||
@@ -218,15 +218,14 @@ void TextLayoutCache::dumpCacheStats() {
|
|||||||
/**
|
/**
|
||||||
* TextLayoutCacheKey
|
* TextLayoutCacheKey
|
||||||
*/
|
*/
|
||||||
TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), start(0), count(0), contextCount(0),
|
TextLayoutCacheKey::TextLayoutCacheKey(): text(NULL), count(0),
|
||||||
dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0),
|
dirFlags(0), typeface(NULL), textSize(0), textSkewX(0), textScaleX(0), flags(0),
|
||||||
hinting(SkPaint::kNo_Hinting) {
|
hinting(SkPaint::kNo_Hinting) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint,
|
TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint,
|
||||||
const UChar* text, size_t start, size_t count,
|
const UChar* text, size_t count, int dirFlags) :
|
||||||
size_t contextCount, int dirFlags) :
|
text(text), count(count),
|
||||||
text(text), start(start), count(count), contextCount(contextCount),
|
|
||||||
dirFlags(dirFlags) {
|
dirFlags(dirFlags) {
|
||||||
typeface = paint->getTypeface();
|
typeface = paint->getTypeface();
|
||||||
textSize = paint->getTextSize();
|
textSize = paint->getTextSize();
|
||||||
@@ -239,9 +238,7 @@ TextLayoutCacheKey::TextLayoutCacheKey(const SkPaint* paint,
|
|||||||
TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
|
TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
|
||||||
text(NULL),
|
text(NULL),
|
||||||
textCopy(other.textCopy),
|
textCopy(other.textCopy),
|
||||||
start(other.start),
|
|
||||||
count(other.count),
|
count(other.count),
|
||||||
contextCount(other.contextCount),
|
|
||||||
dirFlags(other.dirFlags),
|
dirFlags(other.dirFlags),
|
||||||
typeface(other.typeface),
|
typeface(other.typeface),
|
||||||
textSize(other.textSize),
|
textSize(other.textSize),
|
||||||
@@ -256,18 +253,15 @@ TextLayoutCacheKey::TextLayoutCacheKey(const TextLayoutCacheKey& other) :
|
|||||||
|
|
||||||
bool TextLayoutCacheKey::operator<(const TextLayoutCacheKey& rhs) const {
|
bool TextLayoutCacheKey::operator<(const TextLayoutCacheKey& rhs) const {
|
||||||
LTE_INT(count) {
|
LTE_INT(count) {
|
||||||
LTE_INT(contextCount) {
|
LTE_INT(typeface) {
|
||||||
LTE_INT(start) {
|
LTE_FLOAT(textSize) {
|
||||||
LTE_INT(typeface) {
|
LTE_FLOAT(textSkewX) {
|
||||||
LTE_FLOAT(textSize) {
|
LTE_FLOAT(textScaleX) {
|
||||||
LTE_FLOAT(textSkewX) {
|
LTE_INT(flags) {
|
||||||
LTE_FLOAT(textScaleX) {
|
LTE_INT(hinting) {
|
||||||
LTE_INT(flags) {
|
LTE_INT(dirFlags) {
|
||||||
LTE_INT(hinting) {
|
return memcmp(getText(), rhs.getText(),
|
||||||
LTE_INT(dirFlags) {
|
count * sizeof(UChar)) < 0;
|
||||||
return strncmp16(getText(), rhs.getText(), contextCount) < 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,12 +274,12 @@ bool TextLayoutCacheKey::operator<(const TextLayoutCacheKey& rhs) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextLayoutCacheKey::internalTextCopy() {
|
void TextLayoutCacheKey::internalTextCopy() {
|
||||||
textCopy.setTo(text, contextCount);
|
textCopy.setTo(text, count);
|
||||||
text = NULL;
|
text = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TextLayoutCacheKey::getSize() {
|
size_t TextLayoutCacheKey::getSize() {
|
||||||
return sizeof(TextLayoutCacheKey) + sizeof(UChar) * contextCount;
|
return sizeof(TextLayoutCacheKey) + sizeof(UChar) * count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -303,23 +297,23 @@ uint32_t TextLayoutCacheValue::getElapsedTime() {
|
|||||||
return mElapsedTime;
|
return mElapsedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextLayoutCacheValue::computeValues(SkPaint* paint, const UChar* chars, size_t start,
|
void TextLayoutCacheValue::computeValues(SkPaint* paint, const UChar* chars,
|
||||||
size_t count, size_t contextCount, int dirFlags) {
|
size_t contextCount, int dirFlags) {
|
||||||
// Give a hint for advances and glyphs vectors size
|
// Give a hint for advances, glyphs and log clusters vectors size
|
||||||
mAdvances.setCapacity(count);
|
mAdvances.setCapacity(contextCount);
|
||||||
mGlyphs.setCapacity(count);
|
mGlyphs.setCapacity(contextCount);
|
||||||
computeValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags,
|
mLogClusters.setCapacity(contextCount);
|
||||||
&mAdvances, &mTotalAdvance, &mGlyphs);
|
|
||||||
|
computeValuesWithHarfbuzz(paint, chars, contextCount, dirFlags,
|
||||||
|
&mAdvances, &mTotalAdvance, &mGlyphs, &mLogClusters);
|
||||||
#if DEBUG_ADVANCES
|
#if DEBUG_ADVANCES
|
||||||
LOGD("Advances - count=%d - countextCount=%d - totalAdvance=%f - "
|
LOGD("Advances - countextCount=%d - totalAdvance=%f", contextCount, mTotalAdvance);
|
||||||
"adv[0]=%f adv[1]=%f adv[2]=%f adv[3]=%f", count, contextCount, mTotalAdvance,
|
|
||||||
mAdvances[0], mAdvances[1], mAdvances[2], mAdvances[3]);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t TextLayoutCacheValue::getSize() {
|
size_t TextLayoutCacheValue::getSize() {
|
||||||
return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * mAdvances.capacity() +
|
return sizeof(TextLayoutCacheValue) + sizeof(jfloat) * mAdvances.capacity() +
|
||||||
sizeof(jchar) * mGlyphs.capacity();
|
sizeof(jchar) * mGlyphs.capacity() + sizeof(unsigned short) * mLogClusters.capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font,
|
void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font,
|
||||||
@@ -391,9 +385,9 @@ void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontR
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
|
void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
|
||||||
size_t start, size_t count, size_t contextCount, int dirFlags,
|
size_t contextCount, int dirFlags,
|
||||||
Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
|
Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
|
||||||
Vector<jchar>* const outGlyphs) {
|
Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters) {
|
||||||
|
|
||||||
UBiDiLevel bidiReq = 0;
|
UBiDiLevel bidiReq = 0;
|
||||||
bool forceLTR = false;
|
bool forceLTR = false;
|
||||||
@@ -413,8 +407,8 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar
|
|||||||
LOGD("computeValuesWithHarfbuzz -- forcing run with LTR=%d RTL=%d",
|
LOGD("computeValuesWithHarfbuzz -- forcing run with LTR=%d RTL=%d",
|
||||||
forceLTR, forceRTL);
|
forceLTR, forceRTL);
|
||||||
#endif
|
#endif
|
||||||
computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, forceRTL,
|
computeRunValuesWithHarfbuzz(paint, chars, 0, contextCount, contextCount, forceRTL,
|
||||||
outAdvances, outTotalAdvance, outGlyphs);
|
outAdvances, outTotalAdvance, outGlyphs, outLogClusters);
|
||||||
} else {
|
} else {
|
||||||
UBiDi* bidi = ubidi_open();
|
UBiDi* bidi = ubidi_open();
|
||||||
if (bidi) {
|
if (bidi) {
|
||||||
@@ -433,35 +427,16 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar
|
|||||||
bool isRTL = (paraDir == 1);
|
bool isRTL = (paraDir == 1);
|
||||||
#if DEBUG_GLYPHS
|
#if DEBUG_GLYPHS
|
||||||
LOGD("computeValuesWithHarfbuzz -- processing SINGLE run "
|
LOGD("computeValuesWithHarfbuzz -- processing SINGLE run "
|
||||||
"-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL);
|
"-- run-start=%d run-len=%d isRTL=%d", 0, contextCount, isRTL);
|
||||||
#endif
|
#endif
|
||||||
computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount,
|
computeRunValuesWithHarfbuzz(paint, chars, 0, contextCount, contextCount,
|
||||||
isRTL, outAdvances, outTotalAdvance, outGlyphs);
|
isRTL, outAdvances, outTotalAdvance, outGlyphs, outLogClusters);
|
||||||
} else {
|
} else {
|
||||||
int32_t end = start + count;
|
|
||||||
for (size_t i = 0; i < rc; ++i) {
|
for (size_t i = 0; i < rc; ++i) {
|
||||||
int32_t startRun;
|
int32_t startRun;
|
||||||
int32_t lengthRun;
|
int32_t lengthRun;
|
||||||
UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun);
|
UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun);
|
||||||
|
|
||||||
if (startRun >= end) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t endRun = startRun + lengthRun;
|
|
||||||
if (endRun <= start) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startRun < start) {
|
|
||||||
startRun = start;
|
|
||||||
}
|
|
||||||
if (endRun > end) {
|
|
||||||
endRun = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
lengthRun = endRun - startRun;
|
|
||||||
|
|
||||||
bool isRTL = (runDir == UBIDI_RTL);
|
bool isRTL = (runDir == UBIDI_RTL);
|
||||||
jfloat runTotalAdvance = 0;
|
jfloat runTotalAdvance = 0;
|
||||||
#if DEBUG_GLYPHS
|
#if DEBUG_GLYPHS
|
||||||
@@ -471,7 +446,7 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar
|
|||||||
computeRunValuesWithHarfbuzz(paint, chars, startRun,
|
computeRunValuesWithHarfbuzz(paint, chars, startRun,
|
||||||
lengthRun, contextCount, isRTL,
|
lengthRun, contextCount, isRTL,
|
||||||
outAdvances, &runTotalAdvance,
|
outAdvances, &runTotalAdvance,
|
||||||
outGlyphs);
|
outGlyphs, outLogClusters);
|
||||||
|
|
||||||
*outTotalAdvance += runTotalAdvance;
|
*outTotalAdvance += runTotalAdvance;
|
||||||
}
|
}
|
||||||
@@ -483,10 +458,10 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar
|
|||||||
bool isRTL = (bidiReq = 1) || (bidiReq = UBIDI_DEFAULT_RTL);
|
bool isRTL = (bidiReq = 1) || (bidiReq = UBIDI_DEFAULT_RTL);
|
||||||
#if DEBUG_GLYPHS
|
#if DEBUG_GLYPHS
|
||||||
LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering a SINGLE Run "
|
LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering a SINGLE Run "
|
||||||
"-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL);
|
"-- run-start=%d run-len=%d isRTL=%d", 0, contextCount, isRTL);
|
||||||
#endif
|
#endif
|
||||||
computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, isRTL,
|
computeRunValuesWithHarfbuzz(paint, chars, 0, contextCount, contextCount, isRTL,
|
||||||
outAdvances, outTotalAdvance, outGlyphs);
|
outAdvances, outTotalAdvance, outGlyphs, outLogClusters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if DEBUG_GLYPHS
|
#if DEBUG_GLYPHS
|
||||||
@@ -506,7 +481,7 @@ static void logGlyphs(HB_ShaperItem shaperItem) {
|
|||||||
void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
|
void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
|
||||||
size_t start, size_t count, size_t contextCount, bool isRTL,
|
size_t start, size_t count, size_t contextCount, bool isRTL,
|
||||||
Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
|
Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
|
||||||
Vector<jchar>* const outGlyphs) {
|
Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters) {
|
||||||
|
|
||||||
HB_ShaperItem shaperItem;
|
HB_ShaperItem shaperItem;
|
||||||
HB_FontRec font;
|
HB_FontRec font;
|
||||||
@@ -557,15 +532,15 @@ void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UC
|
|||||||
#if DEBUG_ADVANCES
|
#if DEBUG_ADVANCES
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
LOGD("hb-adv[%d] = %f - log_clusters = %d - total = %f", i,
|
LOGD("hb-adv[%d] = %f - log_clusters = %d - total = %f", i,
|
||||||
outAdvances[i], shaperItem.log_clusters[i], totalAdvance);
|
(*outAdvances)[i], shaperItem.log_clusters[i], totalAdvance);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get Glyphs and reverse them in place if RTL
|
// Get Glyphs and reverse them in place if RTL
|
||||||
if (outGlyphs) {
|
if (outGlyphs) {
|
||||||
size_t count = shaperItem.num_glyphs;
|
size_t countGlyphs = shaperItem.num_glyphs;
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < countGlyphs; i++) {
|
||||||
jchar glyph = (jchar) shaperItem.glyphs[(!isRTL) ? i : count - 1 - i];
|
jchar glyph = (jchar) shaperItem.glyphs[(!isRTL) ? i : countGlyphs - 1 - i];
|
||||||
#if DEBUG_GLYPHS
|
#if DEBUG_GLYPHS
|
||||||
LOGD("HARFBUZZ -- glyph[%d]=%d", i, glyph);
|
LOGD("HARFBUZZ -- glyph[%d]=%d", i, glyph);
|
||||||
#endif
|
#endif
|
||||||
@@ -573,6 +548,20 @@ void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get LogClusters
|
||||||
|
if (outLogClusters) {
|
||||||
|
size_t countLogClusters = outLogClusters->size();
|
||||||
|
size_t countGlyphs = shaperItem.num_glyphs;
|
||||||
|
for (size_t i = 0; i < countGlyphs; i++) {
|
||||||
|
// As there may be successive runs, we need to shift the log clusters
|
||||||
|
unsigned short logCluster = shaperItem.log_clusters[i] + countLogClusters;
|
||||||
|
#if DEBUG_GLYPHS
|
||||||
|
LOGD("HARFBUZZ -- logCluster[%d] relative=%d - absolute=%d", i, shaperItem.log_clusters[i], logCluster);
|
||||||
|
#endif
|
||||||
|
outLogClusters->add(logCluster);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Cleaning
|
// Cleaning
|
||||||
deleteGlyphArrays(&shaperItem);
|
deleteGlyphArrays(&shaperItem);
|
||||||
HB_FreeFace(shaperItem.face);
|
HB_FreeFace(shaperItem.face);
|
||||||
@@ -603,5 +592,67 @@ void TextLayoutCacheValue::resetGlyphArrays(HB_ShaperItem* shaperItem) {
|
|||||||
memset(shaperItem->offsets, 0, size * sizeof(shaperItem->offsets[0]));
|
memset(shaperItem->offsets, 0, size * sizeof(shaperItem->offsets[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextLayoutCacheValue::getAdvances(size_t start, size_t count, jfloat* outAdvances) const {
|
||||||
|
memcpy(outAdvances, mAdvances.array() + start, count * sizeof(jfloat));
|
||||||
|
#if DEBUG_ADVANCES
|
||||||
|
LOGD("getAdvances - start=%d count=%d", start, count);
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
LOGD(" adv[%d] = %f", i, outAdvances[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
jfloat TextLayoutCacheValue::getTotalAdvance(size_t start, size_t count) const {
|
||||||
|
jfloat outTotalAdvance = 0;
|
||||||
|
for (size_t i = start; i < start + count; i++) {
|
||||||
|
outTotalAdvance += mAdvances[i];
|
||||||
|
}
|
||||||
|
#if DEBUG_ADVANCES
|
||||||
|
LOGD("getTotalAdvance - start=%d count=%d - total=%f", start, count, outTotalAdvance);
|
||||||
|
#endif
|
||||||
|
return outTotalAdvance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextLayoutCacheValue::getGlyphsIndexAndCount(size_t start, size_t count, size_t* outStartIndex,
|
||||||
|
size_t* outGlyphsCount) const {
|
||||||
|
*outStartIndex = 0;
|
||||||
|
if (count == 0) {
|
||||||
|
*outGlyphsCount = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t endIndex = 0;
|
||||||
|
for(size_t i = 0; i < mGlyphs.size(); i++) {
|
||||||
|
if (mLogClusters[i] <= start) {
|
||||||
|
*outStartIndex = i;
|
||||||
|
endIndex = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mLogClusters[i] <= start + count) {
|
||||||
|
endIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*outGlyphsCount = endIndex - *outStartIndex + 1;
|
||||||
|
#if DEBUG_GLYPHS
|
||||||
|
LOGD("getGlyphsIndexes - start=%d count=%d - startIndex=%d count=%d", start, count,
|
||||||
|
*outStartIndex, *outGlyphsCount);
|
||||||
|
for(size_t i = 0; i < mGlyphs.size(); i++) {
|
||||||
|
LOGD("getGlyphs - all - glyph[%d] = %d", i, mGlyphs[i]);
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < mGlyphs.size(); i++) {
|
||||||
|
LOGD("getGlyphs - all - logcl[%d] = %d", i, mLogClusters[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const jchar* TextLayoutCacheValue::getGlyphs(size_t startIndex, size_t count) {
|
||||||
|
const jchar* glyphs = mGlyphs.array() + startIndex;
|
||||||
|
#if DEBUG_GLYPHS
|
||||||
|
LOGD("getGlyphs - with startIndex = %d count = %d", startIndex, count);
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
LOGD("getGlyphs - result - glyph[%d] = %d", i, glyphs[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return glyphs;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|||||||
@@ -68,9 +68,7 @@ class TextLayoutCacheKey {
|
|||||||
public:
|
public:
|
||||||
TextLayoutCacheKey();
|
TextLayoutCacheKey();
|
||||||
|
|
||||||
TextLayoutCacheKey(const SkPaint* paint,
|
TextLayoutCacheKey(const SkPaint* paint, const UChar* text, size_t count, int dirFlags);
|
||||||
const UChar* text, size_t start, size_t count,
|
|
||||||
size_t contextCount, int dirFlags);
|
|
||||||
|
|
||||||
TextLayoutCacheKey(const TextLayoutCacheKey& other);
|
TextLayoutCacheKey(const TextLayoutCacheKey& other);
|
||||||
|
|
||||||
@@ -90,9 +88,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
const UChar* text; // if text is NULL, use textCopy
|
const UChar* text; // if text is NULL, use textCopy
|
||||||
String16 textCopy;
|
String16 textCopy;
|
||||||
size_t start;
|
|
||||||
size_t count;
|
size_t count;
|
||||||
size_t contextCount;
|
|
||||||
int dirFlags;
|
int dirFlags;
|
||||||
SkTypeface* typeface;
|
SkTypeface* typeface;
|
||||||
SkScalar textSize;
|
SkScalar textSize;
|
||||||
@@ -116,14 +112,13 @@ public:
|
|||||||
void setElapsedTime(uint32_t time);
|
void setElapsedTime(uint32_t time);
|
||||||
uint32_t getElapsedTime();
|
uint32_t getElapsedTime();
|
||||||
|
|
||||||
void computeValues(SkPaint* paint, const UChar* chars, size_t start, size_t count,
|
void computeValues(SkPaint* paint, const UChar* chars, size_t contextCount, int dirFlags);
|
||||||
size_t contextCount, int dirFlags);
|
|
||||||
|
|
||||||
inline const jfloat* getAdvances() const { return mAdvances.array(); }
|
void getAdvances(size_t start, size_t count, jfloat* outAdvances) const;
|
||||||
inline size_t getAdvancesCount() const { return mAdvances.size(); }
|
jfloat getTotalAdvance(size_t start, size_t count) const;
|
||||||
inline jfloat getTotalAdvance() const { return mTotalAdvance; }
|
void getGlyphsIndexAndCount(size_t start, size_t count, size_t* outStartIndex,
|
||||||
inline const jchar* getGlyphs() const { return mGlyphs.array(); }
|
size_t* outGlyphsCount) const;
|
||||||
inline size_t getGlyphsCount() const { return mGlyphs.size(); }
|
const jchar* getGlyphs(size_t startIndex, size_t count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the size of the Cache entry
|
* Get the size of the Cache entry
|
||||||
@@ -138,14 +133,10 @@ public:
|
|||||||
SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount,
|
SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount,
|
||||||
bool isRTL);
|
bool isRTL);
|
||||||
|
|
||||||
static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
|
static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
|
||||||
size_t count, size_t contextCount, int dirFlags,
|
size_t contextCount, int dirFlags,
|
||||||
Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
|
Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
|
||||||
Vector<jchar>* const outGlyphs);
|
Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters);
|
||||||
|
|
||||||
static void computeAdvancesWithICU(SkPaint* paint, const UChar* chars, size_t start,
|
|
||||||
size_t count, size_t contextCount, int dirFlags,
|
|
||||||
jfloat* outAdvances, jfloat* outTotalAdvance);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
@@ -163,6 +154,11 @@ private:
|
|||||||
*/
|
*/
|
||||||
Vector<jchar> mGlyphs;
|
Vector<jchar> mGlyphs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Harfbuzz Log Clusters
|
||||||
|
*/
|
||||||
|
Vector<unsigned short> mLogClusters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time for computing the values (in milliseconds)
|
* Time for computing the values (in milliseconds)
|
||||||
*/
|
*/
|
||||||
@@ -175,7 +171,7 @@ private:
|
|||||||
static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
|
static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
|
||||||
size_t count, size_t contextCount, bool isRTL,
|
size_t count, size_t contextCount, bool isRTL,
|
||||||
Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
|
Vector<jfloat>* const outAdvances, jfloat* outTotalAdvance,
|
||||||
Vector<jchar>* const outGlyphs);
|
Vector<jchar>* const outGlyphs, Vector<unsigned short>* const outLogClusters);
|
||||||
}; // TextLayoutCacheValue
|
}; // TextLayoutCacheValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -199,8 +195,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc);
|
void operator()(TextLayoutCacheKey& text, sp<TextLayoutCacheValue>& desc);
|
||||||
|
|
||||||
sp<TextLayoutCacheValue> getValue(SkPaint* paint,
|
sp<TextLayoutCacheValue> getValue(SkPaint* paint, const jchar* text, jint count,
|
||||||
const jchar* text, jint start, jint count, jint contextCount, jint dirFlags);
|
jint dirFlags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the cache
|
* Clear the cache
|
||||||
|
|||||||
@@ -477,19 +477,21 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
|
|||||||
#if RTL_USE_HARFBUZZ
|
#if RTL_USE_HARFBUZZ
|
||||||
sp<TextLayoutCacheValue> value;
|
sp<TextLayoutCacheValue> value;
|
||||||
#if USE_TEXT_LAYOUT_CACHE
|
#if USE_TEXT_LAYOUT_CACHE
|
||||||
value = TextLayoutCache::getInstance().getValue(paint, text, 0, count, count, flags);
|
value = TextLayoutCache::getInstance().getValue(paint, text, count, flags);
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
LOGE("Cannot get TextLayoutCache value");
|
LOGE("Cannot get TextLayoutCache value");
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
value = new TextLayoutCacheValue();
|
value = new TextLayoutCacheValue();
|
||||||
value->computeValues(paint, text, 0, count, count, flags);
|
value->computeValues(paint, text, count, flags);
|
||||||
#endif
|
#endif
|
||||||
const jchar* glyphArray = value->getGlyphs();
|
size_t startIndex = 0;
|
||||||
int glyphCount = value->getGlyphsCount();
|
size_t glyphsCount = 0;
|
||||||
int bytesCount = glyphCount * sizeof(jchar);
|
value->getGlyphsIndexAndCount(0, count, &startIndex, &glyphsCount);
|
||||||
renderer->drawText((const char*) glyphArray, bytesCount, glyphCount, x, y, paint);
|
const jchar* glyphs = value->getGlyphs(startIndex, glyphsCount);
|
||||||
|
int bytesCount = glyphsCount * sizeof(jchar);
|
||||||
|
renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint);
|
||||||
#else
|
#else
|
||||||
const jchar *workText;
|
const jchar *workText;
|
||||||
jchar* buffer = NULL;
|
jchar* buffer = NULL;
|
||||||
@@ -507,19 +509,21 @@ static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
|
|||||||
#if RTL_USE_HARFBUZZ
|
#if RTL_USE_HARFBUZZ
|
||||||
sp<TextLayoutCacheValue> value;
|
sp<TextLayoutCacheValue> value;
|
||||||
#if USE_TEXT_LAYOUT_CACHE
|
#if USE_TEXT_LAYOUT_CACHE
|
||||||
value = TextLayoutCache::getInstance().getValue(paint, text, start, count, contextCount, flags);
|
value = TextLayoutCache::getInstance().getValue(paint, text, contextCount, flags);
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
LOGE("Cannot get TextLayoutCache value");
|
LOGE("Cannot get TextLayoutCache value");
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
value = new TextLayoutCacheValue();
|
value = new TextLayoutCacheValue();
|
||||||
value->computeValues(paint, text, start, count, contextCount, flags);
|
value->computeValues(paint, text, contextCount, flags);
|
||||||
#endif
|
#endif
|
||||||
const jchar* glyphArray = value->getGlyphs();
|
size_t startIndex = 0;
|
||||||
int glyphCount = value->getGlyphsCount();
|
size_t glyphsCount = 0;
|
||||||
int bytesCount = glyphCount * sizeof(jchar);
|
value->getGlyphsIndexAndCount(start, count, &startIndex, &glyphsCount);
|
||||||
renderer->drawText((const char*) glyphArray, bytesCount, glyphCount, x, y, paint);
|
const jchar* glyphs = value->getGlyphs(startIndex, glyphsCount);
|
||||||
|
int bytesCount = glyphsCount * sizeof(jchar);
|
||||||
|
renderer->drawText((const char*) glyphs, bytesCount, glyphsCount, x, y, paint);
|
||||||
#else
|
#else
|
||||||
uint8_t rtl = flags & 0x1;
|
uint8_t rtl = flags & 0x1;
|
||||||
if (rtl) {
|
if (rtl) {
|
||||||
|
|||||||
Reference in New Issue
Block a user