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 #ifndef SkIcoCodec_DEFINED
8 #define SkIcoCodec_DEFINED
9 
10 #include "SkCodec.h"
11 #include "SkImageInfo.h"
12 #include "SkStream.h"
13 #include "SkTArray.h"
14 #include "SkTypes.h"
15 
16 /*
17  * This class implements the decoding for bmp images
18  */
19 class SkIcoCodec : public SkCodec {
20 public:
21     static bool IsIco(const void*, size_t);
22 
23     /*
24      * Assumes IsIco was called and returned true
25      * Creates an Ico decoder
26      * Reads enough of the stream to determine the image format
27      */
28     static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*);
29 
30 protected:
31 
32     /*
33      * Chooses the best dimensions given the desired scale
34      */
35     SkISize onGetScaledDimensions(float desiredScale) const override;
36 
37     bool onDimensionsSupported(const SkISize&) override;
38 
39     /*
40      * Initiates the Ico decode
41      */
42     Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&,
43             int*) override;
44 
45     SkEncodedImageFormat onGetEncodedFormat() const override {
46         return SkEncodedImageFormat::kICO;
47     }
48 
49     SkScanlineOrder onGetScanlineOrder() const override;
50 
51     bool conversionSupported(const SkImageInfo&, SkColorType, bool,
52                              const SkColorSpace*) const override {
53         // This will be checked by the embedded codec.
54         return true;
55     }
56 
57     // Handled by the embedded codec.
58     bool usesColorXform() const override { return false; }
59 private:
60 
61     Result onStartScanlineDecode(const SkImageInfo& dstInfo,
62             const SkCodec::Options& options) override;
63 
64     int onGetScanlines(void* dst, int count, size_t rowBytes) override;
65 
66     bool onSkipScanlines(int count) override;
67 
68     Result onStartIncrementalDecode(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes,
69             const SkCodec::Options&) override;
70 
71     Result onIncrementalDecode(int* rowsDecoded) override;
72 
73     SkSampler* getSampler(bool createIfNecessary) override;
74 
75     /*
76      * Searches fEmbeddedCodecs for a codec that matches requestedSize.
77      * The search starts at startIndex and ends when an appropriate codec
78      * is found, or we have reached the end of the array.
79      *
80      * @return the index of the matching codec or -1 if there is no
81      *         matching codec between startIndex and the end of
82      *         the array.
83      */
84     int chooseCodec(const SkISize& requestedSize, int startIndex);
85 
86     /*
87      * Constructor called by NewFromStream
88      * @param embeddedCodecs codecs for the embedded images, takes ownership
89      */
90     SkIcoCodec(int width, int height, const SkEncodedInfo& info,
91             SkTArray<std::unique_ptr<SkCodec>, true>* embeddedCodecs, sk_sp<SkColorSpace> colorSpace);
92 
93     std::unique_ptr<SkTArray<std::unique_ptr<SkCodec>, true>> fEmbeddedCodecs;
94 
95     // fCurrCodec is owned by this class, but should not be an
96     // std::unique_ptr.  It will be deleted by the destructor of fEmbeddedCodecs.
97     SkCodec* fCurrCodec;
98 
99     typedef SkCodec INHERITED;
100 };
101 #endif  // SkIcoCodec_DEFINED
102