Cleanup, added properties for the FontRenderer.

Change-Id: I909c74815d3ac394438ad8071d17fef5401dbeed
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index c3d2448..99b34dd 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -44,19 +44,33 @@
         } while (head);
 
         mHasNPot = hasExtension("GL_OES_texture_npot");
+        mHasDrawPath = hasExtension("GL_NV_draw_path");
+        mHasCoverageSample = hasExtension("GL_NV_coverage_sample");
+
+        mExtensions = buffer;
     }
 
     inline bool hasNPot() const { return mHasNPot; }
+    inline bool hasDrawPath() const { return mHasDrawPath; }
+    inline bool hasCoverageSample() const { return mHasCoverageSample; }
 
     bool hasExtension(const char* extension) const {
         const String8 s(extension);
         return mExtensionList.indexOf(s) >= 0;
     }
 
+    void dump() {
+        LOGD("Supported extensions:\n%s", mExtensions);
+    }
+
 private:
     SortedVector<String8> mExtensionList;
 
+    const char* mExtensions;
+
     bool mHasNPot;
+    bool mHasDrawPath;
+    bool mHasCoverageSample;
 }; // class Extensions
 
 }; // namespace uirenderer
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 5ab89e2..24dee55 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -16,14 +16,24 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
-#include "FontRenderer.h"
-
 #include <SkUtils.h>
 
+#include <cutils/properties.h>
+#include <utils/Log.h>
+
+#include "FontRenderer.h"
+
 namespace android {
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+#define DEFAULT_TEXT_CACHE_WIDTH 1024
+#define DEFAULT_TEXT_CACHE_HEIGHT 256
+
+///////////////////////////////////////////////////////////////////////////////
 // Font
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -41,7 +51,7 @@
     }
 
     for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
-        CachedGlyphInfo *glyph = mCachedGlyphs.valueAt(i);
+        CachedGlyphInfo* glyph = mCachedGlyphs.valueAt(i);
         delete glyph;
     }
 }
@@ -53,19 +63,24 @@
 }
 
 void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y) {
-    FontRenderer *state = mState;
-
     int nPenX = x + glyph->mBitmapLeft;
     int nPenY = y + glyph->mBitmapTop + glyph->mBitmapHeight;
 
-    state->appendMeshQuad(nPenX, nPenY, 0, glyph->mBitmapMinU, glyph->mBitmapMaxV,
-            nPenX + (int) glyph->mBitmapWidth, nPenY, 0, glyph->mBitmapMaxU, glyph->mBitmapMaxV,
-            nPenX + (int) glyph->mBitmapWidth, nPenY - (int) glyph->mBitmapHeight,
-            0, glyph->mBitmapMaxU, glyph->mBitmapMinV, nPenX, nPenY - (int) glyph->mBitmapHeight,
-            0, glyph->mBitmapMinU, glyph->mBitmapMinV);
+    float u1 = glyph->mBitmapMinU;
+    float u2 = glyph->mBitmapMaxU;
+    float v1 = glyph->mBitmapMinV;
+    float v2 = glyph->mBitmapMaxV;
+
+    int width = (int) glyph->mBitmapWidth;
+    int height = (int) glyph->mBitmapHeight;
+
+    mState->appendMeshQuad(nPenX, nPenY, 0, u1, v2,
+            nPenX + width, nPenY, 0, u2, v2,
+            nPenX + width, nPenY - height, 0, u2, v1,
+            nPenX, nPenY - height, 0, u1, v1);
 }
 
-void Font::renderUTF(SkPaint* paint, const char *text, uint32_t len, uint32_t start,
+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) {
         return;
@@ -77,13 +92,9 @@
         glyphsLeft = numGlyphs;
     }
 
-    //size_t index = start;
-    //size_t nextIndex = 0;
-
     text += start;
 
     while (glyphsLeft > 0) {
-        //int32_t utfChar = utf32_at(text, len, index, &nextIndex);
         int32_t utfChar = SkUTF16_NextUnichar((const uint16_t**) &text);
 
         // Reached the end of the string or encountered
@@ -91,14 +102,11 @@
             break;
         }
 
-        // Move to the next character in the array
-        //index = nextIndex;
-
-        CachedGlyphInfo *cachedGlyph = mCachedGlyphs.valueFor(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);
@@ -119,7 +127,7 @@
     }
 }
 
-void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph) {
+void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph) {
     glyph->mAdvanceX = skiaGlyph.fAdvanceX;
     glyph->mAdvanceY = skiaGlyph.fAdvanceY;
     glyph->mBitmapLeft = skiaGlyph.fLeft;
@@ -128,11 +136,9 @@
     uint32_t startX = 0;
     uint32_t startY = 0;
 
-    // Let the font state figure out where to put the bitmap
-    FontRenderer *state = mState;
     // Get the bitmap for the glyph
     paint->findImage(skiaGlyph);
-    glyph->mIsValid = state->cacheBitmap(skiaGlyph, &startX, &startY);
+    glyph->mIsValid = mState->cacheBitmap(skiaGlyph, &startX, &startY);
 
     if (!glyph->mIsValid) {
         return;
@@ -144,19 +150,19 @@
     glyph->mBitmapWidth = skiaGlyph.fWidth;
     glyph->mBitmapHeight = skiaGlyph.fHeight;
 
-    uint32_t cacheWidth = state->getCacheWidth();
-    uint32_t cacheHeight = state->getCacheHeight();
+    uint32_t cacheWidth = mState->getCacheWidth();
+    uint32_t cacheHeight = mState->getCacheHeight();
 
     glyph->mBitmapMinU = (float) startX / (float) cacheWidth;
     glyph->mBitmapMinV = (float) startY / (float) cacheHeight;
     glyph->mBitmapMaxU = (float) endX / (float) cacheWidth;
     glyph->mBitmapMaxV = (float) endY / (float) cacheHeight;
 
-    state->mUploadTexture = true;
+    mState->mUploadTexture = true;
 }
 
-Font::CachedGlyphInfo *Font::cacheGlyph(SkPaint* paint, int32_t glyph) {
-    CachedGlyphInfo *newGlyph = new CachedGlyphInfo();
+Font::CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, int32_t glyph) {
+    CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
     mCachedGlyphs.add(glyph, newGlyph);
 
     const SkGlyph& skiaGlyph = paint->getUnicharMetrics(glyph);
@@ -172,9 +178,9 @@
     Vector<Font*> &activeFonts = state->mActiveFonts;
 
     for (uint32_t i = 0; i < activeFonts.size(); i++) {
-        Font *ithFont = activeFonts[i];
-        if (ithFont->mFontId == fontId && ithFont->mFontSize == fontSize) {
-            return ithFont;
+        Font* font = activeFonts[i];
+        if (font->mFontId == fontId && font->mFontSize == fontSize) {
+            return font;
         }
     }
 
@@ -188,14 +194,31 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 FontRenderer::FontRenderer() {
+    LOGD("Creating FontRenderer");
+
     mInitialized = false;
     mMaxNumberOfQuads = 1024;
     mCurrentQuadIndex = 0;
 
     mIndexBufferID = 0;
 
-    mCacheWidth = 1024;
-    mCacheHeight = 256;
+    mCacheWidth = DEFAULT_TEXT_CACHE_WIDTH;
+    mCacheHeight = DEFAULT_TEXT_CACHE_WIDTH;
+
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get(PROPERTY_TEXT_CACHE_WIDTH, property, NULL) > 0) {
+        LOGD("  Setting text cache width to %s pixels", property);
+        mCacheWidth = atoi(property);
+    } else {
+        LOGD("  Using default text cache width of %i pixels", mCacheWidth);
+    }
+
+    if (property_get(PROPERTY_TEXT_CACHE_HEIGHT, property, NULL) > 0) {
+        LOGD("  Setting text cache width to %s pixels", property);
+        mCacheHeight = atoi(property);
+    } else {
+        LOGD("  Using default text cache height of %i pixels", mCacheHeight);
+    }
 }
 
 FontRenderer::~FontRenderer() {
@@ -225,7 +248,7 @@
     }
 }
 
-bool FontRenderer::cacheBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
+bool FontRenderer::cacheBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY) {
     // If the glyph is too tall, don't cache it
     if (glyph.fWidth > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
         LOGE("Font size to large to fit in cache. width, height = %i, %i",
@@ -273,8 +296,8 @@
 
     uint32_t cacheWidth = mCacheWidth;
 
-    unsigned char *cacheBuffer = mTextTexture;
-    unsigned char *bitmapBuffer = (unsigned char*) glyph.fImage;
+    unsigned char* cacheBuffer = mTextTexture;
+    unsigned char* bitmapBuffer = (unsigned char*) glyph.fImage;
     unsigned int stride = glyph.rowBytes();
 
     uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0;
@@ -304,24 +327,24 @@
 
     // Split up our cache texture into lines of certain widths
     int nextLine = 0;
-    mCacheLines.push(new CacheTextureLine(16, mCacheWidth, nextLine, 0));
+    mCacheLines.push(new CacheTextureLine(mCacheWidth, 16, nextLine, 0));
     nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(24, mCacheWidth, nextLine, 0));
+    mCacheLines.push(new CacheTextureLine(mCacheWidth, 24, nextLine, 0));
     nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(32, mCacheWidth, nextLine, 0));
+    mCacheLines.push(new CacheTextureLine(mCacheWidth, 32, nextLine, 0));
     nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(32, mCacheWidth, nextLine, 0));
+    mCacheLines.push(new CacheTextureLine(mCacheWidth, 32, nextLine, 0));
     nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(40, mCacheWidth, nextLine, 0));
+    mCacheLines.push(new CacheTextureLine(mCacheWidth, 40, nextLine, 0));
     nextLine += mCacheLines.top()->mMaxHeight;
-    mCacheLines.push(new CacheTextureLine(mCacheHeight - nextLine, mCacheWidth, nextLine, 0));
+    mCacheLines.push(new CacheTextureLine(mCacheWidth, mCacheHeight - nextLine, nextLine, 0));
 }
 
 // Avoid having to reallocate memory and render quad by quad
 void FontRenderer::initVertexArrayBuffers() {
     uint32_t numIndicies = mMaxNumberOfQuads * 6;
     uint32_t indexBufferSizeBytes = numIndicies * sizeof(uint16_t);
-    uint16_t *indexBufferData = (uint16_t*) malloc(indexBufferSizeBytes);
+    uint16_t* indexBufferData = (uint16_t*) malloc(indexBufferSizeBytes);
 
     // Four verts, two triangles , six indices per quad
     for (uint32_t i = 0; i < mMaxNumberOfQuads; i++) {
@@ -372,8 +395,8 @@
         mUploadTexture = false;
     }
 
-    float *vtx = mTextMeshPtr;
-    float *tex = vtx + 3;
+    float* vtx = mTextMeshPtr;
+    float* tex = vtx + 3;
 
     // position is slot 0
     uint32_t slot = 0;
@@ -396,7 +419,7 @@
 
     const uint32_t vertsPerQuad = 4;
     const uint32_t floatsPerVert = 5;
-    float *currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
+    float* currentPos = mTextMeshPtr + mCurrentQuadIndex * vertsPerQuad * floatsPerVert;
 
     (*currentPos++) = x1;
     (*currentPos++) = y1;
@@ -434,8 +457,8 @@
     mCurrentFont = Font::create(this, fontId, fontSize);
 }
 
-void FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t len,
-        uint32_t startIndex, int numGlyphs, int x, int y) {
+void FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text,
+        uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y) {
     checkInit();
 
     if (!mCurrentFont) {
@@ -444,7 +467,7 @@
     }
 
     mClip = clip;
-    mCurrentFont->renderUTF(paint, text, len, startIndex, numGlyphs, x, y);
+    mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, x, y);
 
     if (mCurrentQuadIndex != 0) {
         issueDrawCommand();
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 3d4d49c..c1cd7fb 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -27,19 +27,29 @@
 #include <GLES2/gl2.h>
 
 #include "Rect.h"
+#include "Properties.h"
 
 namespace android {
 namespace uirenderer {
 
 class FontRenderer;
 
+/**
+ * Represents a font, defined by a Skia font id and a font size. A font is used
+ * to generate glyphs and cache them in the FontState.
+ */
 class Font {
 public:
     ~Font();
 
-    void renderUTF(SkPaint* paint, const char *text, uint32_t len, uint32_t start,
+    /**
+     * Renders the specified string of text.
+     */
+    void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
             int numGlyphs, int x, int y);
-
+    /**
+     * Creates a new font associated with the specified font state.
+     */
     static Font* create(FontRenderer* state, uint32_t fontId, float fontSize);
 
 protected:
@@ -90,8 +100,8 @@
     void deinit();
 
     void setFont(uint32_t fontId, float fontSize);
-    void renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t len,
-            uint32_t startIndex, int numGlyphs, int x, int y);
+    void renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
+            uint32_t len, int numGlyphs, int x, int y);
 
     GLuint getTexture() {
         checkInit();
@@ -107,10 +117,12 @@
         uint32_t mCurrentRow;
         uint32_t mCurrentCol;
 
-        CacheTextureLine(uint16_t maxHeight, uint16_t maxWidth, uint32_t currentRow,
+        CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
                 uint32_t currentCol):
-            mMaxHeight(maxHeight), mMaxWidth(maxWidth), mCurrentRow(currentRow),
-            mCurrentCol(currentCol) {
+                    mMaxHeight(maxHeight),
+                    mMaxWidth(maxWidth),
+                    mCurrentRow(currentRow),
+                    mCurrentCol(currentCol) {
         }
 
         bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 58a3a69..c6a2e33 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -27,6 +27,7 @@
 #include <utils/Log.h>
 
 #include "OpenGLRenderer.h"
+#include "Properties.h"
 
 namespace android {
 namespace uirenderer {
@@ -35,11 +36,6 @@
 // Defines
 ///////////////////////////////////////////////////////////////////////////////
 
-// These properties are defined in mega-bytes
-#define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size"
-#define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
-#define PROPERTY_GRADIENT_CACHE_SIZE "ro.hwui.gradient_cache_size"
-
 #define DEFAULT_TEXTURE_CACHE_SIZE 20.0f
 #define DEFAULT_LAYER_CACHE_SIZE 10.0f
 #define DEFAULT_PATCH_CACHE_SIZE 100
@@ -555,7 +551,7 @@
     const Rect& clip = mSnapshot->getLocalClip();
 
     mFontRenderer.setFont(SkTypeface::UniqueID(paint->getTypeface()), paint->getTextSize());
-    mFontRenderer.renderText(paint, &clip, text, count, 0, count, x, y);
+    mFontRenderer.renderText(paint, &clip, text, 0, count, count, x, y);
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 }
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 6d30282..43e568f 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -30,6 +30,7 @@
 #include <utils/RefBase.h>
 #include <utils/ResourceTypes.h>
 
+#include "Extensions.h"
 #include "Matrix.h"
 #include "Program.h"
 #include "Rect.h"
@@ -40,7 +41,6 @@
 #include "PatchCache.h"
 #include "Vertex.h"
 #include "FontRenderer.h"
-#include "Extensions.h"
 
 namespace android {
 namespace uirenderer {
@@ -362,6 +362,9 @@
     float* mShaderPositions;
     int mShaderCount;
 
+    // GL extensions
+    Extensions mExtensions;
+
     // Font renderer
     FontRenderer mFontRenderer;
 
@@ -370,8 +373,6 @@
     LayerCache mLayerCache;
     GradientCache mGradientCache;
     PatchCache mPatchCache;
-
-    Extensions mExtensions;
 }; // class OpenGLRenderer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
new file mode 100644
index 0000000..4f20a95
--- /dev/null
+++ b/libs/hwui/Properties.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UI_PROPERTIES_H
+#define ANDROID_UI_PROPERTIES_H
+
+/**
+ * This file contains the list of system properties used to configure
+ * the OpenGLRenderer.
+ */
+
+// These properties are defined in mega-bytes
+#define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size"
+#define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
+#define PROPERTY_GRADIENT_CACHE_SIZE "ro.hwui.gradient_cache_size"
+
+// These properties are defined in pixels
+#define PROPERTY_TEXT_CACHE_WIDTH "ro.hwui.text_cache_width"
+#define PROPERTY_TEXT_CACHE_HEIGHT "ro.hwui.text_cache_height"
+
+#endif // ANDROID_UI_PROPERTIES_H
+