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 { |