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