• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #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 
16 class SkScanlineDecoder : public SkNoncopyable {
17 public:
18     // Note for implementations: An SkScanlineDecoder will be deleted by (and
19     // therefore *before*) its associated SkCodec, in case the order matters.
~SkScanlineDecoder()20     virtual ~SkScanlineDecoder() {}
21 
22     /**
23      *  Write the next countLines scanlines into dst.
24      *
25      *  @param dst Must be non-null, and large enough to hold countLines
26      *      scanlines of size rowBytes.
27      *  @param countLines Number of lines to write.
28      *  @param rowBytes Number of bytes per row. Must be large enough to hold
29      *      a scanline based on the SkImageInfo used to create this object.
30      */
getScanlines(void * dst,int countLines,size_t rowBytes)31     SkImageGenerator::Result getScanlines(void* dst, int countLines, size_t rowBytes) {
32         if ((rowBytes < fDstInfo.minRowBytes() && countLines > 1 ) || countLines <= 0
33                 || fCurrScanline + countLines > fDstInfo.height()) {
34             return SkImageGenerator::kInvalidParameters;
35         }
36         const SkImageGenerator::Result result = this->onGetScanlines(dst, countLines, rowBytes);
37         this->checkForFinish(countLines);
38         return result;
39     }
40 
41     /**
42      *  Skip count scanlines.
43      *
44      *  The default version just calls onGetScanlines and discards the dst.
45      *  NOTE: If skipped lines are the only lines with alpha, this default
46      *  will make reallyHasAlpha return true, when it could have returned
47      *  false.
48      */
skipScanlines(int countLines)49     SkImageGenerator::Result skipScanlines(int countLines) {
50         if (fCurrScanline + countLines > fDstInfo.height()) {
51             // Arguably, we could just skip the scanlines which are remaining,
52             // and return kSuccess. We choose to return invalid so the client
53             // can catch their bug.
54             return SkImageGenerator::kInvalidParameters;
55         }
56         const SkImageGenerator::Result result = this->onSkipScanlines(countLines);
57         this->checkForFinish(countLines);
58         return result;
59     }
60 
61     /**
62      *  Some images may initially report that they have alpha due to the format
63      *  of the encoded data, but then never use any colors which have alpha
64      *  less than 100%. This function can be called *after* decoding to
65      *  determine if such an image truly had alpha. Calling it before decoding
66      *  is undefined.
67      *  FIXME: see skbug.com/3582.
68      */
reallyHasAlpha()69     bool reallyHasAlpha() const {
70         return this->onReallyHasAlpha();
71     }
72 
73 protected:
SkScanlineDecoder(const SkImageInfo & requested)74     SkScanlineDecoder(const SkImageInfo& requested)
75         : fDstInfo(requested)
76         , fCurrScanline(0) {}
77 
onReallyHasAlpha()78     virtual bool onReallyHasAlpha() const { return false; }
79 
dstInfo()80     const SkImageInfo& dstInfo() const { return fDstInfo; }
81 
82 private:
83     const SkImageInfo   fDstInfo;
84     int                 fCurrScanline;
85 
86     // Naive default version just calls onGetScanlines on temp memory.
onSkipScanlines(int countLines)87     virtual SkImageGenerator::Result onSkipScanlines(int countLines) {
88         SkAutoMalloc storage(fDstInfo.minRowBytes());
89         // Note that we pass 0 to rowBytes so we continue to use the same memory.
90         // Also note that while getScanlines checks that rowBytes is big enough,
91         // onGetScanlines bypasses that check.
92         // Calling the virtual method also means we do not double count
93         // countLines.
94         return this->onGetScanlines(storage.get(), countLines, 0);
95     }
96 
97     virtual SkImageGenerator::Result onGetScanlines(void* dst, int countLines,
98                                                     size_t rowBytes) = 0;
99 
100     /**
101      *  Called after any set of scanlines read/skipped. Updates fCurrScanline,
102      *  and, if we are at the end, calls onFinish().
103      */
checkForFinish(int countLines)104     void checkForFinish(int countLines) {
105         fCurrScanline += countLines;
106         if (fCurrScanline >= fDstInfo.height()) {
107             this->onFinish();
108         }
109     }
110 
111     /**
112      *  This function will be called after reading/skipping all scanlines to do
113      *  any necessary cleanups.
114      */
onFinish()115     virtual void onFinish() {} // Default does nothing.
116 };
117 #endif // SkScanlineDecoder_DEFINED
118