3b5cb784edd4254f2c7ce4b51ad7d4c2dfe02b4a
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / images / SkDecodingImageGenerator.cpp
1 /*
2  * Copyright 2013 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 #include "SkData.h"
9 #include "SkDecodingImageGenerator.h"
10 #include "SkImageDecoder.h"
11 #include "SkImageInfo.h"
12 #include "SkImageGenerator.h"
13 #include "SkImagePriv.h"
14 #include "SkStream.h"
15 #include "SkUtils.h"
16
17 namespace {
18 bool equal_modulo_alpha(const SkImageInfo& a, const SkImageInfo& b) {
19     return a.width() == b.width() && a.height() == b.height() &&
20            a.colorType() == b.colorType();
21 }
22
23 class DecodingImageGenerator : public SkImageGenerator {
24 public:
25     virtual ~DecodingImageGenerator();
26
27     SkData*                fData;
28     SkStreamRewindable*    fStream;
29     const SkImageInfo      fInfo;
30     const int              fSampleSize;
31     const bool             fDitherImage;
32
33     DecodingImageGenerator(SkData* data,
34                            SkStreamRewindable* stream,
35                            const SkImageInfo& info,
36                            int sampleSize,
37                            bool ditherImage);
38
39 protected:
40     virtual SkData* onRefEncodedData() SK_OVERRIDE;
41     virtual bool onGetInfo(SkImageInfo* info) SK_OVERRIDE {
42         *info = fInfo;
43         return true;
44     }
45     virtual bool onGetPixels(const SkImageInfo& info,
46                              void* pixels, size_t rowBytes,
47                              SkPMColor ctable[], int* ctableCount) SK_OVERRIDE;
48
49 private:
50     typedef SkImageGenerator INHERITED;
51 };
52
53 /**
54  *  Special allocator used by getPixels(). Uses preallocated memory
55  *  provided if possible, else fall-back on the default allocator
56  */
57 class TargetAllocator : public SkBitmap::Allocator {
58 public:
59     TargetAllocator(const SkImageInfo& info,
60                     void* target,
61                     size_t rowBytes)
62         : fInfo(info)
63         , fTarget(target)
64         , fRowBytes(rowBytes)
65     {}
66
67     bool isReady() { return (fTarget != NULL); }
68
69     virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) {
70         if (NULL == fTarget || !equal_modulo_alpha(fInfo, bm->info())) {
71             // Call default allocator.
72             return bm->tryAllocPixels(NULL, ct);
73         }
74
75         // TODO(halcanary): verify that all callers of this function
76         // will respect new RowBytes.  Will be moot once rowbytes belongs
77         // to PixelRef.
78         bm->installPixels(fInfo, fTarget, fRowBytes, ct, NULL, NULL);
79
80         fTarget = NULL;  // never alloc same pixels twice!
81         return true;
82     }
83
84 private:
85     const SkImageInfo fInfo;
86     void* fTarget;  // Block of memory to be supplied as pixel memory
87                     // in allocPixelRef.  Must be large enough to hold
88                     // a bitmap described by fInfo and fRowBytes
89     const size_t fRowBytes;  // rowbytes for the destination bitmap
90
91     typedef SkBitmap::Allocator INHERITED;
92 };
93
94 // TODO(halcanary): Give this macro a better name and move it into SkTypes.h
95 #ifdef SK_DEBUG
96     #define SkCheckResult(expr, value)  SkASSERT((value) == (expr))
97 #else
98     #define SkCheckResult(expr, value)  (void)(expr)
99 #endif
100
101 #ifdef SK_DEBUG
102 inline bool check_alpha(SkAlphaType reported, SkAlphaType actual) {
103     return ((reported == actual)
104             || ((reported == kPremul_SkAlphaType)
105                 && (actual == kOpaque_SkAlphaType)));
106 }
107 #endif  // SK_DEBUG
108
109 ////////////////////////////////////////////////////////////////////////////////
110
111 DecodingImageGenerator::DecodingImageGenerator(
112         SkData* data,
113         SkStreamRewindable* stream,
114         const SkImageInfo& info,
115         int sampleSize,
116         bool ditherImage)
117     : fData(data)
118     , fStream(stream)
119     , fInfo(info)
120     , fSampleSize(sampleSize)
121     , fDitherImage(ditherImage)
122 {
123     SkASSERT(stream != NULL);
124     SkSafeRef(fData);  // may be NULL.
125 }
126
127 DecodingImageGenerator::~DecodingImageGenerator() {
128     SkSafeUnref(fData);
129     fStream->unref();
130 }
131
132 SkData* DecodingImageGenerator::onRefEncodedData() {
133     // This functionality is used in `gm --serialize`
134     // Does not encode options.
135     if (NULL == fData) {
136         // TODO(halcanary): SkStreamRewindable needs a refData() function
137         // which returns a cheap copy of the underlying data.
138         if (!fStream->rewind()) {
139             return NULL;
140         }
141         size_t length = fStream->getLength();
142         if (length) {
143             fData = SkData::NewFromStream(fStream, length);
144         }
145     }
146     return SkSafeRef(fData);
147 }
148
149 bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info,
150                                          void* pixels, size_t rowBytes,
151                                          SkPMColor ctableEntries[], int* ctableCount) {
152     if (fInfo != info) {
153         // The caller has specified a different info.  This is an
154         // error for this kind of SkImageGenerator.  Use the Options
155         // to change the settings.
156         return false;
157     }
158
159     SkAssertResult(fStream->rewind());
160     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
161     if (NULL == decoder.get()) {
162         return false;
163     }
164     decoder->setDitherImage(fDitherImage);
165     decoder->setSampleSize(fSampleSize);
166     decoder->setRequireUnpremultipliedColors(info.alphaType() == kUnpremul_SkAlphaType);
167
168     SkBitmap bitmap;
169     TargetAllocator allocator(fInfo, pixels, rowBytes);
170     decoder->setAllocator(&allocator);
171     bool success = decoder->decode(fStream, &bitmap, info.colorType(),
172                                    SkImageDecoder::kDecodePixels_Mode);
173     decoder->setAllocator(NULL);
174     if (!success) {
175         return false;
176     }
177     if (allocator.isReady()) {  // Did not use pixels!
178         SkBitmap bm;
179         SkASSERT(bitmap.canCopyTo(info.colorType()));
180         bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator);
181         if (!copySuccess || allocator.isReady()) {
182             SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
183             // Earlier we checked canCopyto(); we expect consistency.
184             return false;
185         }
186         SkASSERT(check_alpha(info.alphaType(), bm.alphaType()));
187     } else {
188         SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
189     }
190
191     if (kIndex_8_SkColorType == info.colorType()) {
192         if (kIndex_8_SkColorType != bitmap.colorType()) {
193             return false;   // they asked for Index8, but we didn't receive that from decoder
194         }
195         SkColorTable* ctable = bitmap.getColorTable();
196         if (NULL == ctable) {
197             return false;
198         }
199         const int count = ctable->count();
200         memcpy(ctableEntries, ctable->lockColors(), count * sizeof(SkPMColor));
201         ctable->unlockColors();
202         *ctableCount = count;
203     }
204     return true;
205 }
206
207 // A contructor-type function that returns NULL on failure.  This
208 // prevents the returned SkImageGenerator from ever being in a bad
209 // state.  Called by both Create() functions
210 SkImageGenerator* CreateDecodingImageGenerator(
211         SkData* data,
212         SkStreamRewindable* stream,
213         const SkDecodingImageGenerator::Options& opts) {
214     SkASSERT(stream);
215     SkAutoTUnref<SkStreamRewindable> autoStream(stream);  // always unref this.
216     SkAssertResult(autoStream->rewind());
217     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream));
218     if (NULL == decoder.get()) {
219         return NULL;
220     }
221     SkBitmap bitmap;
222     decoder->setSampleSize(opts.fSampleSize);
223     decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul);
224     if (!decoder->decode(stream, &bitmap, SkImageDecoder::kDecodeBounds_Mode)) {
225         return NULL;
226     }
227     if (kUnknown_SkColorType == bitmap.colorType()) {
228         return NULL;
229     }
230
231     SkImageInfo info = bitmap.info();
232
233     if (opts.fUseRequestedColorType && (opts.fRequestedColorType != info.colorType())) {
234         if (!bitmap.canCopyTo(opts.fRequestedColorType)) {
235             SkASSERT(bitmap.colorType() != opts.fRequestedColorType);
236             return NULL;  // Can not translate to needed config.
237         }
238         info = info.makeColorType(opts.fRequestedColorType);
239     }
240
241     if (opts.fRequireUnpremul && info.alphaType() != kOpaque_SkAlphaType) {
242         info = info.makeAlphaType(kUnpremul_SkAlphaType);
243     }
244
245     SkAlphaType newAlphaType = info.alphaType();
246     if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAlphaType)) {
247         return NULL;
248     }
249
250     return SkNEW_ARGS(DecodingImageGenerator,
251                       (data, autoStream.detach(), info.makeAlphaType(newAlphaType),
252                        opts.fSampleSize, opts.fDitherImage));
253 }
254
255 }  // namespace
256
257 ////////////////////////////////////////////////////////////////////////////////
258
259 SkImageGenerator* SkDecodingImageGenerator::Create(
260         SkData* data,
261         const SkDecodingImageGenerator::Options& opts) {
262     SkASSERT(data != NULL);
263     if (NULL == data) {
264         return NULL;
265     }
266     SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data));
267     SkASSERT(stream != NULL);
268     SkASSERT(stream->unique());
269     return CreateDecodingImageGenerator(data, stream, opts);
270 }
271
272 SkImageGenerator* SkDecodingImageGenerator::Create(
273         SkStreamRewindable* stream,
274         const SkDecodingImageGenerator::Options& opts) {
275     SkASSERT(stream != NULL);
276     SkASSERT(stream->unique());
277     if ((stream == NULL) || !stream->unique()) {
278         SkSafeUnref(stream);
279         return NULL;
280     }
281     return CreateDecodingImageGenerator(NULL, stream, opts);
282 }