Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / codec / SkCodec.cpp
1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "include/codec/SkCodec.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkColorSpace.h"
11 #include "include/core/SkData.h"
12 #include "include/core/SkImage.h"
13 #include "include/core/SkStream.h"
14 #include "include/private/SkHalf.h"
15 #include "src/codec/SkCodecPriv.h"
16 #include "src/codec/SkFrameHolder.h"
17
18 // We always include and compile in these BMP codecs
19 #include "src/codec/SkBmpCodec.h"
20 #include "src/codec/SkWbmpCodec.h"
21
22 #ifdef SK_HAS_ANDROID_CODEC
23 #include "include/codec/SkAndroidCodec.h"
24 #endif
25
26 #ifdef SK_HAS_HEIF_LIBRARY
27 #include "src/codec/SkHeifCodec.h"
28 #endif
29
30 #ifdef SK_CODEC_DECODES_JPEG
31 #include "src/codec/SkJpegCodec.h"
32 #endif
33
34 #ifdef SK_CODEC_DECODES_JPEGXL
35 #include "src/codec/SkJpegxlCodec.h"
36 #endif
37
38 #ifdef SK_CODEC_DECODES_PNG
39 #include "src/codec/SkIcoCodec.h"
40 #include "src/codec/SkPngCodec.h"
41 #endif
42
43 #ifdef SK_CODEC_DECODES_RAW
44 #include "src/codec/SkRawCodec.h"
45 #endif
46
47 #ifdef SK_CODEC_DECODES_WEBP
48 #include "src/codec/SkWebpCodec.h"
49 #endif
50
51 #ifdef SK_HAS_WUFFS_LIBRARY
52 #include "src/codec/SkWuffsCodec.h"
53 #elif defined(SK_USE_LIBGIFCODEC)
54 #include "SkGifCodec.h"
55 #endif
56
57 struct DecoderProc {
58     bool (*IsFormat)(const void*, size_t);
59     std::unique_ptr<SkCodec> (*MakeFromStream)(std::unique_ptr<SkStream>, SkCodec::Result*);
60 };
61
62 static std::vector<DecoderProc>* decoders() {
63     static auto* decoders = new std::vector<DecoderProc> {
64     #ifdef SK_CODEC_DECODES_JPEG
65         { SkJpegCodec::IsJpeg, SkJpegCodec::MakeFromStream },
66     #endif
67     #ifdef SK_CODEC_DECODES_WEBP
68         { SkWebpCodec::IsWebp, SkWebpCodec::MakeFromStream },
69     #endif
70     #ifdef SK_HAS_WUFFS_LIBRARY
71         { SkWuffsCodec_IsFormat, SkWuffsCodec_MakeFromStream },
72     #elif defined(SK_USE_LIBGIFCODEC)
73         { SkGifCodec::IsGif, SkGifCodec::MakeFromStream },
74     #endif
75     #ifdef SK_CODEC_DECODES_PNG
76         { SkIcoCodec::IsIco, SkIcoCodec::MakeFromStream },
77     #endif
78         { SkBmpCodec::IsBmp, SkBmpCodec::MakeFromStream },
79         { SkWbmpCodec::IsWbmp, SkWbmpCodec::MakeFromStream },
80     #ifdef SK_CODEC_DECODES_JPEGXL
81         { SkJpegxlCodec::IsJpegxl, SkJpegxlCodec::MakeFromStream },
82     #endif
83     };
84     return decoders;
85 }
86
87 void SkCodec::Register(
88             bool                     (*peek)(const void*, size_t),
89             std::unique_ptr<SkCodec> (*make)(std::unique_ptr<SkStream>, SkCodec::Result*)) {
90     decoders()->push_back(DecoderProc{peek, make});
91 }
92
93 std::unique_ptr<SkCodec> SkCodec::MakeFromStream(
94         std::unique_ptr<SkStream> stream, Result* outResult,
95         SkPngChunkReader* chunkReader, SelectionPolicy selectionPolicy) {
96     Result resultStorage;
97     if (!outResult) {
98         outResult = &resultStorage;
99     }
100
101     if (!stream) {
102         *outResult = kInvalidInput;
103         return nullptr;
104     }
105
106     if (selectionPolicy != SelectionPolicy::kPreferStillImage
107             && selectionPolicy != SelectionPolicy::kPreferAnimation) {
108         *outResult = kInvalidParameters;
109         return nullptr;
110     }
111
112     constexpr size_t bytesToRead = MinBufferedBytesNeeded();
113
114     char buffer[bytesToRead];
115     size_t bytesRead = stream->peek(buffer, bytesToRead);
116
117     // It is also possible to have a complete image less than bytesToRead bytes
118     // (e.g. a 1 x 1 wbmp), meaning peek() would return less than bytesToRead.
119     // Assume that if bytesRead < bytesToRead, but > 0, the stream is shorter
120     // than bytesToRead, so pass that directly to the decoder.
121     // It also is possible the stream uses too small a buffer for peeking, but
122     // we trust the caller to use a large enough buffer.
123
124     if (0 == bytesRead) {
125         // TODO: After implementing peek in CreateJavaOutputStreamAdaptor.cpp, this
126         // printf could be useful to notice failures.
127         // SkCodecPrintf("Encoded image data failed to peek!\n");
128
129         // It is possible the stream does not support peeking, but does support
130         // rewinding.
131         // Attempt to read() and pass the actual amount read to the decoder.
132         bytesRead = stream->read(buffer, bytesToRead);
133         if (!stream->rewind()) {
134             SkCodecPrintf("Encoded image data could not peek or rewind to determine format!\n");
135             *outResult = kCouldNotRewind;
136             return nullptr;
137         }
138     }
139
140     // PNG is special, since we want to be able to supply an SkPngChunkReader.
141     // But this code follows the same pattern as the loop.
142 #ifdef SK_CODEC_DECODES_PNG
143     if (SkPngCodec::IsPng(buffer, bytesRead)) {
144         return SkPngCodec::MakeFromStream(std::move(stream), outResult, chunkReader);
145     }
146 #endif
147
148     for (DecoderProc proc : *decoders()) {
149         if (proc.IsFormat(buffer, bytesRead)) {
150             return proc.MakeFromStream(std::move(stream), outResult);
151         }
152     }
153
154 #ifdef SK_HAS_HEIF_LIBRARY
155     SkEncodedImageFormat format;
156     if (SkHeifCodec::IsSupported(buffer, bytesRead, &format)) {
157         return SkHeifCodec::MakeFromStream(std::move(stream), selectionPolicy,
158                 format, outResult);
159     }
160 #endif
161
162 #ifdef SK_CODEC_DECODES_RAW
163     // Try to treat the input as RAW if all the other checks failed.
164     return SkRawCodec::MakeFromStream(std::move(stream), outResult);
165 #else
166     if (bytesRead < bytesToRead) {
167         *outResult = kIncompleteInput;
168     } else {
169         *outResult = kUnimplemented;
170     }
171
172     return nullptr;
173 #endif
174 }
175
176 std::unique_ptr<SkCodec> SkCodec::MakeFromData(sk_sp<SkData> data, SkPngChunkReader* reader) {
177     if (!data) {
178         return nullptr;
179     }
180     return MakeFromStream(SkMemoryStream::Make(std::move(data)), nullptr, reader);
181 }
182
183 SkCodec::SkCodec(SkEncodedInfo&& info, XformFormat srcFormat, std::unique_ptr<SkStream> stream,
184                  SkEncodedOrigin origin)
185     : fEncodedInfo(std::move(info))
186     , fSrcXformFormat(srcFormat)
187     , fStream(std::move(stream))
188     , fNeedsRewind(false)
189     , fOrigin(origin)
190     , fDstInfo()
191     , fOptions()
192     , fCurrScanline(-1)
193     , fStartedIncrementalDecode(false)
194     , fAndroidCodecHandlesFrameIndex(false)
195 {}
196
197 SkCodec::~SkCodec() {}
198
199 void SkCodec::setSrcXformFormat(XformFormat pixelFormat) {
200     fSrcXformFormat = pixelFormat;
201 }
202
203 bool SkCodec::queryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
204                             SkYUVAPixmapInfo* yuvaPixmapInfo) const {
205     if (!yuvaPixmapInfo) {
206         return false;
207     }
208     return this->onQueryYUVAInfo(supportedDataTypes, yuvaPixmapInfo) &&
209            yuvaPixmapInfo->isSupported(supportedDataTypes);
210 }
211
212 SkCodec::Result SkCodec::getYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) {
213     if (!yuvaPixmaps.isValid()) {
214         return kInvalidInput;
215     }
216     if (!this->rewindIfNeeded()) {
217         return kCouldNotRewind;
218     }
219     return this->onGetYUVAPlanes(yuvaPixmaps);
220 }
221
222 bool SkCodec::conversionSupported(const SkImageInfo& dst, bool srcIsOpaque, bool needsColorXform) {
223     if (!valid_alpha(dst.alphaType(), srcIsOpaque)) {
224         return false;
225     }
226
227     switch (dst.colorType()) {
228         case kRGBA_8888_SkColorType:
229         case kBGRA_8888_SkColorType:
230         case kRGBA_F16_SkColorType:
231             return true;
232         case kRGB_565_SkColorType:
233             return srcIsOpaque;
234         case kGray_8_SkColorType:
235             return SkEncodedInfo::kGray_Color == fEncodedInfo.color() && srcIsOpaque;
236         case kAlpha_8_SkColorType:
237             // conceptually we can convert anything into alpha_8, but we haven't actually coded
238             // all of those other conversions yet.
239             return SkEncodedInfo::kXAlpha_Color == fEncodedInfo.color();
240         default:
241             return false;
242     }
243 }
244
245 bool SkCodec::rewindIfNeeded() {
246     // Store the value of fNeedsRewind so we can update it. Next read will
247     // require a rewind.
248     const bool needsRewind = fNeedsRewind;
249     fNeedsRewind = true;
250     if (!needsRewind) {
251         return true;
252     }
253
254     // startScanlineDecode will need to be called before decoding scanlines.
255     fCurrScanline = -1;
256     // startIncrementalDecode will need to be called before incrementalDecode.
257     fStartedIncrementalDecode = false;
258
259     // Some codecs do not have a stream.  They may hold onto their own data or another codec.
260     // They must handle rewinding themselves.
261     if (fStream && !fStream->rewind()) {
262         return false;
263     }
264
265     return this->onRewind();
266 }
267
268 static SkIRect frame_rect_on_screen(SkIRect frameRect,
269                                     const SkIRect& screenRect) {
270     if (!frameRect.intersect(screenRect)) {
271         return SkIRect::MakeEmpty();
272     }
273
274     return frameRect;
275 }
276
277 bool zero_rect(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes,
278                SkISize srcDimensions, SkIRect prevRect) {
279     const auto dimensions = dstInfo.dimensions();
280     if (dimensions != srcDimensions) {
281         SkRect src = SkRect::Make(srcDimensions);
282         SkRect dst = SkRect::Make(dimensions);
283         SkMatrix map = SkMatrix::RectToRect(src, dst);
284         SkRect asRect = SkRect::Make(prevRect);
285         if (!map.mapRect(&asRect)) {
286             return false;
287         }
288         asRect.roundOut(&prevRect);
289     }
290
291     if (!prevRect.intersect(SkIRect::MakeSize(dimensions))) {
292         // Nothing to zero, due to scaling or bad frame rect.
293         return true;
294     }
295
296     const SkImageInfo info = dstInfo.makeDimensions(prevRect.size());
297     const size_t bpp = dstInfo.bytesPerPixel();
298     const size_t offset = prevRect.x() * bpp + prevRect.y() * rowBytes;
299     void* eraseDst = SkTAddOffset<void>(pixels, offset);
300     SkSampler::Fill(info, eraseDst, rowBytes, SkCodec::kNo_ZeroInitialized);
301     return true;
302 }
303
304 SkCodec::Result SkCodec::handleFrameIndex(const SkImageInfo& info, void* pixels, size_t rowBytes,
305                                           const Options& options, SkAndroidCodec* androidCodec) {
306     if (androidCodec) {
307         // This is never set back to false. If SkAndroidCodec is calling this method, its fCodec
308         // should never call it directly.
309         fAndroidCodecHandlesFrameIndex = true;
310     } else if (fAndroidCodecHandlesFrameIndex) {
311         return kSuccess;
312     }
313
314     if (!this->rewindIfNeeded()) {
315         return kCouldNotRewind;
316     }
317
318     const int index = options.fFrameIndex;
319     if (0 == index) {
320         return this->initializeColorXform(info, fEncodedInfo.alpha(), fEncodedInfo.opaque())
321             ? kSuccess : kInvalidConversion;
322     }
323
324     if (index < 0) {
325         return kInvalidParameters;
326     }
327
328     if (options.fSubset) {
329         // If we add support for this, we need to update the code that zeroes
330         // a kRestoreBGColor frame.
331         return kInvalidParameters;
332     }
333
334     if (index >= this->onGetFrameCount()) {
335         return kIncompleteInput;
336     }
337
338     const auto* frameHolder = this->getFrameHolder();
339     SkASSERT(frameHolder);
340
341     const auto* frame = frameHolder->getFrame(index);
342     SkASSERT(frame);
343
344     const int requiredFrame = frame->getRequiredFrame();
345     if (requiredFrame != kNoFrame) {
346         const SkFrame* preppedFrame = nullptr;
347         if (options.fPriorFrame == kNoFrame) {
348             Result result = kInternalError;
349             if (androidCodec) {
350 #ifdef SK_HAS_ANDROID_CODEC
351                 SkAndroidCodec::AndroidOptions prevFrameOptions(
352                         reinterpret_cast<const SkAndroidCodec::AndroidOptions&>(options));
353                 prevFrameOptions.fFrameIndex = requiredFrame;
354                 result = androidCodec->getAndroidPixels(info, pixels, rowBytes, &prevFrameOptions);
355 #endif
356             } else {
357                 Options prevFrameOptions(options);
358                 prevFrameOptions.fFrameIndex = requiredFrame;
359                 result = this->getPixels(info, pixels, rowBytes, &prevFrameOptions);
360             }
361             if (result != kSuccess) {
362                 return result;
363             }
364             preppedFrame = frameHolder->getFrame(requiredFrame);
365         } else {
366             // Check for a valid frame as a starting point. Alternatively, we could
367             // treat an invalid frame as not providing one, but rejecting it will
368             // make it easier to catch the mistake.
369             if (options.fPriorFrame < requiredFrame || options.fPriorFrame >= index) {
370                 return kInvalidParameters;
371             }
372             preppedFrame = frameHolder->getFrame(options.fPriorFrame);
373         }
374
375         SkASSERT(preppedFrame);
376         switch (preppedFrame->getDisposalMethod()) {
377             case SkCodecAnimation::DisposalMethod::kRestorePrevious:
378                 SkASSERT(options.fPriorFrame != kNoFrame);
379                 return kInvalidParameters;
380             case SkCodecAnimation::DisposalMethod::kRestoreBGColor:
381                 // If a frame after the required frame is provided, there is no
382                 // need to clear, since it must be covered by the desired frame.
383                 // FIXME: If the required frame is kRestoreBGColor, we don't actually need to decode
384                 // it, since we'll just clear it to transparent. Instead, we could decode *its*
385                 // required frame and then clear.
386                 if (preppedFrame->frameId() == requiredFrame) {
387                     SkIRect preppedRect = preppedFrame->frameRect();
388                     if (!zero_rect(info, pixels, rowBytes, this->dimensions(), preppedRect)) {
389                         return kInternalError;
390                     }
391                 }
392                 break;
393             default:
394                 break;
395         }
396     }
397
398     return this->initializeColorXform(info, frame->reportedAlpha(), !frame->hasAlpha())
399         ? kSuccess : kInvalidConversion;
400 }
401
402 SkCodec::Result SkCodec::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
403                                    const Options* options) {
404     if (kUnknown_SkColorType == info.colorType()) {
405         return kInvalidConversion;
406     }
407     if (nullptr == pixels) {
408         return kInvalidParameters;
409     }
410     if (rowBytes < info.minRowBytes()) {
411         return kInvalidParameters;
412     }
413
414     // Default options.
415     Options optsStorage;
416     if (nullptr == options) {
417         options = &optsStorage;
418     } else {
419         if (options->fSubset) {
420             SkIRect subset(*options->fSubset);
421             if (!this->onGetValidSubset(&subset) || subset != *options->fSubset) {
422                 // FIXME: How to differentiate between not supporting subset at all
423                 // and not supporting this particular subset?
424                 return kUnimplemented;
425             }
426         }
427     }
428
429     const Result frameIndexResult = this->handleFrameIndex(info, pixels, rowBytes,
430                                                            *options);
431     if (frameIndexResult != kSuccess) {
432         return frameIndexResult;
433     }
434
435     // FIXME: Support subsets somehow? Note that this works for SkWebpCodec
436     // because it supports arbitrary scaling/subset combinations.
437     if (!this->dimensionsSupported(info.dimensions())) {
438         return kInvalidScale;
439     }
440
441     fDstInfo = info;
442     fOptions = *options;
443
444     // On an incomplete decode, the subclass will specify the number of scanlines that it decoded
445     // successfully.
446     int rowsDecoded = 0;
447     const Result result = this->onGetPixels(info, pixels, rowBytes, *options, &rowsDecoded);
448
449     // A return value of kIncompleteInput indicates a truncated image stream.
450     // In this case, we will fill any uninitialized memory with a default value.
451     // Some subclasses will take care of filling any uninitialized memory on
452     // their own.  They indicate that all of the memory has been filled by
453     // setting rowsDecoded equal to the height.
454     if ((kIncompleteInput == result || kErrorInInput == result) && rowsDecoded != info.height()) {
455         // FIXME: (skbug.com/5772) fillIncompleteImage will fill using the swizzler's width, unless
456         // there is a subset. In that case, it will use the width of the subset. From here, the
457         // subset will only be non-null in the case of SkWebpCodec, but it treats the subset
458         // differenty from the other codecs, and it needs to use the width specified by the info.
459         // Set the subset to null so SkWebpCodec uses the correct width.
460         fOptions.fSubset = nullptr;
461         this->fillIncompleteImage(info, pixels, rowBytes, options->fZeroInitialized, info.height(),
462                 rowsDecoded);
463     }
464
465     return result;
466 }
467
468 std::tuple<sk_sp<SkImage>, SkCodec::Result> SkCodec::getImage(const SkImageInfo& info,
469                                                               const Options* options) {
470     SkBitmap bm;
471     if (!bm.tryAllocPixels(info)) {
472         return {nullptr, kInternalError};
473     }
474
475     Result result = this->getPixels(info, bm.getPixels(), bm.rowBytes(), options);
476     switch (result) {
477         case kSuccess:
478         case kIncompleteInput:
479         case kErrorInInput:
480             bm.setImmutable();
481             return {bm.asImage(), result};
482
483         default: break;
484     }
485     return {nullptr, result};
486 }
487
488 std::tuple<sk_sp<SkImage>, SkCodec::Result> SkCodec::getImage() {
489     return this->getImage(this->getInfo(), nullptr);
490 }
491
492 SkCodec::Result SkCodec::startIncrementalDecode(const SkImageInfo& info, void* pixels,
493         size_t rowBytes, const SkCodec::Options* options) {
494     fStartedIncrementalDecode = false;
495
496     if (kUnknown_SkColorType == info.colorType()) {
497         return kInvalidConversion;
498     }
499     if (nullptr == pixels) {
500         return kInvalidParameters;
501     }
502
503     // Set options.
504     Options optsStorage;
505     if (nullptr == options) {
506         options = &optsStorage;
507     } else {
508         if (options->fSubset) {
509             SkIRect size = SkIRect::MakeSize(info.dimensions());
510             if (!size.contains(*options->fSubset)) {
511                 return kInvalidParameters;
512             }
513
514             const int top = options->fSubset->top();
515             const int bottom = options->fSubset->bottom();
516             if (top < 0 || top >= info.height() || top >= bottom || bottom > info.height()) {
517                 return kInvalidParameters;
518             }
519         }
520     }
521
522     const Result frameIndexResult = this->handleFrameIndex(info, pixels, rowBytes,
523                                                            *options);
524     if (frameIndexResult != kSuccess) {
525         return frameIndexResult;
526     }
527
528     if (!this->dimensionsSupported(info.dimensions())) {
529         return kInvalidScale;
530     }
531
532     fDstInfo = info;
533     fOptions = *options;
534
535     const Result result = this->onStartIncrementalDecode(info, pixels, rowBytes, fOptions);
536     if (kSuccess == result) {
537         fStartedIncrementalDecode = true;
538     } else if (kUnimplemented == result) {
539         // FIXME: This is temporarily necessary, until we transition SkCodec
540         // implementations from scanline decoding to incremental decoding.
541         // SkAndroidCodec will first attempt to use incremental decoding, but
542         // will fall back to scanline decoding if incremental returns
543         // kUnimplemented. rewindIfNeeded(), above, set fNeedsRewind to true
544         // (after potentially rewinding), but we do not want the next call to
545         // startScanlineDecode() to do a rewind.
546         fNeedsRewind = false;
547     }
548     return result;
549 }
550
551
552 SkCodec::Result SkCodec::startScanlineDecode(const SkImageInfo& info,
553         const SkCodec::Options* options) {
554     // Reset fCurrScanline in case of failure.
555     fCurrScanline = -1;
556
557     // Set options.
558     Options optsStorage;
559     if (nullptr == options) {
560         options = &optsStorage;
561     } else if (options->fSubset) {
562         SkIRect size = SkIRect::MakeSize(info.dimensions());
563         if (!size.contains(*options->fSubset)) {
564             return kInvalidInput;
565         }
566
567         // We only support subsetting in the x-dimension for scanline decoder.
568         // Subsetting in the y-dimension can be accomplished using skipScanlines().
569         if (options->fSubset->top() != 0 || options->fSubset->height() != info.height()) {
570             return kInvalidInput;
571         }
572     }
573
574     // Scanline decoding only supports decoding the first frame.
575     if (options->fFrameIndex != 0) {
576         return kUnimplemented;
577     }
578
579     // The void* dst and rowbytes in handleFrameIndex or only used for decoding prior
580     // frames, which is not supported here anyway, so it is safe to pass nullptr/0.
581     const Result frameIndexResult = this->handleFrameIndex(info, nullptr, 0, *options);
582     if (frameIndexResult != kSuccess) {
583         return frameIndexResult;
584     }
585
586     // FIXME: Support subsets somehow?
587     if (!this->dimensionsSupported(info.dimensions())) {
588         return kInvalidScale;
589     }
590
591     const Result result = this->onStartScanlineDecode(info, *options);
592     if (result != SkCodec::kSuccess) {
593         return result;
594     }
595
596     // FIXME: See startIncrementalDecode. That method set fNeedsRewind to false
597     // so that when onStartScanlineDecode calls rewindIfNeeded it would not
598     // rewind. But it also relies on that call to rewindIfNeeded to set
599     // fNeedsRewind to true for future decodes. When
600     // fAndroidCodecHandlesFrameIndex is true, that call to rewindIfNeeded is
601     // skipped, so this method sets it back to true.
602     SkASSERT(fAndroidCodecHandlesFrameIndex || fNeedsRewind);
603     fNeedsRewind = true;
604
605     fCurrScanline = 0;
606     fDstInfo = info;
607     fOptions = *options;
608     return kSuccess;
609 }
610
611 int SkCodec::getScanlines(void* dst, int countLines, size_t rowBytes) {
612     if (fCurrScanline < 0) {
613         return 0;
614     }
615
616     SkASSERT(!fDstInfo.isEmpty());
617     if (countLines <= 0 || fCurrScanline + countLines > fDstInfo.height()) {
618         return 0;
619     }
620
621     const int linesDecoded = this->onGetScanlines(dst, countLines, rowBytes);
622     if (linesDecoded < countLines) {
623         this->fillIncompleteImage(this->dstInfo(), dst, rowBytes, this->options().fZeroInitialized,
624                 countLines, linesDecoded);
625     }
626     fCurrScanline += countLines;
627     return linesDecoded;
628 }
629
630 bool SkCodec::skipScanlines(int countLines) {
631     if (fCurrScanline < 0) {
632         return false;
633     }
634
635     SkASSERT(!fDstInfo.isEmpty());
636     if (countLines < 0 || fCurrScanline + countLines > fDstInfo.height()) {
637         // Arguably, we could just skip the scanlines which are remaining,
638         // and return true. We choose to return false so the client
639         // can catch their bug.
640         return false;
641     }
642
643     bool result = this->onSkipScanlines(countLines);
644     fCurrScanline += countLines;
645     return result;
646 }
647
648 int SkCodec::outputScanline(int inputScanline) const {
649     SkASSERT(0 <= inputScanline && inputScanline < fEncodedInfo.height());
650     return this->onOutputScanline(inputScanline);
651 }
652
653 int SkCodec::onOutputScanline(int inputScanline) const {
654     switch (this->getScanlineOrder()) {
655         case kTopDown_SkScanlineOrder:
656             return inputScanline;
657         case kBottomUp_SkScanlineOrder:
658             return fEncodedInfo.height() - inputScanline - 1;
659         default:
660             // This case indicates an interlaced gif and is implemented by SkGifCodec.
661             SkASSERT(false);
662             return 0;
663     }
664 }
665
666 void SkCodec::fillIncompleteImage(const SkImageInfo& info, void* dst, size_t rowBytes,
667         ZeroInitialized zeroInit, int linesRequested, int linesDecoded) {
668     if (kYes_ZeroInitialized == zeroInit) {
669         return;
670     }
671
672     const int linesRemaining = linesRequested - linesDecoded;
673     SkSampler* sampler = this->getSampler(false);
674
675     const int fillWidth = sampler          ? sampler->fillWidth()      :
676                           fOptions.fSubset ? fOptions.fSubset->width() :
677                                              info.width()              ;
678     void* fillDst = this->getScanlineOrder() == kBottomUp_SkScanlineOrder ? dst :
679                         SkTAddOffset<void>(dst, linesDecoded * rowBytes);
680     const auto fillInfo = info.makeWH(fillWidth, linesRemaining);
681     SkSampler::Fill(fillInfo, fillDst, rowBytes, kNo_ZeroInitialized);
682 }
683
684 bool sk_select_xform_format(SkColorType colorType, bool forColorTable,
685                             skcms_PixelFormat* outFormat) {
686     SkASSERT(outFormat);
687
688     switch (colorType) {
689         case kRGBA_8888_SkColorType:
690             *outFormat = skcms_PixelFormat_RGBA_8888;
691             break;
692         case kBGRA_8888_SkColorType:
693             *outFormat = skcms_PixelFormat_BGRA_8888;
694             break;
695         case kRGB_565_SkColorType:
696             if (forColorTable) {
697 #ifdef SK_PMCOLOR_IS_RGBA
698                 *outFormat = skcms_PixelFormat_RGBA_8888;
699 #else
700                 *outFormat = skcms_PixelFormat_BGRA_8888;
701 #endif
702                 break;
703             }
704             *outFormat = skcms_PixelFormat_BGR_565;
705             break;
706         case kRGBA_F16_SkColorType:
707             *outFormat = skcms_PixelFormat_RGBA_hhhh;
708             break;
709         case kGray_8_SkColorType:
710             *outFormat = skcms_PixelFormat_G_8;
711             break;
712         default:
713             return false;
714     }
715     return true;
716 }
717
718 bool SkCodec::initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha encodedAlpha,
719                                    bool srcIsOpaque) {
720     fXformTime = kNo_XformTime;
721     bool needsColorXform = false;
722     if (this->usesColorXform()) {
723         if (kRGBA_F16_SkColorType == dstInfo.colorType()) {
724             needsColorXform = true;
725             if (dstInfo.colorSpace()) {
726                 dstInfo.colorSpace()->toProfile(&fDstProfile);
727             } else {
728                 // Use the srcProfile to avoid conversion.
729                 const auto* srcProfile = fEncodedInfo.profile();
730                 fDstProfile = srcProfile ? *srcProfile : *skcms_sRGB_profile();
731             }
732         } else if (dstInfo.colorSpace()) {
733             dstInfo.colorSpace()->toProfile(&fDstProfile);
734             const auto* srcProfile = fEncodedInfo.profile();
735             if (!srcProfile) {
736                 srcProfile = skcms_sRGB_profile();
737             }
738             if (!skcms_ApproximatelyEqualProfiles(srcProfile, &fDstProfile) ) {
739                 needsColorXform = true;
740             }
741         }
742     }
743
744     if (!this->conversionSupported(dstInfo, srcIsOpaque, needsColorXform)) {
745         return false;
746     }
747
748     if (needsColorXform) {
749         fXformTime = SkEncodedInfo::kPalette_Color != fEncodedInfo.color()
750                           || kRGBA_F16_SkColorType == dstInfo.colorType()
751                 ? kDecodeRow_XformTime : kPalette_XformTime;
752         if (!sk_select_xform_format(dstInfo.colorType(), fXformTime == kPalette_XformTime,
753                                     &fDstXformFormat)) {
754             return false;
755         }
756         if (encodedAlpha == SkEncodedInfo::kUnpremul_Alpha
757                 && dstInfo.alphaType() == kPremul_SkAlphaType) {
758             fDstXformAlphaFormat = skcms_AlphaFormat_PremulAsEncoded;
759         } else {
760             fDstXformAlphaFormat = skcms_AlphaFormat_Unpremul;
761         }
762     }
763     return true;
764 }
765
766 void SkCodec::applyColorXform(void* dst, const void* src, int count) const {
767     // It is okay for srcProfile to be null. This will use sRGB.
768     const auto* srcProfile = fEncodedInfo.profile();
769     SkAssertResult(skcms_Transform(src, fSrcXformFormat, skcms_AlphaFormat_Unpremul, srcProfile,
770                                    dst, fDstXformFormat, fDstXformAlphaFormat, &fDstProfile,
771                                    count));
772 }
773
774 std::vector<SkCodec::FrameInfo> SkCodec::getFrameInfo() {
775     const int frameCount = this->getFrameCount();
776     SkASSERT(frameCount >= 0);
777     if (frameCount <= 0) {
778         return std::vector<FrameInfo>{};
779     }
780
781     if (frameCount == 1 && !this->onGetFrameInfo(0, nullptr)) {
782         // Not animated.
783         return std::vector<FrameInfo>{};
784     }
785
786     std::vector<FrameInfo> result(frameCount);
787     for (int i = 0; i < frameCount; ++i) {
788         SkAssertResult(this->onGetFrameInfo(i, &result[i]));
789     }
790     return result;
791 }
792
793 const char* SkCodec::ResultToString(Result result) {
794     switch (result) {
795         case kSuccess:
796             return "success";
797         case kIncompleteInput:
798             return "incomplete input";
799         case kErrorInInput:
800             return "error in input";
801         case kInvalidConversion:
802             return "invalid conversion";
803         case kInvalidScale:
804             return "invalid scale";
805         case kInvalidParameters:
806             return "invalid parameters";
807         case kInvalidInput:
808             return "invalid input";
809         case kCouldNotRewind:
810             return "could not rewind";
811         case kInternalError:
812             return "internal error";
813         case kUnimplemented:
814             return "unimplemented";
815         default:
816             SkASSERT(false);
817             return "bogus result value";
818     }
819 }
820
821 void SkFrame::fillIn(SkCodec::FrameInfo* frameInfo, bool fullyReceived) const {
822     SkASSERT(frameInfo);
823
824     frameInfo->fRequiredFrame = fRequiredFrame;
825     frameInfo->fDuration = fDuration;
826     frameInfo->fFullyReceived = fullyReceived;
827     frameInfo->fAlphaType = fHasAlpha ? kUnpremul_SkAlphaType
828                                       : kOpaque_SkAlphaType;
829     frameInfo->fHasAlphaWithinBounds = this->reportedAlpha() != SkEncodedInfo::kOpaque_Alpha;
830     frameInfo->fDisposalMethod = fDisposalMethod;
831     frameInfo->fBlend = fBlend;
832     frameInfo->fFrameRect = fRect;
833 }
834
835 static bool independent(const SkFrame& frame) {
836     return frame.getRequiredFrame() == SkCodec::kNoFrame;
837 }
838
839 static bool restore_bg(const SkFrame& frame) {
840     return frame.getDisposalMethod() == SkCodecAnimation::DisposalMethod::kRestoreBGColor;
841 }
842
843 // As its name suggests, this method computes a frame's alpha (e.g. completely
844 // opaque, unpremul, binary) and its required frame (a preceding frame that
845 // this frame depends on, to draw the complete image at this frame's point in
846 // the animation stream), and calls this frame's setter methods with that
847 // computed information.
848 //
849 // A required frame of kNoFrame means that this frame is independent: drawing
850 // the complete image at this frame's point in the animation stream does not
851 // require first preparing the pixel buffer based on another frame. Instead,
852 // drawing can start from an uninitialized pixel buffer.
853 //
854 // "Uninitialized" is from the SkCodec's caller's point of view. In the SkCodec
855 // implementation, for independent frames, first party Skia code (in src/codec)
856 // will typically fill the buffer with a uniform background color (e.g.
857 // transparent black) before calling into third party codec-specific code (e.g.
858 // libjpeg or libpng). Pixels outside of the frame's rect will remain this
859 // background color after drawing this frame. For incomplete decodes, pixels
860 // inside that rect may be (at least temporarily) set to that background color.
861 // In an incremental decode, later passes may then overwrite that background
862 // color.
863 //
864 // Determining kNoFrame or otherwise involves testing a number of conditions
865 // sequentially. The first satisfied condition results in setting the required
866 // frame to kNoFrame (an "INDx" condition) or to a non-negative frame number (a
867 // "DEPx" condition), and the function returning early. Those "INDx" and "DEPx"
868 // labels also map to comments in the function body.
869 //
870 //  - IND1: this frame is the first frame.
871 //  - IND2: this frame fills out the whole image, and it is completely opaque
872 //          or it overwrites (not blends with) the previous frame.
873 //  - IND3: all preceding frames' disposals are kRestorePrevious.
874 //  - IND4: the prevFrame's disposal is kRestoreBGColor, and it fills out the
875 //          whole image or it is itself otherwise independent.
876 //  - DEP5: this frame reports alpha (it is not completely opaque) and it
877 //          blends with (not overwrites) the previous frame.
878 //  - IND6: this frame's rect covers the rects of all preceding frames back to
879 //          and including the most recent independent frame before this frame.
880 //  - DEP7: unconditional.
881 //
882 // The "prevFrame" variable initially points to the previous frame (also known
883 // as the prior frame), but that variable may iterate further backwards over
884 // the course of this computation.
885 void SkFrameHolder::setAlphaAndRequiredFrame(SkFrame* frame) {
886     const bool reportsAlpha = frame->reportedAlpha() != SkEncodedInfo::kOpaque_Alpha;
887     const auto screenRect = SkIRect::MakeWH(fScreenWidth, fScreenHeight);
888     const auto frameRect = frame_rect_on_screen(frame->frameRect(), screenRect);
889
890     const int i = frame->frameId();
891     if (0 == i) {
892         frame->setHasAlpha(reportsAlpha || frameRect != screenRect);
893         frame->setRequiredFrame(SkCodec::kNoFrame);  // IND1
894         return;
895     }
896
897
898     const bool blendWithPrevFrame = frame->getBlend() == SkCodecAnimation::Blend::kSrcOver;
899     if ((!reportsAlpha || !blendWithPrevFrame) && frameRect == screenRect) {
900         frame->setHasAlpha(reportsAlpha);
901         frame->setRequiredFrame(SkCodec::kNoFrame);  // IND2
902         return;
903     }
904
905     const SkFrame* prevFrame = this->getFrame(i-1);
906     while (prevFrame->getDisposalMethod() == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
907         const int prevId = prevFrame->frameId();
908         if (0 == prevId) {
909             frame->setHasAlpha(true);
910             frame->setRequiredFrame(SkCodec::kNoFrame);  // IND3
911             return;
912         }
913
914         prevFrame = this->getFrame(prevId - 1);
915     }
916
917     const bool clearPrevFrame = restore_bg(*prevFrame);
918     auto prevFrameRect = frame_rect_on_screen(prevFrame->frameRect(), screenRect);
919
920     if (clearPrevFrame) {
921         if (prevFrameRect == screenRect || independent(*prevFrame)) {
922             frame->setHasAlpha(true);
923             frame->setRequiredFrame(SkCodec::kNoFrame);  // IND4
924             return;
925         }
926     }
927
928     if (reportsAlpha && blendWithPrevFrame) {
929         // Note: We could be more aggressive here. If prevFrame clears
930         // to background color and covers its required frame (and that
931         // frame is independent), prevFrame could be marked independent.
932         // Would this extra complexity be worth it?
933         frame->setRequiredFrame(prevFrame->frameId());  // DEP5
934         frame->setHasAlpha(prevFrame->hasAlpha() || clearPrevFrame);
935         return;
936     }
937
938     while (frameRect.contains(prevFrameRect)) {
939         const int prevRequiredFrame = prevFrame->getRequiredFrame();
940         if (prevRequiredFrame == SkCodec::kNoFrame) {
941             frame->setRequiredFrame(SkCodec::kNoFrame);  // IND6
942             frame->setHasAlpha(true);
943             return;
944         }
945
946         prevFrame = this->getFrame(prevRequiredFrame);
947         prevFrameRect = frame_rect_on_screen(prevFrame->frameRect(), screenRect);
948     }
949
950     frame->setRequiredFrame(prevFrame->frameId());  // DEP7
951     if (restore_bg(*prevFrame)) {
952         frame->setHasAlpha(true);
953         return;
954     }
955     SkASSERT(prevFrame->getDisposalMethod() == SkCodecAnimation::DisposalMethod::kKeep);
956     frame->setHasAlpha(prevFrame->hasAlpha() || (reportsAlpha && !blendWithPrevFrame));
957 }
958