Chromium Code Reviews| Index: include/codec/SkScanlineDecoder.h |
| diff --git a/include/codec/SkScanlineDecoder.h b/include/codec/SkScanlineDecoder.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c047223d7cb27a1b85e0205920919fccc3d2dcb5 |
| --- /dev/null |
| +++ b/include/codec/SkScanlineDecoder.h |
| @@ -0,0 +1,115 @@ |
| +/* |
| + * Copyright 2015 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#ifndef SkScanlineDecoder_DEFINED |
| +#define SkScanlineDecoder_DEFINED |
| + |
| +#include "SkTypes.h" |
| +#include "SkTemplates.h" |
| +#include "SkImageGenerator.h" |
| +#include "SkImageInfo.h" |
| + |
| +class SkScanlineDecoder : public SkNoncopyable { |
| +public: |
| + // Note for implementations: An SkScanlineDecoder will be deleted by (and |
| + // therefore *before*) its associated SkCodec, in case the order matters. |
| + virtual ~SkScanlineDecoder() {} |
| + |
| + /** |
| + * Write the next countLines scanlines into dst. |
| + * |
| + * @param dst Must be non-null, and large enough to hold countLines |
| + * scanlines of size rowBytes. |
| + * @param countLines Number of lines to write. |
| + * @param rowBytes Number of bytes per row. Must be large enough to hold |
| + * a scanline based on the SkImageInfo used to create this object. |
| + */ |
| + SkImageGenerator::Result getScanlines(void* dst, int countLines, size_t rowBytes) { |
| + if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0 |
| + || fCurrScanline + countLines > fDstInfo.height()) { |
| + return SkImageGenerator::kInvalidParameters; |
| + } |
| + const SkImageGenerator::Result result = this->onGetScanlines(dst, countLines, rowBytes); |
| + this->checkForFinish(countLines); |
| + return result; |
| + } |
| + |
| + /** |
| + * Skip count scanlines. |
| + * |
| + * The default version just calls onGetScanlines and discards the dst. |
| + * NOTE: If skipped lines are the only lines with alpha, this default |
| + * will make reallyHasAlpha return true, when it could have returned |
| + * false. |
| + */ |
| + SkImageGenerator::Result skipScanlines(int countLines) { |
| + if (fCurrScanline + countLines > fDstInfo.height()) { |
| + // Arguably, we could just skip the scanlines which are remaining, |
| + // and return kSuccess. We choose to return invalid so the client |
| + // can catch their bug. |
| + return SkImageGenerator::kInvalidParameters; |
| + } |
| + const SkImageGenerator::Result result = this->onSkipScanlines(countLines); |
| + this->checkForFinish(countLines); |
| + return result; |
| + } |
| + |
| + /** |
| + * Some images may initially report that they have alpha due to the format |
| + * of the encoded data, but then never use any colors which have alpha |
| + * less than 100%. This function can be called *after* decoding to |
| + * determine if such an image truly had alpha. Calling it before decoding |
| + * is undefined. |
| + * FIXME: see skbug.com/3582. |
| + */ |
| + bool reallyHasAlpha() const { |
| + return this->onReallyHasAlpha(); |
| + } |
| + |
| +protected: |
| + SkScanlineDecoder(const SkImageInfo& requested) |
| + : fDstInfo(requested) |
| + , fCurrScanline(0) {} |
| + |
| + virtual bool onReallyHasAlpha() const { return false; } |
| + |
| +private: |
| + const SkImageInfo fDstInfo; |
| + int fCurrScanline; |
| + |
| + // Naive default version just calls onGetScanlines on temp memory. |
| + virtual SkImageGenerator::Result onSkipScanlines(int countLines) { |
| + SkAutoMalloc storage(fDstInfo.minRowBytes()); |
|
djsollen
2015/03/25 13:08:42
do the codecs provide no way to skip this data wit
scroggo
2015/03/25 13:49:15
I haven't looked at them all, but to my surprise,
|
| + // Note that we pass 0 to rowBytes so we continue to use the same memory. |
| + // Also note that while getScanlines checks that rowBytes is big enough, |
| + // onGetScanlines bypasses that check. |
| + // Calling the virtual method also means we do not double count |
| + // countLines. |
| + return this->onGetScanlines(storage.get(), countLines, 0); |
| + } |
| + |
| + virtual SkImageGenerator::Result onGetScanlines(void* dst, int countLines, |
| + size_t rowBytes) = 0; |
| + |
| + /** |
| + * Called after any set of scanlines read/skipped. Updates fCurrScanline, |
| + * and, if we are at the end, calls onFinish(). |
| + */ |
| + void checkForFinish(int countLines) { |
| + fCurrScanline += countLines; |
| + if (fCurrScanline >= fDstInfo.height()) { |
| + this->onFinish(); |
| + } |
| + } |
| + |
| + /** |
| + * This function will be called after reading/skipping all scanlines to do |
| + * any necessary cleanups. |
| + */ |
| + virtual void onFinish() {} // Default does nothing. |
| +}; |
| +#endif // SkScanlineDecoder_DEFINED |