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 "SkBitmap.h" | 8 #include "SkBitmap.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkCodecAnimation.h" | 10 #include "SkCodecAnimation.h" |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 // A lot of users (including Chromium!) ignore the background color,
but we (currently) | 259 // A lot of users (including Chromium!) ignore the background color,
but we (currently) |
260 // use it to fill in the color table if it's less than 256 colors. | 260 // use it to fill in the color table if it's less than 256 colors. |
261 fColorTable.reset(create_color_table(*desc.ColorMap, transIndex, SK_
MaxU32)); | 261 fColorTable.reset(create_color_table(*desc.ColorMap, transIndex, SK_
MaxU32)); |
262 } | 262 } |
263 } | 263 } |
264 | 264 |
265 for (int i = 0; i < gif->ImageCount; i++) { | 265 for (int i = 0; i < gif->ImageCount; i++) { |
266 const SavedImage* image = &gif->SavedImages[i]; | 266 const SavedImage* image = &gif->SavedImages[i]; |
267 const GifImageDesc& desc = image->ImageDesc; | 267 const GifImageDesc& desc = image->ImageDesc; |
268 | 268 |
269 auto& frame = fFrameInfos.push_back(); | 269 auto& frame = fFrameInfos[i]; |
270 // FIXME: Probably want to intersect this with the bounds, just in case. | 270 // FIXME: Probably want to intersect this with the bounds, just in case. |
271 // But then we'll need to make sure we draw the right thing... | 271 // But then we'll need to make sure we draw the right thing... |
272 // i.e. if the top is cut off (desc.Top < 0), we want to start off drawi
ng line -desc.Top | 272 // i.e. if the top is cut off (desc.Top < 0), we want to start off drawi
ng line -desc.Top |
273 // (probably?) | 273 // (probably?) |
274 // Or if we're cut off width-wise, we need to ensure we use the original
row bytes | 274 // Or if we're cut off width-wise, we need to ensure we use the original
row bytes |
275 // (desc.Width) but the corrected width. | 275 // (desc.Width) but the corrected width. |
276 frame.fFrameRect = SkIRect::MakeXYWH(desc.Left, desc.Top, desc.Width, de
sc.Height); | 276 frame.fFrameRect = SkIRect::MakeXYWH(desc.Left, desc.Top, desc.Width, de
sc.Height); |
277 if (!read_graphics_extension(*image, &frame.fTransIndex, &frame.fDuratio
n, | 277 if (!read_graphics_extension(*image, &frame.fTransIndex, &frame.fDuratio
n, |
278 &frame.fDisposalMethod)) { | 278 &frame.fDisposalMethod)) { |
279 frame.fDisposalMethod = SkCodecAnimation::Keep_DisposalMethod; | 279 frame.fDisposalMethod = SkCodecAnimation::Keep_DisposalMethod; |
(...skipping 20 matching lines...) Expand all Loading... |
300 frame.fRequiredFrame = kIndependentFrame; | 300 frame.fRequiredFrame = kIndependentFrame; |
301 } else { | 301 } else { |
302 frame.fRequiredFrame = i - 1; | 302 frame.fRequiredFrame = i - 1; |
303 } | 303 } |
304 break; | 304 break; |
305 } | 305 } |
306 } | 306 } |
307 } | 307 } |
308 } | 308 } |
309 | 309 |
310 size_t SkGifCodec::onGetRequiredFrame(size_t index) { | 310 std::vector<SkCodec::FrameInfo> SkGifCodec::onGetFrameInfo() { |
311 if ((int) index >= fFrameInfos.count()) { | 311 const size_t size = fFrameInfos.size(); |
312 return kIndependentFrame; | 312 if (1 == size) { |
| 313 // As with other formats, return empty set for non-animated |
| 314 // FIXME: But it might be animated, we just haven't received the second
frame? |
| 315 // I suppose we could check the duration? But even that might not be per
fect... |
| 316 return {}; |
313 } | 317 } |
314 | 318 std::vector<FrameInfo> result(size); |
315 return fFrameInfos[index].fRequiredFrame; | 319 for (size_t i = 0; i < size; i++) { |
316 } | 320 result[i] = (FrameInfo) fFrameInfos[i]; |
317 | |
318 size_t SkGifCodec::onGetFrameDuration(size_t index) { | |
319 if ((int) index >= fFrameInfos.count()) { | |
320 return 0; | |
321 } | 321 } |
322 | 322 return result; |
323 return fFrameInfos[index].fDuration; | |
324 } | 323 } |
325 | 324 |
326 bool SkGifCodec::GetDimensions(GifFileType* gif, SkISize* size) { | 325 bool SkGifCodec::GetDimensions(GifFileType* gif, SkISize* size) { |
327 // Get the encoded dimension values for the first frame. Some GIFs have fram
es that are bigger | 326 // Get the encoded dimension values for the first frame. Some GIFs have fram
es that are bigger |
328 // than the screen width and height. For the first frame only, we will expan
d in that case. | 327 // than the screen width and height. For the first frame only, we will expan
d in that case. |
329 SavedImage* image = &gif->SavedImages[0]; | 328 SavedImage* image = &gif->SavedImages[0]; |
330 const GifImageDesc& desc = image->ImageDesc; | 329 const GifImageDesc& desc = image->ImageDesc; |
331 int frameLeft = desc.Left; | 330 int frameLeft = desc.Left; |
332 int frameTop = desc.Top; | 331 int frameTop = desc.Top; |
333 int frameWidth = desc.Width; | 332 int frameWidth = desc.Width; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 && dstInfo.colorType() == kIndex_8_SkColorType) { | 420 && dstInfo.colorType() == kIndex_8_SkColorType) { |
422 // FIXME: It is possible that a later frame can be decoded to index8, if
it does one of the | 421 // FIXME: It is possible that a later frame can be decoded to index8, if
it does one of the |
423 // following: | 422 // following: |
424 // - Covers the entire previous frame | 423 // - Covers the entire previous frame |
425 // - Shares a color table (and transparent index) with any prior frames
that are showing. | 424 // - Shares a color table (and transparent index) with any prior frames
that are showing. |
426 // We must support index8 for the first frame to be backwards compatible
on Android. | 425 // We must support index8 for the first frame to be backwards compatible
on Android. |
427 return gif_error("Cannot decode multiframe gif (except frame 0) as index
8.\n", | 426 return gif_error("Cannot decode multiframe gif (except frame 0) as index
8.\n", |
428 kInvalidConversion); | 427 kInvalidConversion); |
429 } | 428 } |
430 | 429 |
431 if (opts.fFrameOptions && (int) opts.fFrameOptions->fIndex > fFrameInfos.cou
nt()) { | 430 if (opts.fFrameOptions && opts.fFrameOptions->fIndex > fFrameInfos.size()) { |
432 return gif_error("frame index out of range!\n", kInvalidParameters); | 431 return gif_error("frame index out of range!\n", kInvalidParameters); |
433 } | 432 } |
434 | 433 |
435 // Initialize color table and copy to the client if necessary | 434 // Initialize color table and copy to the client if necessary |
436 this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount); | 435 this->initializeColorTable(dstInfo, inputColorPtr, inputColorCount); |
437 return kSuccess; | 436 return kSuccess; |
438 } | 437 } |
439 | 438 |
440 /* | 439 /* |
441 * Initiates the gif decode | 440 * Initiates the gif decode |
(...skipping 17 matching lines...) Expand all Loading... |
459 return kSuccess; | 458 return kSuccess; |
460 } | 459 } |
461 | 460 |
462 // FIXME: This should be SkCodec::Result, probably? | 461 // FIXME: This should be SkCodec::Result, probably? |
463 void SkGifCodec::decodeFrame(const SkImageInfo& dstInfo, void* pixels, size_t ds
tRowBytes, | 462 void SkGifCodec::decodeFrame(const SkImageInfo& dstInfo, void* pixels, size_t ds
tRowBytes, |
464 const Options& opts) { | 463 const Options& opts) { |
465 SkBitmap tmpBm; | 464 SkBitmap tmpBm; |
466 void* dst = pixels; | 465 void* dst = pixels; |
467 | 466 |
468 const size_t frameIndex = opts.fFrameOptions ? opts.fFrameOptions->fIndex :
0; | 467 const size_t frameIndex = opts.fFrameOptions ? opts.fFrameOptions->fIndex :
0; |
469 SkASSERT((int) frameIndex < fFrameInfos.count()); | 468 SkASSERT(frameIndex < fFrameInfos.size()); |
470 const auto& frameInfo = fFrameInfos[frameIndex]; | 469 const auto& frameInfo = fFrameInfos[frameIndex]; |
471 const SkIRect& frameRect = frameInfo.fFrameRect; | 470 const SkIRect& frameRect = frameInfo.fFrameRect; |
472 const bool independent = frameInfo.fRequiredFrame == kIndependentFrame; | 471 const bool independent = frameInfo.fRequiredFrame == kIndependentFrame; |
473 if (!independent) { | 472 if (!independent) { |
474 if (opts.fFrameOptions && !opts.fFrameOptions->fHasPriorFrame) { | 473 if (opts.fFrameOptions && !opts.fFrameOptions->fHasPriorFrame) { |
475 // Decode that frame into pixels. | 474 // Decode that frame into pixels. |
476 Options prevFrameOpts(opts); | 475 Options prevFrameOpts(opts); |
477 MultiFrameOptions prevFrameMultiOpts; | 476 MultiFrameOptions prevFrameMultiOpts; |
478 prevFrameMultiOpts.fIndex = frameInfo.fRequiredFrame; | 477 prevFrameMultiOpts.fIndex = frameInfo.fRequiredFrame; |
479 prevFrameMultiOpts.fHasPriorFrame = false; | 478 prevFrameMultiOpts.fHasPriorFrame = false; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 } | 549 } |
551 } | 550 } |
552 | 551 |
553 // FIXME: This is similar to the implementation for bmp and png. Can we share m
ore code or | 552 // FIXME: This is similar to the implementation for bmp and png. Can we share m
ore code or |
554 // possibly make this non-virtual? | 553 // possibly make this non-virtual? |
555 uint64_t SkGifCodec::onGetFillValue(const SkImageInfo& dstInfo) const { | 554 uint64_t SkGifCodec::onGetFillValue(const SkImageInfo& dstInfo) const { |
556 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); | 555 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); |
557 return get_color_table_fill_value(dstInfo.colorType(), dstInfo.alphaType(),
colorPtr, | 556 return get_color_table_fill_value(dstInfo.colorType(), dstInfo.alphaType(),
colorPtr, |
558 fFillIndex, nullptr); | 557 fFillIndex, nullptr); |
559 } | 558 } |
OLD | NEW |