Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "SlsLayeredDevice.hxx"
31 : :
32 : : #include <vcl/window.hxx>
33 : : #include <vcl/virdev.hxx>
34 : :
35 : : #include <boost/bind.hpp>
36 : : #include <boost/function.hpp>
37 : :
38 : :
39 : : namespace sd { namespace slidesorter { namespace view {
40 : :
41 : : namespace {
42 : : static const sal_Int32 gnMaximumLayerCount = 8;
43 : :
44 : : class LayerInvalidator : public ILayerInvalidator
45 : : {
46 : : public:
47 : 260 : LayerInvalidator (
48 : : const ::boost::shared_ptr<LayeredDevice>& rpLayeredDevice,
49 : : const SharedSdWindow& rpTargetWindow,
50 : : const int nLayer)
51 : : : mpLayeredDevice(rpLayeredDevice),
52 : : mpTargetWindow(rpTargetWindow),
53 [ + - ][ + - ]: 260 : mnLayer(nLayer)
54 : : {
55 : 260 : }
56 : :
57 : 520 : virtual ~LayerInvalidator ( )
58 [ + - ][ + - ]: 260 : {
59 [ - + ]: 520 : }
60 : :
61 : 0 : virtual void Invalidate (const Rectangle& rInvalidationBox)
62 : : {
63 : 0 : mpLayeredDevice->Invalidate(rInvalidationBox, mnLayer);
64 : 0 : mpTargetWindow->Invalidate(rInvalidationBox);
65 : 0 : }
66 : :
67 : : private:
68 : : const ::boost::shared_ptr<LayeredDevice> mpLayeredDevice;
69 : : SharedSdWindow mpTargetWindow;
70 : : const int mnLayer;
71 : : };
72 : :
73 : 636 : void DeviceCopy (
74 : : OutputDevice& rTargetDevice,
75 : : OutputDevice& rSourceDevice,
76 : : const Rectangle& rBox)
77 : : {
78 : : rTargetDevice.DrawOutDev(
79 : : rBox.TopLeft(),
80 : : rBox.GetSize(),
81 : : rBox.TopLeft(),
82 : : rBox.GetSize(),
83 [ + - ][ + - ]: 636 : rSourceDevice);
84 : 636 : }
85 : :
86 : :
87 : 636 : void ForAllRectangles (const Region& rRegion, ::boost::function<void(const Rectangle&)> aFunction)
88 : : {
89 : : OSL_ASSERT(aFunction);
90 : :
91 [ + - ]: 636 : if (rRegion.GetRectCount() <= 1)
92 : : {
93 [ + - ]: 636 : aFunction(rRegion.GetBoundRect());
94 : : }
95 : : else
96 : : {
97 [ # # ]: 0 : Region aMutableRegionCopy (rRegion);
98 [ # # ]: 0 : RegionHandle aHandle(aMutableRegionCopy.BeginEnumRects());
99 [ # # ]: 0 : Rectangle aBox;
100 [ # # ][ # # ]: 0 : while (aMutableRegionCopy.GetNextEnumRect(aHandle, aBox))
101 [ # # ]: 0 : aFunction(aBox);
102 [ # # ][ # # ]: 0 : aMutableRegionCopy.EndEnumRects(aHandle);
103 : : }
104 : 636 : }
105 : :
106 : : class Layer : private ::boost::noncopyable
107 : : {
108 : : public:
109 : : Layer (void);
110 : : ~Layer (void);
111 : :
112 : : void Initialize (const SharedSdWindow& rpTargetWindow);
113 : : void InvalidateRectangle (const Rectangle& rInvalidationBox);
114 : : void InvalidateRegion (const Region& rInvalidationRegion);
115 : : void Validate (const MapMode& rMapMode);
116 : : void Repaint (
117 : : OutputDevice& rTargetDevice,
118 : : const Rectangle& rRepaintRectangle);
119 : : void Resize (const Size& rSize);
120 : : void AddPainter (const SharedILayerPainter& rpPainter);
121 : : void RemovePainter (const SharedILayerPainter& rpPainter);
122 : : bool HasPainter (void) const;
123 : : void Dispose (void);
124 : :
125 : : private:
126 : : ::boost::shared_ptr<VirtualDevice> mpLayerDevice;
127 : : ::std::vector<SharedILayerPainter> maPainters;
128 : : Region maInvalidationRegion;
129 : :
130 : : void ValidateRectangle (const Rectangle& rBox);
131 : : };
132 : : typedef ::boost::shared_ptr<Layer> SharedLayer;
133 : :
134 : :
135 : : } // end of anonymous namespace
136 : :
137 : :
138 : : class LayeredDevice::LayerContainer : public ::std::vector<SharedLayer>
139 : : {
140 : : public:
141 : 130 : LayerContainer (void) {}
142 : 130 : ~LayerContainer (void) {}
143 : : };
144 : :
145 : :
146 : :
147 : :
148 : : //===== LayeredDevice =========================================================
149 : :
150 : 130 : LayeredDevice::LayeredDevice (const SharedSdWindow& rpTargetWindow)
151 : : : mpTargetWindow(rpTargetWindow),
152 : 0 : mpLayers(new LayerContainer()),
153 [ + - ]: 260 : mpBackBuffer(new VirtualDevice(*mpTargetWindow)),
154 [ + - ][ + - ]: 390 : maSavedMapMode(rpTargetWindow->GetMapMode())
[ + - ][ + - ]
[ + - ]
155 : : {
156 [ + - ][ + - ]: 130 : mpBackBuffer->SetOutputSizePixel(mpTargetWindow->GetSizePixel());
157 : 130 : }
158 : :
159 : :
160 : :
161 : :
162 [ + - ][ + - ]: 130 : LayeredDevice::~LayeredDevice (void)
[ + - ][ + - ]
163 : : {
164 : 130 : }
165 : :
166 : :
167 : :
168 : :
169 : 0 : void LayeredDevice::Invalidate (
170 : : const Rectangle& rInvalidationArea,
171 : : const sal_Int32 nLayer)
172 : : {
173 [ # # ][ # # ]: 0 : if (nLayer<0 || size_t(nLayer)>=mpLayers->size())
[ # # ]
174 : : {
175 : : OSL_ASSERT(nLayer>=0 && size_t(nLayer)<mpLayers->size());
176 : 0 : return;
177 : : }
178 : :
179 : 0 : (*mpLayers)[nLayer]->InvalidateRectangle(rInvalidationArea);
180 : : }
181 : :
182 : :
183 : :
184 : :
185 : 1910 : void LayeredDevice::InvalidateAllLayers (const Rectangle& rInvalidationArea)
186 : : {
187 [ + + ]: 5730 : for (sal_uInt32 nLayer=0; nLayer<mpLayers->size(); ++nLayer)
188 : 3820 : (*mpLayers)[nLayer]->InvalidateRectangle(rInvalidationArea);
189 : 1910 : }
190 : :
191 : :
192 : :
193 : :
194 : 0 : void LayeredDevice::InvalidateAllLayers (const Region& rInvalidationRegion)
195 : : {
196 [ # # ]: 0 : for (sal_uInt32 nLayer=0; nLayer<mpLayers->size(); ++nLayer)
197 : 0 : (*mpLayers)[nLayer]->InvalidateRegion(rInvalidationRegion);
198 : 0 : }
199 : :
200 : :
201 : :
202 : :
203 : 260 : void LayeredDevice::RegisterPainter (
204 : : const SharedILayerPainter& rpPainter,
205 : : const sal_Int32 nLayer)
206 : : {
207 : : OSL_ASSERT(mpLayers);
208 [ - + ]: 260 : if ( ! rpPainter)
209 : : {
210 : : OSL_ASSERT(rpPainter);
211 : 0 : return;
212 : : }
213 [ + - ][ - + ]: 260 : if (nLayer<0 || nLayer>=gnMaximumLayerCount)
214 : : {
215 : : OSL_ASSERT(nLayer>=0 && nLayer<gnMaximumLayerCount);
216 : 0 : return;
217 : : }
218 : :
219 : : // Provide the layers.
220 [ + + ]: 260 : if (sal_uInt32(nLayer) >= mpLayers->size())
221 : : {
222 : 130 : const sal_Int32 nOldLayerCount (mpLayers->size());
223 : 130 : mpLayers->resize(nLayer+1);
224 : :
225 [ + + ]: 390 : for (size_t nIndex=nOldLayerCount; nIndex<mpLayers->size(); ++nIndex)
226 [ + - ]: 260 : (*mpLayers)[nIndex].reset(new Layer());
227 : : }
228 : :
229 : 260 : (*mpLayers)[nLayer]->AddPainter(rpPainter);
230 [ - + ]: 260 : if (nLayer == 0)
231 : 0 : (*mpLayers)[nLayer]->Initialize(mpTargetWindow);
232 : :
233 : 260 : rpPainter->SetLayerInvalidator(
234 [ + - ][ + - ]: 260 : SharedILayerInvalidator(new LayerInvalidator(shared_from_this(),mpTargetWindow,nLayer)));
[ + - ][ + - ]
[ + - ]
235 : : }
236 : :
237 : :
238 : :
239 : :
240 : 0 : void LayeredDevice::RemovePainter (
241 : : const SharedILayerPainter& rpPainter,
242 : : const sal_Int32 nLayer)
243 : : {
244 [ # # ]: 0 : if ( ! rpPainter)
245 : : {
246 : : OSL_ASSERT(rpPainter);
247 : 0 : return;
248 : : }
249 [ # # ][ # # ]: 0 : if (nLayer<0 || size_t(nLayer)>=mpLayers->size())
[ # # ]
250 : : {
251 : : OSL_ASSERT(nLayer>=0 && size_t(nLayer)<mpLayers->size());
252 : 0 : return;
253 : : }
254 : :
255 [ # # ]: 0 : rpPainter->SetLayerInvalidator(SharedILayerInvalidator());
256 : :
257 : 0 : (*mpLayers)[nLayer]->RemovePainter(rpPainter);
258 : :
259 : : // Remove top most layers that do not contain any painters.
260 [ # # ][ # # ]: 0 : while ( ! mpLayers->empty() && ! mpLayers->back()->HasPainter())
[ # # ]
261 [ # # ][ # # ]: 0 : mpLayers->erase(mpLayers->end()-1);
262 : : }
263 : :
264 : :
265 : :
266 : :
267 : 636 : void LayeredDevice::Repaint (const Region& rRepaintRegion)
268 : : {
269 : : // Validate the contents of all layers (that have their own devices.)
270 : : ::std::for_each(
271 : 636 : mpLayers->begin(),
272 : 636 : mpLayers->end(),
273 [ + - + - ]: 1908 : ::boost::bind(&Layer::Validate, _1, mpTargetWindow->GetMapMode()));
[ + - ][ + - ]
274 : :
275 [ + - ]: 636 : ForAllRectangles(rRepaintRegion, ::boost::bind(&LayeredDevice::RepaintRectangle, this, _1));
276 : 636 : }
277 : :
278 : :
279 : :
280 : :
281 : 636 : void LayeredDevice::RepaintRectangle (const Rectangle& rRepaintRectangle)
282 : : {
283 [ - + ]: 636 : if (mpLayers->empty())
284 : 636 : return;
285 [ - + ]: 636 : else if (mpLayers->size() == 1)
286 : : {
287 : : // Just copy the main layer into the target device.
288 : 0 : (*mpLayers)[0]->Repaint(*mpTargetWindow, rRepaintRectangle);
289 : : }
290 : : else
291 : : {
292 : : // Paint all layers first into the back buffer (to avoid flickering
293 : : // due to synchronous paints) and then copy that into the target
294 : : // device.
295 : 636 : mpBackBuffer->SetMapMode(mpTargetWindow->GetMapMode());
296 : : ::std::for_each(
297 : 636 : mpLayers->begin(),
298 : 636 : mpLayers->end(),
299 : 1908 : ::boost::bind(&Layer::Repaint, _1, ::boost::ref(*mpBackBuffer), rRepaintRectangle));
300 : :
301 : 636 : DeviceCopy(*mpTargetWindow, *mpBackBuffer, rRepaintRectangle);
302 : : }
303 : : }
304 : :
305 : :
306 : :
307 : :
308 : 279 : void LayeredDevice::Resize (void)
309 : : {
310 [ + - ]: 279 : const Size aSize (mpTargetWindow->GetSizePixel());
311 [ + - ]: 279 : mpBackBuffer->SetOutputSizePixel(aSize);
312 [ + - ][ + - ]: 279 : ::std::for_each(mpLayers->begin(), mpLayers->end(), ::boost::bind(&Layer::Resize, _1, aSize));
313 : 279 : }
314 : :
315 : :
316 : :
317 : :
318 : 130 : void LayeredDevice::Dispose (void)
319 : : {
320 : 130 : ::std::for_each(mpLayers->begin(), mpLayers->end(), ::boost::bind(&Layer::Dispose, _1));
321 : 130 : mpLayers->clear();
322 : 130 : }
323 : :
324 : :
325 : :
326 : :
327 : 636 : bool LayeredDevice::HandleMapModeChange (void)
328 : : {
329 : 636 : const MapMode& rMapMode (mpTargetWindow->GetMapMode());
330 [ + + ][ + - ]: 636 : if (maSavedMapMode == rMapMode)
331 : 510 : return false;
332 : :
333 : : const Rectangle aLogicWindowBox (
334 [ + - ][ + - ]: 126 : mpTargetWindow->PixelToLogic(Rectangle(Point(0,0), mpTargetWindow->GetSizePixel())));
[ + - ]
335 [ + - ][ + - ]: 378 : if (maSavedMapMode.GetScaleX() != rMapMode.GetScaleX()
[ + - + - ]
[ + - ]
336 [ + - ]: 126 : || maSavedMapMode.GetScaleY() != rMapMode.GetScaleY()
337 : 126 : || maSavedMapMode.GetMapUnit() != rMapMode.GetMapUnit())
338 : : {
339 : : // When the scale has changed then we have to paint everything.
340 [ + - ]: 126 : InvalidateAllLayers(aLogicWindowBox);
341 : : }
342 [ # # ]: 0 : else if (maSavedMapMode.GetOrigin() != rMapMode.GetOrigin())
343 : : {
344 : : // Window has been scrolled. Adapt contents of backbuffers and
345 : : // layer devices.
346 : 0 : const Point aDelta (rMapMode.GetOrigin() - maSavedMapMode.GetOrigin());
347 : 0 : mpBackBuffer->CopyArea(
348 : : aLogicWindowBox.TopLeft(),
349 : 0 : mpTargetWindow->PixelToLogic(Point(0,0), maSavedMapMode),
350 [ # # ]: 0 : aLogicWindowBox.GetSize());
[ # # # # ]
351 : :
352 : : // Invalidate the area(s) that have been exposed.
353 [ # # ][ # # ]: 0 : const Rectangle aWindowBox (Point(0,0), mpTargetWindow->GetSizePixel());
354 [ # # ]: 0 : if (aDelta.Y() < 0)
355 : 0 : InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
356 : : aWindowBox.Left(),
357 : 0 : aWindowBox.Bottom()+aDelta.Y(),
358 : : aWindowBox.Right(),
359 [ # # # # ]: 0 : aWindowBox.Bottom())));
[ # # ]
360 [ # # ]: 0 : else if (aDelta.Y() > 0)
361 : 0 : InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
362 : : aWindowBox.Left(),
363 : : aWindowBox.Top(),
364 : : aWindowBox.Right(),
365 [ # # # # ]: 0 : aWindowBox.Top()+aDelta.Y())));
[ # # ]
366 [ # # ]: 0 : if (aDelta.X() < 0)
367 : 0 : InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
368 : 0 : aWindowBox.Right()+aDelta.X(),
369 : : aWindowBox.Top(),
370 : : aWindowBox.Right(),
371 [ # # # # ]: 0 : aWindowBox.Bottom())));
[ # # ]
372 [ # # ]: 0 : else if (aDelta.X() > 0)
373 : 0 : InvalidateAllLayers(mpTargetWindow->PixelToLogic(Rectangle(
374 : : aWindowBox.Left(),
375 : : aWindowBox.Top(),
376 : 0 : aWindowBox.Left()+aDelta.X(),
377 [ # # # # ]: 0 : aWindowBox.Bottom())));
[ # # ]
378 : : }
379 : : else
380 : : {
381 : : // Can this happen? Lets trigger a warning when it does.
382 : : OSL_ASSERT(false);
383 : : }
384 : :
385 [ + - ]: 126 : maSavedMapMode = rMapMode;
386 : :
387 : 636 : return true;
388 : : }
389 : :
390 : :
391 : :
392 : :
393 : : //===== Layer =================================================================
394 : :
395 : 260 : Layer::Layer (void)
396 : : : mpLayerDevice(),
397 : : maPainters(),
398 [ + - ][ + - ]: 260 : maInvalidationRegion()
[ + - ]
399 : : {
400 : 260 : }
401 : :
402 : :
403 : :
404 : :
405 [ + - ][ + - ]: 260 : Layer::~Layer (void)
406 : : {
407 : 260 : }
408 : :
409 : :
410 : :
411 : :
412 : 0 : void Layer::Initialize (const SharedSdWindow& rpTargetWindow)
413 : : {
414 : : #if 0
415 : : (void)rpTargetWindow;
416 : : #else
417 [ # # ]: 0 : if ( ! mpLayerDevice)
418 : : {
419 [ # # ]: 0 : mpLayerDevice.reset(new VirtualDevice(*rpTargetWindow));
420 [ # # ]: 0 : mpLayerDevice->SetOutputSizePixel(rpTargetWindow->GetSizePixel());
421 : : }
422 : : #endif
423 : 0 : }
424 : :
425 : :
426 : :
427 : :
428 : 3820 : void Layer::InvalidateRectangle (const Rectangle& rInvalidationBox)
429 : : {
430 : 3820 : maInvalidationRegion.Union(rInvalidationBox);
431 : 3820 : }
432 : :
433 : :
434 : :
435 : :
436 : 0 : void Layer::InvalidateRegion (const Region& rInvalidationRegion)
437 : : {
438 : 0 : maInvalidationRegion.Union(rInvalidationRegion);
439 : 0 : }
440 : :
441 : :
442 : :
443 : :
444 : 1272 : void Layer::Validate (const MapMode& rMapMode)
445 : : {
446 [ - + ][ # # ]: 1272 : if (mpLayerDevice && ! maInvalidationRegion.IsEmpty())
[ - + ]
447 : : {
448 [ # # ]: 0 : Region aRegion (maInvalidationRegion);
449 [ # # ]: 0 : maInvalidationRegion.SetEmpty();
450 : :
451 [ # # ]: 0 : mpLayerDevice->SetMapMode(rMapMode);
452 : : ForAllRectangles(
453 : : aRegion,
454 [ # # ][ # # ]: 0 : ::boost::bind(&Layer::ValidateRectangle, this, _1));
[ # # ][ # # ]
[ # # ]
455 : : }
456 : 1272 : }
457 : :
458 : :
459 : :
460 : :
461 : 0 : void Layer::ValidateRectangle (const Rectangle& rBox)
462 : : {
463 [ # # ]: 0 : if ( ! mpLayerDevice)
464 : 0 : return;
465 [ # # ]: 0 : const Region aSavedClipRegion (mpLayerDevice->GetClipRegion());
466 [ # # ]: 0 : mpLayerDevice->IntersectClipRegion(rBox);
467 : :
468 [ # # ][ # # ]: 0 : for (::std::vector<SharedILayerPainter>::const_iterator
469 [ # # ]: 0 : iPainter(maPainters.begin()),
470 [ # # ]: 0 : iEnd(maPainters.end());
471 : : iPainter!=iEnd;
472 : : ++iPainter)
473 : : {
474 [ # # ]: 0 : (*iPainter)->Paint(*mpLayerDevice, rBox);
475 : : }
476 : :
477 [ # # ][ # # ]: 0 : mpLayerDevice->SetClipRegion(aSavedClipRegion);
478 : : }
479 : :
480 : :
481 : :
482 : :
483 : 1272 : void Layer::Repaint (
484 : : OutputDevice& rTargetDevice,
485 : : const Rectangle& rRepaintRectangle)
486 : : {
487 [ - + ]: 1272 : if (mpLayerDevice)
488 : : {
489 : 0 : DeviceCopy(rTargetDevice, *mpLayerDevice, rRepaintRectangle);
490 : : }
491 : : else
492 : : {
493 : : ::std::for_each(
494 : : maPainters.begin(),
495 : : maPainters.end(),
496 : : ::boost::bind(&ILayerPainter::Paint,
497 : : _1,
498 : : ::boost::ref(rTargetDevice),
499 : 1272 : rRepaintRectangle));
500 : : }
501 : 1272 : }
502 : :
503 : :
504 : :
505 : :
506 : 558 : void Layer::Resize (const Size& rSize)
507 : : {
508 [ - + ]: 558 : if (mpLayerDevice)
509 : : {
510 : 0 : mpLayerDevice->SetOutputSizePixel(rSize);
511 [ # # ][ # # ]: 0 : maInvalidationRegion = Rectangle(Point(0,0), rSize);
512 : : }
513 : 558 : }
514 : :
515 : :
516 : :
517 : :
518 : 260 : void Layer::AddPainter (const SharedILayerPainter& rpPainter)
519 : : {
520 : : OSL_ASSERT(::std::find(maPainters.begin(), maPainters.end(), rpPainter) == maPainters.end());
521 : :
522 : 260 : maPainters.push_back(rpPainter);
523 : 260 : }
524 : :
525 : :
526 : :
527 : :
528 : 0 : void Layer::RemovePainter (const SharedILayerPainter& rpPainter)
529 : : {
530 : : const ::std::vector<SharedILayerPainter>::iterator iPainter (
531 [ # # ]: 0 : ::std::find(maPainters.begin(), maPainters.end(), rpPainter));
532 [ # # ][ # # ]: 0 : if (iPainter != maPainters.end())
533 : : {
534 [ # # ]: 0 : maPainters.erase(iPainter);
535 : : }
536 : : else
537 : : {
538 : : DBG_ASSERT(false,"LayeredDevice::RemovePainter called for painter that is not registered");
539 : : }
540 : 0 : }
541 : :
542 : :
543 : :
544 : :
545 : 0 : bool Layer::HasPainter (void) const
546 : : {
547 : 0 : return !maPainters.empty();
548 : : }
549 : :
550 : :
551 : :
552 : :
553 : 260 : void Layer::Dispose (void)
554 : : {
555 : 260 : maPainters.clear();
556 : 260 : }
557 : :
558 : :
559 [ + - ][ + - ]: 75 : } } } // end of namespace ::sd::slidesorter::view
560 : :
561 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|