OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/layout/ImageQualityController.h" | 5 #include "core/layout/ImageQualityController.h" |
6 | 6 |
7 #include "core/layout/LayoutImage.h" | 7 #include "core/layout/LayoutImage.h" |
8 #include "core/layout/LayoutTestHelper.h" | 8 #include "core/layout/LayoutTestHelper.h" |
9 #include "platform/graphics/GraphicsContext.h" | 9 #include "platform/graphics/GraphicsContext.h" |
10 #include "platform/graphics/paint/PaintController.h" | 10 #include "platform/graphics/paint/PaintController.h" |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 | 109 |
110 RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality); | 110 RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality); |
111 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img
, testImage.get(), testImage.get(), LayoutSize(1, 1))); | 111 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img
, testImage.get(), testImage.get(), LayoutSize(1, 1))); |
112 } | 112 } |
113 | 113 |
114 // TODO(alexclarke): Remove this when possible. | 114 // TODO(alexclarke): Remove this when possible. |
115 class MockTimer : public TaskRunnerTimer<ImageQualityController> { | 115 class MockTimer : public TaskRunnerTimer<ImageQualityController> { |
116 public: | 116 public: |
117 using TimerFiredFunction = typename TaskRunnerTimer<ImageQualityController>:
:TimerFiredFunction; | 117 using TimerFiredFunction = typename TaskRunnerTimer<ImageQualityController>:
:TimerFiredFunction; |
118 | 118 |
119 MockTimer(ImageQualityController* o, TimerFiredFunction f) | 119 static std::unique_ptr<MockTimer> create(ImageQualityController* o, TimerFir
edFunction f) |
120 : TaskRunnerTimer(&m_taskRunner, o, f) | |
121 { | 120 { |
| 121 auto taskRunner = WTF::wrapUnique(new scheduler::FakeWebTaskRunner); |
| 122 return WTF::wrapUnique(new MockTimer(std::move(taskRunner), o, f)); |
122 } | 123 } |
123 | 124 |
124 void fire() | 125 void fire() |
125 { | 126 { |
126 fired(); | 127 fired(); |
127 stop(); | 128 stop(); |
128 } | 129 } |
129 | 130 |
130 void setTime(double newTime) | 131 void setTime(double newTime) |
131 { | 132 { |
132 m_taskRunner.setTime(newTime); | 133 m_taskRunner->setTime(newTime); |
133 } | 134 } |
134 | 135 |
135 private: | 136 private: |
136 scheduler::FakeWebTaskRunner m_taskRunner; | 137 MockTimer(std::unique_ptr<scheduler::FakeWebTaskRunner> taskRunner, ImageQua
lityController* o, TimerFiredFunction f) |
| 138 : TaskRunnerTimer(taskRunner.get(), o, f) |
| 139 , m_taskRunner(std::move(taskRunner)) |
| 140 { |
| 141 } |
| 142 |
| 143 std::unique_ptr<scheduler::FakeWebTaskRunner> m_taskRunner; |
| 144 |
| 145 DISALLOW_COPY_AND_ASSIGN(MockTimer); |
137 }; | 146 }; |
138 | 147 |
139 TEST_F(ImageQualityControllerTest, LowQualityFilterForResizingImage) | 148 TEST_F(ImageQualityControllerTest, LowQualityFilterForResizingImage) |
140 { | 149 { |
141 MockTimer* mockTimer = new MockTimer(controller(), &ImageQualityController::
highQualityRepaintTimerFired); | 150 MockTimer* mockTimer = MockTimer::create(controller(), &ImageQualityControll
er::highQualityRepaintTimerFired).release(); |
142 controller()->setTimer(wrapUnique(mockTimer)); | 151 controller()->setTimer(wrapUnique(mockTimer)); |
143 setBodyInnerHTML("<img src='myimage'></img>"); | 152 setBodyInnerHTML("<img src='myimage'></img>"); |
144 LayoutImage* img = toLayoutImage(document().body()->firstChild()->layoutObje
ct()); | 153 LayoutImage* img = toLayoutImage(document().body()->firstChild()->layoutObje
ct()); |
145 | 154 |
146 RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality); | 155 RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality); |
147 std::unique_ptr<PaintController> paintController = PaintController::create()
; | 156 std::unique_ptr<PaintController> paintController = PaintController::create()
; |
148 GraphicsContext context(*paintController); | 157 GraphicsContext context(*paintController); |
149 | 158 |
150 // Paint once. This will kick off a timer to see if we resize it during that
timer's execution. | 159 // Paint once. This will kick off a timer to see if we resize it during that
timer's execution. |
151 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img
, testImage.get(), testImage.get(), LayoutSize(2, 2))); | 160 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img
, testImage.get(), testImage.get(), LayoutSize(2, 2))); |
152 | 161 |
153 // Go into low-quality mode now that the size changed. | 162 // Go into low-quality mode now that the size changed. |
154 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, t
estImage.get(), testImage.get(), LayoutSize(3, 3))); | 163 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, t
estImage.get(), testImage.get(), LayoutSize(3, 3))); |
155 | 164 |
156 // Stay in low-quality mode since the size changed again. | 165 // Stay in low-quality mode since the size changed again. |
157 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, t
estImage.get(), testImage.get(), LayoutSize(4, 4))); | 166 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, t
estImage.get(), testImage.get(), LayoutSize(4, 4))); |
158 | 167 |
159 mockTimer->fire(); | 168 mockTimer->fire(); |
160 // The timer fired before painting at another size, so this doesn't count as
animation. Therefore not painting at low quality. | 169 // The timer fired before painting at another size, so this doesn't count as
animation. Therefore not painting at low quality. |
161 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img
, testImage.get(), testImage.get(), LayoutSize(4, 4))); | 170 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img
, testImage.get(), testImage.get(), LayoutSize(4, 4))); |
162 } | 171 } |
163 | 172 |
164 TEST_F(ImageQualityControllerTest, MediumQualityFilterForNotAnimatedWhileAnother
Animates) | 173 TEST_F(ImageQualityControllerTest, MediumQualityFilterForNotAnimatedWhileAnother
Animates) |
165 { | 174 { |
166 MockTimer* mockTimer = new MockTimer(controller(), &ImageQualityController::
highQualityRepaintTimerFired); | 175 MockTimer* mockTimer = MockTimer::create(controller(), &ImageQualityControll
er::highQualityRepaintTimerFired).release(); |
167 controller()->setTimer(wrapUnique(mockTimer)); | 176 controller()->setTimer(wrapUnique(mockTimer)); |
168 setBodyInnerHTML("<img id='myAnimatingImage' src='myimage'></img> <img id='m
yNonAnimatingImage' src='myimage2'></img>"); | 177 setBodyInnerHTML("<img id='myAnimatingImage' src='myimage'></img> <img id='m
yNonAnimatingImage' src='myimage2'></img>"); |
169 LayoutImage* animatingImage = toLayoutImage(document().getElementById("myAni
matingImage")->layoutObject()); | 178 LayoutImage* animatingImage = toLayoutImage(document().getElementById("myAni
matingImage")->layoutObject()); |
170 LayoutImage* nonAnimatingImage = toLayoutImage(document().getElementById("my
NonAnimatingImage")->layoutObject()); | 179 LayoutImage* nonAnimatingImage = toLayoutImage(document().getElementById("my
NonAnimatingImage")->layoutObject()); |
171 | 180 |
172 RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality); | 181 RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality); |
173 std::unique_ptr<PaintController> paintController = PaintController::create()
; | 182 std::unique_ptr<PaintController> paintController = PaintController::create()
; |
174 GraphicsContext context(*paintController); | 183 GraphicsContext context(*paintController); |
175 | 184 |
176 // Paint once. This will kick off a timer to see if we resize it during that
timer's execution. | 185 // Paint once. This will kick off a timer to see if we resize it during that
timer's execution. |
177 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*ani
matingImage, testImage.get(), testImage.get(), LayoutSize(2, 2))); | 186 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*ani
matingImage, testImage.get(), testImage.get(), LayoutSize(2, 2))); |
178 | 187 |
179 // Go into low-quality mode now that the size changed. | 188 // Go into low-quality mode now that the size changed. |
180 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*animat
ingImage, testImage.get(), testImage.get(), LayoutSize(3, 3))); | 189 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*animat
ingImage, testImage.get(), testImage.get(), LayoutSize(3, 3))); |
181 | 190 |
182 // The non-animating image receives a medium-quality filter, even though the
other one is animating. | 191 // The non-animating image receives a medium-quality filter, even though the
other one is animating. |
183 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*non
AnimatingImage, testImage.get(), testImage.get(), LayoutSize(4, 4))); | 192 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*non
AnimatingImage, testImage.get(), testImage.get(), LayoutSize(4, 4))); |
184 | 193 |
185 // Now the second image has animated, so it also gets painted with a low-qua
lity filter. | 194 // Now the second image has animated, so it also gets painted with a low-qua
lity filter. |
186 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*nonAni
matingImage, testImage.get(), testImage.get(), LayoutSize(3, 3))); | 195 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*nonAni
matingImage, testImage.get(), testImage.get(), LayoutSize(3, 3))); |
187 | 196 |
188 mockTimer->fire(); | 197 mockTimer->fire(); |
189 // The timer fired before painting at another size, so this doesn't count as
animation. Therefore not painting at low quality for any image. | 198 // The timer fired before painting at another size, so this doesn't count as
animation. Therefore not painting at low quality for any image. |
190 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*ani
matingImage, testImage.get(), testImage.get(), LayoutSize(4, 4))); | 199 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*ani
matingImage, testImage.get(), testImage.get(), LayoutSize(4, 4))); |
191 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*non
AnimatingImage, testImage.get(), testImage.get(), LayoutSize(4, 4))); | 200 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*non
AnimatingImage, testImage.get(), testImage.get(), LayoutSize(4, 4))); |
192 } | 201 } |
193 | 202 |
194 TEST_F(ImageQualityControllerTest, DontKickTheAnimationTimerWhenPaintingAtTheSam
eSize) | 203 TEST_F(ImageQualityControllerTest, DontKickTheAnimationTimerWhenPaintingAtTheSam
eSize) |
195 { | 204 { |
196 MockTimer* mockTimer = new MockTimer(controller(), &ImageQualityController::
highQualityRepaintTimerFired); | 205 MockTimer* mockTimer = MockTimer::create(controller(), &ImageQualityControll
er::highQualityRepaintTimerFired).release(); |
197 controller()->setTimer(wrapUnique(mockTimer)); | 206 controller()->setTimer(wrapUnique(mockTimer)); |
198 setBodyInnerHTML("<img src='myimage'></img>"); | 207 setBodyInnerHTML("<img src='myimage'></img>"); |
199 LayoutImage* img = toLayoutImage(document().body()->firstChild()->layoutObje
ct()); | 208 LayoutImage* img = toLayoutImage(document().body()->firstChild()->layoutObje
ct()); |
200 | 209 |
201 RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality); | 210 RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality); |
202 | 211 |
203 // Paint once. This will kick off a timer to see if we resize it during that
timer's execution. | 212 // Paint once. This will kick off a timer to see if we resize it during that
timer's execution. |
204 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img
, testImage.get(), testImage.get(), LayoutSize(2, 2))); | 213 EXPECT_EQ(InterpolationMedium, controller()->chooseInterpolationQuality(*img
, testImage.get(), testImage.get(), LayoutSize(2, 2))); |
205 | 214 |
206 // Go into low-quality mode now that the size changed. | 215 // Go into low-quality mode now that the size changed. |
207 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, t
estImage.get(), testImage.get(), LayoutSize(3, 3))); | 216 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, t
estImage.get(), testImage.get(), LayoutSize(3, 3))); |
208 | 217 |
209 // Stay in low-quality mode since the size changed again. | 218 // Stay in low-quality mode since the size changed again. |
210 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, t
estImage.get(), testImage.get(), LayoutSize(4, 4))); | 219 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, t
estImage.get(), testImage.get(), LayoutSize(4, 4))); |
211 | 220 |
212 mockTimer->stop(); | 221 mockTimer->stop(); |
213 EXPECT_FALSE(mockTimer->isActive()); | 222 EXPECT_FALSE(mockTimer->isActive()); |
214 // Painted at the same size, so even though timer is still executing, don't
go to low quality. | 223 // Painted at the same size, so even though timer is still executing, don't
go to low quality. |
215 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, t
estImage.get(), testImage.get(), LayoutSize(4, 4))); | 224 EXPECT_EQ(InterpolationLow, controller()->chooseInterpolationQuality(*img, t
estImage.get(), testImage.get(), LayoutSize(4, 4))); |
216 // Check that the timer was not kicked. It should not have been, since the i
mage was painted at the same size as last time. | 225 // Check that the timer was not kicked. It should not have been, since the i
mage was painted at the same size as last time. |
217 EXPECT_FALSE(mockTimer->isActive()); | 226 EXPECT_FALSE(mockTimer->isActive()); |
218 } | 227 } |
219 | 228 |
220 TEST_F(ImageQualityControllerTest, DontRestartTimerUnlessAdvanced) | 229 TEST_F(ImageQualityControllerTest, DontRestartTimerUnlessAdvanced) |
221 { | 230 { |
222 MockTimer* mockTimer = new MockTimer(controller(), &ImageQualityController::
highQualityRepaintTimerFired); | 231 MockTimer* mockTimer = MockTimer::create(controller(), &ImageQualityControll
er::highQualityRepaintTimerFired).release(); |
223 controller()->setTimer(wrapUnique(mockTimer)); | 232 controller()->setTimer(wrapUnique(mockTimer)); |
224 setBodyInnerHTML("<img src='myimage'></img>"); | 233 setBodyInnerHTML("<img src='myimage'></img>"); |
225 LayoutImage* img = toLayoutImage(document().body()->firstChild()->layoutObje
ct()); | 234 LayoutImage* img = toLayoutImage(document().body()->firstChild()->layoutObje
ct()); |
226 | 235 |
227 RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality); | 236 RefPtr<TestImageLowQuality> testImage = adoptRef(new TestImageLowQuality); |
228 | 237 |
229 // Paint once. This will kick off a timer to see if we resize it during that
timer's execution. | 238 // Paint once. This will kick off a timer to see if we resize it during that
timer's execution. |
230 mockTimer->setTime(0.1); | 239 mockTimer->setTime(0.1); |
231 EXPECT_FALSE(controller()->shouldPaintAtLowQuality(*img, testImage.get(), te
stImage.get(), LayoutSize(2, 2), 0.1)); | 240 EXPECT_FALSE(controller()->shouldPaintAtLowQuality(*img, testImage.get(), te
stImage.get(), LayoutSize(2, 2), 0.1)); |
232 EXPECT_EQ(ImageQualityController::cLowQualityTimeThreshold, mockTimer->nextF
ireInterval()); | 241 EXPECT_EQ(ImageQualityController::cLowQualityTimeThreshold, mockTimer->nextF
ireInterval()); |
233 | 242 |
234 // Go into low-quality mode now that the size changed. | 243 // Go into low-quality mode now that the size changed. |
235 double nextTime = 0.1 + ImageQualityController::cTimerRestartThreshold / 2.0
; | 244 double nextTime = 0.1 + ImageQualityController::cTimerRestartThreshold / 2.0
; |
236 mockTimer->setTime(nextTime); | 245 mockTimer->setTime(nextTime); |
237 EXPECT_EQ(true, controller()->shouldPaintAtLowQuality(*img, testImage.get(),
testImage.get(), LayoutSize(3, 3), nextTime)); | 246 EXPECT_EQ(true, controller()->shouldPaintAtLowQuality(*img, testImage.get(),
testImage.get(), LayoutSize(3, 3), nextTime)); |
238 // The fire interval has decreased, because we have not restarted the timer. | 247 // The fire interval has decreased, because we have not restarted the timer. |
239 EXPECT_EQ(ImageQualityController::cLowQualityTimeThreshold - ImageQualityCon
troller::cTimerRestartThreshold / 2.0, mockTimer->nextFireInterval()); | 248 EXPECT_EQ(ImageQualityController::cLowQualityTimeThreshold - ImageQualityCon
troller::cTimerRestartThreshold / 2.0, mockTimer->nextFireInterval()); |
240 | 249 |
241 // This animation is far enough in the future to make the timer restart, sin
ce it is half over. | 250 // This animation is far enough in the future to make the timer restart, sin
ce it is half over. |
242 nextTime = 0.1 + ImageQualityController::cTimerRestartThreshold + 0.01; | 251 nextTime = 0.1 + ImageQualityController::cTimerRestartThreshold + 0.01; |
243 EXPECT_EQ(true, controller()->shouldPaintAtLowQuality(*img, testImage.get(),
testImage.get(), LayoutSize(4, 4), nextTime)); | 252 EXPECT_EQ(true, controller()->shouldPaintAtLowQuality(*img, testImage.get(),
testImage.get(), LayoutSize(4, 4), nextTime)); |
244 // Now the timer has restarted, leading to a larger fire interval. | 253 // Now the timer has restarted, leading to a larger fire interval. |
245 EXPECT_EQ(ImageQualityController::cLowQualityTimeThreshold, mockTimer->nextF
ireInterval()); | 254 EXPECT_EQ(ImageQualityController::cLowQualityTimeThreshold, mockTimer->nextF
ireInterval()); |
246 } | 255 } |
247 | 256 |
248 #endif | 257 #endif |
249 | 258 |
250 } // namespace blink | 259 } // namespace blink |
OLD | NEW |