aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-12-30 14:40:38 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-12-30 14:40:38 +0000
commit57212f9469c8056bab3c85243dbb904e386eab95 (patch)
tree403c9f2ab9d20ab35397ab2e9dd9e2e6a27a441f
parent4ad4ae907fa83773f671137b0e4e8c9525ab81cd (diff)
This reverts commit 68b4b32066ea0ba9dbb5d326a836f8a54297b7aa. BUG= Review URL: https://codereview.chromium.org/122293002 git-svn-id: http://skia.googlecode.com/svn/trunk@12842 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--include/core/Sk64.h7
-rw-r--r--include/core/SkBitmap.h51
-rw-r--r--include/core/SkMath.h26
-rw-r--r--include/core/SkTypes.h4
-rw-r--r--include/utils/SkRandom.h30
-rw-r--r--src/core/SkBitmap.cpp74
-rw-r--r--src/core/SkMallocPixelRef.cpp7
-rw-r--r--src/core/SkMipMap.cpp12
-rw-r--r--src/core/SkRegion_path.cpp16
-rw-r--r--src/images/SkImageDecoder_libpng.cpp8
-rw-r--r--src/images/SkImageDecoder_libwebp.cpp7
-rw-r--r--tests/BitmapCopyTest.cpp12
-rw-r--r--tests/Sk64Test.cpp5
13 files changed, 150 insertions, 109 deletions
diff --git a/include/core/Sk64.h b/include/core/Sk64.h
index 009744938f..c12a97c8a1 100644
--- a/include/core/Sk64.h
+++ b/include/core/Sk64.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,7 +5,6 @@
* found in the LICENSE file.
*/
-
#ifndef Sk64_DEFINED
#define Sk64_DEFINED
@@ -28,6 +26,11 @@ public:
int64_t as64() const { return ((int64_t)fHi << 32) | fLo; }
int64_t getLongLong() const { return this->as64(); }
+ void set64(int64_t value) {
+ fHi = (int32_t)(value >> 32);
+ fLo = (uint32_t)value;
+ }
+
/** Returns non-zero if the Sk64 can be represented as a signed 32 bit integer
*/
SkBool is32() const { return fHi == ((int32_t)fLo >> 31); }
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index c0e299ab94..2b900bef34 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,17 +5,19 @@
* found in the LICENSE file.
*/
-
#ifndef SkBitmap_DEFINED
#define SkBitmap_DEFINED
-#include "Sk64.h"
#include "SkColor.h"
#include "SkColorTable.h"
#include "SkImageInfo.h"
#include "SkPoint.h"
#include "SkRefCnt.h"
+#ifdef SK_SUPPORT_LEGACY_SK64
+ #include "Sk64.h"
+#endif
+
struct SkIRect;
struct SkRect;
class SkPaint;
@@ -149,19 +150,37 @@ public:
*/
size_t getSafeSize() const ;
- /** Return the byte size of the pixels, based on the height and rowBytes.
- This routine is slightly slower than getSize(), but does not truncate
- the answer to 32bits.
- */
+ /**
+ * Return the full size of the bitmap, in bytes.
+ */
+ int64_t computeSize64() const {
+ return sk_64_mul(fHeight, fRowBytes);
+ }
+
+ /**
+ * Return the number of bytes from the pointer returned by getPixels()
+ * to the end of the allocated space in the buffer. This may be smaller
+ * than computeSize64() if there is any rowbytes padding beyond the width.
+ */
+ int64_t computeSafeSize64() const {
+ return ComputeSafeSize64((Config)fConfig, fWidth, fHeight, fRowBytes);
+ }
+
+#ifdef SK_SUPPORT_LEGACY_SK64
+ SK_ATTR_DEPRECATED("use getSize64()")
Sk64 getSize64() const {
Sk64 size;
- size.setMul(fHeight, fRowBytes);
+ size.set64(this->computeSize64());
return size;
}
- /** Same as getSafeSize(), but does not truncate the answer to 32bits.
- */
- Sk64 getSafeSize64() const ;
+ SK_ATTR_DEPRECATED("use getSafeSize64()")
+ Sk64 getSafeSize64() const {
+ Sk64 size;
+ size.set64(this->computeSafeSize64());
+ return size;
+ }
+#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.
@@ -217,7 +236,7 @@ public:
return ComputeBytesPerPixel(c) >> 1;
}
- static Sk64 ComputeSize64(Config, int width, int height);
+ static int64_t ComputeSize64(Config, int width, int height);
static size_t ComputeSize(Config, int width, int height);
/**
@@ -678,10 +697,10 @@ private:
/* Internal computations for safe size.
*/
- static Sk64 ComputeSafeSize64(Config config,
- uint32_t width,
- uint32_t height,
- size_t rowBytes);
+ static int64_t ComputeSafeSize64(Config config,
+ uint32_t width,
+ uint32_t height,
+ size_t rowBytes);
static size_t ComputeSafeSize(Config config,
uint32_t width,
uint32_t height,
diff --git a/include/core/SkMath.h b/include/core/SkMath.h
index affcadaf2c..ba6223ed06 100644
--- a/include/core/SkMath.h
+++ b/include/core/SkMath.h
@@ -35,6 +35,32 @@ int32_t SkSqrtBits(int32_t value, int bitBias);
*/
#define SkSqrt32(n) SkSqrtBits(n, 15)
+// 64bit -> 32bit utilities
+
+/**
+ * Return true iff the 64bit value can exactly be represented in signed 32bits
+ */
+static inline bool sk_64_isS32(int64_t value) {
+ return (int32_t)value == value;
+}
+
+/**
+ * Return the 64bit argument as signed 32bits, asserting in debug that the arg
+ * exactly fits in signed 32bits. In the release build, no checks are preformed
+ * and the return value if the arg does not fit is undefined.
+ */
+static inline int32_t sk_64_asS32(int64_t value) {
+ SkASSERT(sk_64_isS32(value));
+ return (int32_t)value;
+}
+
+// Handy util that can be passed two ints, and will automatically promote to
+// 64bits before the multiply, so the caller doesn't have to remember to cast
+// e.g. (int64_t)a * b;
+static inline int64_t sk_64_mul(int64_t a, int64_t b) {
+ return a * b;
+}
+
///////////////////////////////////////////////////////////////////////////////
//! Returns the number of leading zero bits (0...32)
diff --git a/include/core/SkTypes.h b/include/core/SkTypes.h
index c30a8a2d66..06c8583a61 100644
--- a/include/core/SkTypes.h
+++ b/include/core/SkTypes.h
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
@@ -6,7 +5,6 @@
* found in the LICENSE file.
*/
-
#ifndef SkTypes_DEFINED
#define SkTypes_DEFINED
@@ -15,6 +13,8 @@
#include "SkPostConfig.h"
#include <stdint.h>
+//#define SK_SUPPORT_LEGACY_SK64
+
/** \file SkTypes.h
*/
diff --git a/include/utils/SkRandom.h b/include/utils/SkRandom.h
index eeaa701c6e..9191ec35c1 100644
--- a/include/utils/SkRandom.h
+++ b/include/utils/SkRandom.h
@@ -10,9 +10,12 @@
#ifndef SkRandom_DEFINED
#define SkRandom_DEFINED
-#include "Sk64.h"
#include "SkScalar.h"
+#ifdef SK_SUPPORT_LEGACY_SK64
+ #include "Sk64.h"
+#endif
+
/** \class SkLCGRandom
Utility class that implements pseudo random 32bit numbers using a fast
@@ -123,13 +126,21 @@ public:
return this->nextUScalar1() <= fractionTrue;
}
- /** Return the next pseudo random number as a signed 64bit value.
- */
+ /**
+ * Return the next pseudo random number as a signed 64bit value.
+ */
+ int64_t next64() {
+ int64_t hi = this->nextS();
+ return (hi << 32) | this->nextU();
+ }
+
+#ifdef SK_SUPPORT_LEGACY_SK64
+ SK_ATTR_DEPRECATED("use next64()")
void next64(Sk64* a) {
SkASSERT(a);
a->set(this->nextS(), this->nextU());
}
-
+#endif
/**
* Return the current seed. This allows the caller to later reset to the
* same seed (using setSeed) so it can generate the same sequence.
@@ -276,12 +287,21 @@ public:
return this->nextUScalar1() <= fractionTrue;
}
- /** Return the next pseudo random number as a signed 64bit value.
+ /**
+ * Return the next pseudo random number as a signed 64bit value.
*/
+ int64_t next64() {
+ int64_t hi = this->nextS();
+ return (hi << 32) | this->nextU();
+ }
+
+#ifdef SK_SUPPORT_LEGACY_SK64
+ SK_ATTR_DEPRECATED("use next64()")
void next64(Sk64* a) {
SkASSERT(a);
a->set(this->nextS(), this->nextU());
}
+#endif
/** Reset the random object.
*/
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index d4c3a47d81..11c7cbd69c 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -24,10 +24,6 @@
#include "SkPackBits.h"
#include <new>
-static bool isPos32Bits(const Sk64& value) {
- return !value.isNeg() && value.is32();
-}
-
struct MipLevel {
void* fPixels;
uint32_t fRowBytes;
@@ -44,14 +40,12 @@ struct SkBitmap::MipMap : SkNoncopyable {
if (levelCount < 0) {
return NULL;
}
- Sk64 size;
- size.setMul(levelCount + 1, sizeof(MipLevel));
- size.add(sizeof(MipMap));
- size.add(SkToS32(pixelSize));
- if (!isPos32Bits(size)) {
+ int64_t size = (levelCount + 1) * sizeof(MipLevel);
+ size += sizeof(MipMap) + pixelSize;
+ if (!sk_64_isS32(size)) {
return NULL;
}
- MipMap* mm = (MipMap*)sk_malloc_throw(size.get32());
+ MipMap* mm = (MipMap*)sk_malloc_throw(sk_64_asS32(size));
mm->fRefCnt = 1;
mm->fLevelCount = levelCount;
return mm;
@@ -185,58 +179,49 @@ size_t SkBitmap::ComputeRowBytes(Config c, int width) {
return 0;
}
- Sk64 rowBytes;
- rowBytes.setZero();
+ int64_t rowBytes = 0;
switch (c) {
case kNo_Config:
break;
case kA8_Config:
case kIndex8_Config:
- rowBytes.set(width);
+ rowBytes = width;
break;
case kRGB_565_Config:
case kARGB_4444_Config:
- rowBytes.set(width);
- rowBytes.shiftLeft(1);
+ rowBytes = width << 1;
break;
case kARGB_8888_Config:
- rowBytes.set(width);
- rowBytes.shiftLeft(2);
+ rowBytes = width << 2;
break;
default:
SkDEBUGFAIL("unknown config");
break;
}
- return isPos32Bits(rowBytes) ? rowBytes.get32() : 0;
+ return sk_64_isS32(rowBytes) ? sk_64_asS32(rowBytes) : 0;
}
-Sk64 SkBitmap::ComputeSize64(Config c, int width, int height) {
- Sk64 size;
- size.setMul(SkToS32(SkBitmap::ComputeRowBytes(c, width)), height);
- return size;
+int64_t SkBitmap::ComputeSize64(Config config, int width, int height) {
+ int64_t rowBytes = sk_64_mul(ComputeBytesPerPixel(config), width);
+ return rowBytes * height;
}
size_t SkBitmap::ComputeSize(Config c, int width, int height) {
- Sk64 size = SkBitmap::ComputeSize64(c, width, height);
- return isPos32Bits(size) ? size.get32() : 0;
+ int64_t size = SkBitmap::ComputeSize64(c, width, height);
+ return sk_64_isS32(size) ? sk_64_asS32(size) : 0;
}
-Sk64 SkBitmap::ComputeSafeSize64(Config config,
- uint32_t width,
- uint32_t height,
- size_t rowBytes) {
- Sk64 safeSize;
- safeSize.setZero();
+int64_t SkBitmap::ComputeSafeSize64(Config config,
+ uint32_t width,
+ uint32_t height,
+ size_t rowBytes) {
+ int64_t safeSize = 0;
if (height > 0) {
- // TODO: Handle the case where the return value from
- // ComputeRowBytes is more than 31 bits.
- safeSize.set(SkToS32(ComputeRowBytes(config, width)));
- Sk64 sizeAllButLastRow;
- sizeAllButLastRow.setMul(height - 1, SkToS32(rowBytes));
- safeSize.add(sizeAllButLastRow);
- }
- SkASSERT(!safeSize.isNeg());
+ int64_t lastRow = sk_64_mul(ComputeBytesPerPixel(config), width);
+ safeSize = sk_64_mul(height - 1, rowBytes) + lastRow;
+ }
+ SkASSERT(safeSize >= 0);
return safeSize;
}
@@ -244,8 +229,13 @@ size_t SkBitmap::ComputeSafeSize(Config config,
uint32_t width,
uint32_t height,
size_t rowBytes) {
- Sk64 safeSize = ComputeSafeSize64(config, width, height, rowBytes);
- return (safeSize.is32() ? safeSize.get32() : 0);
+ int64_t safeSize = ComputeSafeSize64(config, width, height, rowBytes);
+ int32_t safeSize32 = (int32_t)safeSize;
+
+ if (safeSize32 != safeSize) {
+ safeSize32 = 0;
+ }
+ return safeSize32;
}
void SkBitmap::getBounds(SkRect* bounds) const {
@@ -558,10 +548,6 @@ size_t SkBitmap::getSafeSize() const {
ComputeRowBytes(this->config(), fWidth): 0);
}
-Sk64 SkBitmap::getSafeSize64() const {
- return ComputeSafeSize64(this->config(), fWidth, fHeight, fRowBytes);
-}
-
bool SkBitmap::copyPixelsTo(void* const dst, size_t dstSize,
size_t dstRowBytes, bool preserveDstPad) const {
diff --git a/src/core/SkMallocPixelRef.cpp b/src/core/SkMallocPixelRef.cpp
index b65197fac8..9e2ea9c980 100644
--- a/src/core/SkMallocPixelRef.cpp
+++ b/src/core/SkMallocPixelRef.cpp
@@ -64,13 +64,12 @@ SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
rowBytes = minRB;
}
- Sk64 bigSize;
- bigSize.setMul(info.fHeight, rowBytes);
- if (!bigSize.is32()) {
+ int64_t bigSize = (int64_t)info.fHeight * rowBytes;
+ if (!sk_64_isS32(bigSize)) {
return NULL;
}
- size_t size = bigSize.get32();
+ size_t size = sk_64_asS32(bigSize);
void* addr = sk_malloc_flags(size, 0);
if (NULL == addr) {
return NULL;
diff --git a/src/core/SkMipMap.cpp b/src/core/SkMipMap.cpp
index 4888b574e4..ff62f4d59d 100644
--- a/src/core/SkMipMap.cpp
+++ b/src/core/SkMipMap.cpp
@@ -109,21 +109,15 @@ static void downsampleby2_proc4444(SkBitmap* dst, int x, int y,
*dst->getAddr16(x >> 1, y >> 1) = (uint16_t)collaps4444(c >> 2);
}
-static bool isPos32Bits(const Sk64& value) {
- return !value.isNeg() && value.is32();
-}
-
SkMipMap::Level* SkMipMap::AllocLevels(int levelCount, size_t pixelSize) {
if (levelCount < 0) {
return NULL;
}
- Sk64 size;
- size.setMul(levelCount + 1, sizeof(Level));
- size.add(SkToS32(pixelSize));
- if (!isPos32Bits(size)) {
+ int64_t size = sk_64_mul(levelCount + 1, sizeof(Level)) + pixelSize;
+ if (!sk_64_isS32(size)) {
return NULL;
}
- return (Level*)sk_malloc_throw(size.get32());
+ return (Level*)sk_malloc_throw(sk_64_asS32(size));
}
SkMipMap* SkMipMap::Build(const SkBitmap& src) {
diff --git a/src/core/SkRegion_path.cpp b/src/core/SkRegion_path.cpp
index a20647c966..95247f403e 100644
--- a/src/core/SkRegion_path.cpp
+++ b/src/core/SkRegion_path.cpp
@@ -107,8 +107,6 @@ bool SkRgnBuilder::init(int maxHeight, int maxTransitions, bool pathIsInverse) {
return false;
}
- Sk64 count, size;
-
if (pathIsInverse) {
// allow for additional X transitions to "invert" each scanline
// [ L' ... normal transitions ... R' ]
@@ -117,25 +115,25 @@ bool SkRgnBuilder::init(int maxHeight, int maxTransitions, bool pathIsInverse) {
}
// compute the count with +1 and +3 slop for the working buffer
- count.setMul(maxHeight + 1, 3 + maxTransitions);
+ int64_t count = sk_64_mul(maxHeight + 1, 3 + maxTransitions);
if (pathIsInverse) {
// allow for two "empty" rows for the top and bottom
// [ Y, 1, L, R, S] == 5 (*2 for top and bottom)
- count.add(10);
+ count += 10;
}
- if (!count.is32() || count.isNeg()) {
+ if (count < 0 || !sk_64_isS32(count)) {
return false;
}
- fStorageCount = count.get32();
+ fStorageCount = sk_64_asS32(count);
- size.setMul(fStorageCount, sizeof(SkRegion::RunType));
- if (!size.is32() || size.isNeg()) {
+ int64_t size = sk_64_mul(fStorageCount, sizeof(SkRegion::RunType));
+ if (size < 0 || !sk_64_isS32(size)) {
return false;
}
- fStorage = (SkRegion::RunType*)sk_malloc_flags(size.get32(), 0);
+ fStorage = (SkRegion::RunType*)sk_malloc_flags(sk_64_asS32(size), 0);
if (NULL == fStorage) {
return false;
}
diff --git a/src/images/SkImageDecoder_libpng.cpp b/src/images/SkImageDecoder_libpng.cpp
index 02ba6af90a..3cc41e3f59 100644
--- a/src/images/SkImageDecoder_libpng.cpp
+++ b/src/images/SkImageDecoder_libpng.cpp
@@ -607,13 +607,9 @@ bool SkPNGImageDecoder::getBitmapConfig(png_structp png_ptr, png_infop info_ptr,
// sanity check for size
{
- Sk64 size;
- size.setMul(origWidth, origHeight);
- if (size.isNeg() || !size.is32()) {
- return false;
- }
+ int64_t size = sk_64_mul(origWidth, origHeight);
// now check that if we are 4-bytes per pixel, we also don't overflow
- if (size.get32() > (0x7FFFFFFF >> 2)) {
+ if (size < 0 || size > (0x7FFFFFFF >> 2)) {
return false;
}
}
diff --git a/src/images/SkImageDecoder_libwebp.cpp b/src/images/SkImageDecoder_libwebp.cpp
index 4a5951020e..05925d03a2 100644
--- a/src/images/SkImageDecoder_libwebp.cpp
+++ b/src/images/SkImageDecoder_libwebp.cpp
@@ -80,13 +80,12 @@ static bool webp_parse_header(SkStream* stream, int* width, int* height, int* al
// sanity check for image size that's about to be decoded.
{
- Sk64 size;
- size.setMul(*width, *height);
- if (size.isNeg() || !size.is32()) {
+ int64_t size = sk_64_mul(*width, *height);
+ if (!sk_64_isS32(size)) {
return false;
}
// now check that if we are 4-bytes per pixel, we also don't overflow
- if (size.get32() > (0x7FFFFFFF >> 2)) {
+ if (sk_64_asS32(size) > (0x7FFFFFFF >> 2)) {
return false;
}
}
diff --git a/tests/BitmapCopyTest.cpp b/tests/BitmapCopyTest.cpp
index 7a1d9acd7c..455fc691e3 100644
--- a/tests/BitmapCopyTest.cpp
+++ b/tests/BitmapCopyTest.cpp
@@ -343,8 +343,8 @@ DEF_TEST(BitmapCopy, reporter) {
SkBitmap tstSafeSize;
tstSafeSize.setConfig(gPairs[i].fConfig, 100000000U,
100000000U);
- Sk64 safeSize = tstSafeSize.getSafeSize64();
- if (safeSize.isNeg()) {
+ int64_t safeSize = tstSafeSize.computeSafeSize64();
+ if (safeSize < 0) {
SkString str;
str.printf("getSafeSize64() negative: %s",
getSkConfigName(tstSafeSize));
@@ -358,20 +358,20 @@ DEF_TEST(BitmapCopy, reporter) {
case SkBitmap::kA8_Config:
case SkBitmap::kIndex8_Config:
- if (safeSize.as64() != 0x2386F26FC10000LL) {
+ if (safeSize != 0x2386F26FC10000LL) {
sizeFail = true;
}
break;
case SkBitmap::kRGB_565_Config:
case SkBitmap::kARGB_4444_Config:
- if (safeSize.as64() != 0x470DE4DF820000LL) {
+ if (safeSize != 0x470DE4DF820000LL) {
sizeFail = true;
}
break;
case SkBitmap::kARGB_8888_Config:
- if (safeSize.as64() != 0x8E1BC9BF040000LL) {
+ if (safeSize != 0x8E1BC9BF040000LL) {
sizeFail = true;
}
break;
@@ -381,7 +381,7 @@ DEF_TEST(BitmapCopy, reporter) {
}
if (sizeFail) {
SkString str;
- str.printf("getSafeSize64() wrong size: %s",
+ str.printf("computeSafeSize64() wrong size: %s",
getSkConfigName(tstSafeSize));
reporter->reportFailed(str);
}
diff --git a/tests/Sk64Test.cpp b/tests/Sk64Test.cpp
index 1777d24d10..d668e5454d 100644
--- a/tests/Sk64Test.cpp
+++ b/tests/Sk64Test.cpp
@@ -7,6 +7,7 @@
#include "Test.h"
#include "TestClassDef.h"
+#include "Sk64.h"
#include "SkRandom.h"
#include <math.h>
@@ -92,8 +93,8 @@ void Sk64::UnitTestWithReporter(void* reporterParam) {
}
for (i = 0; i < 1000; i++) {
- rand.next64(&a); //a.fHi >>= 1; // avoid overflow
- rand.next64(&b); //b.fHi >>= 1; // avoid overflow
+ a.set64(rand.next64());
+ b.set64(rand.next64());
if (!(i & 3)) // want to explicitly test these cases
{