blob: eac31ef40f05ca28b838c4031b037f8c3e979c6e [file] [log] [blame]
scroggo05245902015-03-25 11:11:52 -07001/*
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#ifndef SkScanlineDecoder_DEFINED
9#define SkScanlineDecoder_DEFINED
10
11#include "SkTypes.h"
12#include "SkTemplates.h"
13#include "SkImageGenerator.h"
14#include "SkImageInfo.h"
15
16class SkScanlineDecoder : public SkNoncopyable {
17public:
msarettc0e80c12015-07-01 06:50:35 -070018 /**
19 * Clean up after reading/skipping scanlines.
20 *
21 * It is possible that not all scanlines will have been read/skipped. In
22 * fact, in the case of subset decodes, it is likely that there will be
23 * scanlines at the bottom of the image that have been ignored.
24 *
25 * Note for implementations: An SkScanlineDecoder will be deleted by (and
26 * therefore *before*) its associated SkCodec, in case the order matters.
27 * However, while the SkCodec base class maintains ownership of the
28 * SkScanlineDecoder, the subclass will be deleted before the scanline
29 * decoder. If this is an issue, detachScanlineDecoder() provides
30 * a means for the subclass to take ownership of the SkScanlineDecoder.
31 */
scroggo05245902015-03-25 11:11:52 -070032 virtual ~SkScanlineDecoder() {}
33
34 /**
35 * Write the next countLines scanlines into dst.
36 *
37 * @param dst Must be non-null, and large enough to hold countLines
38 * scanlines of size rowBytes.
39 * @param countLines Number of lines to write.
40 * @param rowBytes Number of bytes per row. Must be large enough to hold
41 * a scanline based on the SkImageInfo used to create this object.
42 */
43 SkImageGenerator::Result getScanlines(void* dst, int countLines, size_t rowBytes) {
44 if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0
45 || fCurrScanline + countLines > fDstInfo.height()) {
46 return SkImageGenerator::kInvalidParameters;
47 }
48 const SkImageGenerator::Result result = this->onGetScanlines(dst, countLines, rowBytes);
msarettc0e80c12015-07-01 06:50:35 -070049 fCurrScanline += countLines;
scroggo05245902015-03-25 11:11:52 -070050 return result;
51 }
52
53 /**
54 * Skip count scanlines.
55 *
56 * The default version just calls onGetScanlines and discards the dst.
57 * NOTE: If skipped lines are the only lines with alpha, this default
58 * will make reallyHasAlpha return true, when it could have returned
59 * false.
60 */
61 SkImageGenerator::Result skipScanlines(int countLines) {
62 if (fCurrScanline + countLines > fDstInfo.height()) {
63 // Arguably, we could just skip the scanlines which are remaining,
64 // and return kSuccess. We choose to return invalid so the client
65 // can catch their bug.
66 return SkImageGenerator::kInvalidParameters;
67 }
68 const SkImageGenerator::Result result = this->onSkipScanlines(countLines);
msarettc0e80c12015-07-01 06:50:35 -070069 fCurrScanline += countLines;
scroggo05245902015-03-25 11:11:52 -070070 return result;
71 }
72
73 /**
74 * Some images may initially report that they have alpha due to the format
75 * of the encoded data, but then never use any colors which have alpha
76 * less than 100%. This function can be called *after* decoding to
77 * determine if such an image truly had alpha. Calling it before decoding
78 * is undefined.
79 * FIXME: see skbug.com/3582.
80 */
81 bool reallyHasAlpha() const {
82 return this->onReallyHasAlpha();
83 }
84
85protected:
86 SkScanlineDecoder(const SkImageInfo& requested)
87 : fDstInfo(requested)
88 , fCurrScanline(0) {}
89
90 virtual bool onReallyHasAlpha() const { return false; }
91
msarett97fdea62015-04-29 08:17:15 -070092 const SkImageInfo& dstInfo() const { return fDstInfo; }
93
scroggo05245902015-03-25 11:11:52 -070094private:
95 const SkImageInfo fDstInfo;
96 int fCurrScanline;
97
98 // Naive default version just calls onGetScanlines on temp memory.
99 virtual SkImageGenerator::Result onSkipScanlines(int countLines) {
100 SkAutoMalloc storage(fDstInfo.minRowBytes());
101 // Note that we pass 0 to rowBytes so we continue to use the same memory.
102 // Also note that while getScanlines checks that rowBytes is big enough,
103 // onGetScanlines bypasses that check.
104 // Calling the virtual method also means we do not double count
105 // countLines.
106 return this->onGetScanlines(storage.get(), countLines, 0);
107 }
108
109 virtual SkImageGenerator::Result onGetScanlines(void* dst, int countLines,
110 size_t rowBytes) = 0;
111
scroggo05245902015-03-25 11:11:52 -0700112};
113#endif // SkScanlineDecoder_DEFINED