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
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
,
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();
54 decoderHelper
.PostFrameStop(Opacity::SOME_TRANSPARENCY
);
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,
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)));
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()));