1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 #include <cppuhelper/compbase1.hxx>
23 #include <comphelper/broadcasthelper.hxx>
24
25 #include <basegfx/matrix/b2dhommatrix.hxx>
26 #include <basegfx/range/b2drectangle.hxx>
27 #include <cppcanvas/spritecanvas.hxx>
28
29 #include "view.hxx"
30 #include "unoview.hxx"
31 #include "unoviewcontainer.hxx"
32 #include "shape.hxx"
33 #include "tests.hxx"
34 #include "../engine/slide/layermanager.hxx"
35 #include "../engine/slide/layer.hxx"
36 #include "gtest/gtest.h"
37 #include "com/sun/star/presentation/XSlideShowView.hpp"
38
39 namespace target = slideshow::internal;
40 using namespace ::com::sun::star;
41
42 // FIXME:
43 #define RUN_OLD_FAILING_TESTS 0
44
45 namespace
46 {
47
48 class LayerManagerTest : public ::testing::Test
49 {
50 protected:
51 target::UnoViewContainer maViews;
52 target::LayerManagerSharedPtr mpLayerManager;
53 TestViewSharedPtr mpTestView;
54 TestShapeSharedPtr mpTestShape;
55
56 public:
SetUp()57 virtual void SetUp()
58 {
59 mpTestShape = createTestShape(
60 basegfx::B2DRange(0.0,0.0,10.0,10.0),
61 1.0);
62 mpTestView = createTestView();
63 maViews.addView( mpTestView );
64
65 mpLayerManager.reset(
66 new target::LayerManager(
67 maViews,
68 basegfx::B2DRange(0.0,0.0,100.0,100.0),
69 false ));
70 }
71
TearDown()72 virtual void TearDown()
73 {
74 mpLayerManager.reset();
75 maViews.dispose();
76 }
77 }; // class LayerManagerTest
78
79
TEST_F(LayerManagerTest,testLayer)80 TEST_F(LayerManagerTest, testLayer)
81 {
82 target::LayerSharedPtr pBgLayer(
83 target::Layer::createBackgroundLayer( basegfx::B2DRange(0,0,100,100) ) );
84 pBgLayer->addView( mpTestView );
85
86 target::LayerSharedPtr pFgLayer(
87 target::Layer::createLayer( basegfx::B2DRange(0,0,100,100) ) );
88 pFgLayer->addView( mpTestView );
89
90 ASSERT_TRUE( pBgLayer->isBackgroundLayer() ) << "BG layer must confess that!";
91 ASSERT_TRUE( !pFgLayer->isBackgroundLayer() ) << "FG layer lies!";
92
93 ASSERT_TRUE( !pBgLayer->isUpdatePending() ) << "BG layer must not have pending updates!";
94 pBgLayer->addUpdateRange( basegfx::B2DRange(0,0,10,10) );
95 ASSERT_TRUE( pBgLayer->isUpdatePending() ) << "BG layer must have pending updates!";
96
97 TestShapeSharedPtr pTestShape = createTestShape(
98 basegfx::B2DRange(0.0,0.0,1000.0,1000.0),
99 1.0);
100 pBgLayer->updateBounds( pTestShape );
101 ASSERT_TRUE( !pBgLayer->commitBounds() ) << "BG layer must not resize!";
102
103 TestShapeSharedPtr pTestShape2 = createTestShape(
104 basegfx::B2DRange(0.0,0.0,1.0,1.0),
105 1.0);
106 pFgLayer->updateBounds( pTestShape2 );
107 ASSERT_TRUE( pFgLayer->commitBounds() ) << "FG layer must resize!";
108 }
109
TEST_F(LayerManagerTest,testBasics)110 TEST_F(LayerManagerTest, testBasics)
111 {
112 mpLayerManager->activate( false );
113
114 ASSERT_TRUE( mpTestShape->getViewLayers().empty() ) << "Un-added shape must have zero view layers";
115 mpLayerManager->addShape(mpTestShape);
116 ASSERT_TRUE( mpLayerManager->isUpdatePending() ) << "Adding a shape requires a LayerManager update";
117
118 // update does the delayed viewAdded call to the shape
119 ASSERT_TRUE( mpLayerManager->update() ) << "Update failed on LayerManager";
120 ASSERT_TRUE( mpTestShape->getViewLayers().size() == 1 ) << "Added shape must have one view layer";
121 ASSERT_TRUE( mpTestShape->getNumRenders() ) << "Shape must been rendered";
122 ASSERT_TRUE( !mpTestShape->getNumUpdates() ) << "Shape must not been updated";
123
124 // test second view, check whether shape gets additional view
125 TestViewSharedPtr pTestView( createTestView() );
126 ASSERT_TRUE( maViews.addView( pTestView ) ) << "Adding second View failed";
127 ASSERT_TRUE( maViews.end() - maViews.begin() == 2 ) << "View container must have two views";
128 mpLayerManager->viewAdded(pTestView);
129 ASSERT_TRUE( mpTestShape->getViewLayers().size() == 2 ) << "Added shape must have two view layers";
130
131 ASSERT_TRUE( maViews.removeView( pTestView ) ) << "Removing second View failed";
132 mpLayerManager->viewRemoved(pTestView);
133 ASSERT_TRUE( mpTestShape->getViewLayers().size() == 1 ) << "Added shape must have one view layer";
134
135 mpLayerManager->deactivate();
136 }
137
TEST_F(LayerManagerTest,testShapeOrdering)138 TEST_F(LayerManagerTest, testShapeOrdering)
139 {
140 TestShapeSharedPtr pShape2( createTestShape(
141 basegfx::B2DRange(0.0,0.0,10.0,10.0),
142 2.0));
143 TestShapeSharedPtr pShape3( createTestShape(
144 basegfx::B2DRange(0.0,0.0,10.0,10.0),
145 3.0));
146 TestShapeSharedPtr pShape4( createTestShape(
147 basegfx::B2DRange(0.0,0.0,10.0,10.0),
148 4.0));
149
150 mpLayerManager->addShape(mpTestShape);
151 mpLayerManager->addShape(pShape2);
152 mpLayerManager->addShape(pShape3);
153 mpLayerManager->addShape(pShape4);
154
155 mpLayerManager->activate( false );
156
157 // update does the delayed viewAdded call to the shape
158 ASSERT_TRUE( mpLayerManager->update() ) << "Update failed on LayerManager";
159 ASSERT_TRUE( mpTestView->getViewLayers().empty() ) << "View must have background layer only";
160
161 // LayerManager must now generate one extra view layer
162 mpLayerManager->enterAnimationMode(pShape2);
163 ASSERT_TRUE( mpLayerManager->isUpdatePending() ) << "No update pending on LayerManager";
164 ASSERT_TRUE( mpLayerManager->update() ) << "Update failed on LayerManager";
165 ASSERT_TRUE( mpTestView->getViewLayers().size() == 1 ) << "View must have one extra layer only";
166 ASSERT_TRUE( mpTestView->getViewLayers().at(0)->getBounds() ==
167 basegfx::B2DRange(0.0,0.0,10.0,10.0) ) << "View layer must have 10x10 size";
168
169 // LayerManager must now remove the extra view layer
170 mpLayerManager->leaveAnimationMode(pShape2);
171 ASSERT_TRUE( mpLayerManager->isUpdatePending() ) << "No update pending on LayerManager";
172 ASSERT_TRUE( mpLayerManager->update() ) << "Update failed on LayerManager #2";
173 ASSERT_TRUE( mpTestShape->getViewLayers().at(0).first == mpTestView ) << "Shape 1 must be on background layer";
174 ASSERT_TRUE( pShape2->getViewLayers().at(0).first == mpTestView ) << "Shape 2 must be on background layer";
175 ASSERT_TRUE( pShape3->getViewLayers().size() == 1 ) << "Shape 3 must have one layer";
176 ASSERT_TRUE( pShape3->getViewLayers().at(0).first == mpTestView ) << "Shape 3 must be on background layer";
177 ASSERT_TRUE( pShape4->getViewLayers().at(0).first == mpTestView ) << "Shape 4 must be on background layer";
178
179 // checking deactivation (all layers except background layer
180 // must vanish)
181 mpLayerManager->enterAnimationMode(pShape3);
182 ASSERT_TRUE( mpLayerManager->isUpdatePending() ) << "No update pending on LayerManager";
183 ASSERT_TRUE( mpLayerManager->update() ) << "Update failed on LayerManager";
184 ASSERT_TRUE( pShape4->getViewLayers().at(0).first != mpTestView ) << "Shape 4 must not be on background layer";
185 mpLayerManager->leaveAnimationMode(pShape3);
186 ASSERT_TRUE( mpLayerManager->update() ) << "Update failed on LayerManager";
187 ASSERT_TRUE( pShape4->getViewLayers().at(0).first == mpTestView ) << "Shape 4 must be on background layer";
188
189 mpLayerManager->deactivate();
190 ASSERT_TRUE( !mpLayerManager->isUpdatePending() ) << "Update pending on deactivated LayerManager";
191 }
192
TEST_F(LayerManagerTest,testShapeRepaint)193 TEST_F(LayerManagerTest, testShapeRepaint)
194 {
195 TestShapeSharedPtr pShape2( createTestShape(
196 basegfx::B2DRange(0.0,0.0,10.0,10.0),
197 2.0));
198 TestShapeSharedPtr pShape3( createTestShape(
199 basegfx::B2DRange(0.0,0.0,10.0,10.0),
200 3.0));
201 TestShapeSharedPtr pShape4( createTestShape(
202 basegfx::B2DRange(0.0,0.0,10.0,10.0),
203 4.0));
204 // NB: priority must differ from pShape4's. Shape::lessThanShape
205 // tie-breaks equal priorities on raw pointer value, so two shapes at the
206 // same priority order by heap address -- which makes updateShapeLayers()
207 // assign them to layers differently depending on allocation history, and
208 // this test then passes or fails with the wind (it survived on x86 and
209 // failed on x64; --gtest_shuffle flips it on either). The tie cannot
210 // occur in production: ShapeImporter hands out priorities from a running
211 // counter (mnAscendingPrio += 1.0 per shape), so they are unique by
212 // construction, and the pointer tie-break exists only to stop std::set
213 // from treating two shapes as equivalent and dropping one.
214 TestShapeSharedPtr pShape5( createTestShape(
215 basegfx::B2DRange(20.0,20.0,30.0,30.0),
216 5.0));
217
218 mpLayerManager->addShape(mpTestShape);
219 mpLayerManager->addShape(pShape2);
220 mpLayerManager->enterAnimationMode(pShape2);
221 mpLayerManager->addShape(pShape3);
222 mpLayerManager->addShape(pShape4);
223 mpLayerManager->addShape(pShape5);
224
225 mpLayerManager->activate( false );
226 mpLayerManager->update();
227
228 ASSERT_TRUE( mpTestShape->getNumRenders() == 1 ) << "First shape not rendered";
229 #if RUN_OLD_FAILING_TESTS
230 ASSERT_TRUE( pShape2->getNumRenders() == 1 ) << "Second shape not rendered";
231 #endif
232 ASSERT_TRUE( pShape3->getNumRenders() == 1 ) << "Third shape not rendered";
233 ASSERT_TRUE( pShape4->getNumRenders() == 1 ) << "Fourth shape not rendered";
234 ASSERT_TRUE( pShape5->getNumRenders() == 1 ) << "Fifth shape not rendered";
235
236 mpLayerManager->enterAnimationMode(pShape4);
237 mpLayerManager->update();
238
239 ASSERT_TRUE( mpTestShape->getNumRenders() == 1 ) << "First shape not rendered";
240 #if RUN_OLD_FAILING_TESTS
241 ASSERT_TRUE( pShape2->getNumRenders() == 1 ) << "Second shape not rendered";
242 #endif
243 ASSERT_TRUE( pShape3->getNumRenders() == 2 ) << "Third shape not rendered";
244 ASSERT_TRUE( pShape4->getNumRenders() == 2 ) << "Fourth shape not rendered";
245 ASSERT_TRUE( pShape5->getNumRenders() == 2 ) << "Fifth shape not rendered";
246
247 mpLayerManager->leaveAnimationMode(pShape2);
248 mpLayerManager->leaveAnimationMode(pShape4);
249 mpLayerManager->update();
250
251 ASSERT_TRUE( mpTestShape->getNumRenders() == 2 ) << "First shape not rendered #2";
252 #if RUN_OLD_FAILING_TESTS
253 ASSERT_TRUE( pShape2->getNumRenders() == 2 ) << "Second shape not rendered #2"
254 #endif
255 ASSERT_TRUE( pShape3->getNumRenders() == 3 ) << "Third shape not rendered #2";
256 ASSERT_TRUE( pShape4->getNumRenders() == 3 ) << "Fourth shape not rendered #2";
257 ASSERT_TRUE( pShape5->getNumRenders() == 3 ) << "Fifth shape not rendered #2";
258 }
259
TEST_F(LayerManagerTest,testRefCounting)260 TEST_F(LayerManagerTest, testRefCounting)
261 {
262 TestShapeSharedPtr pShape2( createTestShape(
263 basegfx::B2DRange(0.0,0.0,10.0,10.0),
264 2.0));
265 TestShapeSharedPtr pShape3( createTestShape(
266 basegfx::B2DRange(0.0,0.0,10.0,10.0),
267 3.0));
268 TestShapeSharedPtr pShape4( createTestShape(
269 basegfx::B2DRange(0.0,0.0,10.0,10.0),
270 4.0));
271
272 mpLayerManager->addShape(mpTestShape);
273 mpLayerManager->addShape(pShape2);
274 mpLayerManager->addShape(pShape3);
275 mpLayerManager->addShape(pShape4);
276
277 mpLayerManager->removeShape(mpTestShape);
278 mpLayerManager->removeShape(pShape2);
279 mpLayerManager->removeShape(pShape3);
280 mpLayerManager->removeShape(pShape4);
281
282 ASSERT_TRUE( mpTestShape.use_count() == 1 ) << "Shape 1 must have refcount of 1";
283 ASSERT_TRUE( pShape2.use_count() == 1 ) << "Shape 2 must have refcount of 1";
284 ASSERT_TRUE( pShape3.use_count() == 1 ) << "Shape 3 must have refcount of 1";
285 ASSERT_TRUE( pShape4.use_count() == 1 ) << "Shape 4 must have refcount of 1";
286
287
288 mpLayerManager->addShape(mpTestShape);
289 mpLayerManager->addShape(pShape2);
290 mpLayerManager->addShape(pShape3);
291 mpLayerManager->addShape(pShape4);
292
293 mpLayerManager->activate( false );
294 mpLayerManager->update();
295
296 mpLayerManager->removeShape(mpTestShape);
297 mpLayerManager->removeShape(pShape2);
298 mpLayerManager->removeShape(pShape3);
299 mpLayerManager->removeShape(pShape4);
300
301 ASSERT_TRUE( mpTestShape.use_count() == 1 ) << "Shape 1 must have refcount of 1";
302 ASSERT_TRUE( pShape2.use_count() == 1 ) << "Shape 2 must have refcount of 1";
303 ASSERT_TRUE( pShape3.use_count() == 1 ) << "Shape 3 must have refcount of 1";
304 ASSERT_TRUE( pShape4.use_count() == 1 ) << "Shape 4 must have refcount of 1";
305
306 maViews.removeView(mpTestView);
307 mpLayerManager->viewRemoved(mpTestView);
308 ASSERT_TRUE( mpTestView.use_count() == 1 ) << "View must have refcount of 1";
309 }
310
311
312 } // namespace
313