summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp')
-rw-r--r--chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp311
1 files changed, 192 insertions, 119 deletions
diff --git a/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp b/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp
index a833c636ff9..88cdef9a321 100644
--- a/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp
+++ b/chromium/third_party/skia/src/images/SkDecodingImageGenerator.cpp
@@ -5,81 +5,133 @@
* found in the LICENSE file.
*/
-#include "SkDecodingImageGenerator.h"
#include "SkData.h"
+#include "SkDecodingImageGenerator.h"
#include "SkImageDecoder.h"
+#include "SkImageInfo.h"
#include "SkImageGenerator.h"
#include "SkImagePriv.h"
#include "SkStream.h"
-
+#include "SkUtils.h"
namespace {
+bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) {
+ return a.width() == b.width() && a.height() == b.height() &&
+ a.colorType() == b.colorType();
+}
+
+class DecodingImageGenerator : public SkImageGenerator {
+public:
+ virtual ~DecodingImageGenerator();
+
+ SkData* fData;
+ SkStreamRewindable* fStream;
+ const SkImageInfo fInfo;
+ const int fSampleSize;
+ const bool fDitherImage;
+
+ DecodingImageGenerator(SkData* data,
+ SkStreamRewindable* stream,
+ const SkImageInfo& info,
+ int sampleSize,
+ bool ditherImage);
+
+protected:
+ virtual SkData* onRefEncodedData() SK_OVERRIDE;
+ virtual bool onGetInfo(SkImageInfo* info) SK_OVERRIDE {
+ *info = fInfo;
+ return true;
+ }
+ virtual bool onGetPixels(const SkImageInfo& info,
+ void* pixels, size_t rowBytes,
+ SkPMColor ctable[], int* ctableCount) SK_OVERRIDE;
+
+private:
+ typedef SkImageGenerator INHERITED;
+};
+
/**
* Special allocator used by getPixels(). Uses preallocated memory
- * provided.
+ * provided if possible, else fall-back on the default allocator
*/
class TargetAllocator : public SkBitmap::Allocator {
public:
- TargetAllocator(void* target, size_t rowBytes, const SkImageInfo& info)
- : fTarget(target)
+ TargetAllocator(const SkImageInfo& info,
+ void* target,
+ size_t rowBytes)
+ : fInfo(info)
+ , fTarget(target)
, fRowBytes(rowBytes)
- , fInfo(info) { }
+ {}
- virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
- if ((SkImageInfoToBitmapConfig(fInfo) != bm->config())
- || (bm->width() != fInfo.fWidth)
- || (bm->height() != fInfo.fHeight)) {
- return false;
+ bool isReady() { return (fTarget != NULL); }
+
+ virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
+ if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) {
+ // Call default allocator.
+ return bm->allocPixels(NULL, ct);
}
- bm->setConfig(bm->config(), bm->width(), bm->height(),
- fRowBytes, bm->alphaType());
- bm->setPixels(fTarget, ct);
+
+ // TODO(halcanary): verify that all callers of this function
+ // will respect new RowBytes. Will be moot once rowbytes belongs
+ // to PixelRef.
+ bm->installPixels(fInfo, fTarget, fRowBytes, ct, NULL, NULL);
+
+ fTarget = NULL; // never alloc same pixels twice!
return true;
}
private:
- void* fTarget;
- size_t fRowBytes;
- SkImageInfo fInfo;
+ const SkImageInfo fInfo;
+ void* fTarget; // Block of memory to be supplied as pixel memory
+ // in allocPixelRef. Must be large enough to hold
+ // a bitmap described by fInfo and fRowBytes
+ const size_t fRowBytes; // rowbytes for the destination bitmap
+
typedef SkBitmap::Allocator INHERITED;
};
-} // namespace
-////////////////////////////////////////////////////////////////////////////////
-SkDecodingImageGenerator::SkDecodingImageGenerator(SkData* data)
- : fData(data)
- , fHasInfo(false)
- , fDoCopyTo(false) {
- SkASSERT(fData != NULL);
- fStream = SkNEW_ARGS(SkMemoryStream, (fData));
- SkASSERT(fStream != NULL);
- SkASSERT(fStream->unique());
- fData->ref();
+// TODO(halcanary): Give this macro a better name and move it into SkTypes.h
+#ifdef SK_DEBUG
+ #define SkCheckResult(expr, value) SkASSERT((value) == (expr))
+#else
+ #define SkCheckResult(expr, value) (void)(expr)
+#endif
+
+#ifdef SK_DEBUG
+inline bool check_alpha(SkAlphaType reported, SkAlphaType actual) {
+ return ((reported == actual)
+ || ((reported == kPremul_SkAlphaType)
+ && (actual == kOpaque_SkAlphaType)));
}
+#endif // SK_DEBUG
+
+////////////////////////////////////////////////////////////////////////////////
-SkDecodingImageGenerator::SkDecodingImageGenerator(SkStreamRewindable* stream)
- : fData(NULL)
+DecodingImageGenerator::DecodingImageGenerator(
+ SkData* data,
+ SkStreamRewindable* stream,
+ const SkImageInfo& info,
+ int sampleSize,
+ bool ditherImage)
+ : fData(data)
, fStream(stream)
- , fHasInfo(false)
- , fDoCopyTo(false) {
- SkASSERT(fStream != NULL);
- SkASSERT(fStream->unique());
+ , fInfo(info)
+ , fSampleSize(sampleSize)
+ , fDitherImage(ditherImage)
+{
+ SkASSERT(stream != NULL);
+ SkSafeRef(fData); // may be NULL.
}
-SkDecodingImageGenerator::~SkDecodingImageGenerator() {
+DecodingImageGenerator::~DecodingImageGenerator() {
SkSafeUnref(fData);
fStream->unref();
}
-// TODO(halcanary): Give this macro a better name and move it into SkTypes.h
-#ifdef SK_DEBUG
- #define SkCheckResult(expr, value) SkASSERT((value) == (expr))
-#else
- #define SkCheckResult(expr, value) (void)(expr)
-#endif
-
-SkData* SkDecodingImageGenerator::refEncodedData() {
+SkData* DecodingImageGenerator::onRefEncodedData() {
// This functionality is used in `gm --serialize`
+ // Does not encode options.
if (fData != NULL) {
return SkSafeRef(fData);
}
@@ -98,111 +150,132 @@ SkData* SkDecodingImageGenerator::refEncodedData() {
return SkSafeRef(fData);
}
-bool SkDecodingImageGenerator::getInfo(SkImageInfo* info) {
- // info can be NULL. If so, will update fInfo, fDoCopyTo, and fHasInfo.
- if (fHasInfo) {
- if (info != NULL) {
- *info = fInfo;
- }
- return true;
+bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info,
+ void* pixels, size_t rowBytes,
+ SkPMColor ctableEntries[], int* ctableCount) {
+ if (fInfo != info) {
+ // The caller has specified a different info. This is an
+ // error for this kind of SkImageGenerator. Use the Options
+ // to change the settings.
+ return false;
}
+
SkAssertResult(fStream->rewind());
SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
if (NULL == decoder.get()) {
return false;
}
+ decoder->setDitherImage(fDitherImage);
+ decoder->setSampleSize(fSampleSize);
+ decoder->setRequireUnpremultipliedColors(
+ info.fAlphaType == kUnpremul_SkAlphaType);
+
SkBitmap bitmap;
- if (!decoder->decode(fStream, &bitmap,
- SkImageDecoder::kDecodeBounds_Mode)) {
- return false;
- }
- if (bitmap.config() == SkBitmap::kNo_Config) {
+ TargetAllocator allocator(fInfo, pixels, rowBytes);
+ decoder->setAllocator(&allocator);
+ bool success = decoder->decode(fStream, &bitmap, info.colorType(),
+ SkImageDecoder::kDecodePixels_Mode);
+ decoder->setAllocator(NULL);
+ if (!success) {
return false;
}
- if (!bitmap.asImageInfo(&fInfo)) {
- // We can't use bitmap.config() as is.
- if (!bitmap.canCopyTo(SkBitmap::kARGB_8888_Config)) {
- SkDEBUGFAIL("!bitmap->canCopyTo(SkBitmap::kARGB_8888_Config)");
+ if (allocator.isReady()) { // Did not use pixels!
+ SkBitmap bm;
+ SkASSERT(bitmap.canCopyTo(info.colorType()));
+ bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator);
+ if (!copySuccess || allocator.isReady()) {
+ SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
+ // Earlier we checked canCopyto(); we expect consistency.
return false;
}
- fDoCopyTo = true;
- fInfo.fWidth = bitmap.width();
- fInfo.fHeight = bitmap.height();
- fInfo.fColorType = kPMColor_SkColorType;
- fInfo.fAlphaType = bitmap.alphaType();
+ SkASSERT(check_alpha(info.alphaType(), bm.alphaType()));
+ } else {
+ SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
}
- if (info != NULL) {
- *info = fInfo;
+
+ if (kIndex_8_SkColorType == info.colorType()) {
+ if (kIndex_8_SkColorType != bitmap.colorType()) {
+ return false; // they asked for Index8, but we didn't receive that from decoder
+ }
+ SkColorTable* ctable = bitmap.getColorTable();
+ if (NULL == ctable) {
+ return false;
+ }
+ const int count = ctable->count();
+ memcpy(ctableEntries, ctable->lockColors(), count * sizeof(SkPMColor));
+ ctable->unlockColors();
+ *ctableCount = count;
}
- fHasInfo = true;
return true;
}
-bool SkDecodingImageGenerator::getPixels(const SkImageInfo& info,
- void* pixels,
- size_t rowBytes) {
- if (NULL == pixels) {
- return false;
- }
- if (!this->getInfo(NULL)) {
- return false;
- }
- if (SkImageInfoToBitmapConfig(info) == SkBitmap::kNo_Config) {
- return false; // Unsupported SkColorType.
- }
- SkAssertResult(fStream->rewind());
- SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
+// A contructor-type function that returns NULL on failure. This
+// prevents the returned SkImageGenerator from ever being in a bad
+// state. Called by both Create() functions
+SkImageGenerator* CreateDecodingImageGenerator(
+ SkData* data,
+ SkStreamRewindable* stream,
+ const SkDecodingImageGenerator::Options& opts) {
+ SkASSERT(stream);
+ SkAutoTUnref<SkStreamRewindable> autoStream(stream); // always unref this.
+ SkAssertResult(autoStream->rewind());
+ SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream));
if (NULL == decoder.get()) {
- return false;
- }
- if (fInfo != info) {
- // The caller has specified a different info. For now, this
- // is an error. In the future, we will check to see if we can
- // convert.
- return false;
- }
- int bpp = SkBitmap::ComputeBytesPerPixel(SkImageInfoToBitmapConfig(info));
- if (static_cast<size_t>(bpp * info.fWidth) > rowBytes) {
- return false;
+ return NULL;
}
SkBitmap bitmap;
- if (!bitmap.setConfig(info, rowBytes)) {
- return false;
+ decoder->setSampleSize(opts.fSampleSize);
+ decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul);
+ if (!decoder->decode(stream, &bitmap, SkImageDecoder::kDecodeBounds_Mode)) {
+ return NULL;
}
-
- TargetAllocator allocator(pixels, rowBytes, info);
- if (!fDoCopyTo) {
- decoder->setAllocator(&allocator);
+ if (kUnknown_SkColorType == bitmap.colorType()) {
+ return NULL;
}
- bool success = decoder->decode(fStream, &bitmap,
- SkImageDecoder::kDecodePixels_Mode);
- decoder->setAllocator(NULL);
- if (!success) {
- return false;
+
+ SkImageInfo info = bitmap.info();
+
+ if (opts.fUseRequestedColorType && (opts.fRequestedColorType != info.colorType())) {
+ if (!bitmap.canCopyTo(opts.fRequestedColorType)) {
+ SkASSERT(bitmap.colorType() != opts.fRequestedColorType);
+ return NULL; // Can not translate to needed config.
+ }
+ info.fColorType = opts.fRequestedColorType;
}
- if (fDoCopyTo) {
- SkBitmap bm8888;
- bitmap.copyTo(&bm8888, SkBitmap::kARGB_8888_Config, &allocator);
+
+ if (opts.fRequireUnpremul && info.fAlphaType != kOpaque_SkAlphaType) {
+ info.fAlphaType = kUnpremul_SkAlphaType;
}
- return true;
+ return SkNEW_ARGS(DecodingImageGenerator,
+ (data, autoStream.detach(), info,
+ opts.fSampleSize, opts.fDitherImage));
}
-bool SkDecodingImageGenerator::Install(SkData* data, SkBitmap* dst,
- SkDiscardableMemory::Factory* factory) {
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkImageGenerator* SkDecodingImageGenerator::Create(
+ SkData* data,
+ const SkDecodingImageGenerator::Options& opts) {
SkASSERT(data != NULL);
- SkASSERT(dst != NULL);
- SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (data)));
- return SkInstallDiscardablePixelRef(gen, dst, factory);
+ if (NULL == data) {
+ return NULL;
+ }
+ SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data));
+ SkASSERT(stream != NULL);
+ SkASSERT(stream->unique());
+ return CreateDecodingImageGenerator(data, stream, opts);
}
-bool SkDecodingImageGenerator::Install(SkStreamRewindable* stream,
- SkBitmap* dst,
- SkDiscardableMemory::Factory* factory) {
+SkImageGenerator* SkDecodingImageGenerator::Create(
+ SkStreamRewindable* stream,
+ const SkDecodingImageGenerator::Options& opts) {
SkASSERT(stream != NULL);
- SkASSERT(dst != NULL);
+ SkASSERT(stream->unique());
if ((stream == NULL) || !stream->unique()) {
SkSafeUnref(stream);
- return false;
+ return NULL;
}
- SkImageGenerator* gen(SkNEW_ARGS(SkDecodingImageGenerator, (stream)));
- return SkInstallDiscardablePixelRef(gen, dst, factory);
+ return CreateDecodingImageGenerator(NULL, stream, opts);
}