• 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 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      */
getInfo()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      */
getScaledDimensions(float desiredScale)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      */
getValidSubset(SkIRect * desiredSubset)138     bool getValidSubset(SkIRect* desiredSubset) const {
139         return this->onGetValidSubset(desiredSubset);
140     }
141 
142     /**
143      *  Format of the encoded data.
144      */
getEncodedFormat()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 {
OptionsOptions213         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      */
queryYUV8(YUVSizeInfo * sizeInfo,SkYUVColorSpace * colorSpace)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      */
getYUV8Planes(const YUVSizeInfo & sizeInfo,void * planes[3])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      */
getScanlineOrder()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      */
nextScanline()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 
onGetScaledDimensions(float)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      */
onDimensionsSupported(const SkISize &)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 
onQueryYUV8(YUVSizeInfo *,SkYUVColorSpace *)534     virtual bool onQueryYUV8(YUVSizeInfo*, SkYUVColorSpace*) const {
535         return false;
536     }
537 
onGetYUV8Planes(const YUVSizeInfo &,void * [3])538     virtual Result onGetYUV8Planes(const YUVSizeInfo&, void*[3] /*planes*/) {
539         return kUnimplemented;
540     }
541 
onGetValidSubset(SkIRect *)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      */
onRewind()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      */
getFillValue(SkColorType colorType)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      */
onGetFillValue(SkColorType)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      */
stream()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      */
onGetScanlineOrder()611     virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
612 
613     /**
614      *  Update the current scanline. Used by interlaced png.
615      */
updateCurrScanline(int newY)616     void updateCurrScanline(int newY) { fCurrScanline = newY; }
617 
dstInfo()618     const SkImageInfo& dstInfo() const { return fDstInfo; }
619 
options()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      */
currScanline()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      */
dimensionsSupported(const SkISize & dim)650     bool dimensionsSupported(const SkISize& dim) {
651         return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim);
652     }
653 
654     // Methods for scanline decoding.
onStartScanlineDecode(const SkImageInfo &,const SkCodec::Options &,SkPMColor *,int *)655     virtual SkCodec::Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
656             const SkCodec::Options& /*options*/, SkPMColor* /*ctable*/, int* /*ctableCount*/) {
657         return kUnimplemented;
658     }
659 
onSkipScanlines(int)660     virtual bool onSkipScanlines(int /*countLines*/) { return false; }
661 
onGetScanlines(void *,int,size_t)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      */
getSampler(bool)689     virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
690 
691     friend class SkSampledCodec;
692     friend class SkIcoCodec;
693 };
694 #endif // SkCodec_DEFINED
695