Revert "Revert "Revert "guard old apis for querying byte-size of a bitmap/imageinfo/pixmap"""

This reverts commit cd284c532376d16fcc4ed75baf3da65c3e4a2e95.

Reason for revert:

assert fired in SkMallocPixelRef.cpp:61: fatal error: "assert(info.computeByteSize(rowBytes) == info.getSafeSize(rowBytes))"

google3 thinks it was from surface_rowbytes

Original change's description:
> Revert "Revert "guard old apis for querying byte-size of a bitmap/imageinfo/pixmap""
> 
> This reverts commit 809cbedd4b252be221b2ac3b4269d312fd8f53a0.
> 
> Bug: skia:
> Change-Id: I680d8daeeeeb15526b44c1305d8fb0c6bfa38e1d
> Reviewed-on: https://skia-review.googlesource.com/52665
> Commit-Queue: Mike Reed <reed@google.com>
> Reviewed-by: Florin Malita <fmalita@chromium.org>

TBR=fmalita@chromium.org,reed@google.com

Change-Id: I41e3f7a3f791cc8183291847e783ed8a53bc91d2
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/53802
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/bench/AndroidCodecBench.cpp b/bench/AndroidCodecBench.cpp
index 886e875..d9abac6 100644
--- a/bench/AndroidCodecBench.cpp
+++ b/bench/AndroidCodecBench.cpp
@@ -38,7 +38,7 @@
         fInfo = fInfo.makeAlphaType(kPremul_SkAlphaType);
     }
 
-    fPixelStorage.reset(fInfo.computeMinByteSize());
+    fPixelStorage.reset(fInfo.getSafeSize(fInfo.minRowBytes()));
 }
 
 void AndroidCodecBench::onDraw(int n, SkCanvas* canvas) {
diff --git a/bench/CodecBench.cpp b/bench/CodecBench.cpp
index 708ab60..2944374 100644
--- a/bench/CodecBench.cpp
+++ b/bench/CodecBench.cpp
@@ -43,7 +43,7 @@
                             .makeAlphaType(fAlphaType)
                             .makeColorSpace(nullptr);
 
-    fPixelStorage.reset(fInfo.computeMinByteSize());
+    fPixelStorage.reset(fInfo.getSafeSize(fInfo.minRowBytes()));
 }
 
 void CodecBench::onDraw(int n, SkCanvas* canvas) {
diff --git a/bench/ColorCodecBench.cpp b/bench/ColorCodecBench.cpp
index 1239e1d..680c1d9 100644
--- a/bench/ColorCodecBench.cpp
+++ b/bench/ColorCodecBench.cpp
@@ -88,10 +88,10 @@
         fDstSpace = static_cast<SkColorSpace_XYZ*>(fDstSpace.get())->makeLinearGamma();
     }
 
-    fDst.reset(fDstInfo.computeMinByteSize());
+    fDst.reset(fDstInfo.getSafeSize(fDstInfo.minRowBytes()));
 
     if (FLAGS_xform_only) {
-        fSrc.reset(fSrcInfo.computeMinByteSize());
+        fSrc.reset(fSrcInfo.getSafeSize(fSrcInfo.minRowBytes()));
         fSrcSpace = codec->getInfo().refColorSpace();
         codec->getPixels(fSrcInfo, fSrc.get(), fSrcInfo.minRowBytes());
     }
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index 2dc41bb..0458330 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -887,7 +887,7 @@
                 SkImageInfo info =
                         codec->getInfo().makeColorType(colorType).makeAlphaType(alphaType);
                 const size_t rowBytes = info.minRowBytes();
-                SkAutoMalloc storage(info.computeByteSize(rowBytes));
+                SkAutoMalloc storage(info.getSafeSize(rowBytes));
 
                 const SkCodec::Result result = codec->getPixels(
                         info, storage.get(), rowBytes);
diff --git a/dm/DM.cpp b/dm/DM.cpp
index ea8ec27..777a593 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -1128,9 +1128,9 @@
                             SkBitmap swizzle;
                             SkAssertResult(sk_tool_utils::copy_to(&swizzle, kRGBA_8888_SkColorType,
                                                                   bitmap));
-                            hash.write(swizzle.getPixels(), swizzle.computeByteSize());
+                            hash.write(swizzle.getPixels(), swizzle.getSize());
                         } else {
-                            hash.write(bitmap.getPixels(), bitmap.computeByteSize());
+                            hash.write(bitmap.getPixels(), bitmap.getSize());
                         }
                     }
                     SkMD5::Digest digest;
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 0968aca..2a0b598 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -454,7 +454,7 @@
 
     const int bpp = SkColorTypeBytesPerPixel(decodeInfo.colorType());
     const size_t rowBytes = size.width() * bpp;
-    const size_t safeSize = decodeInfo.computeByteSize(rowBytes);
+    const size_t safeSize = decodeInfo.getSafeSize(rowBytes);
     SkAutoMalloc pixels(safeSize);
 
     SkCodec::Options options;
@@ -1468,12 +1468,12 @@
 
 static Error compare_bitmaps(const SkBitmap& reference, const SkBitmap& bitmap) {
     // The dimensions are a property of the Src only, and so should be identical.
-    SkASSERT(reference.computeByteSize() == bitmap.computeByteSize());
-    if (reference.computeByteSize() != bitmap.computeByteSize()) {
+    SkASSERT(reference.getSize() == bitmap.getSize());
+    if (reference.getSize() != bitmap.getSize()) {
         return "Dimensions don't match reference";
     }
     // All SkBitmaps in DM are tight, so this comparison is easy.
-    if (0 != memcmp(reference.getPixels(), bitmap.getPixels(), reference.computeByteSize())) {
+    if (0 != memcmp(reference.getPixels(), bitmap.getPixels(), reference.getSize())) {
         SkString encoded;
         SkString errString("Pixels don't match reference");
         if (encode_png_base64(reference, &encoded)) {
diff --git a/gn/flutter_defines.gni b/gn/flutter_defines.gni
index 8d8520e..13cf328 100644
--- a/gn/flutter_defines.gni
+++ b/gn/flutter_defines.gni
@@ -5,5 +5,4 @@
 flutter_defines = [
   "SK_SUPPORT_LEGACY_IMAGE_ENCODE_API",
   "SK_SUPPORT_LEGACY_FONTMGR_API",
-  "SK_SUPPORT_LEGACY_SAFESIZE64",
 ]
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index cea50b8..5b4e1a6 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -147,7 +147,10 @@
      */
     size_t computeByteSize() const { return fInfo.computeByteSize(fRowBytes); }
 
-#ifdef SK_SUPPORT_LEGACY_SAFESIZE64
+    /** Return the byte size of the pixels, based on the height and rowBytes.
+        Note this truncates the result to 32bits. Call getSize64() to detect
+        if the real size exceeds 32bits.
+    */
     size_t getSize() const { return fInfo.height() * fRowBytes; }
 
     /** Return the number of bytes from the pointer returned by getPixels()
@@ -171,7 +174,6 @@
     int64_t computeSafeSize64() const {
         return fInfo.getSafeSize64(fRowBytes);
     }
-#endif
 
     /** Returns true if this bitmap is marked as immutable, meaning that the
         contents of its pixels will not change for the lifetime of the bitmap.
diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h
index 50d068a..c47dbb2 100644
--- a/include/core/SkImageInfo.h
+++ b/include/core/SkImageInfo.h
@@ -300,7 +300,6 @@
     void unflatten(SkReadBuffer&);
     void flatten(SkWriteBuffer&) const;
 
-#ifdef SK_SUPPORT_LEGACY_SAFESIZE64
     int64_t getSafeSize64(size_t rowBytes) const {
         if (0 == fHeight) {
             return 0;
@@ -315,7 +314,6 @@
         }
         return sk_64_asS32(size);
     }
-#endif
 
     /**
      *  Returns the size (in bytes) of the image buffer that this info needs, given the specified
@@ -333,8 +331,8 @@
     }
 
     bool validRowBytes(size_t rowBytes) const {
-        uint64_t minRB = sk_64_mul(fWidth, this->bytesPerPixel());
-        return rowBytes >= minRB;
+        uint64_t rb = sk_64_mul(fWidth, this->bytesPerPixel());
+        return rowBytes >= rb;
     }
 
     void reset() {
diff --git a/include/core/SkPixmap.h b/include/core/SkPixmap.h
index f304bde..8115756 100644
--- a/include/core/SkPixmap.h
+++ b/include/core/SkPixmap.h
@@ -206,7 +206,6 @@
     */
     int shiftPerPixel() const { return fInfo.shiftPerPixel(); }
 
-#ifdef SK_SUPPORT_LEGACY_SAFESIZE64
     /** Returns conservative memory required for pixel storage.
         Includes unused memory on last row when rowBytesAsPixels() exceeds width().
 
@@ -229,7 +228,6 @@
         @return  exact pixel storage size if size fits in signed 32 bits
     */
     size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); }
-#endif
 
     /**
      *  Returns the size (in bytes) of the pixmap's image buffer.
diff --git a/public.bzl b/public.bzl
index 9b3afbe..e832550 100644
--- a/public.bzl
+++ b/public.bzl
@@ -656,7 +656,6 @@
     # Required for building dm.
     "GR_TEST_UTILS",
     # Staging flags for API changes
-    "SK_SUPPORT_LEGACY_SAFESIZE64",
     # Should remove after we update golden images
     "SK_WEBP_ENCODER_USE_DEFAULT_METHOD",
     # Experiment to diagnose image diffs in Google3
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index fef6f97..7beffda 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -344,7 +344,7 @@
             // We made/have an off-screen surface. Extract the pixels exactly as we rendered them:
             SkImageInfo info = win->info();
             size_t rowBytes = info.minRowBytes();
-            size_t size = info.computeByteSize(rowBytes);
+            size_t size = info.getSafeSize(rowBytes);
             auto data = SkData::MakeUninitialized(size);
             SkASSERT(data);
 
diff --git a/src/android/SkBitmapRegionCodec.cpp b/src/android/SkBitmapRegionCodec.cpp
index 493e4b5..f77c702 100644
--- a/src/android/SkBitmapRegionCodec.cpp
+++ b/src/android/SkBitmapRegionCodec.cpp
@@ -96,7 +96,7 @@
     if (SubsetType::kPartiallyInside_SubsetType == type &&
             SkCodec::kNo_ZeroInitialized == zeroInit) {
         void* pixels = bitmap->getPixels();
-        size_t bytes = outInfo.computeByteSize(bitmap->rowBytes());
+        size_t bytes = outInfo.getSafeSize(bitmap->rowBytes());
         memset(pixels, 0, bytes);
     }
 
diff --git a/src/codec/SkIcoCodec.cpp b/src/codec/SkIcoCodec.cpp
index da6d0c3..74affe6 100644
--- a/src/codec/SkIcoCodec.cpp
+++ b/src/codec/SkIcoCodec.cpp
@@ -173,7 +173,7 @@
     int maxIndex = 0;
     for (int i = 0; i < codecs->count(); i++) {
         SkImageInfo info = codecs->operator[](i)->getInfo();
-        size_t size = info.computeMinByteSize();
+        size_t size = info.getSafeSize(info.minRowBytes());
 
         if (size > maxSize) {
             maxSize = size;
diff --git a/src/codec/SkSampler.cpp b/src/codec/SkSampler.cpp
index d18410b..c7d9a3a 100644
--- a/src/codec/SkSampler.cpp
+++ b/src/codec/SkSampler.cpp
@@ -14,8 +14,8 @@
         uint64_t colorOrIndex, SkCodec::ZeroInitialized zeroInit) {
     SkASSERT(dst != nullptr);
 
-    // Calculate bytes to fill.
-    const size_t bytesToFill = info.computeByteSize(rowBytes);
+    // Calculate bytes to fill.  We use getSafeSize since the last row may not be padded.
+    const size_t bytesToFill = info.getSafeSize(rowBytes);
     const int width = info.width();
     const int numRows = info.height();
 
diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp
index baf3468..10b8283 100644
--- a/src/codec/SkWebpCodec.cpp
+++ b/src/codec/SkWebpCodec.cpp
@@ -542,7 +542,7 @@
 
     config.output.u.RGBA.rgba = reinterpret_cast<uint8_t*>(webpDst.getAddr(dstX, dstY));
     config.output.u.RGBA.stride = static_cast<int>(webpDst.rowBytes());
-    config.output.u.RGBA.size = webpDst.computeByteSize();
+    config.output.u.RGBA.size = webpDst.getSafeSize();
 
     SkAutoTCallVProc<WebPIDecoder, WebPIDelete> idec(WebPIDecode(nullptr, 0, &config));
     if (!idec) {
diff --git a/src/core/SkAutoPixmapStorage.cpp b/src/core/SkAutoPixmapStorage.cpp
index df0c0fa..be13e71 100644
--- a/src/core/SkAutoPixmapStorage.cpp
+++ b/src/core/SkAutoPixmapStorage.cpp
@@ -29,7 +29,7 @@
     if (rowBytes) {
         *rowBytes = rb;
     }
-    return info.computeByteSize(rb);
+    return info.getSafeSize(rb);
 }
 
 bool SkAutoPixmapStorage::tryAlloc(const SkImageInfo& info) {
@@ -58,7 +58,7 @@
         return nullptr;
     }
 
-    auto data = SkData::MakeFromMalloc(fStorage, this->computeByteSize());
+    auto data = SkData::MakeFromMalloc(fStorage, this->getSafeSize());
     fStorage = nullptr;
     this->INHERITED::reset();
 
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 4c4f76a..9de2261 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -678,7 +678,7 @@
     }
 
     // write_raw_pixels() always writes snug buffers with rowBytes == minRowBytes().
-    size_t bytes = info.computeMinByteSize();
+    size_t bytes = info.getSafeSize(info.minRowBytes());
     if (!buffer->validate(bytes != 0)) {
         return false;
     }
diff --git a/src/core/SkBitmapCache.cpp b/src/core/SkBitmapCache.cpp
index 8d3991a..b876764 100644
--- a/src/core/SkBitmapCache.cpp
+++ b/src/core/SkBitmapCache.cpp
@@ -160,7 +160,7 @@
 
     const Key& getKey() const override { return fKey; }
     size_t bytesUsed() const override {
-        return sizeof(fKey) + fInfo.computeByteSize(fRowBytes);
+        return sizeof(fKey) + fInfo.getSafeSize(fRowBytes);
     }
     bool canBePurged() override {
         SkAutoMutexAcquire ama(fMutex);
@@ -289,7 +289,7 @@
     }
 
     const size_t rb = info.minRowBytes();
-    size_t size = info.computeByteSize(rb);
+    size_t size = info.getSafeSize(rb);
     if (0 == size) {
         return nullptr;
     }
diff --git a/src/core/SkMallocPixelRef.cpp b/src/core/SkMallocPixelRef.cpp
index 807eb06..50ee91c 100644
--- a/src/core/SkMallocPixelRef.cpp
+++ b/src/core/SkMallocPixelRef.cpp
@@ -35,39 +35,38 @@
 }
 
 
-sk_sp<SkPixelRef> SkMallocPixelRef::MakeUsing(void*(*allocProc)(size_t),
-                                              const SkImageInfo& info,
-                                              size_t rowBytes) {
-    if (rowBytes == 0) {
-        rowBytes = info.minRowBytes();
-    }
-
-    if (!is_valid(info) || !info.validRowBytes(rowBytes)) {
+sk_sp<SkPixelRef> SkMallocPixelRef::MakeUsing(void*(*alloc)(size_t),
+                                           const SkImageInfo& info,
+                                           size_t requestedRowBytes) {
+    if (!is_valid(info)) {
         return nullptr;
     }
 
-    size_t size = 0;
-    // if the info is empty, or rowBytes is 0 (which can be valid), then we don't need to compute
-    // a size.
-    if (!info.isEmpty() && rowBytes > 0) {
-#ifdef SK_SUPPORT_LEGACY_SAFESIZE64
-        int64_t bigSize = (int64_t)info.height() * rowBytes;
-        if (!sk_64_isS32(bigSize)) {
-            return nullptr;
-        }
-
-        size = sk_64_asS32(bigSize);
-        SkASSERT(size >= info.getSafeSize(rowBytes));
-        SkASSERT(info.computeByteSize(rowBytes) == info.getSafeSize(rowBytes));
-#else
-        size = info.computeByteSize(rowBytes);
-#endif
-        if (size == 0) {
-            return nullptr; // overflow
-        }
+    // only want to permit 31bits of rowBytes
+    int64_t minRB = (int64_t)info.minRowBytes64();
+    if (minRB < 0 || !sk_64_isS32(minRB)) {
+        return nullptr;    // allocation will be too large
+    }
+    if (requestedRowBytes > 0 && (int32_t)requestedRowBytes < minRB) {
+        return nullptr;    // cannot meet requested rowbytes
     }
 
-    void* addr = allocProc(size);
+    int32_t rowBytes;
+    if (requestedRowBytes) {
+        rowBytes = SkToS32(requestedRowBytes);
+    } else {
+        rowBytes = minRB;
+    }
+
+    int64_t bigSize = (int64_t)info.height() * rowBytes;
+    if (!sk_64_isS32(bigSize)) {
+        return nullptr;
+    }
+
+    size_t size = sk_64_asS32(bigSize);
+    SkASSERT(size >= info.getSafeSize(rowBytes));
+    SkASSERT(info.getSafeSize(rowBytes) == info.computeByteSize(rowBytes));
+    void* addr = alloc(size);
     if (nullptr == addr) {
         return nullptr;
     }
@@ -109,11 +108,10 @@
                                                 size_t rowBytes,
                                                 sk_sp<SkData> data) {
     SkASSERT(data != nullptr);
-    if (!is_valid(info) || !info.validRowBytes(rowBytes)) {
+    if (!is_valid(info)) {
         return nullptr;
     }
-    size_t sizeNeeded = info.computeByteSize(rowBytes);
-    if (!info.isEmpty() && (sizeNeeded == 0 || data->size() < sizeNeeded)) {
+    if ((rowBytes < info.minRowBytes()) || (data->size() < info.getSafeSize(rowBytes))) {
         return nullptr;
     }
     // must get this address before we call release
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index 460907f..98036cf 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -400,7 +400,7 @@
     } else {
         dst.reset(info, mask.fImage, dstRB);
     }
-    sk_bzero(dst.writable_addr(), dst.computeByteSize());
+    sk_bzero(dst.writable_addr(), dst.getSafeSize());
 
     SkDraw  draw;
     draw.fDst   = dst;
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index db4fadc..db40329 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -219,7 +219,7 @@
 
     SkAlphaType alphaType() const override { return fBitmap.alphaType(); }
 
-    size_t getSize() const override { return fBitmap.computeByteSize(); }
+    size_t getSize() const override { return fBitmap.getSize(); }
 
     void onDraw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint) const override {
         SkRect dst = SkRect::MakeXYWH(x, y,
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 222f662..fd868a1 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -455,7 +455,7 @@
                                                   devPathBounds.height()))) {
                 return false;
             }
-            sk_bzero(dst.writable_addr(), dst.computeByteSize());
+            sk_bzero(dst.writable_addr(), dst.getSafeSize());
 
             // rasterize path
             SkPaint paint;
@@ -562,7 +562,7 @@
                                               devPathBounds.height()))) {
             return false;
         }
-        sk_bzero(dst.writable_addr(), dst.computeByteSize());
+        sk_bzero(dst.writable_addr(), dst.getSafeSize());
 
         // rasterize path
         SkPaint paint;
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index 705efae..3ac8ba8 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -422,10 +422,7 @@
     }
 
     size_t rowBytes = info.minRowBytes();
-    size_t size = info.computeByteSize(rowBytes);
-    if (size == 0) {
-        return nullptr;
-    }
+    size_t size = info.getSafeSize(rowBytes);
     auto data = SkData::MakeUninitialized(size);
     if (!data) {
         return nullptr;
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index e477a5e..0ff288c 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -518,7 +518,7 @@
     }
     SkImageInfo info = as_IB(this)->onImageInfo();
     size_t rowBytes = info.minRowBytes();
-    size_t size = info.computeByteSize(rowBytes);
+    size_t size = info.getSafeSize(rowBytes);
     auto data = SkData::MakeUninitialized(size);
     if (!data) {
         return nullptr;
@@ -667,7 +667,7 @@
     size_t pixelSize = 0;
     if (!isScaled && this->peekPixels(&pixmap) && pixmap.info().colorType() == dstColorType) {
         info = pixmap.info();
-        pixelSize = SkAlign8(pixmap.computeByteSize());
+        pixelSize = SkAlign8(pixmap.getSafeSize());
         if (!dstColorSpace) {
             pixmap.setColorSpace(nullptr);
             info = info.makeColorSpace(nullptr);
@@ -773,7 +773,7 @@
     void* pixels = pixelsAsCharPtr;
 
     memcpy(reinterpret_cast<void*>(SkAlign8(reinterpret_cast<uintptr_t>(pixelsAsCharPtr))),
-                                   pixmap.addr(), pixmap.computeByteSize());
+                                   pixmap.addr(), pixmap.getSafeSize());
 
     // If the context has sRGB support, and we're intending to render to a surface with an attached
     // color space, and the image has an sRGB-like color space attached, then use our gamma (sRGB)
@@ -824,7 +824,7 @@
     }
 
     // Fill in the mipmap levels if they exist
-    char* mipLevelPtr = pixelsAsCharPtr + SkAlign8(pixmap.computeByteSize());
+    char* mipLevelPtr = pixelsAsCharPtr + SkAlign8(pixmap.getSafeSize());
 
     if (useMipMaps) {
         static_assert(std::is_standard_layout<MipMapLevelData>::value,
@@ -845,10 +845,13 @@
             // Make sure the mipmap data starts before the end of the buffer
             SkASSERT(mipLevelPtr < bufferAsCharPtr + pixelOffset + pixelSize);
             // Make sure the mipmap data ends before the end of the buffer
-            SkASSERT(mipLevelPtr + mipLevel.fPixmap.computeByteSize() <=
+            SkASSERT(mipLevelPtr + mipLevel.fPixmap.getSafeSize() <=
                      bufferAsCharPtr + pixelOffset + pixelSize);
 
-            memcpy(mipLevelPtr, mipLevel.fPixmap.addr(), mipLevel.fPixmap.computeByteSize());
+            // getSafeSize includes rowbyte padding except for the last row,
+            // right?
+
+            memcpy(mipLevelPtr, mipLevel.fPixmap.addr(), mipLevel.fPixmap.getSafeSize());
 
             memcpy(bufferAsCharPtr + offsetof(DeferredTextureImage, fMipMapLevelData) +
                    sizeof(MipMapLevelData) * (generatedMipLevelIndex + 1) +
@@ -858,7 +861,7 @@
                    sizeof(MipMapLevelData) * (generatedMipLevelIndex + 1) +
                    offsetof(MipMapLevelData, fRowBytes), &rowBytes, sizeof(rowBytes));
 
-            mipLevelPtr += SkAlign8(mipLevel.fPixmap.computeByteSize());
+            mipLevelPtr += SkAlign8(mipLevel.fPixmap.getSafeSize());
         }
     }
     return size;
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index c576d9d..3150488 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -57,11 +57,11 @@
         if (kUnknown_SkColorType == info.colorType()) {
             return false;
         }
-        if (!info.validRowBytes(rowBytes)) {
+        if (rowBytes < info.minRowBytes()) {
             return false;
         }
 
-        size_t size = info.computeByteSize(rowBytes);
+        size_t size = info.getSafeSize(rowBytes);
         if (0 == size) {
             return false;
         }
diff --git a/src/image/SkSurface_Raster.cpp b/src/image/SkSurface_Raster.cpp
index e9d14fe..3869487 100644
--- a/src/image/SkSurface_Raster.cpp
+++ b/src/image/SkSurface_Raster.cpp
@@ -162,7 +162,7 @@
             fBitmap.allocPixels();
             SkASSERT(prev.info() == fBitmap.info());
             SkASSERT(prev.rowBytes() == fBitmap.rowBytes());
-            memcpy(fBitmap.getPixels(), prev.getPixels(), fBitmap.computeByteSize());
+            memcpy(fBitmap.getPixels(), prev.getPixels(), fBitmap.getSafeSize());
         }
         SkASSERT(fBitmap.rowBytes() == fRowBytes);  // be sure we always use the same value
 
diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp
index 1514ba6..fd55d91 100644
--- a/src/utils/mac/SkCreateCGImageRef.cpp
+++ b/src/utils/mac/SkCreateCGImageRef.cpp
@@ -132,7 +132,7 @@
 
     const int w = bitmap->width();
     const int h = bitmap->height();
-    const size_t s = bitmap->computeByteSize();
+    const size_t s = bitmap->getSize();
 
     // our provider "owns" the bitmap*, and will take care of deleting it
     CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp
index 9b1e0c9..7aaf554 100644
--- a/tests/CanvasTest.cpp
+++ b/tests/CanvasTest.cpp
@@ -573,7 +573,7 @@
 static void test_newraster(skiatest::Reporter* reporter) {
     SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
     const size_t minRowBytes = info.minRowBytes();
-    const size_t size = info.computeByteSize(minRowBytes);
+    const size_t size = info.getSafeSize(minRowBytes);
     SkAutoTMalloc<SkPMColor> storage(size);
     SkPMColor* baseAddr = storage.get();
     sk_bzero(baseAddr, size);
diff --git a/tests/CodecTest.cpp b/tests/CodecTest.cpp
index 91b07ef..8ea3193 100644
--- a/tests/CodecTest.cpp
+++ b/tests/CodecTest.cpp
@@ -584,7 +584,7 @@
 
         // Set up for the decode
         size_t rowBytes = scaledDims.width() * sizeof(SkPMColor);
-        size_t totalBytes = scaledInfo.computeByteSize(rowBytes);
+        size_t totalBytes = scaledInfo.getSafeSize(rowBytes);
         SkAutoTMalloc<SkPMColor> pixels(totalBytes);
 
         SkAndroidCodec::AndroidOptions options;
@@ -1011,7 +1011,7 @@
                                           .makeColorSpace(colorSpace);
 
     size_t rowBytes = dstInfo.minRowBytes();
-    SkAutoMalloc pixelStorage(dstInfo.computeByteSize(rowBytes));
+    SkAutoMalloc pixelStorage(dstInfo.getSafeSize(rowBytes));
     SkCodec::Result result = codec->getAndroidPixels(dstInfo, pixelStorage.get(), rowBytes, &opts);
     REPORTER_ASSERT(r, SkCodec::kSuccess == result);
 }
diff --git a/tests/DrawBitmapRectTest.cpp b/tests/DrawBitmapRectTest.cpp
index 8ad177f..9912901 100644
--- a/tests/DrawBitmapRectTest.cpp
+++ b/tests/DrawBitmapRectTest.cpp
@@ -144,10 +144,9 @@
 
     SkBitmap bm;
     if (bm.tryAllocN32Pixels(width, height)) {
-        bm.eraseColor(SK_ColorRED);
-    } else {
-        shouldBeDrawn = false;
+        // allow this to fail silently, to test the code downstream
     }
+    bm.eraseColor(SK_ColorRED);
 
     matrix.setAll(0.0078740157f,
                   0,
@@ -180,7 +179,7 @@
  *     sign-extension bleed when packing the two values (X,Y) into our 32bit
  *     slot.
  *
- *  This tests exercises the original setup, plus 2 more to ensure that we can,
+ *  This tests exercises the original setup, plus 3 more to ensure that we can,
  *  in fact, handle bitmaps at 64K-1 (assuming we don't exceed the total
  *  memory allocation limit).
  */
@@ -193,6 +192,7 @@
         { 0x1b294, 0x7f,  false },   // crbug 118018 (width exceeds 64K)
         { 0xFFFF, 0x7f,    true },   // should draw, test max width
         { 0x7f, 0xFFFF,    true },   // should draw, test max height
+        { 0xFFFF, 0xFFFF, false },   // allocation fails (too much RAM)
     };
 
     for (size_t i = 0; i < SK_ARRAY_COUNT(gTests); ++i) {
diff --git a/tests/Float16Test.cpp b/tests/Float16Test.cpp
index e67d8f1..64873c3 100644
--- a/tests/Float16Test.cpp
+++ b/tests/Float16Test.cpp
@@ -43,7 +43,7 @@
 
     SkAutoPixmapStorage pm;
     pm.alloc(info);
-    REPORTER_ASSERT(reporter, pm.computeByteSize() == SkToSizeT(w * h * sizeof(uint64_t)));
+    REPORTER_ASSERT(reporter, pm.getSafeSize() == SkToSizeT(w * h * sizeof(uint64_t)));
 
     SkColor4f c4 { 1, 0.5f, 0.25f, 0.5f };
     pm.erase(c4);
diff --git a/tests/ImageNewShaderTest.cpp b/tests/ImageNewShaderTest.cpp
index ff80729..638fa07 100644
--- a/tests/ImageNewShaderTest.cpp
+++ b/tests/ImageNewShaderTest.cpp
@@ -17,8 +17,8 @@
 #endif
 
 static void test_bitmap_equality(skiatest::Reporter* reporter, SkBitmap& bm1, SkBitmap& bm2) {
-    REPORTER_ASSERT(reporter, bm1.computeByteSize() == bm2.computeByteSize());
-    REPORTER_ASSERT(reporter, 0 == memcmp(bm1.getPixels(), bm2.getPixels(), bm1.computeByteSize()));
+    REPORTER_ASSERT(reporter, bm1.getSize() == bm2.getSize());
+    REPORTER_ASSERT(reporter, 0 == memcmp(bm1.getPixels(), bm2.getPixels(), bm1.getSize()));
 }
 
 static void paint_source(SkSurface* sourceSurface) {
diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp
index 9e0137f..96b5b29 100644
--- a/tests/ImageTest.cpp
+++ b/tests/ImageTest.cpp
@@ -549,7 +549,7 @@
 DEF_TEST(ImageDataRef, reporter) {
     SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
     size_t rowBytes = info.minRowBytes();
-    size_t size = info.computeByteSize(rowBytes);
+    size_t size = info.getSafeSize(rowBytes);
     sk_sp<SkData> data = SkData::MakeUninitialized(size);
     REPORTER_ASSERT(reporter, data->unique());
     sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, rowBytes);
diff --git a/tests/MallocPixelRefTest.cpp b/tests/MallocPixelRefTest.cpp
index ac08099..957c8b3 100644
--- a/tests/MallocPixelRefTest.cpp
+++ b/tests/MallocPixelRefTest.cpp
@@ -32,7 +32,7 @@
     }
     {
         size_t rowBytes = info.minRowBytes() - 1;
-        size_t size = info.computeByteSize(rowBytes);
+        size_t size = info.getSafeSize(rowBytes);
         sk_sp<SkData> data(SkData::MakeUninitialized(size));
         sk_sp<SkPixelRef> pr(
             SkMallocPixelRef::MakeWithData(info, rowBytes, data));
@@ -41,7 +41,7 @@
     }
     {
         size_t rowBytes = info.minRowBytes() + 2;
-        size_t size = info.computeByteSize(rowBytes) - 1;
+        size_t size = info.getSafeSize(rowBytes) - 1;
         sk_sp<SkData> data(SkData::MakeUninitialized(size));
         sk_sp<SkPixelRef> pr(
             SkMallocPixelRef::MakeWithData(info, rowBytes, data));
@@ -49,7 +49,7 @@
         REPORTER_ASSERT(reporter, nullptr == pr.get());
     }
     size_t rowBytes = info.minRowBytes() + 7;
-    size_t size = info.computeByteSize(rowBytes) + 9;
+    size_t size = info.getSafeSize(rowBytes) + 9;
     {
         SkAutoMalloc memory(size);
         sk_sp<SkPixelRef> pr(
diff --git a/tests/RecordingXfermodeTest.cpp b/tests/RecordingXfermodeTest.cpp
index 25e99ba..20dccc6 100644
--- a/tests/RecordingXfermodeTest.cpp
+++ b/tests/RecordingXfermodeTest.cpp
@@ -151,8 +151,8 @@
         const SkBitmap& goldenBM = golden.recordAndReplay(drawer, clip, mode);
         const SkBitmap& pictureBM = picture.recordAndReplay(drawer, clip, mode);
 
-        size_t pixelsSize = goldenBM.computeByteSize();
-        REPORTER_ASSERT(reporter, pixelsSize == pictureBM.computeByteSize());
+        size_t pixelsSize = goldenBM.getSize();
+        REPORTER_ASSERT(reporter, pixelsSize == pictureBM.getSize());
 
         // The pixel arrays should match.
 #if FINEGRAIN
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index af33f2d..b3d0bd5 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -49,7 +49,7 @@
     SkBitmap src;
     src.allocN32Pixels(size.width(), size.height());
     src.eraseColor(SK_ColorBLACK);
-    size_t srcSize = src.computeByteSize();
+    size_t srcSize = src.getSize();
 
     size_t initialCacheSize;
     context->getResourceCacheUsage(nullptr, &initialCacheSize);
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index 2fd987f..202df58 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -50,7 +50,7 @@
         *requestedInfo = info;
     }
     const size_t rowBytes = info.minRowBytes();
-    void* storage = sk_malloc_throw(info.computeByteSize(rowBytes));
+    void* storage = sk_malloc_throw(info.getSafeSize(rowBytes));
     return SkSurface::MakeRasterDirectReleaseProc(info, storage, rowBytes,
                                                   release_direct_surface_storage,
                                                   storage);
@@ -565,7 +565,7 @@
     // Try some illegal rowByte values
     auto s = SkSurface::MakeRaster(info, 396, nullptr);    // needs to be at least 400
     REPORTER_ASSERT(reporter, nullptr == s);
-    s = SkSurface::MakeRaster(info, std::numeric_limits<size_t>::max(), nullptr);
+    s = SkSurface::MakeRaster(info, 1 << 30, nullptr); // allocation to large
     REPORTER_ASSERT(reporter, nullptr == s);
 }
 
diff --git a/tests/SwizzlerTest.cpp b/tests/SwizzlerTest.cpp
index 8950efb..655c97e 100644
--- a/tests/SwizzlerTest.cpp
+++ b/tests/SwizzlerTest.cpp
@@ -28,7 +28,7 @@
     // to test on different memory alignments.  If offset is nonzero, we need to increase the
     // size of the memory we allocate in order to make sure that we have enough.  We are
     // still allocating the smallest possible size.
-    const size_t totalBytes = imageInfo.computeByteSize(rowBytes) + offset;
+    const size_t totalBytes = imageInfo.getSafeSize(rowBytes) + offset;
 
     // Create fake image data where every byte has a value of 0
     std::unique_ptr<uint8_t[]> storage(new uint8_t[totalBytes]);
diff --git a/tests/WritePixelsTest.cpp b/tests/WritePixelsTest.cpp
index 7ea0aad..81dcbe7 100644
--- a/tests/WritePixelsTest.cpp
+++ b/tests/WritePixelsTest.cpp
@@ -394,7 +394,7 @@
     const SkImageInfo info = SkImageInfo::MakeN32Premul(DEV_W, DEV_H);
     for (auto& tightRowBytes : { true, false }) {
         const size_t rowBytes = tightRowBytes ? info.minRowBytes() : 4 * DEV_W + 100;
-        const size_t size = info.computeByteSize(rowBytes);
+        const size_t size = info.getSafeSize(rowBytes);
         void* pixels = sk_malloc_throw(size);
         // if rowBytes isn't tight then set the padding to a known value
         if (!tightRowBytes) {