aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--dm/DMSrcSink.cpp6
-rw-r--r--include/codec/SkCodec.h11
-rw-r--r--tests/CodexTest.cpp24
3 files changed, 38 insertions, 3 deletions
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 9826f97822..f766b49c79 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -120,6 +120,12 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
if (size == decodeInfo.dimensions() && 1.0f != fScale) {
return Error::Nonfatal("Test without scaling is uninteresting.");
}
+
+ // Visually inspecting very small output images is not necessary. We will
+ // cover these cases in unit testing.
+ if ((size.width() <= 10 || size.height() <= 10) && 1.0f != fScale) {
+ return Error::Nonfatal("Scaling very small images is uninteresting.");
+ }
decodeInfo = decodeInfo.makeWH(size.width(), size.height());
// Construct a color table for the decode if necessary
diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h
index 3465c1df5b..ae9524b8b7 100644
--- a/include/codec/SkCodec.h
+++ b/include/codec/SkCodec.h
@@ -55,6 +55,17 @@ public:
* scale that it can natively support
*/
SkISize getScaledDimensions(float desiredScale) const {
+ // Negative and zero scales are errors.
+ SkASSERT(desiredScale > 0.0f);
+ if (desiredScale <= 0.0f) {
+ return SkISize::Make(0, 0);
+ }
+
+ // Upscaling is not supported. Return the original size if the client
+ // requests an upscale.
+ if (desiredScale >= 1.0f) {
+ return this->getInfo().dimensions();
+ }
return this->onGetScaledDimensions(desiredScale);
}
diff --git a/tests/CodexTest.cpp b/tests/CodexTest.cpp
index 80164b294b..ec6d645196 100644
--- a/tests/CodexTest.cpp
+++ b/tests/CodexTest.cpp
@@ -10,6 +10,7 @@
#include "SkCodec.h"
#include "SkMD5.h"
#include "SkRandom.h"
+#include "SkScaledCodec.h"
#include "SkScanlineDecoder.h"
#include "Test.h"
@@ -281,17 +282,19 @@ static void test_dimensions(skiatest::Reporter* r, const char path[]) {
SkDebugf("Missing resource '%s'\n", path);
return;
}
- SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach()));
+ SkAutoTDelete<SkCodec> codec(SkScaledCodec::NewFromStream(stream.detach()));
if (!codec) {
ERRORF(r, "Unable to create codec '%s'", path);
return;
}
// Check that the decode is successful for a variety of scales
- for (float scale = -0.05f; scale < 2.0f; scale += 0.05f) {
+ for (float scale = 0.05f; scale < 2.0f; scale += 0.05f) {
// Scale the output dimensions
SkISize scaledDims = codec->getScaledDimensions(scale);
- SkImageInfo scaledInfo = codec->getInfo().makeWH(scaledDims.width(), scaledDims.height());
+ SkImageInfo scaledInfo = codec->getInfo()
+ .makeWH(scaledDims.width(), scaledDims.height())
+ .makeColorType(kN32_SkColorType);
// Set up for the decode
size_t rowBytes = scaledDims.width() * sizeof(SkPMColor);
@@ -312,6 +315,21 @@ DEF_TEST(Codec_Dimensions, r) {
test_dimensions(r, "grayscale.jpg");
test_dimensions(r, "mandrill_512_q075.jpg");
test_dimensions(r, "randPixels.jpg");
+
+ // Decoding small images with very large scaling factors is a potential
+ // source of bugs and crashes. We disable these tests in Gold because
+ // tiny images are not very useful to look at.
+ // Here we make sure that we do not crash or access illegal memory when
+ // performing scaled decodes on small images.
+ test_dimensions(r, "1x1.png");
+ test_dimensions(r, "2x2.png");
+ test_dimensions(r, "3x3.png");
+ test_dimensions(r, "3x1.png");
+ test_dimensions(r, "1x1.png");
+ test_dimensions(r, "16x1.png");
+ test_dimensions(r, "1x16.png");
+ test_dimensions(r, "mandrill_16.png");
+
}
static void test_invalid(skiatest::Reporter* r, const char path[]) {