Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBmpCodec.h" | 8 #include "SkBmpCodec.h" |
| 9 #include "SkCodec.h" | 9 #include "SkCodec.h" |
| 10 #include "SkData.h" | 10 #include "SkData.h" |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 | 146 |
| 147 if (!this->rewindIfNeeded()) { | 147 if (!this->rewindIfNeeded()) { |
| 148 return kCouldNotRewind; | 148 return kCouldNotRewind; |
| 149 } | 149 } |
| 150 | 150 |
| 151 // Default options. | 151 // Default options. |
| 152 Options optsStorage; | 152 Options optsStorage; |
| 153 if (nullptr == options) { | 153 if (nullptr == options) { |
| 154 options = &optsStorage; | 154 options = &optsStorage; |
| 155 } | 155 } |
| 156 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ct able, ctableCount); | 156 |
| 157 // On an incomplete decode, the subclass will specify the number of scanline s that it decoded | |
| 158 // successfully. | |
| 159 int rowsDecoded = 0; | |
| 160 const Result result = this->onGetPixels(info, pixels, rowBytes, *options, ct able, ctableCount, | |
| 161 &rowsDecoded); | |
| 157 | 162 |
| 158 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) { | 163 if ((kIncompleteInput == result || kSuccess == result) && ctableCount) { |
| 159 SkASSERT(*ctableCount >= 0 && *ctableCount <= 256); | 164 SkASSERT(*ctableCount >= 0 && *ctableCount <= 256); |
| 160 } | 165 } |
| 166 | |
| 167 // A return value of kIncompleteInput indicates a truncated image stream. | |
| 168 // In this case, we will fill any uninitialized memory with a default value. | |
| 169 // Some subclasses will take care of filling any uninitialized memory on | |
| 170 // their own. They indicate that all of the memory has been filled by | |
| 171 // setting rowsDecoded equal to the height. | |
| 172 if (kIncompleteInput == result && rowsDecoded != info.height()) { | |
| 173 this->fillIncompleteImage(info, pixels, rowBytes, options->fZeroInitiali zed, | |
| 174 info.height(), rowsDecoded); | |
| 175 } | |
| 176 | |
| 161 return result; | 177 return result; |
| 162 } | 178 } |
| 163 | 179 |
| 164 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { | 180 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) { |
| 165 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr); | 181 return this->getPixels(info, pixels, rowBytes, nullptr, nullptr, nullptr); |
| 166 } | 182 } |
| 167 | 183 |
| 168 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo, | 184 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo, |
| 169 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) { | 185 const SkCodec::Options* options, SkPMColor ctable[], int* ctableCount) { |
| 170 // Reset fCurrScanline in case of failure. | 186 // Reset fCurrScanline in case of failure. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 200 fCurrScanline = 0; | 216 fCurrScanline = 0; |
| 201 fDstInfo = dstInfo; | 217 fDstInfo = dstInfo; |
| 202 fOptions = *options; | 218 fOptions = *options; |
| 203 return kSuccess; | 219 return kSuccess; |
| 204 } | 220 } |
| 205 | 221 |
| 206 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) { | 222 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& dstInfo) { |
| 207 return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr); | 223 return this->startScanlineDecode(dstInfo, nullptr, nullptr, nullptr); |
| 208 } | 224 } |
| 209 | 225 |
| 210 SkCodec::Result SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes ) { | 226 uint32_t SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) { |
|
scroggo
2015/10/01 14:48:31
If we wanted to, we could make getScanlines return
msarett
2015/10/01 18:14:14
It's fair to point out that this API change is no
| |
| 211 if (fCurrScanline < 0) { | 227 if (fCurrScanline < 0) { |
| 212 return kScanlineDecodingNotStarted; | 228 return 0; |
|
scroggo
2015/10/01 14:48:31
Do we still need this enum value?
msarett
2015/10/01 18:14:14
Looks like we don't.
| |
| 213 } | 229 } |
| 214 | 230 |
| 215 SkASSERT(!fDstInfo.isEmpty()); | 231 SkASSERT(!fDstInfo.isEmpty()); |
| 216 if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0 | 232 if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0 |
| 217 || fCurrScanline + countLines > fDstInfo.height()) { | 233 || fCurrScanline + countLines > fDstInfo.height()) { |
| 218 return kInvalidParameters; | 234 return 0; |
| 219 } | 235 } |
| 220 | 236 |
| 221 const Result result = this->onGetScanlines(dst, countLines, rowBytes); | 237 const uint32_t linesDecoded = this->onGetScanlines(dst, countLines, rowBytes ); |
| 222 fCurrScanline += countLines; | 238 if (linesDecoded < countLines) { |
| 223 return result; | 239 this->fillIncompleteImage(this->dstInfo(), dst, rowBytes, this->options( ).fZeroInitialized, |
| 240 countLines, linesDecoded); | |
| 241 } | |
| 242 fCurrScanline += linesDecoded; | |
| 243 return linesDecoded; | |
| 224 } | 244 } |
| 225 | 245 |
| 226 SkCodec::Result SkCodec::skipScanlines(int countLines) { | 246 bool SkCodec::skipScanlines(int countLines) { |
| 227 if (fCurrScanline < 0) { | 247 if (fCurrScanline < 0) { |
| 228 return kScanlineDecodingNotStarted; | 248 return false; |
| 229 } | 249 } |
| 230 | 250 |
| 231 SkASSERT(!fDstInfo.isEmpty()); | 251 SkASSERT(!fDstInfo.isEmpty()); |
| 232 if (fCurrScanline + countLines > fDstInfo.height()) { | 252 if (fCurrScanline + countLines > fDstInfo.height()) { |
| 233 // Arguably, we could just skip the scanlines which are remaining, | 253 // Arguably, we could just skip the scanlines which are remaining, |
| 234 // and return kSuccess. We choose to return invalid so the client | 254 // and return true. We choose to return false so the client |
| 235 // can catch their bug. | 255 // can catch their bug. |
| 236 return SkCodec::kInvalidParameters; | 256 return false; |
| 237 } | 257 } |
| 238 | 258 |
| 239 const Result result = this->onSkipScanlines(countLines); | 259 if (!this->onSkipScanlines(countLines)) { |
| 260 return false; | |
| 261 } | |
| 240 fCurrScanline += countLines; | 262 fCurrScanline += countLines; |
| 241 return result; | 263 return true; |
| 242 } | 264 } |
| 265 | |
| 266 int SkCodec::nextScanline(int srcY) const { | |
| 267 SkASSERT(0 <= srcY && srcY < this->getInfo().height()); | |
| 268 switch (this->getScanlineOrder()) { | |
| 269 case kTopDown_SkScanlineOrder: | |
| 270 case kNone_SkScanlineOrder: | |
| 271 return srcY; | |
| 272 case kBottomUp_SkScanlineOrder: | |
| 273 return this->dstInfo().height() - srcY - 1; | |
| 274 case kOutOfOrder_SkScanlineOrder: | |
| 275 return get_output_row_interlaced(srcY, this->getInfo().height()); | |
|
scroggo
2015/10/01 14:48:31
It's odd to me that kBottomUp takes the dstInfo in
msarett
2015/10/01 18:14:14
We can use getInfo() in both places. This is prob
| |
| 276 } | |
| 277 } | |
| 278 | |
| 279 void SkCodec::fillIncompleteImage(const SkImageInfo& info, void* dst, size_t row Bytes, | |
| 280 ZeroInitialized zeroInit, int linesRequested, int linesDecoded) { | |
| 281 void* fillDst; | |
| 282 SkImageInfo fillInfo; | |
| 283 const uint32_t fillValue = this->getFillValue(info.colorType(), info.alphaTy pe()); | |
| 284 const int linesRemaining = linesRequested - linesDecoded; | |
| 285 switch (this->getScanlineOrder()) { | |
| 286 case kTopDown_SkScanlineOrder: | |
| 287 case kNone_SkScanlineOrder: | |
| 288 fillDst = SkTAddOffset<void>(dst, linesDecoded * rowBytes); | |
| 289 fillInfo = info.makeWH(info.width(), linesRemaining); | |
| 290 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroInit); | |
| 291 break; | |
| 292 case kBottomUp_SkScanlineOrder: | |
| 293 fillDst = dst; | |
| 294 fillInfo = info.makeWH(info.width(), linesRemaining); | |
| 295 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroInit); | |
| 296 break; | |
| 297 case kOutOfOrder_SkScanlineOrder: | |
| 298 SkASSERT(1 == linesRequested || this->getInfo().height() == linesReq uested); | |
|
scroggo
2015/10/01 14:48:31
Do you need the second half? It seems like if it's
msarett
2015/10/01 18:14:13
I don't understand. linesRequested can be 1 or th
scroggo
2015/10/01 20:48:57
Oh, I think I was confused. This is just to discou
msarett
2015/10/01 22:34:51
Yes!
| |
| 299 fillInfo = info.makeWH(info.width(), 1); | |
| 300 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) { | |
| 301 fillDst = SkTAddOffset<void>(dst, this->nextScanline(srcY) * row Bytes); | |
| 302 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroIni t); | |
| 303 } | |
| 304 break; | |
| 305 } | |
| 306 } | |
| OLD | NEW |