blob: 8376e57c09d84bb48c1d7ae295ccd441a7feab48 [file] [log] [blame]
/*
* 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 "SkCodec.h"
#include "SkTemplates.h"
#include "SkImageInfo.h"
class SkScanlineDecoder : public SkNoncopyable {
public:
/**
* Clean up after reading/skipping scanlines.
*
* It is possible that not all scanlines will have been read/skipped. In
* fact, in the case of subset decodes, it is likely that there will be
* scanlines at the bottom of the image that have been ignored.
*/
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.
*/
SkCodec::Result getScanlines(void* dst, int countLines, size_t rowBytes) {
if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0
|| fCurrScanline + countLines > fDstInfo.height()) {
return SkCodec::kInvalidParameters;
}
const SkCodec::Result result = this->onGetScanlines(dst, countLines, rowBytes);
fCurrScanline += 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.
*/
SkCodec::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 SkCodec::kInvalidParameters;
}
const SkCodec::Result result = this->onSkipScanlines(countLines);
fCurrScanline += 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; }
const SkImageInfo& dstInfo() const { return fDstInfo; }
private:
const SkImageInfo fDstInfo;
int fCurrScanline;
// Naive default version just calls onGetScanlines on temp memory.
virtual SkCodec::Result onSkipScanlines(int countLines) {
SkAutoMalloc storage(fDstInfo.minRowBytes());
// 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 SkCodec::Result onGetScanlines(void* dst, int countLines,
size_t rowBytes) = 0;
};
#endif // SkScanlineDecoder_DEFINED