Implement a fast path for solid color lattice rectangle

Add a flag that hints, which lattice rectangles are solid colors.
Draw solid rectangles and 1x1 rectangles with drawRect.

Test: Measured performance of a ninepatch drawn by HWUI
Bug: b/69796044
Change-Id: Ib3b00ca608da42fa9f2d2038cc126a978421ec7c
Reviewed-on: https://skia-review.googlesource.com/79821
Commit-Queue: Stan Iliev <stani@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
diff --git a/src/core/SkLatticeIter.cpp b/src/core/SkLatticeIter.cpp
index 9b2a279..551982e 100644
--- a/src/core/SkLatticeIter.cpp
+++ b/src/core/SkLatticeIter.cpp
@@ -166,16 +166,19 @@
     fNumRectsInLattice = (xCount + 1) * (yCount + 1);
     fNumRectsToDraw = fNumRectsInLattice;
 
-    if (lattice.fFlags) {
-        fFlags.push_back_n(fNumRectsInLattice);
+    if (lattice.fRectTypes) {
+        fRectTypes.push_back_n(fNumRectsInLattice);
+        fColors.push_back_n(fNumRectsInLattice);
 
-        const SkCanvas::Lattice::Flags* flags = lattice.fFlags;
+        const SkCanvas::Lattice::RectType* flags = lattice.fRectTypes;
+        const SkColor* colors = lattice.fColors;
 
         bool hasPadRow = (yCount != origYCount);
         bool hasPadCol = (xCount != origXCount);
         if (hasPadRow) {
             // The first row of rects are all empty, skip the first row of flags.
             flags += origXCount + 1;
+            colors += origXCount + 1;
         }
 
         int i = 0;
@@ -184,17 +187,20 @@
                 if (0 == x && hasPadCol) {
                     // The first column of rects are all empty.  Skip a rect.
                     flags++;
+                    colors++;
                     continue;
                 }
 
-                fFlags[i] = *flags;
+                fRectTypes[i] = *flags;
+                fColors[i] = *colors;
                 flags++;
+                colors++;
                 i++;
             }
         }
 
-        for (int j = 0; j < fFlags.count(); j++) {
-            if (SkCanvas::Lattice::kTransparent_Flags == fFlags[j]) {
+        for (int j = 0; j < fRectTypes.count(); j++) {
+            if (SkCanvas::Lattice::kTransparent == fRectTypes[j]) {
                 fNumRectsToDraw--;
             }
         }
@@ -248,7 +254,7 @@
     fNumRectsToDraw = 9;
 }
 
-bool SkLatticeIter::next(SkRect* src, SkRect* dst) {
+bool SkLatticeIter::next(SkRect* src, SkRect* dst, bool* isFixedColor, SkColor* fixedColor) {
     int currRect = fCurrX + fCurrY * (fSrcX.count() - 1);
     if (currRect == fNumRectsInLattice) {
         return false;
@@ -264,12 +270,20 @@
         fCurrY += 1;
     }
 
-    if (fFlags.count() > 0 && SkToBool(SkCanvas::Lattice::kTransparent_Flags & fFlags[currRect])) {
-        return this->next(src, dst);
+    if (fRectTypes.count() > 0
+        && SkToBool(SkCanvas::Lattice::kTransparent == fRectTypes[currRect])) {
+        return this->next(src, dst, isFixedColor, fixedColor);
     }
 
     src->set(fSrcX[x], fSrcY[y], fSrcX[x + 1], fSrcY[y + 1]);
     dst->set(fDstX[x], fDstY[y], fDstX[x + 1], fDstY[y + 1]);
+    if (isFixedColor && fixedColor) {
+        *isFixedColor = fRectTypes.count() > 0
+                     && SkToBool(SkCanvas::Lattice::kFixedColor == fRectTypes[currRect]);
+        if (*isFixedColor) {
+            *fixedColor = fColors[currRect];
+        }
+    }
     return true;
 }