Isolate SpriteIcon into its own file.

This is to isolate differences between internal master and AOSP so that
the open source intern can work on a relatively new project.

It also isolates a divergent piece of code into SpriteIcon.cpp.

Bug: None
Test: Pointer icons in ApiDemos still work.
Change-Id: I1bf8f23411ad7170de2497d6fee0f70b015e9b5f
Merged-In: I1bf8f23411ad7170de2497d6fee0f70b015e9b5f
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 16f2917..fd4371c 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -17,6 +17,7 @@
     srcs: [
         "PointerController.cpp",
         "SpriteController.cpp",
+        "SpriteIcon.cpp",
     ],
 
     shared_libs: [
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index fd386e9..5f481ca6 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -23,13 +23,6 @@
 #include <utils/String8.h>
 #include <gui/Surface.h>
 
-#include <SkBitmap.h>
-#include <SkCanvas.h>
-#include <SkColor.h>
-#include <SkPaint.h>
-
-#include <android/native_window.h>
-
 namespace android {
 
 // --- SpriteController ---
@@ -132,8 +125,8 @@
         SpriteUpdate& update = updates.editItemAt(i);
 
         if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
-            update.state.surfaceWidth = update.state.icon.bitmap.width();
-            update.state.surfaceHeight = update.state.icon.bitmap.height();
+            update.state.surfaceWidth = update.state.icon.width();
+            update.state.surfaceHeight = update.state.icon.height();
             update.state.surfaceDrawn = false;
             update.state.surfaceVisible = false;
             update.state.surfaceControl = obtainSurface(
@@ -154,8 +147,8 @@
         }
 
         if (update.state.wantSurfaceVisible()) {
-            int32_t desiredWidth = update.state.icon.bitmap.width();
-            int32_t desiredHeight = update.state.icon.bitmap.height();
+            int32_t desiredWidth = update.state.icon.width();
+            int32_t desiredHeight = update.state.icon.height();
             if (update.state.surfaceWidth < desiredWidth
                     || update.state.surfaceHeight < desiredHeight) {
                 needApplyTransaction = true;
@@ -196,40 +189,9 @@
         if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
                 && update.state.wantSurfaceVisible()) {
             sp<Surface> surface = update.state.surfaceControl->getSurface();
-            ANativeWindow_Buffer outBuffer;
-            status_t status = surface->lock(&outBuffer, NULL);
-            if (status) {
-                ALOGE("Error %d locking sprite surface before drawing.", status);
-            } else {
-                SkBitmap surfaceBitmap;
-                ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
-                surfaceBitmap.installPixels(SkImageInfo::MakeN32Premul(outBuffer.width, outBuffer.height),
-                                            outBuffer.bits, bpr);
-
-                SkCanvas surfaceCanvas(surfaceBitmap);
-
-                SkPaint paint;
-                paint.setBlendMode(SkBlendMode::kSrc);
-                surfaceCanvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint);
-
-                if (outBuffer.width > update.state.icon.bitmap.width()) {
-                    paint.setColor(0); // transparent fill color
-                    surfaceCanvas.drawRect(SkRect::MakeLTRB(update.state.icon.bitmap.width(), 0,
-                            outBuffer.width, update.state.icon.bitmap.height()), paint);
-                }
-                if (outBuffer.height > update.state.icon.bitmap.height()) {
-                    paint.setColor(0); // transparent fill color
-                    surfaceCanvas.drawRect(SkRect::MakeLTRB(0, update.state.icon.bitmap.height(),
-                            outBuffer.width, outBuffer.height), paint);
-                }
-
-                status = surface->unlockAndPost();
-                if (status) {
-                    ALOGE("Error %d unlocking and posting sprite surface after drawing.", status);
-                } else {
-                    update.state.surfaceDrawn = true;
-                    update.surfaceChanged = surfaceChanged = true;
-                }
+            if (update.state.icon.draw(surface)) {
+                update.state.surfaceDrawn = true;
+                update.surfaceChanged = surfaceChanged = true;
             }
         }
     }
diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h
index 79a904f..137b564 100644
--- a/libs/input/SpriteController.h
+++ b/libs/input/SpriteController.h
@@ -22,7 +22,7 @@
 
 #include <gui/SurfaceComposerClient.h>
 
-#include <SkBitmap.h>
+#include "SpriteIcon.h"
 
 namespace android {
 
@@ -52,40 +52,6 @@
 };
 
 /*
- * Icon that a sprite displays, including its hotspot.
- */
-struct SpriteIcon {
-    inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) { }
-    inline SpriteIcon(const SkBitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) :
-            bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
-
-    SkBitmap bitmap;
-    int32_t style;
-    float hotSpotX;
-    float hotSpotY;
-
-    inline SpriteIcon copy() const {
-        SkBitmap bitmapCopy;
-        if (bitmapCopy.tryAllocPixels(bitmap.info().makeColorType(kN32_SkColorType))) {
-            bitmap.readPixels(bitmapCopy.info(), bitmapCopy.getPixels(), bitmapCopy.rowBytes(),
-                    0, 0);
-        }
-        return SpriteIcon(bitmapCopy, style, hotSpotX, hotSpotY);
-    }
-
-    inline void reset() {
-        bitmap.reset();
-        style = 0;
-        hotSpotX = 0;
-        hotSpotY = 0;
-    }
-
-    inline bool isValid() const {
-        return !bitmap.isNull() && !bitmap.empty();
-    }
-};
-
-/*
  * A sprite is a simple graphical object that is displayed on-screen above other layers.
  * The basic sprite class is an interface.
  * The implementation is provided by the sprite controller.
@@ -183,7 +149,7 @@
      * This structure is designed so that it can be copied during updates so that
      * surfaces can be resized and redrawn without blocking the client by holding a lock
      * on the sprites for a long time.
-     * Note that the SkBitmap holds a reference to a shared (and immutable) pixel ref. */
+     * Note that the SpriteIcon holds a reference to a shared (and immutable) bitmap. */
     struct SpriteState {
         inline SpriteState() :
                 dirty(0), visible(false),
diff --git a/libs/input/SpriteIcon.cpp b/libs/input/SpriteIcon.cpp
new file mode 100644
index 0000000..10cc458
--- /dev/null
+++ b/libs/input/SpriteIcon.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "SpriteIcon.h"
+
+#include <SkBitmap.h>
+#include <SkCanvas.h>
+#include <SkColor.h>
+#include <SkPaint.h>
+
+#include <android/native_window.h>
+#include <log/log.h>
+
+namespace android {
+
+bool SpriteIcon::draw(sp<Surface> surface) const {
+    ANativeWindow_Buffer outBuffer;
+    status_t status = surface->lock(&outBuffer, NULL);
+    if (status) {
+        ALOGE("Error %d locking sprite surface before drawing.", status);
+        return false;
+    }
+
+    SkBitmap surfaceBitmap;
+    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
+    surfaceBitmap.installPixels(SkImageInfo::MakeN32Premul(outBuffer.width, outBuffer.height),
+                                outBuffer.bits, bpr);
+
+    SkCanvas surfaceCanvas(surfaceBitmap);
+
+    SkPaint paint;
+    paint.setBlendMode(SkBlendMode::kSrc);
+    surfaceCanvas.drawBitmap(bitmap, 0, 0, &paint);
+
+    if (outBuffer.width > width()) {
+        paint.setColor(0); // transparent fill color
+        surfaceCanvas.drawRect(SkRect::MakeLTRB(width(), 0, outBuffer.width, height()), paint);
+    }
+    if (outBuffer.height > height()) {
+        paint.setColor(0); // transparent fill color
+        surfaceCanvas.drawRect(SkRect::MakeLTRB(0, height(), outBuffer.width, outBuffer.height),
+                               paint);
+    }
+
+    status = surface->unlockAndPost();
+    if (status) {
+        ALOGE("Error %d unlocking and posting sprite surface after drawing.", status);
+    }
+    return !status;
+}
+
+} // namespace android
diff --git a/libs/input/SpriteIcon.h b/libs/input/SpriteIcon.h
new file mode 100644
index 0000000..c535faf
--- /dev/null
+++ b/libs/input/SpriteIcon.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 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 _UI_SPRITE_ICON_H
+#define _UI_SPRITE_ICON_H
+
+#include <SkBitmap.h>
+#include <gui/Surface.h>
+
+namespace android {
+
+/*
+ * Icon that a sprite displays, including its hotspot.
+ */
+struct SpriteIcon {
+    inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) { }
+    inline SpriteIcon(const SkBitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) :
+            bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
+
+    SkBitmap bitmap;
+    int32_t style;
+    float hotSpotX;
+    float hotSpotY;
+
+    inline SpriteIcon copy() const {
+        SkBitmap bitmapCopy;
+        if (bitmapCopy.tryAllocPixels(bitmap.info().makeColorType(kN32_SkColorType))) {
+            bitmap.readPixels(bitmapCopy.info(), bitmapCopy.getPixels(), bitmapCopy.rowBytes(),
+                    0, 0);
+        }
+        return SpriteIcon(bitmapCopy, style, hotSpotX, hotSpotY);
+    }
+
+    inline void reset() {
+        bitmap.reset();
+        style = 0;
+        hotSpotX = 0;
+        hotSpotY = 0;
+    }
+
+    inline bool isValid() const { return !bitmap.isNull() && !bitmap.empty(); }
+
+    inline int32_t width() const { return bitmap.width(); }
+    inline int32_t height() const { return bitmap.height(); }
+
+    // Draw the bitmap onto the given surface. Returns true if it's successful, or false otherwise.
+    // Note it doesn't set any metadata to the surface.
+    bool draw(const sp<Surface> surface) const;
+};
+
+
+} // namespace android
+
+#endif // _UI_SPRITE_ICON_H