diff options
-rw-r--r-- | dm/DMSrcSink.cpp | 6 | ||||
-rw-r--r-- | include/codec/SkCodec.h | 11 | ||||
-rw-r--r-- | tests/CodexTest.cpp | 24 |
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[]) { |