| 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 |