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 int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) { |
211 if (fCurrScanline < 0) { | 227 if (fCurrScanline < 0) { |
212 return kScanlineDecodingNotStarted; | 228 return 0; |
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 (countLines < 0 || 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::outputScanline(int inputScanline) const { |
| 267 SkASSERT(0 <= inputScanline && inputScanline < this->getInfo().height()); |
| 268 switch (this->getScanlineOrder()) { |
| 269 case kTopDown_SkScanlineOrder: |
| 270 case kNone_SkScanlineOrder: |
| 271 return inputScanline; |
| 272 case kBottomUp_SkScanlineOrder: |
| 273 return this->getInfo().height() - inputScanline - 1; |
| 274 case kOutOfOrder_SkScanlineOrder: |
| 275 return get_output_row_interlaced(inputScanline, this->getInfo().heig
ht()); |
| 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); |
| 299 fillInfo = info.makeWH(info.width(), 1); |
| 300 for (int srcY = linesDecoded; srcY < linesRequested; srcY++) { |
| 301 fillDst = SkTAddOffset<void>(dst, this->outputScanline(srcY) * r
owBytes); |
| 302 SkSwizzler::Fill(fillDst, fillInfo, rowBytes, fillValue, zeroIni
t); |
| 303 } |
| 304 break; |
| 305 } |
| 306 } |
OLD | NEW |