Auto-dark NinePatches & launcher

Support palette for ninepatches (fixes popupwindow)

Crude heuristic tweak to treat any RenderNode that fully
contains other nodes as background nodes.

Test: all apps is now readable, and so is chrome's menu
Change-Id: I9926973c0be1dbf0088fa2d61e4ee2a414b19a97
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index c30af84..f928de9 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -23,6 +23,7 @@
 #include "SkDrawShadowInfo.h"
 #include "SkImage.h"
 #include "SkImageFilter.h"
+#include "SkLatticeIter.h"
 #include "SkMath.h"
 #include "SkPicture.h"
 #include "SkRSXform.h"
@@ -280,7 +281,8 @@
 
 struct DrawImage final : Op {
     static const auto kType = Type::DrawImage;
-    DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint, BitmapPalette palette)
+    DrawImage(sk_sp<const SkImage>&& image, SkScalar x, SkScalar y, const SkPaint* paint,
+              BitmapPalette palette)
             : image(std::move(image)), x(x), y(y), palette(palette) {
         if (paint) {
             this->paint = *paint;
@@ -312,7 +314,8 @@
 struct DrawImageRect final : Op {
     static const auto kType = Type::DrawImageRect;
     DrawImageRect(sk_sp<const SkImage>&& image, const SkRect* src, const SkRect& dst,
-                  const SkPaint* paint, SkCanvas::SrcRectConstraint constraint, BitmapPalette palette)
+                  const SkPaint* paint, SkCanvas::SrcRectConstraint constraint,
+                  BitmapPalette palette)
             : image(std::move(image)), dst(dst), constraint(constraint), palette(palette) {
         this->src = src ? *src : SkRect::MakeIWH(this->image->width(), this->image->height());
         if (paint) {
@@ -331,8 +334,14 @@
 struct DrawImageLattice final : Op {
     static const auto kType = Type::DrawImageLattice;
     DrawImageLattice(sk_sp<const SkImage>&& image, int xs, int ys, int fs, const SkIRect& src,
-                     const SkRect& dst, const SkPaint* paint)
-            : image(std::move(image)), xs(xs), ys(ys), fs(fs), src(src), dst(dst) {
+                     const SkRect& dst, const SkPaint* paint, BitmapPalette palette)
+            : image(std::move(image))
+            , xs(xs)
+            , ys(ys)
+            , fs(fs)
+            , src(src)
+            , dst(dst)
+            , palette(palette) {
         if (paint) {
             this->paint = *paint;
         }
@@ -342,6 +351,7 @@
     SkIRect src;
     SkRect dst;
     SkPaint paint;
+    BitmapPalette palette;
     void draw(SkCanvas* c, const SkMatrix&) const {
         auto xdivs = pod<int>(this, 0), ydivs = pod<int>(this, xs * sizeof(int));
         auto colors = (0 == fs) ? nullptr : pod<SkColor>(this, (xs + ys) * sizeof(int));
@@ -511,16 +521,13 @@
         tree->getPaintFor(&paint, tree->stagingProperties());
     }
 
-    void draw(SkCanvas* canvas, const SkMatrix&) const {
-        mRoot->draw(canvas, mBounds, paint);
-    }
+    void draw(SkCanvas* canvas, const SkMatrix&) const { mRoot->draw(canvas, mBounds, paint); }
 
     sp<VectorDrawableRoot> mRoot;
     SkRect mBounds;
     SkPaint paint;
     BitmapPalette palette;
 };
-
 }
 
 template <typename T, typename... Args>
@@ -647,14 +654,15 @@
     this->push<DrawImageRect>(0, std::move(image), src, dst, paint, constraint, palette);
 }
 void DisplayListData::drawImageLattice(sk_sp<const SkImage> image, const SkCanvas::Lattice& lattice,
-                                       const SkRect& dst, const SkPaint* paint) {
+                                       const SkRect& dst, const SkPaint* paint,
+                                       BitmapPalette palette) {
     int xs = lattice.fXCount, ys = lattice.fYCount;
     int fs = lattice.fRectTypes ? (xs + 1) * (ys + 1) : 0;
     size_t bytes = (xs + ys) * sizeof(int) + fs * sizeof(SkCanvas::Lattice::RectType) +
                    fs * sizeof(SkColor);
     SkASSERT(lattice.fBounds);
     void* pod = this->push<DrawImageLattice>(bytes, std::move(image), xs, ys, fs, *lattice.fBounds,
-                                             dst, paint);
+                                             dst, paint, palette);
     copy_v(pod, lattice.fXDivs, xs, lattice.fYDivs, ys, lattice.fColors, fs, lattice.fRectTypes,
            fs);
 }
@@ -779,22 +787,26 @@
 
 template <class T>
 constexpr color_transform_fn colorTransformForOp() {
-    if constexpr(has_paint<T> && has_palette<T>) {
-        // It's a bitmap
-        return [](const void* opRaw, ColorTransform transform) {
-            // TODO: We should be const. Or not. Or just use a different map
-            // Unclear, but this is the quick fix
-            const T* op = reinterpret_cast<const T*>(opRaw);
-            transformPaint(transform, const_cast<SkPaint*>(&(op->paint)), op->palette);
-        };
-    } else if constexpr(has_paint<T>) {
-        return [](const void* opRaw, ColorTransform transform) {
-            // TODO: We should be const. Or not. Or just use a different map
-            // Unclear, but this is the quick fix
-            const T* op = reinterpret_cast<const T*>(opRaw);
-            transformPaint(transform, const_cast<SkPaint*>(&(op->paint)));
-        };
-    } else {
+    if
+        constexpr(has_paint<T> && has_palette<T>) {
+            // It's a bitmap
+            return [](const void* opRaw, ColorTransform transform) {
+                // TODO: We should be const. Or not. Or just use a different map
+                // Unclear, but this is the quick fix
+                const T* op = reinterpret_cast<const T*>(opRaw);
+                transformPaint(transform, const_cast<SkPaint*>(&(op->paint)), op->palette);
+            };
+        }
+    else if
+        constexpr(has_paint<T>) {
+            return [](const void* opRaw, ColorTransform transform) {
+                // TODO: We should be const. Or not. Or just use a different map
+                // Unclear, but this is the quick fix
+                const T* op = reinterpret_cast<const T*>(opRaw);
+                transformPaint(transform, const_cast<SkPaint*>(&(op->paint)));
+            };
+        }
+    else {
         return nullptr;
     }
 }
@@ -931,11 +943,12 @@
 }
 void RecordingCanvas::onDrawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRect& dst,
                                        const SkPaint* paint, SrcRectConstraint constraint) {
-    fDL->drawImageRect(SkImage::MakeFromBitmap(bm), src, dst, paint, constraint, BitmapPalette::Unknown);
+    fDL->drawImageRect(SkImage::MakeFromBitmap(bm), src, dst, paint, constraint,
+                       BitmapPalette::Unknown);
 }
 void RecordingCanvas::onDrawBitmapLattice(const SkBitmap& bm, const SkCanvas::Lattice& lattice,
                                           const SkRect& dst, const SkPaint* paint) {
-    fDL->drawImageLattice(SkImage::MakeFromBitmap(bm), lattice, dst, paint);
+    fDL->drawImageLattice(SkImage::MakeFromBitmap(bm), lattice, dst, paint, BitmapPalette::Unknown);
 }
 
 void RecordingCanvas::drawImage(const sk_sp<SkImage>& image, SkScalar x, SkScalar y,
@@ -943,11 +956,34 @@
     fDL->drawImage(image, x, y, paint, palette);
 }
 
-void RecordingCanvas::drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
-                   const SkPaint* paint, SrcRectConstraint constraint, BitmapPalette palette) {
+void RecordingCanvas::drawImageRect(const sk_sp<SkImage>& image, const SkRect& src,
+                                    const SkRect& dst, const SkPaint* paint,
+                                    SrcRectConstraint constraint, BitmapPalette palette) {
     fDL->drawImageRect(image, &src, dst, paint, constraint, palette);
 }
 
+void RecordingCanvas::drawImageLattice(const sk_sp<SkImage>& image, const Lattice& lattice,
+                                       const SkRect& dst, const SkPaint* paint,
+                                       BitmapPalette palette) {
+    if (!image || dst.isEmpty()) {
+        return;
+    }
+
+    SkIRect bounds;
+    Lattice latticePlusBounds = lattice;
+    if (!latticePlusBounds.fBounds) {
+        bounds = SkIRect::MakeWH(image->width(), image->height());
+        latticePlusBounds.fBounds = &bounds;
+    }
+
+    if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
+        fDL->drawImageLattice(image, latticePlusBounds, dst, paint, palette);
+    } else {
+        fDL->drawImageRect(image, nullptr, dst, paint, SrcRectConstraint::kFast_SrcRectConstraint,
+                           palette);
+    }
+}
+
 void RecordingCanvas::onDrawImage(const SkImage* img, SkScalar x, SkScalar y,
                                   const SkPaint* paint) {
     fDL->drawImage(sk_ref_sp(img), x, y, paint, BitmapPalette::Unknown);
@@ -962,7 +998,7 @@
 }
 void RecordingCanvas::onDrawImageLattice(const SkImage* img, const SkCanvas::Lattice& lattice,
                                          const SkRect& dst, const SkPaint* paint) {
-    fDL->drawImageLattice(sk_ref_sp(img), lattice, dst, paint);
+    fDL->drawImageLattice(sk_ref_sp(img), lattice, dst, paint, BitmapPalette::Unknown);
 }
 
 void RecordingCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
@@ -975,8 +1011,8 @@
     fDL->drawPoints(mode, count, pts, paint);
 }
 void RecordingCanvas::onDrawVerticesObject(const SkVertices* vertices,
-                                          const SkVertices::Bone bones[], int boneCount,
-                                          SkBlendMode mode, const SkPaint& paint) {
+                                           const SkVertices::Bone bones[], int boneCount,
+                                           SkBlendMode mode, const SkPaint& paint) {
     fDL->drawVertices(vertices, bones, boneCount, mode, paint);
 }
 void RecordingCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xforms[],
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 80c80ca..099e0be 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -110,7 +110,7 @@
     void drawImageRect(sk_sp<const SkImage>, const SkRect*, const SkRect&, const SkPaint*,
                        SkCanvas::SrcRectConstraint, BitmapPalette palette);
     void drawImageLattice(sk_sp<const SkImage>, const SkCanvas::Lattice&, const SkRect&,
-                          const SkPaint*);
+                          const SkPaint*, BitmapPalette);
 
     void drawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode,
                    const SkPaint&);
@@ -185,11 +185,13 @@
     void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
                           SrcRectConstraint) override;
 
-    void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
-                   const SkPaint* paint, BitmapPalette pallete);
+    void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top, const SkPaint* paint,
+                   BitmapPalette pallete);
 
     void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
                        const SkPaint* paint, SrcRectConstraint constraint, BitmapPalette palette);
+    void drawImageLattice(const sk_sp<SkImage>& image, const Lattice& lattice, const SkRect& dst,
+                          const SkPaint* paint, BitmapPalette palette);
 
     void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) override;
     void onDrawImageLattice(const SkImage*, const Lattice&, const SkRect&, const SkPaint*) override;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index d9a7cc3..d2a8f02 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -282,25 +282,45 @@
     mStagingDisplayList = nullptr;
     if (mDisplayList) {
         mDisplayList->syncContents();
+        handleForceDark(info);
+    }
+}
 
-        if (CC_UNLIKELY(info && !info->disableForceDark)) {
-            auto usage = usageHint();
-            if (mDisplayList->hasText()) {
-                usage = UsageHint::Foreground;
-            }
-            if (usage == UsageHint::Unknown) {
-                if (mDisplayList->mChildNodes.size() > 1) {
-                    usage = UsageHint::Background;
-                } else if (mDisplayList->mChildNodes.size() == 1 &&
-                           mDisplayList->mChildNodes.front().getRenderNode()->usageHint() !=
-                                   UsageHint::Background) {
-                    usage = UsageHint::Background;
-                }
-            }
-            mDisplayList->mDisplayList.applyColorTransform(
-                    usage == UsageHint::Background ? ColorTransform::Dark : ColorTransform::Light);
+void RenderNode::handleForceDark(android::uirenderer::TreeInfo *info) {
+    if (CC_LIKELY(!info || info->disableForceDark)) {
+        return;
+    }
+    auto usage = usageHint();
+    const auto& children = mDisplayList->mChildNodes;
+    if (mDisplayList->hasText()) {
+        usage = UsageHint::Foreground;
+    }
+    if (usage == UsageHint::Unknown) {
+        if (children.size() > 1) {
+            usage = UsageHint::Background;
+        } else if (children.size() == 1 &&
+                children.front().getRenderNode()->usageHint() !=
+                        UsageHint::Background) {
+            usage = UsageHint::Background;
         }
     }
+    if (children.size() > 1) {
+        // Crude overlap check
+        SkRect drawn = SkRect::MakeEmpty();
+        for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
+            const auto& child = iter->getRenderNode();
+            // We use stagingProperties here because we haven't yet sync'd the children
+            SkRect bounds = SkRect::MakeXYWH(child->stagingProperties().getX(), child->stagingProperties().getY(),
+                    child->stagingProperties().getWidth(), child->stagingProperties().getHeight());
+            if (bounds.contains(drawn)) {
+                // This contains everything drawn after it, so make it a background
+                child->setUsageHint(UsageHint::Background);
+            }
+            drawn.join(bounds);
+        }
+    }
+    mDisplayList->mDisplayList.applyColorTransform(
+            usage == UsageHint::Background ? ColorTransform::Dark : ColorTransform::Light);
 }
 
 void RenderNode::pushStagingDisplayListChanges(TreeObserver& observer, TreeInfo& info) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 211dd2d..be0b46b 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -220,6 +220,7 @@
 
     void syncProperties();
     void syncDisplayList(TreeObserver& observer, TreeInfo* info);
+    void handleForceDark(TreeInfo* info);
 
     void prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer);
     void pushStagingPropertiesChanges(TreeInfo& info);
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index fac07d7..3fa73a4 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -245,8 +245,9 @@
     }
     sk_sp<SkColorFilter> colorFilter;
     sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
-    mRecorder.drawImageLattice(image.get(), lattice, dst,
-                               filterBitmap(std::move(filteredPaint), std::move(colorFilter)));
+    mRecorder.drawImageLattice(image, lattice, dst,
+                               filterBitmap(std::move(filteredPaint), std::move(colorFilter)),
+                               bitmap.palette());
     if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }