Upstream version 8.37.180.0
[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->allocPixels(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 (fData != NULL) {
136         return SkSafeRef(fData);
137     }
138     // TODO(halcanary): SkStreamRewindable needs a refData() function
139     // which returns a cheap copy of the underlying data.
140     if (!fStream->rewind()) {
141         return NULL;
142     }
143     size_t length = fStream->getLength();
144     if (0 == length) {
145         return NULL;
146     }
147     void* buffer = sk_malloc_flags(length, 0);
148     SkCheckResult(fStream->read(buffer, length), length);
149     fData = SkData::NewFromMalloc(buffer, length);
150     return SkSafeRef(fData);
151 }
152
153 bool DecodingImageGenerator::onGetPixels(const SkImageInfo& info,
154                                          void* pixels, size_t rowBytes,
155                                          SkPMColor ctableEntries[], int* ctableCount) {
156     if (fInfo != info) {
157         // The caller has specified a different info.  This is an
158         // error for this kind of SkImageGenerator.  Use the Options
159         // to change the settings.
160         return false;
161     }
162
163     SkAssertResult(fStream->rewind());
164     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
165     if (NULL == decoder.get()) {
166         return false;
167     }
168     decoder->setDitherImage(fDitherImage);
169     decoder->setSampleSize(fSampleSize);
170     decoder->setRequireUnpremultipliedColors(
171             info.fAlphaType == kUnpremul_SkAlphaType);
172
173     SkBitmap bitmap;
174     TargetAllocator allocator(fInfo, pixels, rowBytes);
175     decoder->setAllocator(&allocator);
176     bool success = decoder->decode(fStream, &bitmap, info.colorType(),
177                                    SkImageDecoder::kDecodePixels_Mode);
178     decoder->setAllocator(NULL);
179     if (!success) {
180         return false;
181     }
182     if (allocator.isReady()) {  // Did not use pixels!
183         SkBitmap bm;
184         SkASSERT(bitmap.canCopyTo(info.colorType()));
185         bool copySuccess = bitmap.copyTo(&bm, info.colorType(), &allocator);
186         if (!copySuccess || allocator.isReady()) {
187             SkDEBUGFAIL("bitmap.copyTo(requestedConfig) failed.");
188             // Earlier we checked canCopyto(); we expect consistency.
189             return false;
190         }
191         SkASSERT(check_alpha(info.alphaType(), bm.alphaType()));
192     } else {
193         SkASSERT(check_alpha(info.alphaType(), bitmap.alphaType()));
194     }
195
196     if (kIndex_8_SkColorType == info.colorType()) {
197         if (kIndex_8_SkColorType != bitmap.colorType()) {
198             return false;   // they asked for Index8, but we didn't receive that from decoder
199         }
200         SkColorTable* ctable = bitmap.getColorTable();
201         if (NULL == ctable) {
202             return false;
203         }
204         const int count = ctable->count();
205         memcpy(ctableEntries, ctable->lockColors(), count * sizeof(SkPMColor));
206         ctable->unlockColors();
207         *ctableCount = count;
208     }
209     return true;
210 }
211
212 // A contructor-type function that returns NULL on failure.  This
213 // prevents the returned SkImageGenerator from ever being in a bad
214 // state.  Called by both Create() functions
215 SkImageGenerator* CreateDecodingImageGenerator(
216         SkData* data,
217         SkStreamRewindable* stream,
218         const SkDecodingImageGenerator::Options& opts) {
219     SkASSERT(stream);
220     SkAutoTUnref<SkStreamRewindable> autoStream(stream);  // always unref this.
221     SkAssertResult(autoStream->rewind());
222     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(autoStream));
223     if (NULL == decoder.get()) {
224         return NULL;
225     }
226     SkBitmap bitmap;
227     decoder->setSampleSize(opts.fSampleSize);
228     decoder->setRequireUnpremultipliedColors(opts.fRequireUnpremul);
229     if (!decoder->decode(stream, &bitmap, SkImageDecoder::kDecodeBounds_Mode)) {
230         return NULL;
231     }
232     if (kUnknown_SkColorType == bitmap.colorType()) {
233         return NULL;
234     }
235
236     SkImageInfo info = bitmap.info();
237
238     if (opts.fUseRequestedColorType && (opts.fRequestedColorType != info.colorType())) {
239         if (!bitmap.canCopyTo(opts.fRequestedColorType)) {
240             SkASSERT(bitmap.colorType() != opts.fRequestedColorType);
241             return NULL;  // Can not translate to needed config.
242         }
243         info.fColorType = opts.fRequestedColorType;
244     }
245
246     if (opts.fRequireUnpremul && info.fAlphaType != kOpaque_SkAlphaType) {
247         info.fAlphaType = kUnpremul_SkAlphaType;
248     }
249     return SkNEW_ARGS(DecodingImageGenerator,
250                       (data, autoStream.detach(), info,
251                        opts.fSampleSize, opts.fDitherImage));
252 }
253
254 }  // namespace
255
256 ////////////////////////////////////////////////////////////////////////////////
257
258 SkImageGenerator* SkDecodingImageGenerator::Create(
259         SkData* data,
260         const SkDecodingImageGenerator::Options& opts) {
261     SkASSERT(data != NULL);
262     if (NULL == data) {
263         return NULL;
264     }
265     SkStreamRewindable* stream = SkNEW_ARGS(SkMemoryStream, (data));
266     SkASSERT(stream != NULL);
267     SkASSERT(stream->unique());
268     return CreateDecodingImageGenerator(data, stream, opts);
269 }
270
271 SkImageGenerator* SkDecodingImageGenerator::Create(
272         SkStreamRewindable* stream,
273         const SkDecodingImageGenerator::Options& opts) {
274     SkASSERT(stream != NULL);
275     SkASSERT(stream->unique());
276     if ((stream == NULL) || !stream->unique()) {
277         SkSafeUnref(stream);
278         return NULL;
279     }
280     return CreateDecodingImageGenerator(NULL, stream, opts);
281 }