summaryrefslogtreecommitdiffstats
path: root/image/test/gtest/TestFrameAnimator.cpp
blob: 8bc913b752cba88cb472b8604b30191e634abc66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "gtest/gtest.h"

#include "Common.h"
#include "AnimationSurfaceProvider.h"
#include "Decoder.h"
#include "ImageFactory.h"
#include "nsIInputStream.h"
#include "RasterImage.h"

using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::image;

static void CheckFrameAnimatorBlendResults(const ImageTestCase& aTestCase,
                                           RasterImage* aImage) {
  // Allow the animation to actually begin.
  aImage->IncrementAnimationConsumers();

  // Initialize for the first frame so we can advance.
  TimeStamp now = TimeStamp::Now();
  aImage->RequestRefresh(now);

  RefPtr<SourceSurface> surface =
      aImage->GetFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_NONE);
  ASSERT_TRUE(surface != nullptr);

  CheckGeneratedSurface(surface, IntRect(0, 0, 50, 50),
                        BGRAColor::Transparent(),
                        aTestCase.ChooseColor(BGRAColor::Red()));

  // Advance to the next/final frame.
  now = TimeStamp::Now() + TimeDuration::FromMilliseconds(500);
  aImage->RequestRefresh(now);

  surface =
      aImage->GetFrame(imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_NONE);
  ASSERT_TRUE(surface != nullptr);
  CheckGeneratedSurface(surface, IntRect(0, 0, 50, 50),
                        aTestCase.ChooseColor(BGRAColor::Green()),
                        aTestCase.ChooseColor(BGRAColor::Red()));
}

template <typename Func>
static void WithFrameAnimatorDecode(const ImageTestCase& aTestCase,
                                    Func aResultChecker) {
  // Create an image.
  RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
      nsDependentCString(aTestCase.mMimeType));
  ASSERT_TRUE(!image->HasError());

  NotNull<RefPtr<RasterImage>> rasterImage =
      WrapNotNull(static_cast<RasterImage*>(image.get()));

  nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
  ASSERT_TRUE(inputStream != nullptr);

  // Figure out how much data we have.
  uint64_t length;
  nsresult rv = inputStream->Available(&length);
  ASSERT_NS_SUCCEEDED(rv);

  // Write the data into a SourceBuffer.
  NotNull<RefPtr<SourceBuffer>> sourceBuffer = WrapNotNull(new SourceBuffer());
  sourceBuffer->ExpectLength(length);
  rv = sourceBuffer->AppendFromInputStream(inputStream, length);
  ASSERT_NS_SUCCEEDED(rv);
  sourceBuffer->Complete(NS_OK);

  // Create a metadata decoder first, because otherwise RasterImage will get
  // unhappy about finding out the image is animated during a full decode.
  DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
  RefPtr<IDecodingTask> task = DecoderFactory::CreateMetadataDecoder(
      decoderType, rasterImage, sourceBuffer);
  ASSERT_TRUE(task != nullptr);

  // Run the metadata decoder synchronously.
  task->Run();
  task = nullptr;

  // Create an AnimationSurfaceProvider which will manage the decoding process
  // and make this decoder's output available in the surface cache.
  DecoderFlags decoderFlags = DefaultDecoderFlags();
  SurfaceFlags surfaceFlags = aTestCase.mSurfaceFlags;
  rv = DecoderFactory::CreateAnimationDecoder(
      decoderType, rasterImage, sourceBuffer, aTestCase.mSize, decoderFlags,
      surfaceFlags, 0, getter_AddRefs(task));
  EXPECT_EQ(rv, NS_OK);
  ASSERT_TRUE(task != nullptr);

  // Run the full decoder synchronously.
  task->Run();

  // Call the lambda to verify the expected results.
  aResultChecker(rasterImage.get());
}

static void CheckFrameAnimatorBlend(const ImageTestCase& aTestCase) {
  WithFrameAnimatorDecode(aTestCase, [&](RasterImage* aImage) {
    CheckFrameAnimatorBlendResults(aTestCase, aImage);
  });
}

class ImageFrameAnimator : public ::testing::Test {
 protected:
  AutoInitializeImageLib mInit;
};

TEST_F(ImageFrameAnimator, BlendGIFWithFilter) {
  CheckFrameAnimatorBlend(BlendAnimatedGIFTestCase());
}

TEST_F(ImageFrameAnimator, BlendPNGWithFilter) {
  CheckFrameAnimatorBlend(BlendAnimatedPNGTestCase());
}

TEST_F(ImageFrameAnimator, BlendWebPWithFilter) {
  CheckFrameAnimatorBlend(BlendAnimatedWebPTestCase());
}