Home | History | Annotate | Download | only in codec
      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 SkCodec_DEFINED
      9 #define SkCodec_DEFINED
     10 
     11 #include "../private/SkTemplates.h"
     12 #include "SkColor.h"
     13 #include "SkEncodedFormat.h"
     14 #include "SkImageInfo.h"
     15 #include "SkSize.h"
     16 #include "SkStream.h"
     17 #include "SkTypes.h"
     18 
     19 class SkData;
     20 class SkPngChunkReader;
     21 class SkSampler;
     22 
     23 /**
     24  *  Abstraction layer directly on top of an image codec.
     25  */
     26 class SkCodec : SkNoncopyable {
     27 public:
     28     /**
     29      *  Minimum number of bytes that must be buffered in SkStream input.
     30      *
     31      *  An SkStream passed to NewFromStream must be able to use this many
     32      *  bytes to determine the image type. Then the same SkStream must be
     33      *  passed to the correct decoder to read from the beginning.
     34      *
     35      *  This can be accomplished by implementing peek() to support peeking
     36      *  this many bytes, or by implementing rewind() to be able to rewind()
     37      *  after reading this many bytes.
     38      */
     39     static size_t MinBufferedBytesNeeded();
     40 
     41     /**
     42      *  If this stream represents an encoded image that we know how to decode,
     43      *  return an SkCodec that can decode it. Otherwise return NULL.
     44      *
     45      *  As stated above, this call must be able to peek or read
     46      *  MinBufferedBytesNeeded to determine the correct format, and then start
     47      *  reading from the beginning. First it will attempt to peek, and it
     48      *  assumes that if less than MinBufferedBytesNeeded bytes (but more than
     49      *  zero) are returned, this is because the stream is shorter than this,
     50      *  so falling back to reading would not provide more data. If peek()
     51      *  returns zero bytes, this call will instead attempt to read(). This
     52      *  will require that the stream can be rewind()ed.
     53      *
     54      *  If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
     55      *  the image is a png.
     56      *
     57      *  If the SkPngChunkReader is not NULL then:
     58      *      If the image is not a PNG, the SkPngChunkReader will be ignored.
     59      *      If the image is a PNG, the SkPngChunkReader will be reffed.
     60      *      If the PNG has unknown chunks, the SkPngChunkReader will be used
     61      *      to handle these chunks.  SkPngChunkReader will be called to read
     62      *      any unknown chunk at any point during the creation of the codec
     63      *      or the decode.  Note that if SkPngChunkReader fails to read a
     64      *      chunk, this could result in a failure to create the codec or a
     65      *      failure to decode the image.
     66      *      If the PNG does not contain unknown chunks, the SkPngChunkReader
     67      *      will not be used or modified.
     68      *
     69      *  If NULL is returned, the stream is deleted immediately. Otherwise, the
     70      *  SkCodec takes ownership of it, and will delete it when done with it.
     71      */
     72     static SkCodec* NewFromStream(SkStream*, SkPngChunkReader* = NULL);
     73 
     74     /**
     75      *  If this data represents an encoded image that we know how to decode,
     76      *  return an SkCodec that can decode it. Otherwise return NULL.
     77      *
     78      *  If the SkPngChunkReader is not NULL then:
     79      *      If the image is not a PNG, the SkPngChunkReader will be ignored.
     80      *      If the image is a PNG, the SkPngChunkReader will be reffed.
     81      *      If the PNG has unknown chunks, the SkPngChunkReader will be used
     82      *      to handle these chunks.  SkPngChunkReader will be called to read
     83      *      any unknown chunk at any point during the creation of the codec
     84      *      or the decode.  Note that if SkPngChunkReader fails to read a
     85      *      chunk, this could result in a failure to create the codec or a
     86      *      failure to decode the image.
     87      *      If the PNG does not contain unknown chunks, the SkPngChunkReader
     88      *      will not be used or modified.
     89      *
     90      *  Will take a ref if it returns a codec, else will not affect the data.
     91      */
     92     static SkCodec* NewFromData(SkData*, SkPngChunkReader* = NULL);
     93 
     94     virtual ~SkCodec();
     95 
     96     /**
     97      *  Return the ImageInfo associated with this codec.
     98      */
     99     const SkImageInfo& getInfo() const { return fSrcInfo; }
    100 
    101     /**
    102      *  Return a size that approximately supports the desired scale factor.
    103      *  The codec may not be able to scale efficiently to the exact scale
    104      *  factor requested, so return a size that approximates that scale.
    105      *  The returned value is the codec's suggestion for the closest valid
    106      *  scale that it can natively support
    107      */
    108     SkISize getScaledDimensions(float desiredScale) const {
    109         // Negative and zero scales are errors.
    110         SkASSERT(desiredScale > 0.0f);
    111         if (desiredScale <= 0.0f) {
    112             return SkISize::Make(0, 0);
    113         }
    114 
    115         // Upscaling is not supported. Return the original size if the client
    116         // requests an upscale.
    117         if (desiredScale >= 1.0f) {
    118             return this->getInfo().dimensions();
    119         }
    120         return this->onGetScaledDimensions(desiredScale);
    121     }
    122 
    123     /**
    124      *  Return (via desiredSubset) a subset which can decoded from this codec,
    125      *  or false if this codec cannot decode subsets or anything similar to
    126      *  desiredSubset.
    127      *
    128      *  @param desiredSubset In/out parameter. As input, a desired subset of
    129      *      the original bounds (as specified by getInfo). If true is returned,
    130      *      desiredSubset may have been modified to a subset which is
    131      *      supported. Although a particular change may have been made to
    132      *      desiredSubset to create something supported, it is possible other
    133      *      changes could result in a valid subset.
    134      *      If false is returned, desiredSubset's value is undefined.
    135      *  @return true if this codec supports decoding desiredSubset (as
    136      *      returned, potentially modified)
    137      */
    138     bool getValidSubset(SkIRect* desiredSubset) const {
    139         return this->onGetValidSubset(desiredSubset);
    140     }
    141 
    142     /**
    143      *  Format of the encoded data.
    144      */
    145     SkEncodedFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
    146 
    147     /**
    148      *  Used to describe the result of a call to getPixels().
    149      *
    150      *  Result is the union of possible results from subclasses.
    151      */
    152     enum Result {
    153         /**
    154          *  General return value for success.
    155          */
    156         kSuccess,
    157         /**
    158          *  The input is incomplete. A partial image was generated.
    159          */
    160         kIncompleteInput,
    161         /**
    162          *  The generator cannot convert to match the request, ignoring
    163          *  dimensions.
    164          */
    165         kInvalidConversion,
    166         /**
    167          *  The generator cannot scale to requested size.
    168          */
    169         kInvalidScale,
    170         /**
    171          *  Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes
    172          *  too small, etc.
    173          */
    174         kInvalidParameters,
    175         /**
    176          *  The input did not contain a valid image.
    177          */
    178         kInvalidInput,
    179         /**
    180          *  Fulfilling this request requires rewinding the input, which is not
    181          *  supported for this input.
    182          */
    183         kCouldNotRewind,
    184         /**
    185          *  This method is not implemented by this codec.
    186          *  FIXME: Perhaps this should be kUnsupported?
    187          */
    188         kUnimplemented,
    189     };
    190 
    191     /**
    192      *  Whether or not the memory passed to getPixels is zero initialized.
    193      */
    194     enum ZeroInitialized {
    195         /**
    196          *  The memory passed to getPixels is zero initialized. The SkCodec
    197          *  may take advantage of this by skipping writing zeroes.
    198          */
    199         kYes_ZeroInitialized,
    200         /**
    201          *  The memory passed to getPixels has not been initialized to zero,
    202          *  so the SkCodec must write all zeroes to memory.
    203          *
    204          *  This is the default. It will be used if no Options struct is used.
    205          */
    206         kNo_ZeroInitialized,
    207     };
    208 
    209     /**
    210      *  Additional options to pass to getPixels.
    211      */
    212     struct Options {
    213         Options()
    214             : fZeroInitialized(kNo_ZeroInitialized)
    215             , fSubset(NULL)
    216         {}
    217 
    218         ZeroInitialized fZeroInitialized;
    219         /**
    220          *  If not NULL, represents a subset of the original image to decode.
    221          *  Must be within the bounds returned by getInfo().
    222          *  If the EncodedFormat is kWEBP_SkEncodedFormat (the only one which
    223          *  currently supports subsets), the top and left values must be even.
    224          *
    225          *  In getPixels, we will attempt to decode the exact rectangular
    226          *  subset specified by fSubset.
    227          *
    228          *  In a scanline decode, it does not make sense to specify a subset
    229          *  top or subset height, since the client already controls which rows
    230          *  to get and which rows to skip.  During scanline decodes, we will
    231          *  require that the subset top be zero and the subset height be equal
    232          *  to the full height.  We will, however, use the values of
    233          *  subset left and subset width to decode partial scanlines on calls
    234          *  to getScanlines().
    235          */
    236         SkIRect*        fSubset;
    237     };
    238 
    239     /**
    240      *  Decode into the given pixels, a block of memory of size at
    241      *  least (info.fHeight - 1) * rowBytes + (info.fWidth *
    242      *  bytesPerPixel)
    243      *
    244      *  Repeated calls to this function should give the same results,
    245      *  allowing the PixelRef to be immutable.
    246      *
    247      *  @param info A description of the format (config, size)
    248      *         expected by the caller.  This can simply be identical
    249      *         to the info returned by getInfo().
    250      *
    251      *         This contract also allows the caller to specify
    252      *         different output-configs, which the implementation can
    253      *         decide to support or not.
    254      *
    255      *         A size that does not match getInfo() implies a request
    256      *         to scale. If the generator cannot perform this scale,
    257      *         it will return kInvalidScale.
    258      *
    259      *  If info is kIndex8_SkColorType, then the caller must provide storage for up to 256
    260      *  SkPMColor values in ctable. On success the generator must copy N colors into that storage,
    261      *  (where N is the logical number of table entries) and set ctableCount to N.
    262      *
    263      *  If info is not kIndex8_SkColorType, then the last two parameters may be NULL. If ctableCount
    264      *  is not null, it will be set to 0.
    265      *
    266      *  If a scanline decode is in progress, scanline mode will end, requiring the client to call
    267      *  startScanlineDecode() in order to return to decoding scanlines.
    268      *
    269      *  @return Result kSuccess, or another value explaining the type of failure.
    270      */
    271     Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*,
    272                      SkPMColor ctable[], int* ctableCount);
    273 
    274     /**
    275      *  Simplified version of getPixels() that asserts that info is NOT kIndex8_SkColorType and
    276      *  uses the default Options.
    277      */
    278     Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
    279 
    280     struct YUVSizeInfo {
    281         SkISize fYSize;
    282         SkISize fUSize;
    283         SkISize fVSize;
    284 
    285         /**
    286          * While the widths of the Y, U, and V planes are not restricted, the
    287          * implementation requires that the width of the memory allocated for
    288          * each plane be a multiple of DCTSIZE (which is always 8).
    289          *
    290          * This struct allows us to inform the client how many "widthBytes"
    291          * that we need.  Note that we use the new idea of "widthBytes"
    292          * because this idea is distinct from "rowBytes" (used elsewhere in
    293          * Skia).  "rowBytes" allow the last row of the allocation to not
    294          * include any extra padding, while, in this case, every single row of
    295          * the allocation must be at least "widthBytes".
    296          */
    297         size_t fYWidthBytes;
    298         size_t fUWidthBytes;
    299         size_t fVWidthBytes;
    300     };
    301 
    302     /**
    303      *  If decoding to YUV is supported, this returns true.  Otherwise, this
    304      *  returns false and does not modify any of the parameters.
    305      *
    306      *  @param sizeInfo   Output parameter indicating the sizes and required
    307      *                    allocation widths of the Y, U, and V planes.
    308      *  @param colorSpace Output parameter.  If non-NULL this is set to kJPEG,
    309      *                    otherwise this is ignored.
    310      */
    311     bool queryYUV8(YUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
    312         if (nullptr == sizeInfo) {
    313             return false;
    314         }
    315 
    316         return this->onQueryYUV8(sizeInfo, colorSpace);
    317     }
    318 
    319     /**
    320      *  Returns kSuccess, or another value explaining the type of failure.
    321      *  This always attempts to perform a full decode.  If the client only
    322      *  wants size, it should call queryYUV8().
    323      *
    324      *  @param sizeInfo   Needs to exactly match the values returned by the
    325      *                    query, except the WidthBytes may be larger than the
    326      *                    recommendation (but not smaller).
    327      *  @param planes     Memory for each of the Y, U, and V planes.
    328      */
    329     Result getYUV8Planes(const YUVSizeInfo& sizeInfo, void* planes[3]) {
    330         if (nullptr == planes || nullptr == planes[0] || nullptr == planes[1] ||
    331                 nullptr == planes[2]) {
    332             return kInvalidInput;
    333         }
    334 
    335         if (!this->rewindIfNeeded()) {
    336             return kCouldNotRewind;
    337         }
    338 
    339         return this->onGetYUV8Planes(sizeInfo, planes);
    340     }
    341 
    342     /**
    343      * The remaining functions revolve around decoding scanlines.
    344      */
    345 
    346     /**
    347      *  Prepare for a scanline decode with the specified options.
    348      *
    349      *  After this call, this class will be ready to decode the first scanline.
    350      *
    351      *  This must be called in order to call getScanlines or skipScanlines.
    352      *
    353      *  This may require rewinding the stream.
    354      *
    355      *  Not all SkCodecs support this.
    356      *
    357      *  @param dstInfo Info of the destination. If the dimensions do not match
    358      *      those of getInfo, this implies a scale.
    359      *  @param options Contains decoding options, including if memory is zero
    360      *      initialized.
    361      *  @param ctable A pointer to a color table.  When dstInfo.colorType() is
    362      *      kIndex8, this should be non-NULL and have enough storage for 256
    363      *      colors.  The color table will be populated after decoding the palette.
    364      *  @param ctableCount A pointer to the size of the color table.  When
    365      *      dstInfo.colorType() is kIndex8, this should be non-NULL.  It will
    366      *      be modified to the true size of the color table (<= 256) after
    367      *      decoding the palette.
    368      *  @return Enum representing success or reason for failure.
    369      */
    370     Result startScanlineDecode(const SkImageInfo& dstInfo, const SkCodec::Options* options,
    371             SkPMColor ctable[], int* ctableCount);
    372 
    373     /**
    374      *  Simplified version of startScanlineDecode() that asserts that info is NOT
    375      *  kIndex8_SkColorType and uses the default Options.
    376      */
    377     Result startScanlineDecode(const SkImageInfo& dstInfo);
    378 
    379     /**
    380      *  Write the next countLines scanlines into dst.
    381      *
    382      *  Not valid to call before calling startScanlineDecode().
    383      *
    384      *  @param dst Must be non-null, and large enough to hold countLines
    385      *      scanlines of size rowBytes.
    386      *  @param countLines Number of lines to write.
    387      *  @param rowBytes Number of bytes per row. Must be large enough to hold
    388      *      a scanline based on the SkImageInfo used to create this object.
    389      *  @return the number of lines successfully decoded.  If this value is
    390      *      less than countLines, this will fill the remaining lines with a
    391      *      default value.
    392      */
    393     int getScanlines(void* dst, int countLines, size_t rowBytes);
    394 
    395     /**
    396      *  Skip count scanlines.
    397      *
    398      *  Not valid to call before calling startScanlineDecode().
    399      *
    400      *  The default version just calls onGetScanlines and discards the dst.
    401      *  NOTE: If skipped lines are the only lines with alpha, this default
    402      *  will make reallyHasAlpha return true, when it could have returned
    403      *  false.
    404      *
    405      *  @return true if the scanlines were successfully skipped
    406      *          false on failure, possible reasons for failure include:
    407      *              An incomplete input image stream.
    408      *              Calling this function before calling startScanlineDecode().
    409      *              If countLines is less than zero or so large that it moves
    410      *                  the current scanline past the end of the image.
    411      */
    412     bool skipScanlines(int countLines);
    413 
    414     /**
    415      *  The order in which rows are output from the scanline decoder is not the
    416      *  same for all variations of all image types.  This explains the possible
    417      *  output row orderings.
    418      */
    419     enum SkScanlineOrder {
    420         /*
    421          * By far the most common, this indicates that the image can be decoded
    422          * reliably using the scanline decoder, and that rows will be output in
    423          * the logical order.
    424          */
    425         kTopDown_SkScanlineOrder,
    426 
    427         /*
    428          * This indicates that the scanline decoder reliably outputs rows, but
    429          * they will be returned in reverse order.  If the scanline format is
    430          * kBottomUp, the nextScanline() API can be used to determine the actual
    431          * y-coordinate of the next output row, but the client is not forced
    432          * to take advantage of this, given that it's not too tough to keep
    433          * track independently.
    434          *
    435          * For full image decodes, it is safe to get all of the scanlines at
    436          * once, since the decoder will handle inverting the rows as it
    437          * decodes.
    438          *
    439          * For subset decodes and sampling, it is simplest to get and skip
    440          * scanlines one at a time, using the nextScanline() API.  It is
    441          * possible to ask for larger chunks at a time, but this should be used
    442          * with caution.  As with full image decodes, the decoder will handle
    443          * inverting the requested rows, but rows will still be delivered
    444          * starting from the bottom of the image.
    445          *
    446          * Upside down bmps are an example.
    447          */
    448         kBottomUp_SkScanlineOrder,
    449 
    450         /*
    451          * This indicates that the scanline decoder reliably outputs rows, but
    452          * they will not be in logical order.  If the scanline format is
    453          * kOutOfOrder, the nextScanline() API should be used to determine the
    454          * actual y-coordinate of the next output row.
    455          *
    456          * For this scanline ordering, it is advisable to get and skip
    457          * scanlines one at a time.
    458          *
    459          * Interlaced gifs are an example.
    460          */
    461         kOutOfOrder_SkScanlineOrder,
    462 
    463         /*
    464          * Indicates that the entire image must be decoded in order to output
    465          * any amount of scanlines.  In this case, it is a REALLY BAD IDEA to
    466          * request scanlines 1-by-1 or in small chunks.  The client should
    467          * determine which scanlines are needed and ask for all of them in
    468          * a single call to getScanlines().
    469          *
    470          * Interlaced pngs are an example.
    471          */
    472         kNone_SkScanlineOrder,
    473     };
    474 
    475     /**
    476      *  An enum representing the order in which scanlines will be returned by
    477      *  the scanline decoder.
    478      *
    479      *  This is undefined before startScanlineDecode() is called.
    480      */
    481     SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
    482 
    483     /**
    484      *  Returns the y-coordinate of the next row to be returned by the scanline
    485      *  decoder.
    486      *
    487      *  This will equal fCurrScanline, except in the case of strangely
    488      *  encoded image types (bottom-up bmps, interlaced gifs).
    489      *
    490      *  Results are undefined when not in scanline decoding mode.
    491      */
    492     int nextScanline() const { return this->outputScanline(fCurrScanline); }
    493 
    494     /**
    495      *  Returns the output y-coordinate of the row that corresponds to an input
    496      *  y-coordinate.  The input y-coordinate represents where the scanline
    497      *  is located in the encoded data.
    498      *
    499      *  This will equal inputScanline, except in the case of strangely
    500      *  encoded image types (bottom-up bmps, interlaced gifs).
    501      */
    502     int outputScanline(int inputScanline) const;
    503 
    504 protected:
    505     SkCodec(const SkImageInfo&, SkStream*);
    506 
    507     virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const {
    508         // By default, scaling is not supported.
    509         return this->getInfo().dimensions();
    510     }
    511 
    512     // FIXME: What to do about subsets??
    513     /**
    514      *  Subclasses should override if they support dimensions other than the
    515      *  srcInfo's.
    516      */
    517     virtual bool onDimensionsSupported(const SkISize&) {
    518         return false;
    519     }
    520 
    521     virtual SkEncodedFormat onGetEncodedFormat() const = 0;
    522 
    523     /**
    524      * @param rowsDecoded When the encoded image stream is incomplete, this function
    525      *                    will return kIncompleteInput and rowsDecoded will be set to
    526      *                    the number of scanlines that were successfully decoded.
    527      *                    This will allow getPixels() to fill the uninitialized memory.
    528      */
    529     virtual Result onGetPixels(const SkImageInfo& info,
    530                                void* pixels, size_t rowBytes, const Options&,
    531                                SkPMColor ctable[], int* ctableCount,
    532                                int* rowsDecoded) = 0;
    533 
    534     virtual bool onQueryYUV8(YUVSizeInfo*, SkYUVColorSpace*) const {
    535         return false;
    536     }
    537 
    538     virtual Result onGetYUV8Planes(const YUVSizeInfo&, void*[3] /*planes*/) {
    539         return kUnimplemented;
    540     }
    541 
    542     virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const {
    543         // By default, subsets are not supported.
    544         return false;
    545     }
    546 
    547     /**
    548      *  If the stream was previously read, attempt to rewind.
    549      *
    550      *  If the stream needed to be rewound, call onRewind.
    551      *  @returns true if the codec is at the right position and can be used.
    552      *      false if there was a failure to rewind.
    553      *
    554      *  This is called by getPixels() and start(). Subclasses may call if they
    555      *  need to rewind at another time.
    556      */
    557     bool SK_WARN_UNUSED_RESULT rewindIfNeeded();
    558 
    559     /**
    560      *  Called by rewindIfNeeded, if the stream needed to be rewound.
    561      *
    562      *  Subclasses should do any set up needed after a rewind.
    563      */
    564     virtual bool onRewind() {
    565         return true;
    566     }
    567 
    568     /**
    569      * On an incomplete input, getPixels() and getScanlines() will fill any uninitialized
    570      * scanlines.  This allows the subclass to indicate what value to fill with.
    571      *
    572      * @param colorType Destination color type.
    573      * @return          The value with which to fill uninitialized pixels.
    574      *
    575      * Note that we can interpret the return value as an SkPMColor, a 16-bit 565 color,
    576      * an 8-bit gray color, or an 8-bit index into a color table, depending on the color
    577      * type.
    578      */
    579     uint32_t getFillValue(SkColorType colorType) const {
    580         return this->onGetFillValue(colorType);
    581     }
    582 
    583     /**
    584      * Some subclasses will override this function, but this is a useful default for the color
    585      * types that we support.  Note that for color types that do not use the full 32-bits,
    586      * we will simply take the low bits of the fill value.
    587      *
    588      * kN32_SkColorType: Transparent or Black, depending on the src alpha type
    589      * kRGB_565_SkColorType: Black
    590      * kGray_8_SkColorType: Black
    591      * kIndex_8_SkColorType: First color in color table
    592      */
    593     virtual uint32_t onGetFillValue(SkColorType /*colorType*/) const {
    594         return kOpaque_SkAlphaType == fSrcInfo.alphaType() ? SK_ColorBLACK : SK_ColorTRANSPARENT;
    595     }
    596 
    597     /**
    598      * Get method for the input stream
    599      */
    600     SkStream* stream() {
    601         return fStream.get();
    602     }
    603 
    604     /**
    605      *  The remaining functions revolve around decoding scanlines.
    606      */
    607 
    608     /**
    609      *  Most images types will be kTopDown and will not need to override this function.
    610      */
    611     virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
    612 
    613     /**
    614      *  Update the current scanline. Used by interlaced png.
    615      */
    616     void updateCurrScanline(int newY) { fCurrScanline = newY; }
    617 
    618     const SkImageInfo& dstInfo() const { return fDstInfo; }
    619 
    620     const SkCodec::Options& options() const { return fOptions; }
    621 
    622     /**
    623      *  Returns the number of scanlines that have been decoded so far.
    624      *  This is unaffected by the SkScanlineOrder.
    625      *
    626      *  Returns -1 if we have not started a scanline decode.
    627      */
    628     int currScanline() const { return fCurrScanline; }
    629 
    630     virtual int onOutputScanline(int inputScanline) const;
    631 
    632 private:
    633     const SkImageInfo       fSrcInfo;
    634     SkAutoTDelete<SkStream> fStream;
    635     bool                    fNeedsRewind;
    636     // These fields are only meaningful during scanline decodes.
    637     SkImageInfo             fDstInfo;
    638     SkCodec::Options        fOptions;
    639     int                     fCurrScanline;
    640 
    641     /**
    642      *  Return whether these dimensions are supported as a scale.
    643      *
    644      *  The codec may choose to cache the information about scale and subset.
    645      *  Either way, the same information will be passed to onGetPixels/onStart
    646      *  on success.
    647      *
    648      *  This must return true for a size returned from getScaledDimensions.
    649      */
    650     bool dimensionsSupported(const SkISize& dim) {
    651         return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim);
    652     }
    653 
    654     // Methods for scanline decoding.
    655     virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
    656             const SkCodec::Options& /*options*/, SkPMColor* /*ctable*/, int* /*ctableCount*/) {
    657         return kUnimplemented;
    658     }
    659 
    660     virtual bool onSkipScanlines(int /*countLines*/) { return false; }
    661 
    662     virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
    663 
    664     /**
    665      * On an incomplete decode, getPixels() and getScanlines() will call this function
    666      * to fill any uinitialized memory.
    667      *
    668      * @param dstInfo        Contains the destination color type
    669      *                       Contains the destination alpha type
    670      *                       Contains the destination width
    671      *                       The height stored in this info is unused
    672      * @param dst            Pointer to the start of destination pixel memory
    673      * @param rowBytes       Stride length in destination pixel memory
    674      * @param zeroInit       Indicates if memory is zero initialized
    675      * @param linesRequested Number of lines that the client requested
    676      * @param linesDecoded   Number of lines that were successfully decoded
    677      */
    678     void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
    679             ZeroInitialized zeroInit, int linesRequested, int linesDecoded);
    680 
    681     /**
    682      *  Return an object which will allow forcing scanline decodes to sample in X.
    683      *
    684      *  May create a sampler, if one is not currently being used. Otherwise, does
    685      *  not affect ownership.
    686      *
    687      *  Only valid during scanline decoding.
    688      */
    689     virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
    690 
    691     friend class SkSampledCodec;
    692     friend class SkIcoCodec;
    693 };
    694 #endif // SkCodec_DEFINED
    695