Revert "Revert "Serialize mipmaps""

Fix: use ImageGenerator factory instead of SkCodec, in case the client
provides generators in some other fashion (other than SkCodec).

This reverts commit 442d424a72870d860b9f027b92431a15ed9f7dbf.

Change-Id: Ia22f44ef83900413f905fe38570d18a640fca98e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/303496
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/src/core/SkReadBuffer.cpp b/src/core/SkReadBuffer.cpp
index 52d4dfa..d3c9981 100644
--- a/src/core/SkReadBuffer.cpp
+++ b/src/core/SkReadBuffer.cpp
@@ -288,7 +288,9 @@
  *  size (31bits)
  *  data [ encoded, with raw width/height ]
  */
-sk_sp<SkImage> SkReadBuffer::readImage() {
+sk_sp<SkImage> SkReadBuffer::readImage_preV78() {
+    SkASSERT(this->isVersionLT(SkPicturePriv::kSerializeMipmaps_Version));
+
     SkIRect bounds;
     this->readIRect(&bounds);
 
@@ -348,6 +350,61 @@
     return image ? image : MakeEmptyImage(width, height);
 }
 
+#include "src/core/SkMipmap.h"
+
+// If we see a corrupt stream, we return null (fail). If we just fail trying to decode
+// the image, we don't fail, but return a dummy image.
+sk_sp<SkImage> SkReadBuffer::readImage() {
+    if (this->isVersionLT(SkPicturePriv::kSerializeMipmaps_Version)) {
+        return this->readImage_preV78();
+    }
+
+    uint32_t flags = this->read32();
+
+    sk_sp<SkImage> image;
+    {
+        sk_sp<SkData> data = this->readByteArrayAsData();
+        if (!data) {
+            this->validate(false);
+            return nullptr;
+        }
+        if (fProcs.fImageProc) {
+            image = fProcs.fImageProc(data->data(), data->size(), fProcs.fImageCtx);
+        }
+        if (!image) {
+            image = SkImage::MakeFromEncoded(std::move(data));
+        }
+    }
+
+    if (flags & SkWriteBufferImageFlags::kHasSubsetRect) {
+        SkIRect subset;
+        this->readIRect(&subset);
+        if (image) {
+            image = image->makeSubset(subset);
+        }
+    }
+
+    if (flags & SkWriteBufferImageFlags::kHasMipmap) {
+        sk_sp<SkData> data = this->readByteArrayAsData();
+        if (!data) {
+            this->validate(false);
+            return nullptr;
+        }
+        if (image) {
+            SkMipmapBuilder builder(image->imageInfo());
+            if (SkMipmap::Deserialize(&builder, data->data(), data->size())) {
+                // TODO: need to make lazy images support mips
+                if (auto ri = image->makeRasterImage()) {
+                    image = ri;
+                }
+                image = image->withMipmaps(builder.detach());
+                SkASSERT(image);    // withMipmaps should never return null
+            }
+        }
+    }
+    return image ? image : MakeEmptyImage(1, 1);
+}
+
 sk_sp<SkTypeface> SkReadBuffer::readTypeface() {
     // Read 32 bits (signed)
     //   0 -- return null (default font)