| Index: src/codec/SkBmpStandardCodec.cpp
|
| diff --git a/src/codec/SkBmpStandardCodec.cpp b/src/codec/SkBmpStandardCodec.cpp
|
| index 9e90f3c630006a3bcb28e751679bec77dbc876c6..fd4d6d18bc2d3df2ea6366554dc3bf56ec72700e 100644
|
| --- a/src/codec/SkBmpStandardCodec.cpp
|
| +++ b/src/codec/SkBmpStandardCodec.cpp
|
| @@ -27,7 +27,6 @@
|
| , fSrcRowBytes(SkAlign4(compute_row_bytes(this->getInfo().width(), this->bitsPerPixel())))
|
| , fSrcBuffer(new uint8_t [fSrcRowBytes])
|
| , fInIco(inIco)
|
| - , fAndMaskRowBytes(fInIco ? SkAlign4(compute_row_bytes(this->getInfo().width(), 1)) : 0)
|
| {}
|
|
|
| /*
|
| @@ -60,6 +59,9 @@
|
| if (rows != dstInfo.height()) {
|
| *rowsDecoded = rows;
|
| return kIncompleteInput;
|
| + }
|
| + if (fInIco) {
|
| + return this->decodeIcoMask(dstInfo, dst, dstRowBytes);
|
| }
|
| return kSuccess;
|
| }
|
| @@ -225,8 +227,9 @@
|
| /*
|
| * Performs the bitmap decoding for standard input format
|
| */
|
| -int SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes,
|
| - const Options& opts) {
|
| +int SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo,
|
| + void* dst, size_t dstRowBytes,
|
| + const Options& opts) {
|
| // Iterate over rows of the image
|
| const int height = dstInfo.height();
|
| for (int y = 0; y < height; y++) {
|
| @@ -243,75 +246,29 @@
|
| fSwizzler->swizzle(dstRow, fSrcBuffer.get());
|
| }
|
|
|
| - if (fInIco) {
|
| - const int startScanline = this->currScanline();
|
| - if (startScanline < 0) {
|
| - // We are not performing a scanline decode.
|
| - // Just decode the entire ICO mask and return.
|
| - decodeIcoMask(this->stream(), dstInfo, dst, dstRowBytes);
|
| - return height;
|
| - }
|
| -
|
| - // In order to perform a scanline ICO decode, we must be able
|
| - // to skip ahead in the stream in order to apply the AND mask
|
| - // to the requested scanlines.
|
| - // We will do this by taking advantage of the fact that
|
| - // SkIcoCodec always uses a SkMemoryStream as its underlying
|
| - // representation of the stream.
|
| - const void* memoryBase = this->stream()->getMemoryBase();
|
| - SkASSERT(nullptr != memoryBase);
|
| - SkASSERT(this->stream()->hasLength());
|
| - SkASSERT(this->stream()->hasPosition());
|
| -
|
| - const size_t length = this->stream()->getLength();
|
| - const size_t currPosition = this->stream()->getPosition();
|
| -
|
| - // Calculate how many bytes we must skip to reach the AND mask.
|
| - const int remainingScanlines = this->getInfo().height() - startScanline - height;
|
| - const size_t bytesToSkip = remainingScanlines * fSrcRowBytes +
|
| - startScanline * fAndMaskRowBytes;
|
| - const size_t subStreamStartPosition = currPosition + bytesToSkip;
|
| - if (subStreamStartPosition >= length) {
|
| - // FIXME: How can we indicate that this decode was actually incomplete?
|
| - return height;
|
| - }
|
| -
|
| - // Create a subStream to pass to decodeIcoMask(). It is useful to encapsulate
|
| - // the memory base into a stream in order to safely handle incomplete images
|
| - // without reading out of bounds memory.
|
| - const void* subStreamMemoryBase = SkTAddOffset<const void>(memoryBase,
|
| - subStreamStartPosition);
|
| - const size_t subStreamLength = length - subStreamStartPosition;
|
| - // This call does not transfer ownership of the subStreamMemoryBase.
|
| - SkMemoryStream subStream(subStreamMemoryBase, subStreamLength, false);
|
| -
|
| - // FIXME: If decodeIcoMask does not succeed, is there a way that we can
|
| - // indicate the decode was incomplete?
|
| - decodeIcoMask(&subStream, dstInfo, dst, dstRowBytes);
|
| - }
|
| -
|
| + // Finished decoding the entire image
|
| return height;
|
| }
|
|
|
| -void SkBmpStandardCodec::decodeIcoMask(SkStream* stream, const SkImageInfo& dstInfo,
|
| +// TODO (msarett): This function will need to be modified in order to perform row by row decodes
|
| +// when the Ico scanline decoder is implemented.
|
| +SkCodec::Result SkBmpStandardCodec::decodeIcoMask(const SkImageInfo& dstInfo,
|
| void* dst, size_t dstRowBytes) {
|
| // BMP in ICO have transparency, so this cannot be 565, and this mask
|
| // prevents us from using kIndex8. The below code depends on the output
|
| // being an SkPMColor.
|
| SkASSERT(dstInfo.colorType() == kN32_SkColorType);
|
|
|
| - // If we are sampling, make sure that we only mask the sampled pixels.
|
| - // We do not need to worry about sampling in the y-dimension because that
|
| - // should be handled by SkSampledCodec.
|
| - int sampleX = fSwizzler->sampleX();
|
| - int startX = get_start_coord(sampleX);
|
| + // The AND mask is always 1 bit per pixel
|
| + const int width = this->getInfo().width();
|
| + const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1));
|
|
|
| SkPMColor* dstPtr = (SkPMColor*) dst;
|
| for (int y = 0; y < dstInfo.height(); y++) {
|
| // The srcBuffer will at least be large enough
|
| - if (stream->read(fSrcBuffer.get(), fAndMaskRowBytes) != fAndMaskRowBytes) {
|
| + if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) {
|
| SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n");
|
| - return;
|
| + return kIncompleteInput;
|
| }
|
|
|
| int row = this->getDstRow(y, dstInfo.height());
|
| @@ -319,15 +276,17 @@
|
| SkPMColor* dstRow =
|
| SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes);
|
|
|
| - for (int x = startX; x < this->getInfo().width(); x += sampleX) {
|
| + for (int x = 0; x < width; x++) {
|
| int quotient;
|
| int modulus;
|
| SkTDivMod(x, 8, "ient, &modulus);
|
| uint32_t shift = 7 - modulus;
|
| - uint32_t alphaBit = (fSrcBuffer.get()[quotient] >> shift) & 0x1;
|
| - dstRow[get_dst_coord(x, sampleX)] &= alphaBit - 1;
|
| - }
|
| - }
|
| + uint32_t alphaBit =
|
| + (fSrcBuffer.get()[quotient] >> shift) & 0x1;
|
| + dstRow[x] &= alphaBit - 1;
|
| + }
|
| + }
|
| + return kSuccess;
|
| }
|
|
|
| uint32_t SkBmpStandardCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const {
|
|
|