Add hack for custom re-rasterization buckets

bug:14083128

Moves all of the font transform management into
OpenGLRenderer::findBestFontTransform(), and now simply passes down
final rasterization transforms into the FontRenderer.

Change-Id: Ie02752e6af863347b142367c7d628db5f9fc2998
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 402f28b..8e3c444 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -724,14 +724,18 @@
         propertyLightDiameter = fmin(fmax(atof(value), 0.0), 3000.0);
         ALOGD("lightDiameter = %.2f", propertyLightDiameter);
         return;
-    }  else if (!strcmp(name, "lightPosY")) {
+    } else if (!strcmp(name, "lightPosY")) {
         propertyLightPosY = fmin(fmax(atof(value), 0.0), 3000.0);
         ALOGD("lightPos Y = %.2f", propertyLightPosY);
         return;
-    }  else if (!strcmp(name, "lightPosZ")) {
+    } else if (!strcmp(name, "lightPosZ")) {
         propertyLightPosZ = fmin(fmax(atof(value), 0.0), 3000.0);
         ALOGD("lightPos Z = %.2f", propertyLightPosZ);
         return;
+    } else if (!strcmp(name, "extraRasterBucket")) {
+        float bucket = atof(value);
+        propertyExtraRasterBuckets.push_back(bucket);
+        return;
     }
     ALOGD("    failed");
 }
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 83a5d9a..8727941 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -21,6 +21,8 @@
     #define LOG_TAG "OpenGLRenderer"
 #endif
 
+#include <vector>
+
 #include <GLES3/gl3.h>
 
 #include <utils/KeyedVector.h>
@@ -366,7 +368,7 @@
     float propertyAmbientRatio;
     int propertyAmbientShadowStrength;
     int propertySpotShadowStrength;
-
+    std::vector<float> propertyExtraRasterBuckets;
 private:
     enum OverdrawColorSet {
         kColorSet_Default = 0,
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 9fb972b..901c69e 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1313,7 +1313,7 @@
             const DeferredDisplayState& state) {
         const SkPaint* paint = getPaint(renderer);
         FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
-        fontRenderer.precache(paint, mText, mCount, mat4::identity());
+        fontRenderer.precache(paint, mText, mCount, SkMatrix::I());
 
         deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
                 DeferredDisplayList::kOpBatch_Text :
@@ -1372,14 +1372,15 @@
             const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
             : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
             mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
-        memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
+        mPrecacheTransform = SkMatrix::InvalidMatrix();
     }
 
     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
             const DeferredDisplayState& state) {
         const SkPaint* paint = getPaint(renderer);
         FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
-        const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
+        SkMatrix transform;
+        renderer.findBestFontTransform(state.mMatrix, &transform);
         if (mPrecacheTransform != transform) {
             fontRenderer.precache(paint, mText, mCount, transform);
             mPrecacheTransform = transform;
@@ -1436,7 +1437,7 @@
     float mY;
     const float* mPositions;
     float mTotalAdvance;
-    mat4 mPrecacheTransform;
+    SkMatrix mPrecacheTransform;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index bf0ab5c..3910381 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -587,7 +587,7 @@
     }
 }
 
-void FontRenderer::setFont(const SkPaint* paint, const mat4& matrix) {
+void FontRenderer::setFont(const SkPaint* paint, const SkMatrix& matrix) {
     mCurrentFont = Font::create(this, paint, matrix);
 }
 
@@ -678,7 +678,7 @@
 }
 
 void FontRenderer::precache(const SkPaint* paint, const char* text, int numGlyphs,
-        const mat4& matrix) {
+        const SkMatrix& matrix) {
     Font* font = Font::create(this, paint, matrix);
     font->precache(paint, text, numGlyphs);
 }
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 8ce22b0..5c96c6b 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -95,9 +95,9 @@
         mGammaTable = gammaTable;
     }
 
-    void setFont(const SkPaint* paint, const mat4& matrix);
+    void setFont(const SkPaint* paint, const SkMatrix& matrix);
 
-    void precache(const SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix);
+    void precache(const SkPaint* paint, const char* text, int numGlyphs, const SkMatrix& matrix);
     void endPrecaching();
 
     // bounds is an out parameter
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index ce48ad3..1bbcff1 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2699,7 +2699,7 @@
     }
 
     FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
-    fontRenderer.setFont(paint, mat4::identity());
+    fontRenderer.setFont(paint, SkMatrix::I());
 
     int alpha;
     SkXfermode::Mode mode;
@@ -2736,20 +2736,41 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-mat4 OpenGLRenderer::findBestFontTransform(const mat4& transform) const {
-    mat4 fontTransform;
+bool OpenGLRenderer::findBestFontTransform(const mat4& transform, SkMatrix* outMatrix) const {
     if (CC_LIKELY(transform.isPureTranslate())) {
-        fontTransform = mat4::identity();
-    } else {
-        if (CC_UNLIKELY(transform.isPerspective())) {
-            fontTransform = mat4::identity();
-        } else {
-            float sx, sy;
-            currentTransform()->decomposeScale(sx, sy);
-            fontTransform.loadScale(sx, sy, 1.0f);
-        }
+        outMatrix->setIdentity();
+        return false;
+    } else if (CC_UNLIKELY(transform.isPerspective())) {
+        outMatrix->setIdentity();
+        return true;
     }
-    return fontTransform;
+
+    /**
+     * Input is a non-perspective, scaling transform. Generate a scale-only transform, based upon
+     * bucketed scale values. Special case for 'extra raster buckets' - disable filtration in the
+     * case of an exact match, and isSimple() transform
+     */
+    float sx, sy;
+    transform.decomposeScale(sx, sy);
+
+    float bestSx = roundf(fmaxf(1.0f, sx));
+    float bestSy = roundf(fmaxf(1.0f, sy));
+    bool filter = true;
+
+    for (unsigned int i = 0; i < mCaches.propertyExtraRasterBuckets.size(); i++) {
+        float bucket = mCaches.propertyExtraRasterBuckets[i];
+        if (sx == bucket && sy == bucket) {
+            bestSx = bestSy = bucket;
+            filter = !transform.isSimple(); // disable filter, if simple
+            break;
+        }
+
+        if (fabs(bucket - sx) < fabs(bestSx - sx)) bestSx = sx;
+        if (fabs(bucket - sy) < fabs(bestSy - sy)) bestSy = sy;
+    }
+
+    outMatrix->setScale(bestSx, bestSy);
+    return filter;
 }
 
 status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y,
@@ -2783,7 +2804,7 @@
     FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
 
     if (CC_UNLIKELY(hasTextShadow(paint))) {
-        fontRenderer.setFont(paint, mat4::identity());
+        fontRenderer.setFont(paint, SkMatrix::I());
         drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
                 alpha, oldX, oldY);
     }
@@ -2801,11 +2822,11 @@
     // Applying the full matrix in the shader is the easiest way to handle
     // rotation and perspective and allows us to always generated quads in the
     // font renderer which greatly simplifies the code, clipping in particular.
-    mat4 fontTransform = findBestFontTransform(transform);
+    SkMatrix fontTransform;
+    bool linearFilter = findBestFontTransform(transform, &fontTransform)
+            || fabs(y - (int) y) > 0.0f
+            || fabs(x - (int) x) > 0.0f;
     fontRenderer.setFont(paint, fontTransform);
-
-    // Pick the appropriate texture filtering
-    bool linearFilter = !pureTranslate || fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f;
     fontRenderer.setTextureFiltering(linearFilter);
 
     // TODO: Implement better clipping for scaled/rotated text
@@ -2849,7 +2870,7 @@
     mCaches.enableScissor();
 
     FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
-    fontRenderer.setFont(paint, mat4::identity());
+    fontRenderer.setFont(paint, SkMatrix::I());
     fontRenderer.setTextureFiltering(true);
 
     int alpha;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 8a1aebc..e7328be 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -316,10 +316,12 @@
     }
 
     /**
-     * Return the best transform to use to rasterize text given a full
-     * transform matrix.
+     * Build the best transform to use to rasterize text given a full
+     * transform matrix, and whether filteration is needed.
+     *
+     * Returns whether filtration is needed
      */
-    mat4 findBestFontTransform(const mat4& transform) const;
+    bool findBestFontTransform(const mat4& transform, SkMatrix* outMatrix) const;
 
 #if DEBUG_MERGE_BEHAVIOR
     void drawScreenSpaceColorRect(float left, float top, float right, float bottom, int color) {
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index a71db5b..2ea6c8c 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -45,7 +45,8 @@
     mDeviceProperties = SkDeviceProperties::Make(SkDeviceProperties::Geometry::MakeDefault(), 1.0f);
 }
 
-Font::FontDescription::FontDescription(const SkPaint* paint, const mat4& matrix) {
+Font::FontDescription::FontDescription(const SkPaint* paint, const SkMatrix& rasterMatrix)
+        : mLookupTransform(rasterMatrix) {
     mFontId = SkTypeface::UniqueID(paint->getTypeface());
     mFontSize = paint->getTextSize();
     mFlags = 0;
@@ -58,9 +59,6 @@
     mStrokeWidth = paint->getStrokeWidth();
     mAntiAliasing = paint->isAntiAlias();
     mHinting = paint->getHinting();
-    mLookupTransform.reset();
-    mLookupTransform[SkMatrix::kMScaleX] = roundf(fmaxf(1.0f, matrix[mat4::kScaleX]));
-    mLookupTransform[SkMatrix::kMScaleY] = roundf(fmaxf(1.0f, matrix[mat4::kScaleY]));
     if (!mLookupTransform.invert(&mInverseLookupTransform)) {
         ALOGW("Could not query the inverse lookup transform for this font");
     }
@@ -486,7 +484,7 @@
     return newGlyph;
 }
 
-Font* Font::create(FontRenderer* state, const SkPaint* paint, const mat4& matrix) {
+Font* Font::create(FontRenderer* state, const SkPaint* paint, const SkMatrix& matrix) {
     FontDescription description(paint, matrix);
     Font* font = state->mActiveFonts.get(description);
 
diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h
index 6ddd4f2..0f10464 100644
--- a/libs/hwui/font/Font.h
+++ b/libs/hwui/font/Font.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HWUI_FONT_H
 #define ANDROID_HWUI_FONT_H
 
+#include <vector>
+
 #include <utils/KeyedVector.h>
 
 #include <SkScalar.h>
@@ -50,7 +52,7 @@
     };
 
     struct FontDescription {
-        FontDescription(const SkPaint* paint, const mat4& matrix);
+        FontDescription(const SkPaint* paint, const SkMatrix& matrix);
 
         static int compare(const FontDescription& lhs, const FontDescription& rhs);
 
@@ -92,7 +94,7 @@
     /**
      * Creates a new font associated with the specified font state.
      */
-    static Font* create(FontRenderer* state, const SkPaint* paint, const mat4& matrix);
+    static Font* create(FontRenderer* state, const SkPaint* paint, const SkMatrix& matrix);
 
 private:
     friend class FontRenderer;