Revert "Revert "Delete copyTo(Allocator), hide copyTo() behind flag""

This reverts commit 0122af08f6af0dee490e1a4f35b552377d0d4753.

Reason for revert: Fixed Android callsite

Original change's description:
> Revert "Delete copyTo(Allocator), hide copyTo() behind flag"
> 
> This reverts commit d4a338f4d0a0cdc08d7d3668931c60997f0fa971.
> 
> Reason for revert: Looks like I missed something I was supposed to delete in Android.
> 
> Original change's description:
> > Delete copyTo(Allocator), hide copyTo() behind flag
> > 
> > Replace uses of copyTo() in Skia.
> > 
> > Bug: skia:6464
> > Change-Id: I921dc53a1c29a5176d18f05741f7c0b5a008e548
> > Reviewed-on: https://skia-review.googlesource.com/14502
> > Commit-Queue: Matt Sarett <msarett@google.com>
> > Reviewed-by: Mike Reed <reed@google.com>
> > 
> 
> TBR=msarett@google.com,reed@google.com
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> 
> Change-Id: I4d252940cc6a2462b030007055ea6c229471fc6e
> Reviewed-on: https://skia-review.googlesource.com/14602
> Reviewed-by: Matt Sarett <msarett@google.com>
> Commit-Queue: Matt Sarett <msarett@google.com>
> 

TBR=msarett@google.com,reviews@skia.org,reed@google.com

Change-Id: I81659a820f79f1958fda23cb62513065b57db99d
Reviewed-on: https://skia-review.googlesource.com/14640
Commit-Queue: Matt Sarett <msarett@google.com>
Reviewed-by: Matt Sarett <msarett@google.com>
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 707c4c9..6c8daf9 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -1123,7 +1123,8 @@
                         // We might consider promoting 565 to RGBA too.
                         if (bitmap.colorType() == kBGRA_8888_SkColorType) {
                             SkBitmap swizzle;
-                            SkAssertResult(bitmap.copyTo(&swizzle, kRGBA_8888_SkColorType));
+                            SkAssertResult(sk_tool_utils::copy_to(&swizzle, kRGBA_8888_SkColorType,
+                                                                  bitmap));
                             hash.write(swizzle.getPixels(), swizzle.getSize());
                         } else {
                             hash.write(bitmap.getPixels(), bitmap.getSize());
diff --git a/gm/all_bitmap_configs.cpp b/gm/all_bitmap_configs.cpp
index 7e9dfab..98d6621 100644
--- a/gm/all_bitmap_configs.cpp
+++ b/gm/all_bitmap_configs.cpp
@@ -14,8 +14,15 @@
 #include "SkColorPriv.h"
 
 static SkBitmap copy_bitmap(const SkBitmap& src, SkColorType colorType) {
+    const SkBitmap* srcPtr = &src;
+    SkBitmap tmp(src);
+    if (kRGB_565_SkColorType == colorType) {
+        tmp.setAlphaType(kOpaque_SkAlphaType);
+        srcPtr = &tmp;
+    }
+
     SkBitmap copy;
-    src.copyTo(&copy, colorType);
+    sk_tool_utils::copy_to(&copy, colorType, *srcPtr);
     copy.setImmutable();
     return copy;
 }
@@ -200,7 +207,7 @@
         const SkColorType ct = kBGRA_8888_SkColorType;
     #endif
     static_assert(ct != kN32_SkColorType, "BRGA!=RGBA");
-    SkAssertResult(n32bitmap.copyTo(&notN32bitmap, ct));
+    SkAssertResult(sk_tool_utils::copy_to(&notN32bitmap, ct, n32bitmap));
     SkASSERT(notN32bitmap.colorType() == ct);
     return SkImage::MakeFromBitmap(notN32bitmap);
 }
diff --git a/gm/animatedGif.cpp b/gm/animatedGif.cpp
index c7871e0..dd08abf 100644
--- a/gm/animatedGif.cpp
+++ b/gm/animatedGif.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "gm.h"
+#include "sk_tool_utils.h"
 #include "SkAnimTimer.h"
 #include "SkCanvas.h"
 #include "SkCodec.h"
@@ -59,7 +60,8 @@
                          && static_cast<size_t>(requiredFrame) < fFrames.size());
                 SkBitmap& requiredBitmap = fFrames[requiredFrame];
                 // For simplicity, do not try to cache old frames
-                if (requiredBitmap.getPixels() && requiredBitmap.copyTo(&bm)) {
+                if (requiredBitmap.getPixels() &&
+                        sk_tool_utils::copy_to(&bm, requiredBitmap.colorType(), requiredBitmap)) {
                     opts.fHasPriorFrame = true;
                 }
             }
diff --git a/gm/bitmapcopy.cpp b/gm/bitmapcopy.cpp
index 60eecf2..7428c20 100644
--- a/gm/bitmapcopy.cpp
+++ b/gm/bitmapcopy.cpp
@@ -71,7 +71,7 @@
         draw_checks(&canvasTmp, 40, 40);
 
         for (unsigned i = 0; i < NUM_CONFIGS; ++i) {
-            src.copyTo(&fDst[i], gColorTypes[i]);
+            sk_tool_utils::copy_to(&fDst[i], gColorTypes[i], src);
         }
 
         canvas->clear(sk_tool_utils::color_to_565(0xFFDDDDDD));
diff --git a/gm/bitmapfilters.cpp b/gm/bitmapfilters.cpp
index 22e5d09..7dc9692 100644
--- a/gm/bitmapfilters.cpp
+++ b/gm/bitmapfilters.cpp
@@ -68,9 +68,9 @@
 class FilterGM : public skiagm::GM {
     void onOnceBeforeDraw() override {
         make_bm(&fBM8);
-        fBM8.copyTo(&fBM4444, kARGB_4444_SkColorType);
-        fBM8.copyTo(&fBM16, kRGB_565_SkColorType);
-        fBM8.copyTo(&fBM32, kN32_SkColorType);
+        sk_tool_utils::copy_to(&fBM4444, kARGB_4444_SkColorType, fBM8);
+        sk_tool_utils::copy_to(&fBM16, kRGB_565_SkColorType, fBM8);
+        sk_tool_utils::copy_to(&fBM32, kN32_SkColorType, fBM8);
     }
 
 public:
diff --git a/gm/copyTo4444.cpp b/gm/copyTo4444.cpp
index 64f2c60..f593a19 100644
--- a/gm/copyTo4444.cpp
+++ b/gm/copyTo4444.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "gm.h"
+#include "sk_tool_utils.h"
 
 #include "Resources.h"
 #include "SkCanvas.h"
@@ -37,7 +38,7 @@
             return;
         }
         canvas->drawBitmap(bm, 0, 0);
-        SkAssertResult(bm.copyTo(&bm4444, kARGB_4444_SkColorType));
+        SkAssertResult(sk_tool_utils::copy_to(&bm4444, kARGB_4444_SkColorType, bm));
         canvas->drawBitmap(bm4444, SkIntToScalar(bm.width()), 0);
     }
 
diff --git a/gm/showmiplevels.cpp b/gm/showmiplevels.cpp
index e5374e4..3e2091f 100644
--- a/gm/showmiplevels.cpp
+++ b/gm/showmiplevels.cpp
@@ -120,7 +120,7 @@
 
     static void DrawAndFrame(SkCanvas* canvas, const SkBitmap& orig, SkScalar x, SkScalar y) {
         SkBitmap bm;
-        orig.copyTo(&bm);
+        sk_tool_utils::copy_to(&bm, orig.colorType(), orig);
         apply_gamma(bm);
 
         canvas->drawBitmap(bm, x, y, nullptr);
@@ -218,7 +218,14 @@
         return sk_tool_utils::copy_to_g8(dst, src);
     }
 
-    src.copyTo(dst, dstColorType);
+    const SkBitmap* srcPtr = &src;
+    SkBitmap tmp(src);
+    if (kRGB_565_SkColorType == dstColorType) {
+        tmp.setAlphaType(kOpaque_SkAlphaType);
+        srcPtr = &tmp;
+    }
+
+    sk_tool_utils::copy_to(dst, dstColorType, *srcPtr);
 }
 
 /**
diff --git a/gm/simpleaaclip.cpp b/gm/simpleaaclip.cpp
index 8f6c5c9..4c7407d 100644
--- a/gm/simpleaaclip.cpp
+++ b/gm/simpleaaclip.cpp
@@ -27,7 +27,7 @@
     // need to copy for deferred drawing test to work
     SkBitmap bm2;
 
-    bm.deepCopyTo(&bm2);
+    sk_tool_utils::copy_to(&bm2, bm.colorType(), bm);
 
     canvas->drawBitmap(bm2,
                        SK_Scalar1 * mask.fBounds.fLeft,
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index 8818829..d38898c 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -552,39 +552,15 @@
     */
     bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
 
-#ifdef SK_BUILD_FOR_ANDROID
-    /** Makes a deep copy of this bitmap, respecting the requested colorType,
-     *  and allocating the dst pixels on the cpu.
-     *  Returns false if either there is an error (i.e. the src does not have
-     *  pixels) or the request cannot be satisfied (e.g. the src has per-pixel
-     *  alpha, and the requested colortype does not support alpha).
-     *  @param dst The bitmap to be sized and allocated
-     *  @param ct The desired colorType for dst
-     *  @param allocator Allocator used to allocate the pixelref for the dst
-     *                   bitmap. If this is null, the standard HeapAllocator
-     *                   will be used.
-     *  @return true if the copy was made.
-     */
-    bool copyTo(SkBitmap* dst, SkColorType ct, Allocator*) const;
-
-    bool copyTo(SkBitmap* dst, Allocator* allocator) const {
-        return this->copyTo(dst, this->colorType(), allocator);
-    }
-#endif
-
-    /** Makes a deep copy of this bitmap, respecting the requested colorType.
-     *  Returns false if either there is an error (i.e. the src does not have
-     *  pixels) or the request cannot be satisfied (e.g. the src has per-pixel
-     *  alpha, and the requested colortype does not support alpha).
-     *  @param dst The bitmap to be sized and allocated
-     *  @param ct The desired colorType for dst
-     *  @return true if the copy was made.
-     */
+#ifdef SK_SUPPORT_LEGACY_BITMAP_COPYTO
     bool copyTo(SkBitmap* dst, SkColorType ct) const;
-
     bool copyTo(SkBitmap* dst) const {
         return this->copyTo(dst, this->colorType());
     }
+    bool deepCopyTo(SkBitmap* dst) const {
+        return this->copyTo(dst, this->colorType());
+    }
+#endif
 
     /**
      *  Copy the bitmap's pixels into the specified buffer (pixels + rowBytes),
@@ -625,20 +601,6 @@
         return this->writePixels(src, 0, 0);
     }
 
-    /**
-     *  Returns true if this bitmap's pixels can be converted into the requested
-     *  colorType, such that copyTo() could succeed.
-     */
-    bool canCopyTo(SkColorType colorType) const;
-
-    /** Makes a deep copy of this bitmap, keeping the copied pixels
-     *  in the same domain as the source: If the src pixels are allocated for
-     *  the cpu, then so will the dst. If the src pixels are allocated on the
-     *  gpu (typically as a texture), the it will do the same for the dst.
-     *  If the request cannot be fulfilled, returns false and dst is unmodified.
-     */
-    bool deepCopyTo(SkBitmap* dst) const;
-
 #ifdef SK_BUILD_FOR_ANDROID
     bool hasHardwareMipMap() const {
         return (fFlags & kHasHardwareMipMap_Flag) != 0;
@@ -736,7 +698,8 @@
     uint8_t             fFlags;
 
     bool writePixels(const SkPixmap& src, int x, int y, SkTransferFunctionBehavior behavior);
-    bool internalCopyTo(SkBitmap* dst, SkColorType ct, Allocator*) const;
+
+    bool canCopyTo(SkColorType colorType) const;
 
     /*  Unreference any pixelrefs or colortables
     */
diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h
index 036fb6d..535c6e1 100644
--- a/include/core/SkPixelRef.h
+++ b/include/core/SkPixelRef.h
@@ -178,11 +178,6 @@
     friend class SkImage_Raster;
     friend class SkSpecialImage_Raster;
 
-    // When copying a bitmap to another with the same shape and config, we can safely
-    // clone the pixelref generation ID too, which makes them equivalent under caching.
-    friend class SkBitmap;  // only for cloneGenID
-    void cloneGenID(const SkPixelRef&);
-
     void setImmutableWithID(uint32_t genID);
     friend class SkImage_Gpu;
     friend class SkImage_Lazy;
diff --git a/public.bzl b/public.bzl
index bb27e995..f0ac995 100644
--- a/public.bzl
+++ b/public.bzl
@@ -648,6 +648,7 @@
 ]
 
 DEFINES_ALL = [
+    "SK_SUPPORT_LEGACY_BITMAP_COPYTO",
     # Chrome DEFINES.
     "SK_USE_FLOATBITS",
     "SK_USE_FREETYPE_EMBOLDEN",
diff --git a/samplecode/SampleDither.cpp b/samplecode/SampleDither.cpp
index 76ebecc..6d91fda 100644
--- a/samplecode/SampleDither.cpp
+++ b/samplecode/SampleDither.cpp
@@ -19,6 +19,7 @@
 #include "SkColorPriv.h"
 #include "SkColorFilter.h"
 #include "SkDither.h"
+#include "sk_tool_utils.h"
 
 static void draw_sweep(SkCanvas* c, int width, int height, SkScalar angle) {
     SkRect  r;
@@ -111,7 +112,7 @@
         make_bm(&fBM);
         make_bm(&fBMPreDither);
         pre_dither(fBMPreDither);
-        fBM.copyTo(&fBM16, kARGB_4444_SkColorType);
+        sk_tool_utils::copy_to(&fBM16, kARGB_4444_SkColorType, fBM);
 
         fAngle = 0;
 
diff --git a/samplecode/SampleDitherBitmap.cpp b/samplecode/SampleDitherBitmap.cpp
index e5f7369..2f3de35 100644
--- a/samplecode/SampleDitherBitmap.cpp
+++ b/samplecode/SampleDitherBitmap.cpp
@@ -13,6 +13,7 @@
 #include "SkRegion.h"
 #include "SkUtils.h"
 #include "SkView.h"
+#include "sk_tool_utils.h"
 
 static void draw_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
     canvas->drawRect(r, p);
@@ -77,7 +78,7 @@
     DitherBitmapView() {
         fResult = test_pathregion();
         fBM8 = make_bitmap();
-        fBM8.copyTo(&fBM32, kN32_SkColorType);
+        sk_tool_utils::copy_to(&fBM32, kN32_SkColorType, fBM8);
 
         this->setBGColor(0xFFDDDDDD);
     }
diff --git a/samplecode/SampleFilter.cpp b/samplecode/SampleFilter.cpp
index d12f804..00f3853 100644
--- a/samplecode/SampleFilter.cpp
+++ b/samplecode/SampleFilter.cpp
@@ -78,9 +78,9 @@
 
     FilterView() {
         make_bm(&fBM8);
-        fBM8.copyTo(&fBM4444, kARGB_4444_SkColorType);
-        fBM8.copyTo(&fBM16, kRGB_565_SkColorType);
-        fBM8.copyTo(&fBM32, kN32_SkColorType);
+        sk_tool_utils::copy_to(&fBM4444, kARGB_4444_SkColorType, fBM8);
+        sk_tool_utils::copy_to(&fBM16, kRGB_565_SkColorType, fBM8);
+        sk_tool_utils::copy_to(&fBM32, kN32_SkColorType, fBM8);
 
         this->setBGColor(0xFFDDDDDD);
     }
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 0c1bc7d..8bd2684 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -529,7 +529,6 @@
         case kRGB_565_SkColorType:
         case kRGBA_8888_SkColorType:
         case kBGRA_8888_SkColorType:
-        case kRGBA_F16_SkColorType:
             break;
         case kGray_8_SkColorType:
             if (!sameConfigs) {
@@ -575,7 +574,8 @@
     return true;
 }
 
-bool SkBitmap::internalCopyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc) const {
+#ifdef SK_SUPPORT_LEGACY_BITMAP_COPYTO
+bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType) const {
     if (!this->canCopyTo(dstColorType)) {
         return false;
     }
@@ -585,36 +585,8 @@
         return false;
     }
 
-    // Various Android specific compatibility modes.
-    // TODO:
-    // Move the logic of this entire function into the framework, then call readPixels() directly.
-    SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
-    switch (dstColorType) {
-        case kRGB_565_SkColorType:
-            // copyTo() is not strict on alpha type.  Here we set the src to opaque to allow
-            // the call to readPixels() to succeed and preserve this lenient behavior.
-            if (kOpaque_SkAlphaType != srcPM.alphaType()) {
-                srcPM = SkPixmap(srcPM.info().makeAlphaType(kOpaque_SkAlphaType), srcPM.addr(),
-                                 srcPM.rowBytes(), srcPM.ctable());
-                dstInfo = dstInfo.makeAlphaType(kOpaque_SkAlphaType);
-            }
-            break;
-        case kRGBA_F16_SkColorType:
-            // The caller does not have an opportunity to pass a dst color space.  Assume that
-            // they want linear sRGB.
-            dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGBLinear());
-
-            if (!srcPM.colorSpace()) {
-                // We can't do a sane conversion to F16 without a dst color space.  Guess sRGB
-                // in this case.
-                srcPM.setColorSpace(SkColorSpace::MakeSRGB());
-            }
-            break;
-        default:
-            break;
-    }
-
     SkBitmap tmpDst;
+    SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
     if (!tmpDst.setInfo(dstInfo)) {
         return false;
     }
@@ -624,7 +596,7 @@
     if (dstColorType == kIndex_8_SkColorType) {
         ctable.reset(SkRef(srcPM.ctable()));
     }
-    if (!tmpDst.tryAllocPixels(alloc, ctable.get())) {
+    if (!tmpDst.tryAllocPixels(ctable.get())) {
         return false;
     }
 
@@ -633,60 +605,15 @@
         return false;
     }
 
-    // We can't do a sane conversion from F16 without a src color space.  Guess sRGB in this case.
-    if (kRGBA_F16_SkColorType == srcPM.colorType() && !dstPM.colorSpace()) {
-        dstPM.setColorSpace(SkColorSpace::MakeSRGB());
-    }
-
-    // readPixels does not yet support color spaces with parametric transfer functions.  This
-    // works around that restriction when the color spaces are equal.
-    if (kRGBA_F16_SkColorType != dstColorType && kRGBA_F16_SkColorType != srcPM.colorType() &&
-            dstPM.colorSpace() == srcPM.colorSpace()) {
-        dstPM.setColorSpace(nullptr);
-        srcPM.setColorSpace(nullptr);
-    }
-
     if (!srcPM.readPixels(dstPM)) {
         return false;
     }
 
-    //  (for BitmapHeap) Clone the pixelref genID even though we have a new pixelref.
-    //  The old copyTo impl did this, so we continue it for now.
-    //
-    //  TODO: should we ignore rowbytes (i.e. getSize)? Then it could just be
-    //      if (src_pixelref->info == dst_pixelref->info)
-    //
-    if (srcPM.colorType() == dstColorType && tmpDst.getSize() == srcPM.getSize64()) {
-        if (tmpDst.info() == this->info() && tmpDst.pixelRef()->width() == fPixelRef->width() &&
-                tmpDst.pixelRef()->height() == fPixelRef->height()) {
-            tmpDst.pixelRef()->cloneGenID(*fPixelRef);
-        }
-    }
-
     dst->swap(tmpDst);
     return true;
 }
-
-bool SkBitmap::copyTo(SkBitmap* dst, SkColorType ct) const {
-    return this->internalCopyTo(dst, ct, nullptr);
-}
-
-#ifdef SK_BUILD_FOR_ANDROID
-bool SkBitmap::copyTo(SkBitmap* dst, SkColorType ct, Allocator* alloc) const {
-    return this->internalCopyTo(dst, ct, alloc);
-}
 #endif
 
-// TODO: can we merge this with copyTo?
-bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
-    const SkColorType dstCT = this->colorType();
-
-    if (!this->canCopyTo(dstCT)) {
-        return false;
-    }
-    return this->copyTo(dst, dstCT);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp
index a32b153..487779c 100644
--- a/src/core/SkPixelRef.cpp
+++ b/src/core/SkPixelRef.cpp
@@ -133,20 +133,6 @@
     SkASSERT(!this->genIDIsUnique()); // This method isn't threadsafe, so the assert should be fine.
 }
 
-void SkPixelRef::cloneGenID(const SkPixelRef& that) {
-    // This is subtle.  We must call that.getGenerationID() to make sure its genID isn't 0.
-    uint32_t genID = that.getGenerationID();
-
-    // Neither ID is unique any more.
-    // (These & ~1u are actually redundant.  that.getGenerationID() just did it for us.)
-    this->fTaggedGenID.store(genID & ~1u);
-    that. fTaggedGenID.store(genID & ~1u);
-
-    // This method isn't threadsafe, so these asserts should be fine.
-    SkASSERT(!this->genIDIsUnique());
-    SkASSERT(!that. genIDIsUnique());
-}
-
 uint32_t SkPixelRef::getGenerationID() const {
     uint32_t id = fTaggedGenID.load();
     if (0 == id) {
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index a142576..b22335b 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -327,13 +327,15 @@
     }
 
     const SkBitmap* srcBM = &bm;
-    SkBitmap tmpStorage;
+    SkBitmap tmp;
     // ImageFilters only handle N32 at the moment, so force our src to be that
     if (!valid_for_imagefilters(bm.info())) {
-        if (!bm.copyTo(&tmpStorage, kN32_SkColorType)) {
+        if (!tmp.tryAllocPixels(bm.info().makeColorType(kN32_SkColorType)) ||
+            !bm.readPixels(tmp.info(), tmp.getPixels(), tmp.rowBytes(), 0, 0))
+        {
             return nullptr;
         }
-        srcBM = &tmpStorage;
+        srcBM = &tmp;
     }
     return sk_make_sp<SkSpecialImage_Raster>(subset, *srcBM, props);
 }
diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp
index 19460a4..b58aaf4 100644
--- a/src/pdf/SkPDFBitmap.cpp
+++ b/src/pdf/SkPDFBitmap.cpp
@@ -147,7 +147,8 @@
         return input;
     }
     // ARGB_4444 is rarely used, so we can do a wasteful tmp copy.
-    SkAssertResult(input.copyTo(copy, kN32_SkColorType));
+    copy->allocPixels(input.info().makeColorType(kN32_SkColorType));
+    SkAssertResult(input.readPixels(copy->info(), copy->getPixels(), copy->rowBytes(), 0, 0));
     copy->setImmutable();
     return *copy;
 }
diff --git a/src/ports/SkImageEncoder_CG.cpp b/src/ports/SkImageEncoder_CG.cpp
index b3fd243..8c2a542 100644
--- a/src/ports/SkImageEncoder_CG.cpp
+++ b/src/ports/SkImageEncoder_CG.cpp
@@ -89,9 +89,10 @@
             // <Error>: CGImageDestinationFinalize image destination does not have enough images
             // So instead we copy to 8888.
             if (bm.colorType() == kARGB_4444_SkColorType) {
-                SkBitmap bitmap8888;
-                bm.copyTo(&bitmap8888, kN32_SkColorType);
-                bm.swap(bitmap8888);
+                SkBitmap bitmapN32;
+                bitmapN32.allocPixels(bm.info().makeColorType(kN32_SkColorType));
+                bm.readPixels(bitmapN32.info(), bitmapN32.getPixels(), bitmapN32.rowBytes(), 0, 0);
+                bm.swap(bitmapN32);
             }
             type = kUTTypePNG;
             break;
diff --git a/src/ports/SkImageEncoder_WIC.cpp b/src/ports/SkImageEncoder_WIC.cpp
index 6d355c1..1ae9257 100644
--- a/src/ports/SkImageEncoder_WIC.cpp
+++ b/src/ports/SkImageEncoder_WIC.cpp
@@ -70,7 +70,9 @@
 
     // First convert to BGRA if necessary.
     SkBitmap bitmap;
-    if (!bitmapOrig.copyTo(&bitmap, kBGRA_8888_SkColorType)) {
+    if (!bitmap.tryAllocPixels(bitmapOrig.info().makeColorType(kBGRA_8888_SkColorType)) ||
+        !bitmapOrig.readPixels(bitmap.info(), bitmap.getPixels(), bitmap.rowBytes(), 0, 0))
+    {
         return false;
     }
 
diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp
index 880c566..b5df423 100644
--- a/src/utils/mac/SkCreateCGImageRef.cpp
+++ b/src/utils/mac/SkCreateCGImageRef.cpp
@@ -110,9 +110,10 @@
     SkBitmap* copy;
     if (upscaleTo32) {
         copy = new SkBitmap;
-        // here we make a ceep copy of the pixels, since CG won't take our
+        // here we make a deep copy of the pixels, since CG won't take our
         // 565 directly
-        bm.copyTo(copy, kN32_SkColorType);
+        copy->allocPixels(bm.info().makeColorType(kN32_SkColorType));
+        bm.readPixels(copy->info(), copy->getPixels(), copy->rowBytes(), 0, 0);
     } else {
         copy = new SkBitmap(bm);
     }
diff --git a/tests/BitmapCopyTest.cpp b/tests/BitmapCopyTest.cpp
index aadf192..dd5bf1a 100644
--- a/tests/BitmapCopyTest.cpp
+++ b/tests/BitmapCopyTest.cpp
@@ -9,6 +9,7 @@
 #include "SkRect.h"
 #include "SkTemplates.h"
 #include "Test.h"
+#include "sk_tool_utils.h"
 
 static void init_src(const SkBitmap& bitmap) {
     if (bitmap.getPixels()) {
@@ -112,7 +113,7 @@
             // Test copying an extracted subset.
             for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
                 SkBitmap copy;
-                bool success = subset.copyTo(&copy, gPairs[j].fColorType);
+                bool success = sk_tool_utils::copy_to(&copy, gPairs[j].fColorType, subset);
                 if (!success) {
                     // Skip checking that success matches fValid, which is redundant
                     // with the code below.
@@ -236,20 +237,3 @@
         }
     }
 }
-
-DEF_TEST(BitmapCopy_ColorSpaceMatch, r) {
-    // We should support matching color spaces, even if they are parametric.
-    SkColorSpaceTransferFn fn;
-    fn.fA = 1.f; fn.fB = 0.f; fn.fC = 0.f; fn.fD = 0.f; fn.fE = 0.f; fn.fF = 0.f; fn.fG = 1.8f;
-    sk_sp<SkColorSpace> cs = SkColorSpace::MakeRGB(fn, SkColorSpace::kRec2020_Gamut);
-
-    SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1, cs);
-    SkBitmap bitmap;
-    bitmap.allocPixels(info);
-    bitmap.eraseColor(0);
-
-    SkBitmap copy;
-    bool success = bitmap.copyTo(&copy, kN32_SkColorType);
-    REPORTER_ASSERT(r, success);
-    REPORTER_ASSERT(r, cs.get() == copy.colorSpace());
-}
diff --git a/tests/BitmapTest.cpp b/tests/BitmapTest.cpp
index 0d4b785..e0a7f78 100644
--- a/tests/BitmapTest.cpp
+++ b/tests/BitmapTest.cpp
@@ -9,6 +9,7 @@
 #include "SkMallocPixelRef.h"
 #include "SkRandom.h"
 #include "Test.h"
+#include "sk_tool_utils.h"
 
 static void test_peekpixels(skiatest::Reporter* reporter) {
     const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
@@ -137,7 +138,7 @@
     };
     for (SkColorType ct : colorTypes) {
         SkBitmap copy;
-        if (!source.copyTo(&copy, ct)) {
+        if (!sk_tool_utils::copy_to(&copy, ct, source)) {
             ERRORF(r, "SkBitmap::copy failed %d", (int)ct);
             continue;
         }
diff --git a/tests/CodecAnimTest.cpp b/tests/CodecAnimTest.cpp
index 79e03bd..24b9c13 100644
--- a/tests/CodecAnimTest.cpp
+++ b/tests/CodecAnimTest.cpp
@@ -14,6 +14,7 @@
 
 #include "Resources.h"
 #include "Test.h"
+#include "sk_tool_utils.h"
 
 #include <initializer_list>
 #include <vector>
@@ -239,7 +240,8 @@
                     // First copy the pixels from the cached frame
                     const int requiredFrame = frameInfos[index].fRequiredFrame;
                     if (requiredFrame != SkCodec::kNone) {
-                        const bool success = cachedFrames[requiredFrame].copyTo(bm);
+                        const bool success = sk_tool_utils::copy_to(bm, kN32_SkColorType,
+                                cachedFrames[requiredFrame]);
                         REPORTER_ASSERT(r, success);
                     }
                 }
diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp
index 7944877..4a13533 100644
--- a/tests/CodecTest.cpp
+++ b/tests/CodecTest.cpp
@@ -850,7 +850,7 @@
 
     if (decodedBm.colorType() != bm.colorType()) {
         SkBitmap tmp;
-        bool success = decodedBm.copyTo(&tmp, bm.colorType());
+        bool success = sk_tool_utils::copy_to(&tmp, bm.colorType(), decodedBm);
         REPORTER_ASSERT(r, success);
         if (!success) {
             return;
diff --git a/tools/debugger/SkDrawCommand.cpp b/tools/debugger/SkDrawCommand.cpp
index e386f46..23cc6b2 100644
--- a/tools/debugger/SkDrawCommand.cpp
+++ b/tools/debugger/SkDrawCommand.cpp
@@ -837,7 +837,9 @@
         return bitmap;
     }
     SkBitmap* dst = new SkBitmap();
-    if (bitmap->copyTo(dst, colorType)) {
+    if (dst->tryAllocPixels(bitmap->info().makeColorType(colorType)) &&
+        bitmap->readPixels(dst->info(), dst->getPixels(), dst->rowBytes(), 0, 0))
+    {
         delete bitmap;
         return dst;
     }
diff --git a/tools/picture_utils.cpp b/tools/picture_utils.cpp
index 27e91cc..bd32f19 100644
--- a/tools/picture_utils.cpp
+++ b/tools/picture_utils.cpp
@@ -126,7 +126,7 @@
             // Convert smaller formats up to premul linear 8-bit (in SkPMColor order).
             if (bitmap.colorType() != kN32_SkColorType) {
                 SkBitmap n32;
-                if (!bitmap.copyTo(&n32, kN32_SkColorType)) {
+                if (!sk_tool_utils::copy_to(&n32, kN32_SkColorType, bitmap)) {
                     return nullptr;
                 }
                 bitmap = n32;
diff --git a/tools/sk_tool_utils.cpp b/tools/sk_tool_utils.cpp
index 9a4bb2b..c69b17d 100644
--- a/tools/sk_tool_utils.cpp
+++ b/tools/sk_tool_utils.cpp
@@ -586,6 +586,44 @@
     return SkRect::MakeLTRB(r.fLeft + maxL, r.fTop, r.fRight - maxR, r.fBottom);
 }
 
+bool copy_to(SkBitmap* dst, SkColorType dstColorType, const SkBitmap& src) {
+    SkPixmap srcPM;
+    if (!src.peekPixels(&srcPM)) {
+        return false;
+    }
+
+    SkBitmap tmpDst;
+    SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
+    if (!tmpDst.setInfo(dstInfo)) {
+        return false;
+    }
+
+    // allocate colortable if srcConfig == kIndex8_Config
+    sk_sp<SkColorTable> ctable = nullptr;
+    if (dstColorType == kIndex_8_SkColorType) {
+        if (src.colorType() != kIndex_8_SkColorType) {
+            return false;
+        }
+
+        ctable = sk_ref_sp(srcPM.ctable());
+    }
+    if (!tmpDst.tryAllocPixels(ctable.get())) {
+        return false;
+    }
+
+    SkPixmap dstPM;
+    if (!tmpDst.peekPixels(&dstPM)) {
+        return false;
+    }
+
+    if (!srcPM.readPixels(dstPM)) {
+        return false;
+    }
+
+    dst->swap(tmpDst);
+    return true;
+}
+
 void copy_to_g8(SkBitmap* dst, const SkBitmap& src) {
     SkASSERT(kBGRA_8888_SkColorType == src.colorType() ||
              kRGBA_8888_SkColorType == src.colorType());
diff --git a/tools/sk_tool_utils.h b/tools/sk_tool_utils.h
index e319411..111f966 100644
--- a/tools/sk_tool_utils.h
+++ b/tools/sk_tool_utils.h
@@ -253,6 +253,7 @@
         return sk_make_sp<EncodeImagePixelSerializer>();
     }
 
+    bool copy_to(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src);
     void copy_to_g8(SkBitmap* dst, const SkBitmap& src);
 
 #if SK_SUPPORT_GPU
diff --git a/tools/skdiff/skdiff_utils.cpp b/tools/skdiff/skdiff_utils.cpp
index 05e1c50..7a1b7e8 100644
--- a/tools/skdiff/skdiff_utils.cpp
+++ b/tools/skdiff/skdiff_utils.cpp
@@ -80,7 +80,7 @@
 
 bool write_bitmap(const SkString& path, const SkBitmap& bitmap) {
     SkBitmap copy;
-    bitmap.copyTo(&copy, kN32_SkColorType);
+    sk_tool_utils::copy_to(&copy, kN32_SkColorType, bitmap);
     force_all_opaque(copy);
     return sk_tool_utils::EncodeImageToFile(path.c_str(), copy,
                                       SkEncodedImageFormat::kPNG, 100);