Hardware implementation of glyph positioning (bug 5443796)

This implementation adds a drawGeneralText() method to the OpenGL
Renderer, which supports both a global x, y position, an array of
individual glyph positions, and also a length parameter (which enables
drawing of underline and strikethrough. It also adds the method to the
display list (with marshalling and unmarshalling).

With this change, the existing drawText() method is removed entirely, as
it's subsumed by the new method. It's easy enough to revert to the old
functionality if needed by passing in a NULL positions array.

Change-Id: I8c9e6ce4309fd51cc5511db85df99f6de8f4f6f5
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 133f63f..7161c58 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -61,9 +61,9 @@
     "DrawPath",
     "DrawLines",
     "DrawPoints",
-    "DrawText",
     "DrawTextOnPath",
     "DrawPosText",
+    "DrawGeneralText",
     "ResetShader",
     "SetupShader",
     "ResetColorFilter",
@@ -572,17 +572,6 @@
                 ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
             }
             break;
-            case DrawText: {
-                getText(&text);
-                int32_t count = getInt();
-                float x = getFloat();
-                float y = getFloat();
-                SkPaint* paint = getPaint(renderer);
-                float length = getFloat();
-                ALOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent, OP_NAMES[op],
-                        text.text(), text.length(), count, x, y, paint, length);
-            }
-            break;
             case DrawTextOnPath: {
                 getText(&text);
                 int32_t count = getInt();
@@ -603,6 +592,17 @@
                 ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
                         text.text(), text.length(), count, paint);
             }
+            break;
+            case DrawGeneralText: {
+                getText(&text);
+                int count = getInt();
+                int positionsCount = 0;
+                float* positions = getFloats(positionsCount);
+                SkPaint* paint = getPaint(renderer);
+                ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
+                        text.text(), text.length(), count, paint);
+            }
+            break;
             case ResetShader: {
                 ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
             }
@@ -1196,19 +1196,6 @@
                 drawGlStatus |= renderer.drawPoints(points, count, paint);
             }
             break;
-            case DrawText: {
-                getText(&text);
-                int32_t count = getInt();
-                float x = getFloat();
-                float y = getFloat();
-                SkPaint* paint = getPaint(renderer);
-                float length = getFloat();
-                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
-                        OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
-                drawGlStatus |= renderer.drawText(text.text(), text.length(), count, x, y,
-                        paint, length);
-            }
-            break;
             case DrawTextOnPath: {
                 getText(&text);
                 int32_t count = getInt();
@@ -1234,6 +1221,21 @@
                         positions, paint);
             }
             break;
+            case DrawGeneralText: {
+                getText(&text);
+                int32_t count = getInt();
+                float x = getFloat();
+                float y = getFloat();
+                int32_t positionsCount = 0;
+                float* positions = getFloats(positionsCount);
+                SkPaint* paint = getPaint(renderer);
+                float length = getFloat();
+                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
+                        OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
+                drawGlStatus |= renderer.drawGeneralText(text.text(), text.length(), count,
+                        x, y, positions, paint, length);
+            }
+            break;
             case ResetShader: {
                 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
                 renderer.resetShader();
@@ -1684,37 +1686,6 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
-        float x, float y, SkPaint* paint, float length) {
-    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
-
-    // TODO: We should probably make a copy of the paint instead of modifying
-    //       it; modifying the paint will change its generationID the first
-    //       time, which might impact caches. More investigation needed to
-    //       see if it matters.
-    //       If we make a copy, then drawTextDecorations() should *not* make
-    //       its own copy as it does right now.
-    // Beware: this needs Glyph encoding (already done on the Paint constructor)
-    paint->setAntiAlias(true);
-    if (length < 0.0f) length = paint->measureText(text, bytesCount);
-
-    bool reject = false;
-    if (CC_LIKELY(paint->getTextAlign() == SkPaint::kLeft_Align)) {
-        SkPaint::FontMetrics metrics;
-        paint->getFontMetrics(&metrics, 0.0f);
-        reject = quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom);
-    }
-
-    uint32_t* location = addOp(DisplayList::DrawText, reject);
-    addText(text, bytesCount);
-    addInt(count);
-    addPoint(x, y);
-    addPaint(paint);
-    addFloat(length);
-    addSkip(location);
-    return DrawGlInfo::kStatusDone;
-}
-
 status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
         SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
@@ -1741,6 +1712,39 @@
     return DrawGlInfo::kStatusDone;
 }
 
+status_t DisplayListRenderer::drawGeneralText(const char* text, int bytesCount, int count,
+        float x, float y, const float* positions, SkPaint* paint, float length) {
+    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
+
+    // TODO: We should probably make a copy of the paint instead of modifying
+    //       it; modifying the paint will change its generationID the first
+    //       time, which might impact caches. More investigation needed to
+    //       see if it matters.
+    //       If we make a copy, then drawTextDecorations() should *not* make
+    //       its own copy as it does right now.
+    // Beware: this needs Glyph encoding (already done on the Paint constructor)
+    paint->setAntiAlias(true);
+    if (length < 0.0f) length = paint->measureText(text, bytesCount);
+
+    bool reject = false;
+    if (CC_LIKELY(paint->getTextAlign() == SkPaint::kLeft_Align)) {
+        SkPaint::FontMetrics metrics;
+        paint->getFontMetrics(&metrics, 0.0f);
+        reject = quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom);
+    }
+
+    uint32_t* location = addOp(DisplayList::DrawGeneralText, reject);
+    addText(text, bytesCount);
+    addInt(count);
+    addFloat(x);
+    addFloat(y);
+    addFloats(positions, count * 2);
+    addPaint(paint);
+    addFloat(length);
+    addSkip(location);
+    return DrawGlInfo::kStatusDone;
+}
+
 void DisplayListRenderer::resetShader() {
     addOp(DisplayList::ResetShader);
 }