Implement onSkipScanlines() for bmp and wbmp

TBR=reed@google.com
BUG=skia:4270
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1691083002

Review URL: https://codereview.chromium.org/1691083002
This commit is contained in:
msarett 2016-02-11 13:29:36 -08:00 committed by Commit bot
parent f8289d9bd1
commit 9b9497ef14
11 changed files with 44 additions and 26 deletions

View File

@ -657,18 +657,7 @@ private:
return kUnimplemented; return kUnimplemented;
} }
// Naive default version just calls onGetScanlines on temp memory. virtual bool onSkipScanlines(int /*countLines*/) { return false; }
virtual bool onSkipScanlines(int countLines) {
// FIXME (msarett): Make this a pure virtual and always override this.
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 countLines == this->onGetScanlines(storage.get(), countLines, 0);
}
virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; } virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }

View File

@ -546,6 +546,7 @@ SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
: INHERITED(info, stream) : INHERITED(info, stream)
, fBitsPerPixel(bitsPerPixel) , fBitsPerPixel(bitsPerPixel)
, fRowOrder(rowOrder) , fRowOrder(rowOrder)
, fSrcRowBytes(SkAlign4(compute_row_bytes(info.width(), fBitsPerPixel)))
{} {}
bool SkBmpCodec::onRewind() { bool SkBmpCodec::onRewind() {
@ -577,3 +578,12 @@ int SkBmpCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
// Decode the requested rows // Decode the requested rows
return this->decodeRows(rowInfo, dst, rowBytes, this->options()); return this->decodeRows(rowInfo, dst, rowBytes, this->options());
} }
bool SkBmpCodec::skipRows(int count) {
const size_t bytesToSkip = count * fSrcRowBytes;
return this->stream()->skip(bytesToSkip) == bytesToSkip;
}
bool SkBmpCodec::onSkipScanlines(int count) {
return this->skipRows(count);
}

View File

@ -81,6 +81,7 @@ protected:
*/ */
uint16_t bitsPerPixel() const { return fBitsPerPixel; } uint16_t bitsPerPixel() const { return fBitsPerPixel; }
SkScanlineOrder onGetScanlineOrder() const override { return fRowOrder; } SkScanlineOrder onGetScanlineOrder() const override { return fRowOrder; }
size_t srcRowBytes() const { return fSrcRowBytes; }
/* /*
* To be overriden by bmp subclasses, which provide unique implementations. * To be overriden by bmp subclasses, which provide unique implementations.
@ -127,15 +128,18 @@ private:
virtual int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, virtual int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes,
const Options& opts) = 0; const Options& opts) = 0;
virtual bool skipRows(int count);
Result onStartScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options&, Result onStartScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options&,
SkPMColor inputColorPtr[], int* inputColorCount) override; SkPMColor inputColorPtr[], int* inputColorCount) override;
int onGetScanlines(void* dst, int count, size_t rowBytes) override; int onGetScanlines(void* dst, int count, size_t rowBytes) override;
// TODO(msarett): Override default skipping with something more clever. bool onSkipScanlines(int count) override;
const uint16_t fBitsPerPixel; const uint16_t fBitsPerPixel;
const SkScanlineOrder fRowOrder; const SkScanlineOrder fRowOrder;
const size_t fSrcRowBytes;
typedef SkCodec INHERITED; typedef SkCodec INHERITED;
}; };

View File

@ -18,8 +18,7 @@ SkBmpMaskCodec::SkBmpMaskCodec(const SkImageInfo& info, SkStream* stream,
: INHERITED(info, stream, bitsPerPixel, rowOrder) : INHERITED(info, stream, bitsPerPixel, rowOrder)
, fMasks(masks) , fMasks(masks)
, fMaskSwizzler(nullptr) , fMaskSwizzler(nullptr)
, fSrcRowBytes(SkAlign4(compute_row_bytes(this->getInfo().width(), this->bitsPerPixel()))) , fSrcBuffer(new uint8_t [this->srcRowBytes()])
, fSrcBuffer(new uint8_t [fSrcRowBytes])
{} {}
/* /*
@ -92,7 +91,7 @@ int SkBmpMaskCodec::decodeRows(const SkImageInfo& dstInfo,
const int height = dstInfo.height(); const int height = dstInfo.height();
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
// Read a row of the input // Read a row of the input
if (this->stream()->read(srcRow, fSrcRowBytes) != fSrcRowBytes) { if (this->stream()->read(srcRow, this->srcRowBytes()) != this->srcRowBytes()) {
SkCodecPrintf("Warning: incomplete input stream.\n"); SkCodecPrintf("Warning: incomplete input stream.\n");
return y; return y;
} }

View File

@ -55,7 +55,6 @@ private:
SkAutoTDelete<SkMasks> fMasks; // owned SkAutoTDelete<SkMasks> fMasks; // owned
SkAutoTDelete<SkMaskSwizzler> fMaskSwizzler; SkAutoTDelete<SkMaskSwizzler> fMaskSwizzler;
const size_t fSrcRowBytes;
SkAutoTDeleteArray<uint8_t> fSrcBuffer; SkAutoTDeleteArray<uint8_t> fSrcBuffer;
typedef SkBmpCodec INHERITED; typedef SkBmpCodec INHERITED;

View File

@ -201,7 +201,7 @@ size_t SkBmpRLECodec::checkForMoreData() {
void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes, void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes,
const SkImageInfo& dstInfo, uint32_t x, uint32_t y, const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
uint8_t index) { uint8_t index) {
if (is_coord_necessary(x, fSampleX, dstInfo.width())) { if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) {
// Set the row // Set the row
uint32_t row = this->getDstRow(y, dstInfo.height()); uint32_t row = this->getDstRow(y, dstInfo.height());
@ -234,7 +234,7 @@ void SkBmpRLECodec::setRGBPixel(void* dst, size_t dstRowBytes,
const SkImageInfo& dstInfo, uint32_t x, const SkImageInfo& dstInfo, uint32_t x,
uint32_t y, uint8_t red, uint8_t green, uint32_t y, uint8_t red, uint8_t green,
uint8_t blue) { uint8_t blue) {
if (is_coord_necessary(x, fSampleX, dstInfo.width())) { if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) {
// Set the row // Set the row
uint32_t row = this->getDstRow(y, dstInfo.height()); uint32_t row = this->getDstRow(y, dstInfo.height());
@ -316,7 +316,9 @@ int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowB
// Because of the need for transparent pixels, kN32 is the only color // Because of the need for transparent pixels, kN32 is the only color
// type that makes sense for the destination format. // type that makes sense for the destination format.
SkASSERT(kN32_SkColorType == dstInfo.colorType()); SkASSERT(kN32_SkColorType == dstInfo.colorType());
if (dst) {
SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZeroInitialized); SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZeroInitialized);
}
// Adjust the height and the dst if the previous call to decodeRows() left us // Adjust the height and the dst if the previous call to decodeRows() left us
// with lines that need to be skipped. // with lines that need to be skipped.
@ -500,6 +502,13 @@ int SkBmpRLECodec::decodeRows(const SkImageInfo& info, void* dst, size_t dstRowB
} }
} }
bool SkBmpRLECodec::skipRows(int count) {
const SkImageInfo rowInfo = SkImageInfo::Make(this->getInfo().width(), count, kN32_SkColorType,
kUnpremul_SkAlphaType);
return count == this->decodeRows(rowInfo, nullptr, 0, this->options());
}
// FIXME: Make SkBmpRLECodec have no knowledge of sampling. // FIXME: Make SkBmpRLECodec have no knowledge of sampling.
// Or it should do all sampling natively. // Or it should do all sampling natively.
// It currently is a hybrid that needs to know what SkScaledCodec is doing. // It currently is a hybrid that needs to know what SkScaledCodec is doing.

View File

@ -84,9 +84,14 @@ private:
const SkImageInfo& dstInfo, uint32_t x, uint32_t y, const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
uint8_t red, uint8_t green, uint8_t blue); uint8_t red, uint8_t green, uint8_t blue);
/*
* If dst is NULL, this is a signal to skip the rows.
*/
int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes,
const Options& opts) override; const Options& opts) override;
bool skipRows(int count) override;
SkSampler* getSampler(bool createIfNecessary) override; SkSampler* getSampler(bool createIfNecessary) override;
SkAutoTUnref<SkColorTable> fColorTable; // owned SkAutoTUnref<SkColorTable> fColorTable; // owned

View File

@ -25,8 +25,7 @@ SkBmpStandardCodec::SkBmpStandardCodec(const SkImageInfo& info, SkStream* stream
, fBytesPerColor(bytesPerColor) , fBytesPerColor(bytesPerColor)
, fOffset(offset) , fOffset(offset)
, fSwizzler(nullptr) , fSwizzler(nullptr)
, fSrcRowBytes(SkAlign4(compute_row_bytes(this->getInfo().width(), this->bitsPerPixel()))) , fSrcBuffer(new uint8_t [this->srcRowBytes()])
, fSrcBuffer(new uint8_t [fSrcRowBytes])
, fIsOpaque(isOpaque) , fIsOpaque(isOpaque)
, fInIco(inIco) , fInIco(inIco)
, fAndMaskRowBytes(fInIco ? SkAlign4(compute_row_bytes(this->getInfo().width(), 1)) : 0) , fAndMaskRowBytes(fInIco ? SkAlign4(compute_row_bytes(this->getInfo().width(), 1)) : 0)
@ -225,7 +224,7 @@ int SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo, void* dst, size_t
const int height = dstInfo.height(); const int height = dstInfo.height();
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
// Read a row of the input // Read a row of the input
if (this->stream()->read(fSrcBuffer.get(), fSrcRowBytes) != fSrcRowBytes) { if (this->stream()->read(fSrcBuffer.get(), this->srcRowBytes()) != this->srcRowBytes()) {
SkCodecPrintf("Warning: incomplete input stream.\n"); SkCodecPrintf("Warning: incomplete input stream.\n");
return y; return y;
} }
@ -262,7 +261,7 @@ int SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo, void* dst, size_t
// Calculate how many bytes we must skip to reach the AND mask. // Calculate how many bytes we must skip to reach the AND mask.
const int remainingScanlines = this->getInfo().height() - startScanline - height; const int remainingScanlines = this->getInfo().height() - startScanline - height;
const size_t bytesToSkip = remainingScanlines * fSrcRowBytes + const size_t bytesToSkip = remainingScanlines * this->srcRowBytes() +
startScanline * fAndMaskRowBytes; startScanline * fAndMaskRowBytes;
const size_t subStreamStartPosition = currPosition + bytesToSkip; const size_t subStreamStartPosition = currPosition + bytesToSkip;
if (subStreamStartPosition >= length) { if (subStreamStartPosition >= length) {

View File

@ -90,7 +90,6 @@ private:
const uint32_t fBytesPerColor; const uint32_t fBytesPerColor;
const uint32_t fOffset; const uint32_t fOffset;
SkAutoTDelete<SkSwizzler> fSwizzler; SkAutoTDelete<SkSwizzler> fSwizzler;
const size_t fSrcRowBytes;
SkAutoTDeleteArray<uint8_t> fSrcBuffer; SkAutoTDeleteArray<uint8_t> fSrcBuffer;
const bool fIsOpaque; const bool fIsOpaque;
const bool fInIco; const bool fInIco;

View File

@ -181,6 +181,11 @@ int SkWbmpCodec::onGetScanlines(void* dst, int count, size_t dstRowBytes) {
return count; return count;
} }
bool SkWbmpCodec::onSkipScanlines(int count) {
const size_t bytesToSkip = count * fSrcRowBytes;
return this->stream()->skip(bytesToSkip) == bytesToSkip;
}
SkCodec::Result SkWbmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, SkCodec::Result SkWbmpCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
const Options& options, SkPMColor inputColorTable[], int* inputColorCount) { const Options& options, SkPMColor inputColorTable[], int* inputColorCount) {
if (options.fSubset) { if (options.fSubset) {

View File

@ -52,8 +52,8 @@ private:
SkAutoTUnref<SkColorTable> fColorTable; SkAutoTUnref<SkColorTable> fColorTable;
SkAutoTMalloc<uint8_t> fSrcBuffer; SkAutoTMalloc<uint8_t> fSrcBuffer;
// FIXME: Override onSkipScanlines to avoid swizzling.
int onGetScanlines(void* dst, int count, size_t dstRowBytes) override; int onGetScanlines(void* dst, int count, size_t dstRowBytes) override;
bool onSkipScanlines(int count) override;
Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& options, Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& options,
SkPMColor inputColorTable[], int* inputColorCount) override; SkPMColor inputColorTable[], int* inputColorCount) override;