1/*
2 * Copyright 2007, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *  * Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 *  * Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#define LOG_TAG "ImageSourceAndroid"
27
28#include "config.h"
29
30#include "AndroidLog.h"
31#include "BitmapAllocatorAndroid.h"
32#include "ImageSource.h"
33#include "IntSize.h"
34#include "NotImplemented.h"
35#include "SharedBuffer.h"
36#include "PlatformString.h"
37
38#include "SkBitmapRef.h"
39#include "SkImageDecoder.h"
40#include "SkImageRef.h"
41#include "SkStream.h"
42#include "SkTemplates.h"
43
44#ifdef ANDROID_ANIMATED_GIF
45    #include "EmojiFont.h"
46    #include "GIFImageDecoder.h"
47
48    using namespace android;
49#endif
50
51// TODO: We should make use of some of the common code in platform/graphics/ImageSource.cpp.
52
53//#define TRACE_SUBSAMPLE_BITMAPS
54
55
56// flag to tell us when we're on a large-ram device (e.g. >= 256M)
57#ifdef ANDROID_LARGE_MEMORY_DEVICE
58    // see dox for computeMaxBitmapSizeForCache()
59    #define MAX_SIZE_BEFORE_SUBSAMPLE   (32*1024*1024)
60
61    // preserve quality for 24/32bit src
62    static const SkBitmap::Config gPrefConfigTable[6] = {
63        SkBitmap::kIndex8_Config,       // src: index, opaque
64        SkBitmap::kIndex8_Config,       // src: index, alpha
65        SkBitmap::kRGB_565_Config,      // src: 16bit, opaque
66        SkBitmap::kARGB_8888_Config,    // src: 16bit, alpha  (promote to 32bit)
67        SkBitmap::kARGB_8888_Config,    // src: 32bit, opaque
68        SkBitmap::kARGB_8888_Config,    // src: 32bit, alpha
69    };
70#else
71    #define MAX_SIZE_BEFORE_SUBSAMPLE   (2*1024*1024)
72
73    // tries to minimize memory usage (i.e. demote opaque 32bit -> 16bit)
74    static const SkBitmap::Config gPrefConfigTable[6] = {
75        SkBitmap::kIndex8_Config,       // src: index, opaque
76        SkBitmap::kIndex8_Config,       // src: index, alpha
77        SkBitmap::kRGB_565_Config,      // src: 16bit, opaque
78        SkBitmap::kARGB_8888_Config,    // src: 16bit, alpha  (promote to 32bit)
79        SkBitmap::kRGB_565_Config,      // src: 32bit, opaque (demote to 16bit)
80        SkBitmap::kARGB_8888_Config,    // src: 32bit, alpha
81    };
82#endif
83
84/*  Images larger than this should be subsampled. Using ashmem, the decoded
85    pixels will be purged as needed, so this value can be pretty large. Making
86    it too small hurts image quality (e.g. abc.com background). 2Meg works for
87    the sites I've tested, but if we hit important sites that need more, we
88    should try increasing it and see if it has negative impact on performance
89    (i.e. we end up thrashing because we need to keep decoding images that have
90    been purged.
91
92    Perhaps this value should be some fraction of the available RAM...
93*/
94size_t computeMaxBitmapSizeForCache() {
95    return MAX_SIZE_BEFORE_SUBSAMPLE;
96}
97///////////////////////////////////////////////////////////////////////////////
98
99class PrivateAndroidImageSourceRec : public SkBitmapRef {
100public:
101    PrivateAndroidImageSourceRec(const SkBitmap& bm, int origWidth,
102                                 int origHeight, int sampleSize)
103            : SkBitmapRef(bm), fSampleSize(sampleSize), fAllDataReceived(false) {
104        this->setOrigSize(origWidth, origHeight);
105    }
106
107    int  fSampleSize;
108    bool fAllDataReceived;
109};
110
111namespace WebCore {
112
113ImageSource::ImageSource(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
114    : m_alphaOption(alphaOption)
115    , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
116{
117    m_decoder.m_image = NULL;
118#ifdef ANDROID_ANIMATED_GIF
119    m_decoder.m_gifDecoder = 0;
120#endif
121}
122
123ImageSource::~ImageSource() {
124    delete m_decoder.m_image;
125#ifdef ANDROID_ANIMATED_GIF
126    delete m_decoder.m_gifDecoder;
127#endif
128}
129
130bool ImageSource::initialized() const {
131    return
132#ifdef ANDROID_ANIMATED_GIF
133        m_decoder.m_gifDecoder ||
134#endif
135        m_decoder.m_image != NULL;
136}
137
138static int computeSampleSize(const SkBitmap& bitmap) {
139    const size_t maxSize = computeMaxBitmapSizeForCache();
140    size_t size = bitmap.getSize();
141    int sampleSize = 1;
142
143    while (size > maxSize) {
144        sampleSize <<= 1;
145        size >>= 2;
146    }
147
148#ifdef TRACE_SUBSAMPLE_BITMAPS
149    if (sampleSize > 1) {
150        ALOGD("------- bitmap [%d %d] config=%d origSize=%d predictSize=%d sampleSize=%d\n",
151                 bitmap.width(), bitmap.height(), bitmap.config(),
152                 bitmap.getSize(), size, sampleSize);
153    }
154#endif
155    return sampleSize;
156}
157
158void ImageSource::clearURL()
159{
160    m_decoder.m_url.reset();
161}
162
163void ImageSource::setURL(const String& url)
164{
165    m_decoder.m_url.setUTF16(url.characters(), url.length());
166}
167
168#ifdef ANDROID_ANIMATED_GIF
169// we only animate small GIFs for now, to save memory
170// also, we only support this in Japan, hence the Emoji check
171static bool should_use_animated_gif(int width, int height) {
172#ifdef ANDROID_LARGE_MEMORY_DEVICE
173    return true;
174#else
175    return EmojiFont::IsAvailable() &&
176           width <= 32 && height <= 32;
177#endif
178}
179#endif
180
181void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
182{
183#ifdef ANDROID_ANIMATED_GIF
184    // This is only necessary if we allow ourselves to partially decode GIF
185    bool disabledAnimatedGif = false;
186    if (m_decoder.m_gifDecoder
187            && !m_decoder.m_gifDecoder->failed()) {
188        m_decoder.m_gifDecoder->setData(data, allDataReceived);
189        if (!allDataReceived || m_decoder.m_gifDecoder->frameCount() != 1)
190            return;
191        disabledAnimatedGif = true;
192        delete m_decoder.m_gifDecoder;
193        m_decoder.m_gifDecoder = 0;
194    }
195#endif
196    if (NULL == m_decoder.m_image
197#ifdef ANDROID_ANIMATED_GIF
198          && !m_decoder.m_gifDecoder
199#endif
200                                            ) {
201        SkBitmap tmp;
202
203        SkMemoryStream stream(data->data(), data->size(), false);
204        SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
205        if (!codec)
206            return;
207
208        SkAutoTDelete<SkImageDecoder> ad(codec);
209        codec->setPrefConfigTable(gPrefConfigTable);
210        if (!codec->decode(&stream, &tmp, SkImageDecoder::kDecodeBounds_Mode))
211            return;
212
213        int origW = tmp.width();
214        int origH = tmp.height();
215
216#ifdef ANDROID_ANIMATED_GIF
217        // First, check to see if this is an animated GIF
218        const char* contents = data->data();
219        if (data->size() > 3 && strncmp(contents, "GIF8", 4) == 0
220                && should_use_animated_gif(origW, origH)
221                && !disabledAnimatedGif) {
222            // This means we are looking at a GIF, so create special
223            // GIF Decoder
224            // Need to wait for all data received if we are assigning an
225            // allocator (which we are not at the moment).
226            if (!m_decoder.m_gifDecoder /*&& allDataReceived*/)
227                m_decoder.m_gifDecoder = new GIFImageDecoder(m_alphaOption, m_gammaAndColorProfileOption);
228            int frameCount = 0;
229            if (!m_decoder.m_gifDecoder->failed()) {
230                m_decoder.m_gifDecoder->setData(data, allDataReceived);
231                if (!allDataReceived)
232                    return;
233                frameCount = m_decoder.m_gifDecoder->frameCount();
234            }
235            if (frameCount != 1)
236                return;
237            delete m_decoder.m_gifDecoder;
238            m_decoder.m_gifDecoder = 0;
239        }
240#endif
241
242        int sampleSize = computeSampleSize(tmp);
243        if (sampleSize > 1) {
244            codec->setSampleSize(sampleSize);
245            stream.rewind();
246            if (!codec->decode(&stream, &tmp,
247                               SkImageDecoder::kDecodeBounds_Mode)) {
248                return;
249            }
250        }
251
252        m_decoder.m_image = new PrivateAndroidImageSourceRec(tmp, origW, origH,
253                                                     sampleSize);
254
255//        ALOGD("----- started: [%d %d] %s\n", origW, origH, m_decoder.m_url.c_str());
256    }
257
258    PrivateAndroidImageSourceRec* decoder = m_decoder.m_image;
259    if (allDataReceived && decoder && !decoder->fAllDataReceived) {
260        decoder->fAllDataReceived = true;
261
262        SkBitmap* bm = &decoder->bitmap();
263
264        BitmapAllocatorAndroid alloc(data, decoder->fSampleSize);
265        if (!alloc.allocPixelRef(bm, NULL)) {
266            return;
267        }
268        SkPixelRef* ref = bm->pixelRef();
269
270        // we promise to never change the pixels (makes picture recording fast)
271        ref->setImmutable();
272        // give it the URL if we have one
273        ref->setURI(m_decoder.m_url);
274    }
275}
276
277bool ImageSource::isSizeAvailable()
278{
279    return
280#ifdef ANDROID_ANIMATED_GIF
281            (m_decoder.m_gifDecoder
282                    && m_decoder.m_gifDecoder->isSizeAvailable()) ||
283#endif
284            m_decoder.m_image != NULL;
285}
286
287IntSize ImageSource::size() const
288{
289#ifdef ANDROID_ANIMATED_GIF
290    if (m_decoder.m_gifDecoder)
291        return m_decoder.m_gifDecoder->size();
292#endif
293    if (m_decoder.m_image) {
294        return IntSize(m_decoder.m_image->origWidth(), m_decoder.m_image->origHeight());
295    }
296    return IntSize(0, 0);
297}
298
299int ImageSource::repetitionCount()
300{
301#ifdef ANDROID_ANIMATED_GIF
302    if (m_decoder.m_gifDecoder)
303        return m_decoder.m_gifDecoder->repetitionCount();
304    if (!m_decoder.m_image) return 0;
305#endif
306    return 1;
307    // A property with value 0 means loop forever.
308}
309
310size_t ImageSource::frameCount() const
311{
312#ifdef ANDROID_ANIMATED_GIF
313    if (m_decoder.m_gifDecoder) {
314        return m_decoder.m_gifDecoder->failed() ? 0
315                : m_decoder.m_gifDecoder->frameCount();
316    }
317#endif
318    // i.e. 0 frames if we're not decoded, or 1 frame if we are
319    return m_decoder.m_image != NULL;
320}
321
322SkBitmapRef* ImageSource::createFrameAtIndex(size_t index)
323{
324#ifdef ANDROID_ANIMATED_GIF
325    if (m_decoder.m_gifDecoder) {
326        ImageFrame* buffer =
327                m_decoder.m_gifDecoder->frameBufferAtIndex(index);
328        if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
329            return 0;
330        SkBitmap& bitmap = buffer->bitmap();
331        SkPixelRef* pixelRef = bitmap.pixelRef();
332        if (pixelRef)
333            pixelRef->setURI(m_decoder.m_url);
334        return new SkBitmapRef(bitmap);
335    }
336#else
337    SkASSERT(index == 0);
338#endif
339    SkASSERT(m_decoder.m_image != NULL);
340    m_decoder.m_image->ref();
341    return m_decoder.m_image;
342}
343
344float ImageSource::frameDurationAtIndex(size_t index)
345{
346    float duration = 0;
347#ifdef ANDROID_ANIMATED_GIF
348    if (m_decoder.m_gifDecoder) {
349        ImageFrame* buffer
350                = m_decoder.m_gifDecoder->frameBufferAtIndex(index);
351        if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
352            return 0;
353        duration = buffer->duration() / 1000.0f;
354    }
355#else
356    SkASSERT(index == 0);
357#endif
358
359    // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
360    // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
361    // a duration of <= 10 ms. See gfxImageFrame::GetTimeout in Gecko or Radar 4051389 for more.
362    if (duration <= 0.010f)
363        duration = 0.100f;
364    return duration;
365}
366
367bool ImageSource::frameHasAlphaAtIndex(size_t index)
368{
369#ifdef ANDROID_ANIMATED_GIF
370    if (m_decoder.m_gifDecoder) {
371        ImageFrame* buffer =
372                m_decoder.m_gifDecoder->frameBufferAtIndex(index);
373        if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
374            return false;
375
376        return buffer->hasAlpha();
377    }
378#else
379    SkASSERT(0 == index);
380#endif
381
382    if (NULL == m_decoder.m_image)
383        return true;    // if we're not sure, assume the worse-case
384    const PrivateAndroidImageSourceRec& decoder = *m_decoder.m_image;
385    // if we're 16bit, we know even without all the data available
386    if (decoder.bitmap().getConfig() == SkBitmap::kRGB_565_Config)
387        return false;
388
389    if (!decoder.fAllDataReceived)
390        return true;    // if we're not sure, assume the worse-case
391
392    return !decoder.bitmap().isOpaque();
393}
394
395bool ImageSource::frameIsCompleteAtIndex(size_t index)
396{
397#ifdef ANDROID_ANIMATED_GIF
398    if (m_decoder.m_gifDecoder) {
399        ImageFrame* buffer =
400                m_decoder.m_gifDecoder->frameBufferAtIndex(index);
401        return buffer && buffer->status() == ImageFrame::FrameComplete;
402    }
403#else
404    SkASSERT(0 == index);
405#endif
406	return m_decoder.m_image && m_decoder.m_image->fAllDataReceived;
407}
408
409void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer* data, bool allDataReceived)
410{
411#ifdef ANDROID_ANIMATED_GIF
412    if (!destroyAll) {
413        if (m_decoder.m_gifDecoder)
414            m_decoder.m_gifDecoder->clearFrameBufferCache(clearBeforeFrame);
415        return;
416    }
417
418    delete m_decoder.m_gifDecoder;
419    m_decoder.m_gifDecoder = 0;
420    if (data)
421        setData(data, allDataReceived);
422#endif
423    // do nothing, since the cache is managed elsewhere
424}
425
426IntSize ImageSource::frameSizeAtIndex(size_t index) const
427{
428    // for now, all (1) of our frames are the same size
429    return this->size();
430}
431
432String ImageSource::filenameExtension() const
433{
434    // FIXME: need to add virtual to our decoders to return "jpg/png/gif/..."
435#ifdef ANDROID_ANIMATED_GIF
436    if (m_decoder.m_gifDecoder)
437        return m_decoder.m_gifDecoder->filenameExtension();
438#endif
439    return String();
440}
441
442bool ImageSource::getHotSpot(IntPoint&) const
443{
444    return false;
445}
446
447size_t ImageSource::bytesDecodedToDetermineProperties() const
448{
449    return 0;
450}
451
452}
453