diff options
Diffstat (limited to 'src/codec/SkCodec.cpp')
-rw-r--r-- | src/codec/SkCodec.cpp | 125 |
1 files changed, 92 insertions, 33 deletions
diff --git a/src/codec/SkCodec.cpp b/src/codec/SkCodec.cpp index 3da7f5fb07..3c485c8beb 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()) { \ + 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,78 @@ 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, void* pixels, + size_t rowBytes, const SkCodec::Options* options, SkPMColor* ctable, int* ctableCount) { + fStartedIncrementalDecode = false; + + if (kUnknown_SkColorType == info.colorType()) { + return kInvalidConversion; + } + if (nullptr == pixels) { + return kInvalidParameters; + } + // 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, pixels, rowBytes, + fOptions, ctable, ctableCount); + if (kSuccess == result) { + fStartedIncrementalDecode = true; + } else if (kUnimplemented == result) { + // FIXME: This is temporarily necessary, until we transition SkCodec + // implementations from scanline decoding to incremental decoding. + // SkAndroidCodec will first attempt to use incremental decoding, but + // will fall back to scanline decoding if incremental returns + // kUnimplemented. rewindIfNeeded(), above, set fNeedsRewind to true + // (after potentially rewinding), but we do not want the next call to + // startScanlineDecode() to do a rewind. + fNeedsRewind = false; + } + 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 +313,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 +392,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 +425,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); |