no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / image / test / gtest / TestBlendAnimationFilter.cpp
blob7291fbc3f6408d911290325a844e35b407f72e96
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "gtest/gtest.h"
9 #include "mozilla/gfx/2D.h"
10 #include "skia/include/core/SkColorPriv.h" // for SkPMSrcOver
11 #include "Common.h"
12 #include "Decoder.h"
13 #include "DecoderFactory.h"
14 #include "SourceBuffer.h"
15 #include "SurfaceFilters.h"
16 #include "SurfacePipe.h"
18 using namespace mozilla;
19 using namespace mozilla::gfx;
20 using namespace mozilla::image;
22 static already_AddRefed<image::Decoder> CreateTrivialBlendingDecoder() {
23 DecoderType decoderType = DecoderFactory::GetDecoderType("image/gif");
24 DecoderFlags decoderFlags = DefaultDecoderFlags();
25 SurfaceFlags surfaceFlags = DefaultSurfaceFlags();
26 auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
27 return DecoderFactory::CreateAnonymousDecoder(
28 decoderType, sourceBuffer, Nothing(), decoderFlags, surfaceFlags);
31 template <typename Func>
32 RawAccessFrameRef WithBlendAnimationFilter(image::Decoder* aDecoder,
33 const AnimationParams& aAnimParams,
34 const IntSize& aOutputSize,
35 Func aFunc) {
36 DecoderTestHelper decoderHelper(aDecoder);
38 if (!aDecoder->HasAnimation()) {
39 decoderHelper.PostIsAnimated(aAnimParams.mTimeout);
42 BlendAnimationConfig blendAnim{aDecoder};
43 SurfaceConfig surfaceSink{aDecoder, aOutputSize, SurfaceFormat::OS_RGBA,
44 false, Some(aAnimParams)};
46 auto func = [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
47 aFunc(aDecoder, aFilter);
50 WithFilterPipeline(aDecoder, func, false, blendAnim, surfaceSink);
52 RawAccessFrameRef current = aDecoder->GetCurrentFrameRef();
53 if (current) {
54 decoderHelper.PostFrameStop(Opacity::SOME_TRANSPARENCY);
57 return current;
60 void AssertConfiguringBlendAnimationFilterFails(const IntRect& aFrameRect,
61 const IntSize& aOutputSize) {
62 RefPtr<image::Decoder> decoder = CreateTrivialBlendingDecoder();
63 ASSERT_TRUE(decoder != nullptr);
65 AnimationParams animParams{aFrameRect, FrameTimeout::FromRawMilliseconds(0),
66 0, BlendMethod::SOURCE, DisposalMethod::KEEP};
67 BlendAnimationConfig blendAnim{decoder};
68 SurfaceConfig surfaceSink{decoder, aOutputSize, SurfaceFormat::OS_RGBA, false,
69 Some(animParams)};
70 AssertConfiguringPipelineFails(decoder, blendAnim, surfaceSink);
73 TEST(ImageBlendAnimationFilter, BlendFailsForNegativeFrameRect)
75 // A negative frame rect size is disallowed.
76 AssertConfiguringBlendAnimationFilterFails(
77 IntRect(IntPoint(0, 0), IntSize(-1, -1)), IntSize(100, 100));
80 TEST(ImageBlendAnimationFilter, WriteFullFirstFrame)
82 RefPtr<image::Decoder> decoder = CreateTrivialBlendingDecoder();
83 ASSERT_TRUE(decoder != nullptr);
85 AnimationParams params{
86 IntRect(0, 0, 100, 100), FrameTimeout::FromRawMilliseconds(0),
87 /* aFrameNum */ 0, BlendMethod::SOURCE, DisposalMethod::KEEP};
88 RawAccessFrameRef frame0 = WithBlendAnimationFilter(
89 decoder, params, IntSize(100, 100),
90 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
91 CheckWritePixels(aDecoder, aFilter, Some(IntRect(0, 0, 100, 100)));
92 });
93 EXPECT_EQ(IntRect(0, 0, 100, 100), frame0->GetDirtyRect());
96 TEST(ImageBlendAnimationFilter, WritePartialFirstFrame)
98 RefPtr<image::Decoder> decoder = CreateTrivialBlendingDecoder();
99 ASSERT_TRUE(decoder != nullptr);
101 AnimationParams params{
102 IntRect(25, 50, 50, 25), FrameTimeout::FromRawMilliseconds(0),
103 /* aFrameNum */ 0, BlendMethod::SOURCE, DisposalMethod::KEEP};
104 RawAccessFrameRef frame0 = WithBlendAnimationFilter(
105 decoder, params, IntSize(100, 100),
106 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
107 CheckWritePixels(aDecoder, aFilter, Some(IntRect(0, 0, 100, 100)),
108 Nothing(), Some(IntRect(25, 50, 50, 25)),
109 Some(IntRect(25, 50, 50, 25)));
111 EXPECT_EQ(IntRect(0, 0, 100, 100), frame0->GetDirtyRect());
114 static void TestWithBlendAnimationFilterClear(BlendMethod aBlendMethod) {
115 RefPtr<image::Decoder> decoder = CreateTrivialBlendingDecoder();
116 ASSERT_TRUE(decoder != nullptr);
118 AnimationParams params0{
119 IntRect(0, 0, 100, 100), FrameTimeout::FromRawMilliseconds(0),
120 /* aFrameNum */ 0, BlendMethod::SOURCE, DisposalMethod::KEEP};
121 RawAccessFrameRef frame0 = WithBlendAnimationFilter(
122 decoder, params0, IntSize(100, 100),
123 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
124 auto result = aFilter->WritePixels<uint32_t>(
125 [&] { return AsVariant(BGRAColor::Green().AsPixel()); });
126 EXPECT_EQ(WriteState::FINISHED, result);
128 EXPECT_EQ(IntRect(0, 0, 100, 100), frame0->GetDirtyRect());
130 AnimationParams params1{
131 IntRect(0, 40, 100, 20), FrameTimeout::FromRawMilliseconds(0),
132 /* aFrameNum */ 1, BlendMethod::SOURCE, DisposalMethod::CLEAR};
133 RawAccessFrameRef frame1 = WithBlendAnimationFilter(
134 decoder, params1, IntSize(100, 100),
135 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
136 auto result = aFilter->WritePixels<uint32_t>(
137 [&] { return AsVariant(BGRAColor::Red().AsPixel()); });
138 EXPECT_EQ(WriteState::FINISHED, result);
140 EXPECT_EQ(IntRect(0, 40, 100, 20), frame1->GetDirtyRect());
142 ASSERT_TRUE(frame1.get() != nullptr);
144 RefPtr<SourceSurface> surface = frame1->GetSourceSurface();
145 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 40, BGRAColor::Green()));
146 EXPECT_TRUE(RowsAreSolidColor(surface, 40, 20, BGRAColor::Red()));
147 EXPECT_TRUE(RowsAreSolidColor(surface, 60, 40, BGRAColor::Green()));
149 AnimationParams params2{
150 IntRect(0, 50, 100, 20), FrameTimeout::FromRawMilliseconds(0),
151 /* aFrameNum */ 2, aBlendMethod, DisposalMethod::KEEP};
152 RawAccessFrameRef frame2 = WithBlendAnimationFilter(
153 decoder, params2, IntSize(100, 100),
154 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
155 auto result = aFilter->WritePixels<uint32_t>(
156 [&] { return AsVariant(BGRAColor::Blue().AsPixel()); });
157 EXPECT_EQ(WriteState::FINISHED, result);
160 ASSERT_TRUE(frame2.get() != nullptr);
162 surface = frame2->GetSourceSurface();
163 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 40, BGRAColor::Green()));
164 EXPECT_TRUE(RowsAreSolidColor(surface, 40, 10, BGRAColor::Transparent()));
165 EXPECT_TRUE(RowsAreSolidColor(surface, 50, 20, BGRAColor::Blue()));
166 EXPECT_TRUE(RowsAreSolidColor(surface, 70, 30, BGRAColor::Green()));
169 TEST(ImageBlendAnimationFilter, ClearWithOver)
170 { TestWithBlendAnimationFilterClear(BlendMethod::OVER); }
172 TEST(ImageBlendAnimationFilter, ClearWithSource)
173 { TestWithBlendAnimationFilterClear(BlendMethod::SOURCE); }
175 TEST(ImageBlendAnimationFilter, KeepWithSource)
177 RefPtr<image::Decoder> decoder = CreateTrivialBlendingDecoder();
178 ASSERT_TRUE(decoder != nullptr);
180 AnimationParams params0{
181 IntRect(0, 0, 100, 100), FrameTimeout::FromRawMilliseconds(0),
182 /* aFrameNum */ 0, BlendMethod::SOURCE, DisposalMethod::KEEP};
183 RawAccessFrameRef frame0 = WithBlendAnimationFilter(
184 decoder, params0, IntSize(100, 100),
185 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
186 auto result = aFilter->WritePixels<uint32_t>(
187 [&] { return AsVariant(BGRAColor::Green().AsPixel()); });
188 EXPECT_EQ(WriteState::FINISHED, result);
190 EXPECT_EQ(IntRect(0, 0, 100, 100), frame0->GetDirtyRect());
192 AnimationParams params1{
193 IntRect(0, 40, 100, 20), FrameTimeout::FromRawMilliseconds(0),
194 /* aFrameNum */ 1, BlendMethod::SOURCE, DisposalMethod::KEEP};
195 RawAccessFrameRef frame1 = WithBlendAnimationFilter(
196 decoder, params1, IntSize(100, 100),
197 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
198 auto result = aFilter->WritePixels<uint32_t>(
199 [&] { return AsVariant(BGRAColor::Red().AsPixel()); });
200 EXPECT_EQ(WriteState::FINISHED, result);
202 EXPECT_EQ(IntRect(0, 40, 100, 20), frame1->GetDirtyRect());
204 ASSERT_TRUE(frame1.get() != nullptr);
206 RefPtr<SourceSurface> surface = frame1->GetSourceSurface();
207 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 40, BGRAColor::Green()));
208 EXPECT_TRUE(RowsAreSolidColor(surface, 40, 20, BGRAColor::Red()));
209 EXPECT_TRUE(RowsAreSolidColor(surface, 60, 40, BGRAColor::Green()));
212 TEST(ImageBlendAnimationFilter, KeepWithOver)
214 RefPtr<image::Decoder> decoder = CreateTrivialBlendingDecoder();
215 ASSERT_TRUE(decoder != nullptr);
217 AnimationParams params0{
218 IntRect(0, 0, 100, 100), FrameTimeout::FromRawMilliseconds(0),
219 /* aFrameNum */ 0, BlendMethod::SOURCE, DisposalMethod::KEEP};
220 BGRAColor frameColor0(0, 0xFF, 0, 0x40);
221 RawAccessFrameRef frame0 = WithBlendAnimationFilter(
222 decoder, params0, IntSize(100, 100),
223 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
224 auto result = aFilter->WritePixels<uint32_t>(
225 [&] { return AsVariant(frameColor0.AsPixel()); });
226 EXPECT_EQ(WriteState::FINISHED, result);
228 EXPECT_EQ(IntRect(0, 0, 100, 100), frame0->GetDirtyRect());
230 AnimationParams params1{
231 IntRect(0, 40, 100, 20), FrameTimeout::FromRawMilliseconds(0),
232 /* aFrameNum */ 1, BlendMethod::OVER, DisposalMethod::KEEP};
233 BGRAColor frameColor1(0, 0, 0xFF, 0x80);
234 RawAccessFrameRef frame1 = WithBlendAnimationFilter(
235 decoder, params1, IntSize(100, 100),
236 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
237 auto result = aFilter->WritePixels<uint32_t>(
238 [&] { return AsVariant(frameColor1.AsPixel()); });
239 EXPECT_EQ(WriteState::FINISHED, result);
241 EXPECT_EQ(IntRect(0, 40, 100, 20), frame1->GetDirtyRect());
243 ASSERT_TRUE(frame1.get() != nullptr);
245 BGRAColor blendedColor(0, 0x20, 0x80, 0xA0, true); // already premultiplied
246 EXPECT_EQ(SkPMSrcOver(frameColor1.AsPixel(), frameColor0.AsPixel()),
247 blendedColor.AsPixel());
249 RefPtr<SourceSurface> surface = frame1->GetSourceSurface();
250 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 40, frameColor0));
251 EXPECT_TRUE(RowsAreSolidColor(surface, 40, 20, blendedColor));
252 EXPECT_TRUE(RowsAreSolidColor(surface, 60, 40, frameColor0));
255 TEST(ImageBlendAnimationFilter, RestorePreviousWithOver)
257 RefPtr<image::Decoder> decoder = CreateTrivialBlendingDecoder();
258 ASSERT_TRUE(decoder != nullptr);
260 AnimationParams params0{
261 IntRect(0, 0, 100, 100), FrameTimeout::FromRawMilliseconds(0),
262 /* aFrameNum */ 0, BlendMethod::SOURCE, DisposalMethod::KEEP};
263 BGRAColor frameColor0(0, 0xFF, 0, 0x40);
264 RawAccessFrameRef frame0 = WithBlendAnimationFilter(
265 decoder, params0, IntSize(100, 100),
266 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
267 auto result = aFilter->WritePixels<uint32_t>(
268 [&] { return AsVariant(frameColor0.AsPixel()); });
269 EXPECT_EQ(WriteState::FINISHED, result);
271 EXPECT_EQ(IntRect(0, 0, 100, 100), frame0->GetDirtyRect());
273 AnimationParams params1{
274 IntRect(0, 10, 100, 80), FrameTimeout::FromRawMilliseconds(0),
275 /* aFrameNum */ 1, BlendMethod::SOURCE, DisposalMethod::RESTORE_PREVIOUS};
276 BGRAColor frameColor1 = BGRAColor::Green();
277 RawAccessFrameRef frame1 = WithBlendAnimationFilter(
278 decoder, params1, IntSize(100, 100),
279 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
280 auto result = aFilter->WritePixels<uint32_t>(
281 [&] { return AsVariant(frameColor1.AsPixel()); });
282 EXPECT_EQ(WriteState::FINISHED, result);
284 EXPECT_EQ(IntRect(0, 10, 100, 80), frame1->GetDirtyRect());
286 AnimationParams params2{
287 IntRect(0, 40, 100, 20), FrameTimeout::FromRawMilliseconds(0),
288 /* aFrameNum */ 2, BlendMethod::OVER, DisposalMethod::KEEP};
289 BGRAColor frameColor2(0, 0, 0xFF, 0x80);
290 RawAccessFrameRef frame2 = WithBlendAnimationFilter(
291 decoder, params2, IntSize(100, 100),
292 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
293 auto result = aFilter->WritePixels<uint32_t>(
294 [&] { return AsVariant(frameColor2.AsPixel()); });
295 EXPECT_EQ(WriteState::FINISHED, result);
297 EXPECT_EQ(IntRect(0, 10, 100, 80), frame2->GetDirtyRect());
299 ASSERT_TRUE(frame2.get() != nullptr);
301 BGRAColor blendedColor(0, 0x20, 0x80, 0xA0, true); // already premultiplied
302 EXPECT_EQ(SkPMSrcOver(frameColor2.AsPixel(), frameColor0.AsPixel()),
303 blendedColor.AsPixel());
305 RefPtr<SourceSurface> surface = frame2->GetSourceSurface();
306 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 40, frameColor0));
307 EXPECT_TRUE(RowsAreSolidColor(surface, 40, 20, blendedColor));
308 EXPECT_TRUE(RowsAreSolidColor(surface, 60, 40, frameColor0));
311 TEST(ImageBlendAnimationFilter, RestorePreviousWithSource)
313 RefPtr<image::Decoder> decoder = CreateTrivialBlendingDecoder();
314 ASSERT_TRUE(decoder != nullptr);
316 AnimationParams params0{
317 IntRect(0, 0, 100, 100), FrameTimeout::FromRawMilliseconds(0),
318 /* aFrameNum */ 0, BlendMethod::SOURCE, DisposalMethod::KEEP};
319 BGRAColor frameColor0(0, 0xFF, 0, 0x40);
320 RawAccessFrameRef frame0 = WithBlendAnimationFilter(
321 decoder, params0, IntSize(100, 100),
322 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
323 auto result = aFilter->WritePixels<uint32_t>(
324 [&] { return AsVariant(frameColor0.AsPixel()); });
325 EXPECT_EQ(WriteState::FINISHED, result);
327 EXPECT_EQ(IntRect(0, 0, 100, 100), frame0->GetDirtyRect());
329 AnimationParams params1{
330 IntRect(0, 10, 100, 80), FrameTimeout::FromRawMilliseconds(0),
331 /* aFrameNum */ 1, BlendMethod::SOURCE, DisposalMethod::RESTORE_PREVIOUS};
332 BGRAColor frameColor1 = BGRAColor::Green();
333 RawAccessFrameRef frame1 = WithBlendAnimationFilter(
334 decoder, params1, IntSize(100, 100),
335 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
336 auto result = aFilter->WritePixels<uint32_t>(
337 [&] { return AsVariant(frameColor1.AsPixel()); });
338 EXPECT_EQ(WriteState::FINISHED, result);
340 EXPECT_EQ(IntRect(0, 10, 100, 80), frame1->GetDirtyRect());
342 AnimationParams params2{
343 IntRect(0, 40, 100, 20), FrameTimeout::FromRawMilliseconds(0),
344 /* aFrameNum */ 2, BlendMethod::SOURCE, DisposalMethod::KEEP};
345 BGRAColor frameColor2(0, 0, 0xFF, 0x80);
346 RawAccessFrameRef frame2 = WithBlendAnimationFilter(
347 decoder, params2, IntSize(100, 100),
348 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
349 auto result = aFilter->WritePixels<uint32_t>(
350 [&] { return AsVariant(frameColor2.AsPixel()); });
351 EXPECT_EQ(WriteState::FINISHED, result);
353 EXPECT_EQ(IntRect(0, 10, 100, 80), frame2->GetDirtyRect());
355 ASSERT_TRUE(frame2.get() != nullptr);
357 RefPtr<SourceSurface> surface = frame2->GetSourceSurface();
358 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 40, frameColor0));
359 EXPECT_TRUE(RowsAreSolidColor(surface, 40, 20, frameColor2));
360 EXPECT_TRUE(RowsAreSolidColor(surface, 60, 40, frameColor0));
363 TEST(ImageBlendAnimationFilter, RestorePreviousClearWithSource)
365 RefPtr<image::Decoder> decoder = CreateTrivialBlendingDecoder();
366 ASSERT_TRUE(decoder != nullptr);
368 AnimationParams params0{
369 IntRect(0, 0, 100, 100), FrameTimeout::FromRawMilliseconds(0),
370 /* aFrameNum */ 0, BlendMethod::SOURCE, DisposalMethod::KEEP};
371 BGRAColor frameColor0 = BGRAColor::Red();
372 RawAccessFrameRef frame0 = WithBlendAnimationFilter(
373 decoder, params0, IntSize(100, 100),
374 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
375 auto result = aFilter->WritePixels<uint32_t>(
376 [&] { return AsVariant(frameColor0.AsPixel()); });
377 EXPECT_EQ(WriteState::FINISHED, result);
379 EXPECT_EQ(IntRect(0, 0, 100, 100), frame0->GetDirtyRect());
381 AnimationParams params1{
382 IntRect(0, 0, 100, 20), FrameTimeout::FromRawMilliseconds(0),
383 /* aFrameNum */ 1, BlendMethod::SOURCE, DisposalMethod::CLEAR};
384 BGRAColor frameColor1 = BGRAColor::Blue();
385 RawAccessFrameRef frame1 = WithBlendAnimationFilter(
386 decoder, params1, IntSize(100, 100),
387 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
388 auto result = aFilter->WritePixels<uint32_t>(
389 [&] { return AsVariant(frameColor1.AsPixel()); });
390 EXPECT_EQ(WriteState::FINISHED, result);
392 EXPECT_EQ(IntRect(0, 0, 100, 20), frame1->GetDirtyRect());
394 AnimationParams params2{
395 IntRect(0, 10, 100, 80), FrameTimeout::FromRawMilliseconds(0),
396 /* aFrameNum */ 2, BlendMethod::SOURCE, DisposalMethod::RESTORE_PREVIOUS};
397 BGRAColor frameColor2 = BGRAColor::Green();
398 RawAccessFrameRef frame2 = WithBlendAnimationFilter(
399 decoder, params2, IntSize(100, 100),
400 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
401 auto result = aFilter->WritePixels<uint32_t>(
402 [&] { return AsVariant(frameColor2.AsPixel()); });
403 EXPECT_EQ(WriteState::FINISHED, result);
405 EXPECT_EQ(IntRect(0, 0, 100, 90), frame2->GetDirtyRect());
407 AnimationParams params3{
408 IntRect(0, 40, 100, 20), FrameTimeout::FromRawMilliseconds(0),
409 /* aFrameNum */ 3, BlendMethod::SOURCE, DisposalMethod::KEEP};
410 BGRAColor frameColor3 = BGRAColor::Blue();
411 RawAccessFrameRef frame3 = WithBlendAnimationFilter(
412 decoder, params3, IntSize(100, 100),
413 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
414 auto result = aFilter->WritePixels<uint32_t>(
415 [&] { return AsVariant(frameColor3.AsPixel()); });
416 EXPECT_EQ(WriteState::FINISHED, result);
418 EXPECT_EQ(IntRect(0, 0, 100, 90), frame3->GetDirtyRect());
420 ASSERT_TRUE(frame3.get() != nullptr);
422 RefPtr<SourceSurface> surface = frame3->GetSourceSurface();
423 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 20, BGRAColor::Transparent()));
424 EXPECT_TRUE(RowsAreSolidColor(surface, 20, 20, frameColor0));
425 EXPECT_TRUE(RowsAreSolidColor(surface, 40, 20, frameColor3));
426 EXPECT_TRUE(RowsAreSolidColor(surface, 60, 40, frameColor0));
429 TEST(ImageBlendAnimationFilter, PartialOverlapFrameRect)
431 RefPtr<image::Decoder> decoder = CreateTrivialBlendingDecoder();
432 ASSERT_TRUE(decoder != nullptr);
434 AnimationParams params0{
435 IntRect(-10, -20, 110, 100), FrameTimeout::FromRawMilliseconds(0),
436 /* aFrameNum */ 0, BlendMethod::SOURCE, DisposalMethod::KEEP};
437 BGRAColor frameColor0 = BGRAColor::Red();
438 RawAccessFrameRef frame0 = WithBlendAnimationFilter(
439 decoder, params0, IntSize(100, 100),
440 [&](image::Decoder* aDecoder, SurfaceFilter* aFilter) {
441 auto result = aFilter->WritePixels<uint32_t>(
442 [&] { return AsVariant(frameColor0.AsPixel()); });
443 EXPECT_EQ(WriteState::FINISHED, result);
445 EXPECT_EQ(IntRect(0, 0, 100, 100), frame0->GetDirtyRect());
447 RefPtr<SourceSurface> surface = frame0->GetSourceSurface();
448 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 80, frameColor0));
449 EXPECT_TRUE(RowsAreSolidColor(surface, 80, 20, BGRAColor::Transparent()));