When font cache still has empty space,
precache some commonly used characters to reduce studder.
Change-Id: I1f66f57482c4a025672dfd1d8ecaf2b9736cd9a0
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 14ad7d7..5595ab0 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -80,6 +80,21 @@
nPenX, nPenY - height, 0, u1, v1);
}
+Font::CachedGlyphInfo* Font::getCachedUTFChar(SkPaint* paint, int32_t utfChar) {
+ CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueFor(utfChar);
+ if (cachedGlyph == NULL) {
+ cachedGlyph = cacheGlyph(paint, utfChar);
+ }
+
+ // Is the glyph still in texture cache?
+ if (!cachedGlyph->mIsValid) {
+ const SkGlyph& skiaGlyph = paint->getUnicharMetrics(utfChar);
+ updateGlyphCache(paint, skiaGlyph, cachedGlyph);
+ }
+
+ return cachedGlyph;
+}
+
void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
int numGlyphs, int x, int y) {
if (numGlyphs == 0 || text == NULL || len == 0) {
@@ -102,16 +117,7 @@
break;
}
- CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueFor(utfChar);
- if (cachedGlyph == NULL) {
- cachedGlyph = cacheGlyph(paint, utfChar);
- }
-
- // Is the glyph still in texture cache?
- if (!cachedGlyph->mIsValid) {
- const SkGlyph& skiaGlyph = paint->getUnicharMetrics(utfChar);
- updateGlyphCache(paint, skiaGlyph, cachedGlyph);
- }
+ CachedGlyphInfo* cachedGlyph = getCachedUTFChar(paint, utfChar);
// If it's still not valid, we couldn't cache it, so we shouldn't draw garbage
if (cachedGlyph->mIsValid) {
@@ -340,6 +346,8 @@
nextLine += mCacheLines.top()->mMaxHeight;
mCacheLines.push(new CacheTextureLine(mCacheWidth, 24, nextLine, 0));
nextLine += mCacheLines.top()->mMaxHeight;
+ mCacheLines.push(new CacheTextureLine(mCacheWidth, 24, nextLine, 0));
+ nextLine += mCacheLines.top()->mMaxHeight;
mCacheLines.push(new CacheTextureLine(mCacheWidth, 32, nextLine, 0));
nextLine += mCacheLines.top()->mMaxHeight;
mCacheLines.push(new CacheTextureLine(mCacheWidth, 32, nextLine, 0));
@@ -392,6 +400,12 @@
initTextTexture();
initVertexArrayBuffers();
+ // We store a string with letters in a rough frequency of occurrence
+ mLatinPrecache = String16("eisarntolcdugpmhbyfvkwzxjq ");
+ mLatinPrecache += String16("EISARNTOLCDUGPMHBYFVKWZXJQ");
+ mLatinPrecache += String16(",.?!()-+@;:`'");
+ mLatinPrecache += String16("0123456789");
+
mInitialized = true;
}
@@ -484,8 +498,38 @@
}
}
-void FontRenderer::setFont(uint32_t fontId, float fontSize) {
+uint32_t FontRenderer::getRemainingCacheCapacity() {
+ uint32_t remainingCapacity = 0;
+ float totalPixels = 0;
+ for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
+ remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol);
+ totalPixels += mCacheLines[i]->mMaxWidth;
+ }
+ remainingCapacity = (remainingCapacity * 100) / totalPixels;
+ return remainingCapacity;
+}
+
+void FontRenderer::precacheLatin(SkPaint* paint) {
+ // Remaining capacity is measured in %
+ uint32_t remainingCapacity = getRemainingCacheCapacity();
+ uint32_t precacheIdx = 0;
+ while(remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) {
+ mCurrentFont->getCachedUTFChar(paint, (int32_t)mLatinPrecache[precacheIdx]);
+ remainingCapacity = getRemainingCacheCapacity();
+ precacheIdx ++;
+ }
+}
+
+void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) {
+ uint32_t currentNumFonts = mActiveFonts.size();
mCurrentFont = Font::create(this, fontId, fontSize);
+
+ const float maxPrecacheFontSize = 40.0f;
+ bool isNewFont = currentNumFonts != mActiveFonts.size();
+
+ if(isNewFont && fontSize <= maxPrecacheFontSize ){
+ precacheLatin(paint);
+ }
}
void FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text,