| 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 "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| 11 #include "SkData.h" | 11 #include "SkData.h" |
| 12 #include "SkIcoCodec.h" | 12 #include "SkIcoCodec.h" |
| 13 #include "SkPngCodec.h" | 13 #include "SkPngCodec.h" |
| 14 #include "SkStream.h" | 14 #include "SkStream.h" |
| 15 #include "SkTDArray.h" | 15 #include "SkTDArray.h" |
| 16 #include "SkTSort.h" | 16 #include "SkTSort.h" |
| 17 | 17 |
| 18 #ifdef SK_HAS_PNG_LIBRARY | |
| 19 /* | 18 /* |
| 20 * Checks the start of the stream to see if the image is an Ico or Cur | 19 * Checks the start of the stream to see if the image is an Ico or Cur |
| 21 */ | 20 */ |
| 22 bool SkIcoCodec::IsIco(const void* buffer, size_t bytesRead) { | 21 bool SkIcoCodec::IsIco(const void* buffer, size_t bytesRead) { |
| 23 const char icoSig[] = { '\x00', '\x00', '\x01', '\x00' }; | 22 const char icoSig[] = { '\x00', '\x00', '\x01', '\x00' }; |
| 24 const char curSig[] = { '\x00', '\x00', '\x02', '\x00' }; | 23 const char curSig[] = { '\x00', '\x00', '\x02', '\x00' }; |
| 25 return bytesRead >= sizeof(icoSig) && | 24 return bytesRead >= sizeof(icoSig) && |
| 26 (!memcmp(buffer, icoSig, sizeof(icoSig)) || | 25 (!memcmp(buffer, icoSig, sizeof(icoSig)) || |
| 27 !memcmp(buffer, curSig, sizeof(curSig))); | 26 !memcmp(buffer, curSig, sizeof(curSig))); |
| 28 } | 27 } |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 180 | 179 |
| 181 /* | 180 /* |
| 182 * Creates an instance of the decoder | 181 * Creates an instance of the decoder |
| 183 * Called only by NewFromStream | 182 * Called only by NewFromStream |
| 184 */ | 183 */ |
| 185 SkIcoCodec::SkIcoCodec(int width, int height, const SkEncodedInfo& info, | 184 SkIcoCodec::SkIcoCodec(int width, int height, const SkEncodedInfo& info, |
| 186 SkTArray<SkAutoTDelete<SkCodec>, true>* codecs) | 185 SkTArray<SkAutoTDelete<SkCodec>, true>* codecs) |
| 187 : INHERITED(width, height, info, nullptr) | 186 : INHERITED(width, height, info, nullptr) |
| 188 , fEmbeddedCodecs(codecs) | 187 , fEmbeddedCodecs(codecs) |
| 189 , fCurrScanlineCodec(nullptr) | 188 , fCurrScanlineCodec(nullptr) |
| 190 , fCurrIncrementalCodec(nullptr) | |
| 191 {} | 189 {} |
| 192 | 190 |
| 193 /* | 191 /* |
| 194 * Chooses the best dimensions given the desired scale | 192 * Chooses the best dimensions given the desired scale |
| 195 */ | 193 */ |
| 196 SkISize SkIcoCodec::onGetScaledDimensions(float desiredScale) const { | 194 SkISize SkIcoCodec::onGetScaledDimensions(float desiredScale) const { |
| 197 // We set the dimensions to the largest candidate image by default. | 195 // We set the dimensions to the largest candidate image by default. |
| 198 // Regardless of the scale request, this is the largest image that we | 196 // Regardless of the scale request, this is the largest image that we |
| 199 // will decode. | 197 // will decode. |
| 200 int origWidth = this->getInfo().width(); | 198 int origWidth = this->getInfo().width(); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 while (true) { | 282 while (true) { |
| 285 index = this->chooseCodec(dstInfo.dimensions(), index); | 283 index = this->chooseCodec(dstInfo.dimensions(), index); |
| 286 if (index < 0) { | 284 if (index < 0) { |
| 287 break; | 285 break; |
| 288 } | 286 } |
| 289 | 287 |
| 290 SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index); | 288 SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index); |
| 291 result = embeddedCodec->startScanlineDecode(dstInfo, &options, colorTabl
e, colorCount); | 289 result = embeddedCodec->startScanlineDecode(dstInfo, &options, colorTabl
e, colorCount); |
| 292 if (kSuccess == result) { | 290 if (kSuccess == result) { |
| 293 fCurrScanlineCodec = embeddedCodec; | 291 fCurrScanlineCodec = embeddedCodec; |
| 294 fCurrIncrementalCodec = nullptr; | |
| 295 return result; | 292 return result; |
| 296 } | 293 } |
| 297 | 294 |
| 298 index++; | 295 index++; |
| 299 } | 296 } |
| 300 | 297 |
| 301 SkCodecPrintf("Error: No matching candidate image in ico.\n"); | 298 SkCodecPrintf("Error: No matching candidate image in ico.\n"); |
| 302 return result; | 299 return result; |
| 303 } | 300 } |
| 304 | 301 |
| 305 int SkIcoCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { | 302 int SkIcoCodec::onGetScanlines(void* dst, int count, size_t rowBytes) { |
| 306 SkASSERT(fCurrScanlineCodec); | 303 SkASSERT(fCurrScanlineCodec); |
| 307 return fCurrScanlineCodec->getScanlines(dst, count, rowBytes); | 304 return fCurrScanlineCodec->getScanlines(dst, count, rowBytes); |
| 308 } | 305 } |
| 309 | 306 |
| 310 bool SkIcoCodec::onSkipScanlines(int count) { | 307 bool SkIcoCodec::onSkipScanlines(int count) { |
| 311 SkASSERT(fCurrScanlineCodec); | 308 SkASSERT(fCurrScanlineCodec); |
| 312 return fCurrScanlineCodec->skipScanlines(count); | 309 return fCurrScanlineCodec->skipScanlines(count); |
| 313 } | 310 } |
| 314 | 311 |
| 315 SkCodec::Result SkIcoCodec::onStartIncrementalDecode(const SkImageInfo& dstInfo, | |
| 316 void* pixels, size_t rowBytes, const SkCodec::Options& options, | |
| 317 SkPMColor* colorTable, int* colorCount) { | |
| 318 int index = 0; | |
| 319 while (true) { | |
| 320 index = this->chooseCodec(dstInfo.dimensions(), index); | |
| 321 if (index < 0) { | |
| 322 break; | |
| 323 } | |
| 324 | |
| 325 SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index); | |
| 326 switch (embeddedCodec->startIncrementalDecode(dstInfo, | |
| 327 pixels, rowBytes, &options, colorTable, colorCount)) { | |
| 328 case kSuccess: | |
| 329 fCurrIncrementalCodec = embeddedCodec; | |
| 330 fCurrScanlineCodec = nullptr; | |
| 331 return kSuccess; | |
| 332 case kUnimplemented: | |
| 333 // FIXME: embeddedCodec is a BMP. If scanline decoding would wor
k, | |
| 334 // return kUnimplemented so that SkSampledCodec will fall throug
h | |
| 335 // to use the scanline decoder. | |
| 336 // Note that calling startScanlineDecode will require an extra | |
| 337 // rewind. The embedded codec has an SkMemoryStream, which is | |
| 338 // cheap to rewind, though it will do extra work re-reading the | |
| 339 // header. | |
| 340 // Also note that we pass nullptr for Options. This is because | |
| 341 // Options that are valid for incremental decoding may not be | |
| 342 // valid for scanline decoding. | |
| 343 // Once BMP supports incremental decoding this workaround can go | |
| 344 // away. | |
| 345 if (embeddedCodec->startScanlineDecode(dstInfo, nullptr, | |
| 346 colorTable, colorCount) == kSuccess) { | |
| 347 return kUnimplemented; | |
| 348 } | |
| 349 // Move on to the next embedded codec. | |
| 350 break; | |
| 351 default: | |
| 352 break; | |
| 353 } | |
| 354 | |
| 355 index++; | |
| 356 } | |
| 357 | |
| 358 SkCodecPrintf("Error: No matching candidate image in ico.\n"); | |
| 359 return kInvalidScale; | |
| 360 } | |
| 361 | |
| 362 SkCodec::Result SkIcoCodec::onIncrementalDecode(int* rowsDecoded) { | |
| 363 SkASSERT(fCurrIncrementalCodec); | |
| 364 return fCurrIncrementalCodec->incrementalDecode(rowsDecoded); | |
| 365 } | |
| 366 | |
| 367 SkCodec::SkScanlineOrder SkIcoCodec::onGetScanlineOrder() const { | 312 SkCodec::SkScanlineOrder SkIcoCodec::onGetScanlineOrder() const { |
| 368 // FIXME: This function will possibly return the wrong value if it is called | 313 // FIXME: This function will possibly return the wrong value if it is called |
| 369 // before startScanlineDecode()/startIncrementalDecode(). | 314 // before startScanlineDecode(). |
| 370 if (fCurrScanlineCodec) { | 315 return fCurrScanlineCodec ? fCurrScanlineCodec->getScanlineOrder() : |
| 371 SkASSERT(!fCurrIncrementalCodec); | 316 INHERITED::onGetScanlineOrder(); |
| 372 return fCurrScanlineCodec->getScanlineOrder(); | |
| 373 } | |
| 374 | |
| 375 if (fCurrIncrementalCodec) { | |
| 376 return fCurrIncrementalCodec->getScanlineOrder(); | |
| 377 } | |
| 378 | |
| 379 return INHERITED::onGetScanlineOrder(); | |
| 380 } | 317 } |
| 381 | 318 |
| 382 SkSampler* SkIcoCodec::getSampler(bool createIfNecessary) { | 319 SkSampler* SkIcoCodec::getSampler(bool createIfNecessary) { |
| 383 if (fCurrScanlineCodec) { | 320 return fCurrScanlineCodec ? fCurrScanlineCodec->getSampler(createIfNecessary
) : nullptr; |
| 384 SkASSERT(!fCurrIncrementalCodec); | |
| 385 return fCurrScanlineCodec->getSampler(createIfNecessary); | |
| 386 } | |
| 387 | |
| 388 if (fCurrIncrementalCodec) { | |
| 389 return fCurrIncrementalCodec->getSampler(createIfNecessary); | |
| 390 } | |
| 391 | |
| 392 return nullptr; | |
| 393 } | 321 } |
| 394 #endif // SK_HAS_PNG_LIBRARY | |
| OLD | NEW |