Draw an empty border around glyphs to avoid sampling issues
Bug #6942209

The font renderer was preserving a 1 px border around each glyph to ensure
bilinear filtering would work nicely. Unfortunately, this border was not
set to 0 when glyphs were added in the cache to replace old evicted glyphs.

Change-Id: Ib85afca7ebad5cb63f960dc0e87ae162333dbfe8
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 7f0ed73..11f30fc 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -37,7 +37,7 @@
 #define DEFAULT_TEXT_CACHE_WIDTH 1024
 #define DEFAULT_TEXT_CACHE_HEIGHT 256
 #define MAX_TEXT_CACHE_WIDTH 2048
-#define TEXTURE_BORDER_SIZE 2
+#define TEXTURE_BORDER_SIZE 1
 
 #define AUTO_KERN(prev, next) (((next) - (prev) + 32) >> 6 << 16)
 
@@ -50,10 +50,10 @@
         return false;
     }
 
-    if (mCurrentCol + glyph.fWidth + TEXTURE_BORDER_SIZE < mMaxWidth) {
-        *retOriginX = mCurrentCol + 1;
-        *retOriginY = mCurrentRow + 1;
-        mCurrentCol += glyph.fWidth + TEXTURE_BORDER_SIZE;
+    if (mCurrentCol + glyph.fWidth + TEXTURE_BORDER_SIZE * 2 < mMaxWidth) {
+        *retOriginX = mCurrentCol + TEXTURE_BORDER_SIZE;
+        *retOriginY = mCurrentRow + TEXTURE_BORDER_SIZE;
+        mCurrentCol += glyph.fWidth + TEXTURE_BORDER_SIZE * 2;
         mDirty = true;
         return true;
     }
@@ -412,10 +412,10 @@
     uint32_t cacheWidth = glyph->mCachedTextureLine->mCacheTexture->mWidth;
     uint32_t cacheHeight = glyph->mCachedTextureLine->mCacheTexture->mHeight;
 
-    glyph->mBitmapMinU = (float) startX / (float) cacheWidth;
-    glyph->mBitmapMinV = (float) startY / (float) cacheHeight;
-    glyph->mBitmapMaxU = (float) endX / (float) cacheWidth;
-    glyph->mBitmapMaxV = (float) endY / (float) cacheHeight;
+    glyph->mBitmapMinU = startX / (float) cacheWidth;
+    glyph->mBitmapMinV = startY / (float) cacheHeight;
+    glyph->mBitmapMaxU = endX / (float) cacheWidth;
+    glyph->mBitmapMaxV = endY / (float) cacheHeight;
 
     mState->mUploadTexture = true;
 }
@@ -590,9 +590,6 @@
     int height = cacheTexture->mHeight;
 
     cacheTexture->mTexture = new uint8_t[width * height];
-#if DEBUG_FONT_RENDERER
-    memset(cacheTexture->mTexture, 0, width * height * sizeof(uint8_t));
-#endif
 
     if (!cacheTexture->mTextureId) {
         glGenTextures(1, &cacheTexture->mTextureId);
@@ -617,7 +614,7 @@
         uint32_t* retOriginX, uint32_t* retOriginY) {
     cachedGlyph->mIsValid = false;
     // If the glyph is too tall, don't cache it
-    if (glyph.fHeight + TEXTURE_BORDER_SIZE > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
+    if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
         ALOGE("Font size to large to fit in cache. width, height = %i, %i",
                 (int) glyph.fWidth, (int) glyph.fHeight);
         return;
@@ -677,6 +674,18 @@
     unsigned int stride = glyph.rowBytes();
 
     uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
+
+    for (cacheX = startX - TEXTURE_BORDER_SIZE; cacheX < endX + TEXTURE_BORDER_SIZE; cacheX++) {
+        cacheBuffer[(startY - TEXTURE_BORDER_SIZE) * cacheWidth + cacheX] = 0;
+        cacheBuffer[(endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + cacheX] = 0;
+    }
+
+    for (cacheY = startY - TEXTURE_BORDER_SIZE + 1;
+            cacheY < endY + TEXTURE_BORDER_SIZE - 1; cacheY++) {
+        cacheBuffer[cacheY * cacheWidth + startX - TEXTURE_BORDER_SIZE] = 0;
+        cacheBuffer[cacheY * cacheWidth + endX + TEXTURE_BORDER_SIZE - 1] = 0;
+    }
+
     if (mGammaTable) {
         for (cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) {
             for (cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY++) {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 580d6b5..6639231 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2892,7 +2892,7 @@
         // the blending, turn blending off here
         // If the blend mode cannot be implemented using shaders, fall
         // back to the default SrcOver blend mode instead
-        if CC_UNLIKELY((mode > SkXfermode::kScreen_Mode)) {
+        if (CC_UNLIKELY(mode > SkXfermode::kScreen_Mode)) {
             if (CC_UNLIKELY(mCaches.extensions.hasFramebufferFetch())) {
                 description.framebufferMode = mode;
                 description.swapSrcDst = swapSrcDst;
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
index 0a868fa..4a1f5a2 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
@@ -153,6 +153,12 @@
             canvas.drawText("Hello OpenGL renderer!", 100, 300, mLargePaint);
             canvas.restore();
 
+//            mStrikePaint.setUnderlineText(false);
+//            canvas.save();
+//            canvas.scale(20.0f, 20.0f);
+//            canvas.drawText("aeiouyw", 5.0f, 750 / 20.0f, mStrikePaint);
+//            canvas.restore();
+//            mStrikePaint.setUnderlineText(true);
         }
     }
 }