Coverage Report

Created: 2021-08-22 09:07

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