Revert of Add SkPngChunkReader. (patchset #9 id:160001 of https://codereview.chromium.org/1040453002/ )

Reason for revert:
Busted Chromium builds:

../../third_party/skia/src/ports/SkImageDecoder_empty.cpp:63:17: error: no type
named 'Peeker' in 'SkImageDecoder'
SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker*) {
~~~~~~~~~~~~~~~~^
../../third_party/skia/src/ports/SkImageDecoder_empty.cpp:63:51: error: unknown
type name 'Peeker'
SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker*) {

Original issue's description:
> Add SkPngChunkReader.
>
> This class allows a client of SkCodec to read chunks in the data
> stream that are not recognized by libpng. This is used by Android
> to specify ninepatch data.
>
> Taken from SkImageDecoder::Peeker. Modify the name of the class
> and its method to be more specific to their use. Make
> SkImageDecoder::Peeker a subclass of the new class, to help stage
> the change in Android.
>
> Add a test to verify that it works.
>
> BUG=skia:4574
> BUG=skia:3257
>
> Committed: https://skia.googlesource.com/skia/+/3389e00136188800b98ca69488c0418c374fd78b

TBR=djsollen@google.com,reed@google.com,msarett@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=skia:4574

Review URL: https://codereview.chromium.org/1472863003
diff --git a/gyp/skia_for_android_framework_defines.gypi b/gyp/skia_for_android_framework_defines.gypi
index 825429b..773c530 100644
--- a/gyp/skia_for_android_framework_defines.gypi
+++ b/gyp/skia_for_android_framework_defines.gypi
@@ -19,7 +19,6 @@
       'SK_IGNORE_LINEONLY_AA_CONVEX_PATH_OPTS',
       'SK_SUPPORT_LEGACY_GRADIENT_DITHERING',
       'SK_IGNORE_GL_TEXTURE_TARGET',
-      'SK_LEGACY_PEEKER',
     ],
   },
 }
diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h
index dffab6b..d90fea8 100644
--- a/include/codec/SkCodec.h
+++ b/include/codec/SkCodec.h
@@ -17,7 +17,6 @@
 #include "SkTypes.h"
 
 class SkData;
-class SkPngChunkReader;
 class SkSampler;
 
 /**
@@ -29,24 +28,18 @@
      *  If this stream represents an encoded image that we know how to decode,
      *  return an SkCodec that can decode it. Otherwise return NULL.
      *
-     *  If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
-     *  the image is a png.
-     *
      *  If NULL is returned, the stream is deleted immediately. Otherwise, the
      *  SkCodec takes ownership of it, and will delete it when done with it.
      */
-    static SkCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL);
+    static SkCodec* NewFromStream(SkStream*);
 
     /**
      *  If this data represents an encoded image that we know how to decode,
      *  return an SkCodec that can decode it. Otherwise return NULL.
      *
-     *  If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
-     *  the image is a png.
-     *
      *  Will take a ref if it returns a codec, else will not affect the data.
      */
-    static SkCodec* NewFromData(SkData*, SkPngChunkReader* = NULL);
+    static SkCodec* NewFromData(SkData*);
 
     virtual ~SkCodec();
 
diff --git a/include/core/SkImageDecoder.h b/include/core/SkImageDecoder.h
index 30323b5..144878c 100644
--- a/include/core/SkImageDecoder.h
+++ b/include/core/SkImageDecoder.h
@@ -10,14 +10,11 @@
 
 #include "SkBitmap.h"
 #include "SkImage.h"
-#include "SkPngChunkReader.h"
 #include "SkRect.h"
 #include "SkRefCnt.h"
 #include "SkTRegistry.h"
 #include "SkTypes.h"
 
-//#define SK_LEGACY_PEEKER
-
 class SkStream;
 class SkStreamRewindable;
 
@@ -129,20 +126,23 @@
     */
     bool getRequireUnpremultipliedColors() const { return fRequireUnpremultipliedColors; }
 
-#ifdef SK_LEGACY_PEEKER
-    // Android subclasses SkImageDecoder::Peeker, which has been changed into SkPngChunkReader.
-    // Temporarily use this class until Android can be updated to directly inherit from
-    // SkPngChunkReader.
-    class Peeker : public SkPngChunkReader {
+    /** \class Peeker
+
+        Base class for optional callbacks to retrieve meta/chunk data out of
+        an image as it is being decoded.
+    */
+    class Peeker : public SkRefCnt {
     public:
-        bool readChunk(const char tag[], const void* data, size_t length) final {
-            return this->peek(tag, data, length);
-        }
+        /** Return true to continue decoding, or false to indicate an error, which
+            will cause the decoder to not return the image.
+        */
         virtual bool peek(const char tag[], const void* data, size_t length) = 0;
+    private:
+        typedef SkRefCnt INHERITED;
     };
-#endif
-    SkPngChunkReader* getPeeker() const { return fPeeker; }
-    SkPngChunkReader* setPeeker(SkPngChunkReader*);
+
+    Peeker* getPeeker() const { return fPeeker; }
+    Peeker* setPeeker(Peeker*);
 
     /**
      *  By default, the codec will try to comply with the "pref" colortype
@@ -229,8 +229,8 @@
         to allocate the memory from a cache, volatile memory, or even from
         an existing bitmap's memory.
 
-        If an SkPngChunkReader is installed via setPeeker, it may be used to
-        peek into meta data during the decode.
+        If a Peeker is installed via setPeeker, it may be used to peek into
+        meta data during the decode.
     */
     Result decode(SkStream*, SkBitmap* bitmap, SkColorType pref, Mode);
     Result decode(SkStream* stream, SkBitmap* bitmap, Mode mode) {
@@ -350,7 +350,7 @@
     SkColorType getPrefColorType(SrcDepth, bool hasAlpha) const;
 
 private:
-    SkPngChunkReader*       fPeeker;
+    Peeker*                 fPeeker;
     SkBitmap::Allocator*    fAllocator;
     int                     fSampleSize;
     SkColorType             fDefaultPref;   // use if fUsePrefTable is false
diff --git a/include/core/SkPngChunkReader.h b/include/core/SkPngChunkReader.h
deleted file mode 100644
index f424dd8..0000000
--- a/include/core/SkPngChunkReader.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkPngChunkReader_DEFINED
-#define SkPngChunkReader_DEFINED
-
-#include "SkTypes.h"
-#include "SkRefCnt.h"
-
-/**
- *  SkPngChunkReader
- *
- *  Base class for optional callbacks to retrieve meta/chunk data out of a PNG
- *  encoded image as it is being decoded.
- *  Used by SkImageDecoder and SkCodec.
- */
-class SkPngChunkReader : public SkRefCnt {
-public:
-    /**
-     *  This will be called by the decoder when it sees an unknown chunk.
-     *
-     *  Use by SkCodec:
-     *  Depending on the location of the unknown chunks, this callback may be
-     *  called by
-     *      - the factory (NewFromStream/NewFromData)
-     *      - getPixels
-     *      - startScanlineDecode
-     *      - the first call to getScanlines/skipScanlines
-     *  The callback may be called from a different thread (e.g. if the SkCodec
-     *  is passed to another thread), and it may be called multiple times, if
-     *  the SkCodec is used multiple times.
-     *
-     *  @param tag Name for this type of chunk.
-     *  @param data Data to be interpreted by the subclass.
-     *  @param length Number of bytes of data in the chunk.
-     *  @return true to continue decoding, or false to indicate an error, which
-     *      will cause the decoder to not return the image.
-     */
-    virtual bool readChunk(const char tag[], const void* data, size_t length) = 0;
-};
-#endif // SkPngChunkReader_DEFINED
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp
index 11eb1f9..071a4b8 100644
--- a/src/codec/SkCodec.cpp
+++ b/src/codec/SkCodec.cpp
@@ -25,6 +25,7 @@
 };
 
 static const DecoderProc gDecoderProcs[] = {
+    { SkPngCodec::IsPng, SkPngCodec::NewFromStream },
 #if !defined(GOOGLE3)
     { SkJpegCodec::IsJpeg, SkJpegCodec::NewFromStream },
 #endif
@@ -35,8 +36,7 @@
     { SkWbmpCodec::IsWbmp, SkWbmpCodec::NewFromStream }
 };
 
-SkCodec* SkCodec::NewFromStream(SkStream* stream,
-                                SkPngChunkReader* chunkReader) {
+SkCodec* SkCodec::NewFromStream(SkStream* stream) {
     if (!stream) {
         return nullptr;
     }
@@ -44,24 +44,15 @@
     SkAutoTDelete<SkStream> streamDeleter(stream);
     
     SkAutoTDelete<SkCodec> codec(nullptr);
-    // PNG is special, since we want to be able to supply an SkPngChunkReader.
-    // But this code follows the same pattern as the loop.
-    const bool isPng = SkPngCodec::IsPng(stream);
-    if (!stream->rewind()) {
-        return NULL;
-    }
-    if (isPng) {
-        codec.reset(SkPngCodec::NewFromStream(streamDeleter.detach(), chunkReader));
-    } else {
-        for (DecoderProc proc : gDecoderProcs) {
-            const bool correctFormat = proc.IsFormat(stream);
-            if (!stream->rewind()) {
-                return nullptr;
-            }
-            if (correctFormat) {
-                codec.reset(proc.NewFromStream(streamDeleter.detach()));
-                break;
-            }
+    for (uint32_t i = 0; i < SK_ARRAY_COUNT(gDecoderProcs); i++) {
+        DecoderProc proc = gDecoderProcs[i];
+        const bool correctFormat = proc.IsFormat(stream);
+        if (!stream->rewind()) {
+            return nullptr;
+        }
+        if (correctFormat) {
+            codec.reset(proc.NewFromStream(streamDeleter.detach()));
+            break;
         }
     }
 
@@ -77,11 +68,11 @@
     }
 }
 
-SkCodec* SkCodec::NewFromData(SkData* data, SkPngChunkReader* reader) {
+SkCodec* SkCodec::NewFromData(SkData* data) {
     if (!data) {
         return nullptr;
     }
-    return NewFromStream(new SkMemoryStream(data), reader);
+    return NewFromStream(new SkMemoryStream(data));
 }
 
 SkCodec::SkCodec(const SkImageInfo& info, SkStream* stream)
diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp
index 355d493..82c952e 100644
--- a/src/codec/SkCodec_libpng.cpp
+++ b/src/codec/SkCodec_libpng.cpp
@@ -65,14 +65,6 @@
     }
 }
 
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
-    SkPngChunkReader* chunkReader = (SkPngChunkReader*)png_get_user_chunk_ptr(png_ptr);
-    // readChunk() returning true means continue decoding
-    return chunkReader->readChunk((const char*)chunk->name, chunk->data, chunk->size) ? 1 : -1;
-}
-#endif
-
 ///////////////////////////////////////////////////////////////////////////////
 // Helpers
 ///////////////////////////////////////////////////////////////////////////////
@@ -219,29 +211,14 @@
     return true;
 }
 
-// Reads the header and initializes the output fields, if not NULL.
-//
-// @param stream Input data. Will be read to get enough information to properly
-//      setup the codec.
-// @param chunkReader SkPngChunkReader, for reading unknown chunks. May be NULL.
-//      If not NULL, png_ptr will hold an *unowned* pointer to it. The caller is
-//      expected to continue to own it for the lifetime of the png_ptr.
-// @param png_ptrp Optional output variable. If non-NULL, will be set to a new
-//      png_structp on success.
-// @param info_ptrp Optional output variable. If non-NULL, will be set to a new
-//      png_infop on success;
-// @param imageInfo Optional output variable. If non-NULL, will be set to
-//      reflect the properties of the encoded image on success.
-// @param bitDepthPtr Optional output variable. If non-NULL, will be set to the
-//      bit depth of the encoded image on success.
-// @param numberPassesPtr Optional output variable. If non-NULL, will be set to
-//      the number_passes of the encoded image on success.
-// @return true on success, in which case the caller is responsible for calling
-//      png_destroy_read_struct(png_ptrp, info_ptrp).
-//      If it returns false, the passed in fields (except stream) are unchanged.
-static bool read_header(SkStream* stream, SkPngChunkReader* chunkReader,
-                        png_structp* png_ptrp, png_infop* info_ptrp,
-                        SkImageInfo* imageInfo, int* bitDepthPtr, int* numberPassesPtr) {
+// Reads the header, and initializes the passed in fields, if not nullptr (except
+// stream, which is passed to the read function).
+// Returns true on success, in which case the caller is responsible for calling
+// png_destroy_read_struct. If it returns false, the passed in fields (except
+// stream) are unchanged.
+static bool read_header(SkStream* stream, png_structp* png_ptrp,
+                        png_infop* info_ptrp, SkImageInfo* imageInfo,
+                        int* bitDepthPtr, int* numberPassesPtr) {
     // The image is known to be a PNG. Decode enough to know the SkImageInfo.
     png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr,
                                                  sk_error_fn, sk_warning_fn);
@@ -266,14 +243,10 @@
 
     png_set_read_fn(png_ptr, static_cast<void*>(stream), sk_read_fn);
 
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-    // FIXME: Does this need to be installed so early?
-    // hookup our chunkReader so we can see any user-chunks the caller may be interested in
-    if (chunkReader) {
-        png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"", 0);
-        png_set_read_user_chunk_fn(png_ptr, (png_voidp) chunkReader, sk_read_user_chunk);
-    }
-#endif
+    // FIXME: This is where the old code hooks up the Peeker. Does it need to
+    // be set this early? (i.e. where are the user chunks? early in the stream,
+    // potentially?)
+    // If it does, we need to figure out a way to set it here.
 
     // The call to png_read_info() gives us all of the information from the
     // PNG file before the first IDAT (image data chunk).
@@ -383,10 +356,9 @@
     return true;
 }
 
-SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, SkPngChunkReader* chunkReader,
+SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream,
                        png_structp png_ptr, png_infop info_ptr, int bitDepth, int numberPasses)
     : INHERITED(info, stream)
-    , fPngChunkReader(SkSafeRef(chunkReader))
     , fPng_ptr(png_ptr)
     , fInfo_ptr(info_ptr)
     , fSrcConfig(SkSwizzler::kUnknown)
@@ -481,8 +453,7 @@
 
     png_structp png_ptr;
     png_infop info_ptr;
-    if (!read_header(this->stream(), fPngChunkReader.get(), &png_ptr, &info_ptr,
-                     nullptr, nullptr, nullptr)) {
+    if (!read_header(this->stream(), &png_ptr, &info_ptr, nullptr, nullptr, nullptr)) {
         return false;
     }
 
@@ -631,8 +602,8 @@
 class SkPngScanlineDecoder : public SkPngCodec {
 public:
     SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream,
-            SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_ptr, int bitDepth)
-        : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1)
+            png_structp png_ptr, png_infop info_ptr, int bitDepth)
+        : INHERITED(srcInfo, stream, png_ptr, info_ptr, bitDepth, 1)
         , fAlphaState(kUnknown_AlphaState)
         , fSrcRow(nullptr)
     {}
@@ -715,9 +686,8 @@
 class SkPngInterlacedScanlineDecoder : public SkPngCodec {
 public:
     SkPngInterlacedScanlineDecoder(const SkImageInfo& srcInfo, SkStream* stream,
-            SkPngChunkReader* chunkReader, png_structp png_ptr, png_infop info_ptr,
-            int bitDepth, int numberPasses)
-        : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, numberPasses)
+            png_structp png_ptr, png_infop info_ptr, int bitDepth, int numberPasses)
+        : INHERITED(srcInfo, stream, png_ptr, info_ptr, bitDepth, numberPasses)
         , fAlphaState(kUnknown_AlphaState)
         , fHeight(-1)
         , fCanSkipRewind(false)
@@ -852,7 +822,7 @@
     typedef SkPngCodec INHERITED;
 };
 
-SkCodec* SkPngCodec::NewFromStream(SkStream* stream, SkPngChunkReader* chunkReader) {
+SkCodec* SkPngCodec::NewFromStream(SkStream* stream) {
     SkAutoTDelete<SkStream> streamDeleter(stream);
     png_structp png_ptr;
     png_infop info_ptr;
@@ -860,16 +830,15 @@
     int bitDepth;
     int numberPasses;
 
-    if (!read_header(stream, chunkReader, &png_ptr, &info_ptr, &imageInfo, &bitDepth,
-                     &numberPasses)) {
+    if (!read_header(stream, &png_ptr, &info_ptr, &imageInfo, &bitDepth, &numberPasses)) {
         return nullptr;
     }
 
     if (1 == numberPasses) {
-        return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), chunkReader,
-                                        png_ptr, info_ptr, bitDepth);
+        return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), png_ptr, info_ptr,
+                                        bitDepth);
     }
 
-    return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(), chunkReader,
-                                              png_ptr, info_ptr, bitDepth, numberPasses);
+    return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(), png_ptr,
+                                              info_ptr, bitDepth, numberPasses);
 }
diff --git a/src/codec/SkCodec_libpng.h b/src/codec/SkCodec_libpng.h
index c2a5f4a..9809b0c 100644
--- a/src/codec/SkCodec_libpng.h
+++ b/src/codec/SkCodec_libpng.h
@@ -7,7 +7,6 @@
 
 #include "SkCodec.h"
 #include "SkColorTable.h"
-#include "SkPngChunkReader.h"
 #include "SkEncodedFormat.h"
 #include "SkImageInfo.h"
 #include "SkRefCnt.h"
@@ -22,7 +21,7 @@
     static bool IsPng(SkStream*);
 
     // Assume IsPng was called and returned true.
-    static SkCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL);
+    static SkCodec* NewFromStream(SkStream*);
 
     virtual ~SkPngCodec();
 
@@ -42,7 +41,7 @@
         return fSwizzler;
     }
 
-    SkPngCodec(const SkImageInfo&, SkStream*, SkPngChunkReader*, png_structp, png_infop, int, int);
+    SkPngCodec(const SkImageInfo&, SkStream*, png_structp, png_infop, int, int);
 
     png_structp png_ptr() { return fPng_ptr; }
     SkSwizzler* swizzler() { return fSwizzler; }
@@ -63,18 +62,17 @@
     virtual AlphaState alphaInScanlineDecode() const = 0;
 
 private:
-    SkAutoTUnref<SkPngChunkReader>  fPngChunkReader;
-    png_structp                     fPng_ptr;
-    png_infop                       fInfo_ptr;
+    png_structp                 fPng_ptr;
+    png_infop                   fInfo_ptr;
 
     // These are stored here so they can be used both by normal decoding and scanline decoding.
-    SkAutoTUnref<SkColorTable>      fColorTable;    // May be unpremul.
-    SkAutoTDelete<SkSwizzler>       fSwizzler;
+    SkAutoTUnref<SkColorTable>  fColorTable;    // May be unpremul.
+    SkAutoTDelete<SkSwizzler>   fSwizzler;
 
-    SkSwizzler::SrcConfig           fSrcConfig;
-    const int                       fNumberPasses;
-    int                             fBitDepth;
-    AlphaState                      fAlphaState;
+    SkSwizzler::SrcConfig       fSrcConfig;
+    const int                   fNumberPasses;
+    int                         fBitDepth;
+    AlphaState                  fAlphaState;
 
     bool decodePalette(bool premultiply, int* ctableCount);
     void destroyReadStruct();
diff --git a/src/images/SkImageDecoder.cpp b/src/images/SkImageDecoder.cpp
index 221faf7..d2ad553 100644
--- a/src/images/SkImageDecoder.cpp
+++ b/src/images/SkImageDecoder.cpp
@@ -83,7 +83,7 @@
     return "Unknown Format";
 }
 
-SkPngChunkReader* SkImageDecoder::setPeeker(SkPngChunkReader* peeker) {
+SkImageDecoder::Peeker* SkImageDecoder::setPeeker(Peeker* peeker) {
     SkRefCnt_SafeAssign(fPeeker, peeker);
     return peeker;
 }
diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp
index a03ed10..47963b5 100644
--- a/src/images/SkImageDecoder_libpng.cpp
+++ b/src/images/SkImageDecoder_libpng.cpp
@@ -124,9 +124,10 @@
 
 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
 static int sk_read_user_chunk(png_structp png_ptr, png_unknown_chunkp chunk) {
-    SkPngChunkReader* peeker = (SkPngChunkReader*)png_get_user_chunk_ptr(png_ptr);
-    // readChunk() returning true means continue decoding
-    return peeker->readChunk((const char*)chunk->name, chunk->data, chunk->size) ?
+    SkImageDecoder::Peeker* peeker =
+                    (SkImageDecoder::Peeker*)png_get_user_chunk_ptr(png_ptr);
+    // peek() returning true means continue decoding
+    return peeker->peek((const char*)chunk->name, chunk->data, chunk->size) ?
             1 : -1;
 }
 #endif
diff --git a/tests/CodexTest.cpp b/tests/CodexTest.cpp
index b53cbe1..febaf7d 100644
--- a/tests/CodexTest.cpp
+++ b/tests/CodexTest.cpp
@@ -12,12 +12,8 @@
 #include "SkData.h"
 #include "SkMD5.h"
 #include "SkRandom.h"
-#include "SkStream.h"
-#include "SkPngChunkReader.h"
 #include "Test.h"
 
-#include "png.h"
-
 static SkStreamAsset* resource(const char path[]) {
     SkString fullPath = GetResourcePath(path);
     return SkStream::NewFromFile(fullPath.c_str());
@@ -689,159 +685,3 @@
     test_invalid_parameters(r, "index8.png");
     test_invalid_parameters(r, "mandrill.wbmp");
 }
-
-static void codex_test_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) {
-    SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr);
-    if (!sk_stream->write(data, len)) {
-        png_error(png_ptr, "sk_write_fn Error!");
-    }
-}
-
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-DEF_TEST(Codec_pngChunkReader, r) {
-    // Create a dummy bitmap. Use unpremul RGBA for libpng.
-    SkBitmap bm;
-    const int w = 1;
-    const int h = 1;
-    const SkImageInfo bmInfo = SkImageInfo::Make(w, h, kRGBA_8888_SkColorType,
-                                                 kUnpremul_SkAlphaType);
-    bm.setInfo(bmInfo);
-    bm.allocPixels();
-    bm.eraseColor(SK_ColorBLUE);
-    SkMD5::Digest goodDigest;
-    md5(bm, &goodDigest);
-
-    // Write to a png file.
-    png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
-    REPORTER_ASSERT(r, png);
-    if (!png) {
-        return;
-    }
-
-    png_infop info = png_create_info_struct(png);
-    REPORTER_ASSERT(r, info);
-    if (!info) {
-        png_destroy_write_struct(&png, nullptr);
-        return;
-    }
-
-    if (setjmp(png_jmpbuf(png))) {
-        ERRORF(r, "failed writing png");
-        png_destroy_write_struct(&png, &info);
-        return;
-    }
-
-    SkDynamicMemoryWStream wStream;
-    png_set_write_fn(png, (void*) (&wStream), codex_test_write_fn, nullptr);
-
-    png_set_IHDR(png, info, (png_uint_32)w, (png_uint_32)h, 8,
-                 PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
-                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
-
-    // Create some chunks that match the Android framework's use.
-    static png_unknown_chunk gUnknowns[] = {
-        { "npOl", (png_byte*)"outline", sizeof("outline"), PNG_HAVE_PLTE },
-        { "npLb", (png_byte*)"layoutBounds", sizeof("layoutBounds"), PNG_HAVE_PLTE },
-        { "npTc", (png_byte*)"ninePatchData", sizeof("ninePatchData"), PNG_HAVE_PLTE },
-    };
-
-    png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS, (png_byte*)"npOl\0npLb\0npTc\0", 3);
-    png_set_unknown_chunks(png, info, gUnknowns, SK_ARRAY_COUNT(gUnknowns));
-#if PNG_LIBPNG_VER < 10600
-    /* Deal with unknown chunk location bug in 1.5.x and earlier */
-    png_set_unknown_chunk_location(png, info, 0, PNG_HAVE_PLTE);
-    png_set_unknown_chunk_location(png, info, 1, PNG_HAVE_PLTE);
-#endif
-
-    png_write_info(png, info);
-
-    for (int j = 0; j < h; j++) {
-        png_bytep row = (png_bytep)(bm.getAddr(0, j));
-        png_write_rows(png, &row, 1);
-    }
-    png_write_end(png, info);
-    png_destroy_write_struct(&png, &info);
-
-    class ChunkReader : public SkPngChunkReader {
-    public:
-        ChunkReader(skiatest::Reporter* r)
-            : fReporter(r)
-        {
-            this->reset();
-        }
-
-        bool readChunk(const char tag[], const void* data, size_t length) override {
-            for (size_t i = 0; i < SK_ARRAY_COUNT(gUnknowns); ++i) {
-                if (!strcmp(tag, (const char*) gUnknowns[i].name)) {
-                    // Tag matches. This should have been the first time we see it.
-                    REPORTER_ASSERT(fReporter, !fSeen[i]);
-                    fSeen[i] = true;
-
-                    // Data and length should match
-                    REPORTER_ASSERT(fReporter, length == gUnknowns[i].size);
-                    REPORTER_ASSERT(fReporter, !strcmp((const char*) data,
-                                                       (const char*) gUnknowns[i].data));
-                    return true;
-                }
-            }
-            ERRORF(fReporter, "Saw an unexpected unknown chunk.");
-            return true;
-        }
-
-        bool allHaveBeenSeen() {
-            bool ret = true;
-            for (auto seen : fSeen) {
-                ret &= seen;
-            }
-            return ret;
-        }
-
-        void reset() {
-            sk_bzero(fSeen, sizeof(fSeen));
-        }
-
-    private:
-        skiatest::Reporter* fReporter;  // Unowned
-        bool fSeen[3];
-    };
-
-    ChunkReader chunkReader(r);
-
-    // Now read the file with SkCodec.
-    SkAutoTUnref<SkData> data(wStream.copyToData());
-    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(data, &chunkReader));
-    REPORTER_ASSERT(r, codec);
-    if (!codec) {
-        return;
-    }
-
-    // Now compare to the original.
-    SkBitmap decodedBm;
-    decodedBm.setInfo(codec->getInfo());
-    decodedBm.allocPixels();
-    SkCodec::Result result = codec->getPixels(codec->getInfo(), decodedBm.getPixels(),
-                                              decodedBm.rowBytes());
-    REPORTER_ASSERT(r, SkCodec::kSuccess == result);
-
-    if (decodedBm.colorType() != bm.colorType()) {
-        SkBitmap tmp;
-        bool success = decodedBm.copyTo(&tmp, bm.colorType());
-        REPORTER_ASSERT(r, success);
-        if (!success) {
-            return;
-        }
-
-        tmp.swap(decodedBm);
-    }
-
-    compare_to_good_digest(r, goodDigest, decodedBm);
-    REPORTER_ASSERT(r, chunkReader.allHaveBeenSeen());
-
-    // Decoding again will read the chunks again.
-    chunkReader.reset();
-    REPORTER_ASSERT(r, !chunkReader.allHaveBeenSeen());
-    result = codec->getPixels(codec->getInfo(), decodedBm.getPixels(), decodedBm.rowBytes());
-    REPORTER_ASSERT(r, SkCodec::kSuccess == result);
-    REPORTER_ASSERT(r, chunkReader.allHaveBeenSeen());
-}
-#endif // PNG_READ_UNKNOWN_CHUNKS_SUPPORTED