Index: src/codec/SkBmpStandardCodec.cpp |
diff --git a/src/codec/SkBmpStandardCodec.cpp b/src/codec/SkBmpStandardCodec.cpp |
index fd4d6d18bc2d3df2ea6366554dc3bf56ec72700e..901c1d2f3ae1968eb91ec07ff2d0547e05f2add6 100644 |
--- a/src/codec/SkBmpStandardCodec.cpp |
+++ b/src/codec/SkBmpStandardCodec.cpp |
@@ -60,9 +60,6 @@ SkCodec::Result SkBmpStandardCodec::onGetPixels(const SkImageInfo& dstInfo, |
*rowsDecoded = rows; |
return kIncompleteInput; |
} |
- if (fInIco) { |
- return this->decodeIcoMask(dstInfo, dst, dstRowBytes); |
- } |
return kSuccess; |
} |
@@ -227,9 +224,8 @@ SkCodec::Result SkBmpStandardCodec::prepareToDecode(const SkImageInfo& dstInfo, |
/* |
* 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++) { |
@@ -246,29 +242,57 @@ int SkBmpStandardCodec::decodeRows(const SkImageInfo& dstInfo, |
fSwizzler->swizzle(dstRow, fSrcBuffer.get()); |
} |
- // Finished decoding the entire image |
+ if (fInIco) { |
+ const int startScanline = this->currScanline(); |
+ const size_t andMaskRowBytes = SkAlign4(compute_row_bytes(this->getInfo().width(), 1)); |
+ if (startScanline < 0) { |
+ // We are not performing a scanline decode. |
+ // Just decode the entire ICO mask and return. |
+ decodeIcoMask(dstInfo, dst, dstRowBytes, andMaskRowBytes); |
+ 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 also must be able to return |
+ // the stream to its original position in order to decode the |
+ // next scanline on a subsequent request. |
+ // We will do this by taking advantage of the fact that |
+ // SkIcoCodec always uses a SkMemoryStream as its underlying |
+ // representation of the stream. |
+ SkMemoryStream* stream = (SkMemoryStream*) this->stream(); |
+ const size_t startPosition = stream->getPosition(); |
+ |
+ const int remainingScanlines = this->getInfo().height() - startScanline - height; |
+ const size_t bytesToSkip = remainingScanlines * fSrcRowBytes + |
+ startScanline * andMaskRowBytes; |
+ if (bytesToSkip != stream->skip(bytesToSkip)) { |
+ // FIXME: How can we indicate that this decode was actually incomplete? |
+ stream->seek(startPosition); |
+ return height; |
+ } |
+ // FIXME: If decodeIcoMask does not succeed, is there a way that we can |
+ // indicate the decode was incomplete? |
+ decodeIcoMask(dstInfo, dst, dstRowBytes, andMaskRowBytes); |
+ stream->seek(startPosition); |
+ } |
+ |
return height; |
} |
-// 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) { |
+void SkBmpStandardCodec::decodeIcoMask(const SkImageInfo& dstInfo, |
+ void* dst, size_t dstRowBytes, size_t srcRowBytes) { |
// 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); |
- // 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(), rowBytes) != rowBytes) { |
+ if (this->stream()->read(fSrcBuffer.get(), srcRowBytes) != srcRowBytes) { |
SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n"); |
- return kIncompleteInput; |
+ return; |
} |
int row = this->getDstRow(y, dstInfo.height()); |
@@ -276,7 +300,7 @@ SkCodec::Result SkBmpStandardCodec::decodeIcoMask(const SkImageInfo& dstInfo, |
SkPMColor* dstRow = |
SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); |
- for (int x = 0; x < width; x++) { |
+ for (int x = 0; x < this->getInfo().width(); x++) { |
int quotient; |
int modulus; |
SkTDivMod(x, 8, "ient, &modulus); |
@@ -286,7 +310,6 @@ SkCodec::Result SkBmpStandardCodec::decodeIcoMask(const SkImageInfo& dstInfo, |
dstRow[x] &= alphaBit - 1; |
msarett
2015/11/24 22:43:35
This is currently broken. We either need to know
|
} |
} |
- return kSuccess; |
} |
uint32_t SkBmpStandardCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const { |