| /* | 
 |  * Copyright 2011 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #include "SkData.h" | 
 | #include "SkFlate.h" | 
 | #include "SkStream.h" | 
 | #include "Test.h" | 
 |  | 
 | // A memory stream that reports zero size with the standard call, like | 
 | // an unseekable file stream would. | 
 | class SkZeroSizeMemStream : public SkMemoryStream { | 
 | public: | 
 |     virtual size_t read(void* buffer, size_t size) { | 
 |         if (buffer == NULL && size == 0) | 
 |             return 0; | 
 |         if (buffer == NULL && size == kGetSizeKey) | 
 |             size = 0; | 
 |         return SkMemoryStream::read(buffer, size); | 
 |     } | 
 |  | 
 |     static const size_t kGetSizeKey = 0xDEADBEEF; | 
 | }; | 
 |  | 
 | // Returns a deterministic data of the given size that should be | 
 | // very compressible. | 
 | static SkData* new_test_data(size_t dataSize) { | 
 |     SkAutoTMalloc<uint8_t> testBuffer(dataSize); | 
 |     for (size_t i = 0; i < dataSize; ++i) { | 
 |         testBuffer[SkToInt(i)] = i % 64; | 
 |     } | 
 |     return SkData::NewFromMalloc(testBuffer.detach(), dataSize); | 
 | } | 
 |  | 
 | static void TestFlate(skiatest::Reporter* reporter, SkMemoryStream* testStream, | 
 |                       size_t dataSize) { | 
 |     SkASSERT(testStream != NULL); | 
 |  | 
 |     SkAutoDataUnref testData(new_test_data(dataSize)); | 
 |     SkASSERT(testData->size() == dataSize); | 
 |  | 
 |     testStream->setMemory(testData->data(), dataSize, /*copyData=*/ true); | 
 |     SkDynamicMemoryWStream compressed; | 
 |     bool deflateSuccess = SkFlate::Deflate(testStream, &compressed); | 
 |     REPORTER_ASSERT(reporter, deflateSuccess); | 
 |  | 
 |     // Check that the input data wasn't changed. | 
 |     size_t inputSize = testStream->getLength(); | 
 |     if (inputSize == 0) { | 
 |         inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey); | 
 |     } | 
 |     REPORTER_ASSERT(reporter, dataSize == inputSize); | 
 |     if (dataSize == inputSize) { | 
 |         REPORTER_ASSERT(reporter, memcmp(testData->data(), | 
 |                                          testStream->getMemoryBase(), | 
 |                                          dataSize) == 0); | 
 |     } | 
 |  | 
 |     size_t compressedSize = compressed.getOffset(); | 
 |  | 
 |     SkAutoDataUnref compressedData(compressed.copyToData()); | 
 |     testStream->setData(compressedData.get()); | 
 |  | 
 |     SkDynamicMemoryWStream uncompressed; | 
 |     bool inflateSuccess = SkFlate::Inflate(testStream, &uncompressed); | 
 |     REPORTER_ASSERT(reporter, inflateSuccess); | 
 |  | 
 |     // Check that the input data wasn't changed. | 
 |     inputSize = testStream->getLength(); | 
 |     if (inputSize == 0) { | 
 |         inputSize = testStream->read(NULL, SkZeroSizeMemStream::kGetSizeKey); | 
 |     } | 
 |     REPORTER_ASSERT(reporter,  compressedSize == inputSize); | 
 |     if (compressedData->size() == inputSize) { | 
 |         REPORTER_ASSERT(reporter, memcmp(testStream->getMemoryBase(), | 
 |                                          compressedData->data(), | 
 |                                          compressedData->size()) == 0); | 
 |     } | 
 |  | 
 |     // Check that the uncompressed data matches the source data. | 
 |     SkAutoDataUnref uncompressedData(uncompressed.copyToData()); | 
 |     REPORTER_ASSERT(reporter, dataSize == uncompressedData->size()); | 
 |     if (dataSize == uncompressedData->size()) { | 
 |         REPORTER_ASSERT(reporter, memcmp(testData->data(), | 
 |                                          uncompressedData->data(), | 
 |                                          dataSize) == 0); | 
 |     } | 
 |  | 
 |     if (compressedSize < 1) { return; } | 
 |  | 
 |     double compressionRatio = static_cast<double>(dataSize) / compressedSize; | 
 |     // Assert that some compression took place. | 
 |     REPORTER_ASSERT(reporter, compressionRatio > 1.2); | 
 |  | 
 |     if (reporter->verbose()) { | 
 |         SkDebugf("Flate Test: \t input size: " SK_SIZE_T_SPECIFIER | 
 |                  "\tcompressed size: " SK_SIZE_T_SPECIFIER | 
 |                  "\tratio: %.4g\n", | 
 |                  dataSize, compressedSize, compressionRatio); | 
 |     } | 
 | } | 
 |  | 
 | DEF_TEST(Flate, reporter) { | 
 |     SkMemoryStream memStream; | 
 |     TestFlate(reporter, &memStream, 512); | 
 |     TestFlate(reporter, &memStream, 10240); | 
 |  | 
 |     SkZeroSizeMemStream fileStream; | 
 |     TestFlate(reporter, &fileStream, 512); | 
 |     TestFlate(reporter, &fileStream, 10240); | 
 | } |