Home | History | Annotate | Download | only in image-decoders
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 
     33 #include "core/platform/image-decoders/ImageDecoder.h"
     34 
     35 #include "wtf/OwnPtr.h"
     36 #include "wtf/PassOwnPtr.h"
     37 #include "wtf/Vector.h"
     38 #include <gtest/gtest.h>
     39 
     40 using namespace WebCore;
     41 
     42 class TestImageDecoder : public ImageDecoder {
     43 public:
     44     TestImageDecoder()
     45         : ImageDecoder(ImageSource::AlphaNotPremultiplied, ImageSource::GammaAndColorProfileApplied)
     46     {
     47     }
     48 
     49     virtual String filenameExtension() const OVERRIDE { return ""; }
     50     virtual ImageFrame* frameBufferAtIndex(size_t) OVERRIDE { return 0; }
     51 
     52     Vector<ImageFrame, 1>& frameBufferCache()
     53     {
     54         return m_frameBufferCache;
     55     }
     56 
     57     void resetRequiredPreviousFrames()
     58     {
     59         for (size_t i = 0; i < m_frameBufferCache.size(); ++i)
     60             m_frameBufferCache[i].setRequiredPreviousFrameIndex(findRequiredPreviousFrame(i));
     61     }
     62 
     63     void initFrames(size_t numFrames, unsigned width = 100, unsigned height = 100)
     64     {
     65         setSize(width, height);
     66         m_frameBufferCache.resize(numFrames);
     67         for (size_t i = 0; i < numFrames; ++i)
     68             m_frameBufferCache[i].setOriginalFrameRect(IntRect(0, 0, width, height));
     69     }
     70 };
     71 
     72 TEST(ImageDecoderTest, requiredPreviousFrameIndex)
     73 {
     74     OwnPtr<TestImageDecoder> decoder(adoptPtr(new TestImageDecoder()));
     75     decoder->initFrames(6);
     76     Vector<ImageFrame, 1>& decoderFrameBufferCache = decoder->frameBufferCache();
     77 
     78     decoderFrameBufferCache[1].setDisposalMethod(ImageFrame::DisposeKeep);
     79     decoderFrameBufferCache[2].setDisposalMethod(ImageFrame::DisposeOverwritePrevious);
     80     decoderFrameBufferCache[3].setDisposalMethod(ImageFrame::DisposeOverwritePrevious);
     81     decoderFrameBufferCache[4].setDisposalMethod(ImageFrame::DisposeKeep);
     82 
     83     decoder->resetRequiredPreviousFrames();
     84 
     85     // The first frame doesn't require any previous frame.
     86     EXPECT_EQ(notFound, decoderFrameBufferCache[0].requiredPreviousFrameIndex());
     87     // The previous DisposeNotSpecified frame is required.
     88     EXPECT_EQ(0u, decoderFrameBufferCache[1].requiredPreviousFrameIndex());
     89     // DisposeKeep is treated as DisposeNotSpecified.
     90     EXPECT_EQ(1u, decoderFrameBufferCache[2].requiredPreviousFrameIndex());
     91     // Previous DisposeOverwritePrevious frames are skipped.
     92     EXPECT_EQ(1u, decoderFrameBufferCache[3].requiredPreviousFrameIndex());
     93     EXPECT_EQ(1u, decoderFrameBufferCache[4].requiredPreviousFrameIndex());
     94     EXPECT_EQ(4u, decoderFrameBufferCache[5].requiredPreviousFrameIndex());
     95 }
     96 
     97 TEST(ImageDecoderTest, requiredPreviousFrameIndexDisposeOverwriteBgcolor)
     98 {
     99     OwnPtr<TestImageDecoder> decoder(adoptPtr(new TestImageDecoder()));
    100     decoder->initFrames(3);
    101     Vector<ImageFrame, 1>& decoderFrameBufferCache = decoder->frameBufferCache();
    102 
    103     // Fully covering DisposeOverwriteBgcolor previous frame resets the starting state.
    104     decoderFrameBufferCache[1].setDisposalMethod(ImageFrame::DisposeOverwriteBgcolor);
    105     decoder->resetRequiredPreviousFrames();
    106     EXPECT_EQ(notFound, decoderFrameBufferCache[2].requiredPreviousFrameIndex());
    107 
    108     // Partially covering DisposeOverwriteBgcolor previous frame is required by this frame.
    109     decoderFrameBufferCache[1].setOriginalFrameRect(IntRect(50, 50, 50, 50));
    110     decoder->resetRequiredPreviousFrames();
    111     EXPECT_EQ(1u, decoderFrameBufferCache[2].requiredPreviousFrameIndex());
    112 }
    113 
    114 TEST(ImageDecoderTest, requiredPreviousFrameIndexForFrame1)
    115 {
    116     OwnPtr<TestImageDecoder> decoder(adoptPtr(new TestImageDecoder()));
    117     decoder->initFrames(2);
    118     Vector<ImageFrame, 1>& decoderFrameBufferCache = decoder->frameBufferCache();
    119 
    120     decoder->resetRequiredPreviousFrames();
    121     EXPECT_EQ(0u, decoderFrameBufferCache[1].requiredPreviousFrameIndex());
    122 
    123     // The first frame with DisposeOverwritePrevious or DisposeOverwriteBgcolor
    124     // resets the starting state.
    125     decoderFrameBufferCache[0].setDisposalMethod(ImageFrame::DisposeOverwritePrevious);
    126     decoder->resetRequiredPreviousFrames();
    127     EXPECT_EQ(notFound, decoderFrameBufferCache[1].requiredPreviousFrameIndex());
    128     decoderFrameBufferCache[0].setDisposalMethod(ImageFrame::DisposeOverwriteBgcolor);
    129     decoder->resetRequiredPreviousFrames();
    130     EXPECT_EQ(notFound, decoderFrameBufferCache[1].requiredPreviousFrameIndex());
    131 
    132     // ... even if it partially covers.
    133     decoderFrameBufferCache[0].setOriginalFrameRect(IntRect(50, 50, 50, 50));
    134 
    135     decoderFrameBufferCache[0].setDisposalMethod(ImageFrame::DisposeOverwritePrevious);
    136     decoder->resetRequiredPreviousFrames();
    137     EXPECT_EQ(notFound, decoderFrameBufferCache[1].requiredPreviousFrameIndex());
    138     decoderFrameBufferCache[0].setDisposalMethod(ImageFrame::DisposeOverwriteBgcolor);
    139     decoder->resetRequiredPreviousFrames();
    140     EXPECT_EQ(notFound, decoderFrameBufferCache[1].requiredPreviousFrameIndex());
    141 }
    142 
    143 TEST(ImageDecoderTest, clearCacheExceptFrameDoNothing)
    144 {
    145     OwnPtr<TestImageDecoder> decoder(adoptPtr(new TestImageDecoder()));
    146     decoder->clearCacheExceptFrame(0);
    147 
    148     // This should not crash.
    149     decoder->initFrames(20);
    150     decoder->clearCacheExceptFrame(notFound);
    151 }
    152 
    153 TEST(ImageDecoderTest, clearCacheExceptFrameAll)
    154 {
    155     const size_t numFrames = 10;
    156     OwnPtr<TestImageDecoder> decoder(adoptPtr(new TestImageDecoder()));
    157     decoder->initFrames(numFrames);
    158     Vector<ImageFrame, 1>& decoderFrameBufferCache = decoder->frameBufferCache();
    159     for (size_t i = 0; i < numFrames; ++i)
    160         decoderFrameBufferCache[i].setStatus(i % 2 ? ImageFrame::FramePartial : ImageFrame::FrameComplete);
    161 
    162     decoder->clearCacheExceptFrame(notFound);
    163 
    164     for (size_t i = 0; i < numFrames; ++i) {
    165         SCOPED_TRACE(testing::Message() << i);
    166         EXPECT_EQ(ImageFrame::FrameEmpty, decoderFrameBufferCache[i].status());
    167     }
    168 }
    169 
    170 TEST(ImageDecoderTest, clearCacheExceptFramePreverveClearExceptFrame)
    171 {
    172     const size_t numFrames = 10;
    173     OwnPtr<TestImageDecoder> decoder(adoptPtr(new TestImageDecoder()));
    174     decoder->initFrames(numFrames);
    175     Vector<ImageFrame, 1>& decoderFrameBufferCache = decoder->frameBufferCache();
    176     for (size_t i = 0; i < numFrames; ++i)
    177         decoderFrameBufferCache[i].setStatus(ImageFrame::FrameComplete);
    178 
    179     decoder->resetRequiredPreviousFrames();
    180     decoder->clearCacheExceptFrame(5);
    181     for (size_t i = 0; i < numFrames; ++i) {
    182         SCOPED_TRACE(testing::Message() << i);
    183         if (i == 5)
    184             EXPECT_EQ(ImageFrame::FrameComplete, decoderFrameBufferCache[i].status());
    185         else
    186             EXPECT_EQ(ImageFrame::FrameEmpty, decoderFrameBufferCache[i].status());
    187     }
    188 }
    189