Chromium Code Reviews| Index: src/codec/SkCodec.cpp |
| diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp |
| index 8468f8a09996d1c7e79363970f9103e106049c7a..0f781642e40444eb6522cee07658b20411ec3502 100644 |
| --- a/src/codec/SkCodec.cpp |
| +++ b/src/codec/SkCodec.cpp |
| @@ -154,6 +154,20 @@ bool SkCodec::rewindIfNeeded() { |
| return this->onRewind(); |
| } |
| +#define CHECK_COLOR_TABLE \ |
| + if (kIndex_8_SkColorType == info.colorType()) { \ |
|
msarett
2016/05/20 18:21:38
nit: line up slash?
scroggo_chromium
2016/05/20 18:58:37
D'oh! edited this after putting the slash there. D
|
| + if (nullptr == ctable || nullptr == ctableCount) { \ |
| + return SkCodec::kInvalidParameters; \ |
| + } \ |
| + } else { \ |
| + if (ctableCount) { \ |
| + *ctableCount = 0; \ |
| + } \ |
| + ctableCount = nullptr; \ |
| + ctable = nullptr; \ |
| + } |
| + |
| + |
| SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, |
| const Options* options, SkPMColor ctable[], int* ctableCount) { |
| if (kUnknown_SkColorType == info.colorType()) { |
| @@ -166,17 +180,7 @@ SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t |
| return kInvalidParameters; |
| } |
| - if (kIndex_8_SkColorType == info.colorType()) { |
| - if (nullptr == ctable || nullptr == ctableCount) { |
| - return kInvalidParameters; |
| - } |
| - } else { |
| - if (ctableCount) { |
| - *ctableCount = 0; |
| - } |
| - ctableCount = nullptr; |
| - ctable = nullptr; |
| - } |
| + CHECK_COLOR_TABLE; |
| if (!this->rewindIfNeeded()) { |
| return kCouldNotRewind; |
| @@ -228,23 +232,62 @@ SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t |
| return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr); |
| } |
| -SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo, |
| - const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) { |
| - // Reset fCurrScanline in case of failure. |
| - fCurrScanline = -1; |
| +SkCodec::Result SkCodec::startIncrementalDecode(const SkImageInfo& info, |
| + const SkCodec::Options* options, SkPMColor* ctable, int* ctableCount) { |
| + fStartedIncrementalDecode = false; |
| + |
| // Ensure that valid color ptrs are passed in for kIndex8 color type |
| - if (kIndex_8_SkColorType == dstInfo.colorType()) { |
| - if (nullptr == ctable || nullptr == ctableCount) { |
| - return SkCodec::kInvalidParameters; |
| + CHECK_COLOR_TABLE; |
| + |
| + // FIXME: If the rows come after the rows of a previous incremental decode, |
| + // we might be able to skip the rewind, but only the implementation knows |
| + // that. (e.g. PNG will always need to rewind, since we called longjmp, but |
| + // a bottom-up BMP could skip rewinding if the new rows are above the old |
| + // rows.) |
| + if (!this->rewindIfNeeded()) { |
| + return kCouldNotRewind; |
| + } |
| + |
| + // Set options. |
| + Options optsStorage; |
| + if (nullptr == options) { |
| + options = &optsStorage; |
| + } else if (options->fSubset) { |
| + SkIRect size = SkIRect::MakeSize(info.dimensions()); |
| + if (!size.contains(*options->fSubset)) { |
| + return kInvalidParameters; |
| } |
| - } else { |
| - if (ctableCount) { |
| - *ctableCount = 0; |
| + |
| + const int top = options->fSubset->top(); |
| + const int bottom = options->fSubset->bottom(); |
| + if (top < 0 || top >= info.height() || top >= bottom || bottom > info.height()) { |
| + return kInvalidParameters; |
| } |
| - ctableCount = nullptr; |
| - ctable = nullptr; |
| } |
| + if (!this->dimensionsSupported(info.dimensions())) { |
| + return kInvalidScale; |
| + } |
| + |
| + fDstInfo = info; |
| + fOptions = *options; |
| + |
| + const Result result = this->onStartIncrementalDecode(info, fOptions, ctable, |
| + ctableCount); |
| + if (kSuccess == result) { |
| + fStartedIncrementalDecode = true; |
| + } |
| + return result; |
| +} |
| + |
| + |
| +SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& info, |
| + const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) { |
| + // Reset fCurrScanline in case of failure. |
| + fCurrScanline = -1; |
| + // Ensure that valid color ptrs are passed in for kIndex8 color type |
| + CHECK_COLOR_TABLE; |
| + |
| if (!this->rewindIfNeeded()) { |
| return kCouldNotRewind; |
| } |
| @@ -254,36 +297,38 @@ SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo, |
| if (nullptr == options) { |
| options = &optsStorage; |
| } else if (options->fSubset) { |
| - SkIRect size = SkIRect::MakeSize(dstInfo.dimensions()); |
| + SkIRect size = SkIRect::MakeSize(info.dimensions()); |
| if (!size.contains(*options->fSubset)) { |
| return kInvalidInput; |
| } |
| // We only support subsetting in the x-dimension for scanline decoder. |
| // Subsetting in the y-dimension can be accomplished using skipScanlines(). |
| - if (options->fSubset->top() != 0 || options->fSubset->height() != dstInfo.height()) { |
| + if (options->fSubset->top() != 0 || options->fSubset->height() != info.height()) { |
| return kInvalidInput; |
| } |
| } |
| // FIXME: Support subsets somehow? |
| - if (!this->dimensionsSupported(dstInfo.dimensions())) { |
| + if (!this->dimensionsSupported(info.dimensions())) { |
| return kInvalidScale; |
| } |
| - const Result result = this->onStartScanlineDecode(dstInfo, *options, ctable, ctableCount); |
| + const Result result = this->onStartScanlineDecode(info, *options, ctable, ctableCount); |
| if (result != SkCodec::kSuccess) { |
| return result; |
| } |
| fCurrScanline = 0; |
| - fDstInfo = dstInfo; |
| + fDstInfo = info; |
| fOptions = *options; |
| return kSuccess; |
| } |
| -SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) { |
| - return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr); |
| +#undef CHECK_COLOR_TABLE |
| + |
| +SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& info) { |
| + return this->startScanlineDecode(info, nullptr, nullptr, nullptr); |
| } |
| int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) { |
| @@ -331,7 +376,6 @@ int SkCodec::outputScanline(int inputScanline) const { |
| int SkCodec::onOutputScanline(int inputScanline) const { |
| switch (this->getScanlineOrder()) { |
| case kTopDown_SkScanlineOrder: |
| - case kNone_SkScanlineOrder: |
| return inputScanline; |
| case kBottomUp_SkScanlineOrder: |
| return this->getInfo().height() - inputScanline - 1; |
| @@ -365,8 +409,7 @@ void SkCodec::fillIncompleteImage(const SkImageInfo& info, void* dst, size_t row |
| } |
| switch (this->getScanlineOrder()) { |
| - case kTopDown_SkScanlineOrder: |
| - case kNone_SkScanlineOrder: { |
| + case kTopDown_SkScanlineOrder: { |
| const SkImageInfo fillInfo = info.makeWH(fillWidth, linesRemaining); |
| fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes); |
| fill_proc(fillInfo, fillDst, rowBytes, fillValue, zeroInit, sampler); |