Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <svx/sdr/contact/objectcontactofpageview.hxx>
21 : #include <svx/sdr/contact/viewobjectcontactofunocontrol.hxx>
22 : #include <svx/svdpagv.hxx>
23 : #include <svx/svdpage.hxx>
24 : #include <svx/sdr/contact/displayinfo.hxx>
25 : #include <svx/sdr/contact/viewobjectcontact.hxx>
26 : #include <svx/svdview.hxx>
27 : #include <svx/sdr/contact/viewcontact.hxx>
28 : #include <svx/sdr/animation/objectanimator.hxx>
29 : #include <svx/sdr/event/eventhandler.hxx>
30 : #include <svx/sdrpagewindow.hxx>
31 : #include <svx/sdrpaintwindow.hxx>
32 : #include <drawinglayer/processor2d/vclprocessor2d.hxx>
33 : #include <basegfx/matrix/b2dhommatrix.hxx>
34 : #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
35 : #include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
36 : #include <com/sun/star/rendering/XSpriteCanvas.hpp>
37 : #include <svx/unoapi.hxx>
38 :
39 : //////////////////////////////////////////////////////////////////////////////
40 :
41 : using namespace com::sun::star;
42 :
43 : //////////////////////////////////////////////////////////////////////////////
44 :
45 : namespace sdr
46 : {
47 : namespace contact
48 : {
49 : // internal access to SdrPage of SdrPageView
50 2448 : SdrPage* ObjectContactOfPageView::GetSdrPage() const
51 : {
52 2448 : return GetPageWindow().GetPageView().GetPage();
53 : }
54 :
55 134 : ObjectContactOfPageView::ObjectContactOfPageView(SdrPageWindow& rPageWindow)
56 : : ObjectContact(),
57 134 : mrPageWindow(rPageWindow)
58 : {
59 : // init PreviewRenderer flag
60 134 : setPreviewRenderer(((SdrPaintView&)rPageWindow.GetPageView().GetView()).IsPreviewRenderer());
61 :
62 : // init timer
63 134 : SetTimeout(1);
64 134 : Stop();
65 134 : }
66 :
67 27 : ObjectContactOfPageView::~ObjectContactOfPageView()
68 : {
69 : // execute missing LazyInvalidates and stop timer
70 9 : Timeout();
71 18 : }
72 :
73 : // LazyInvalidate request. Take action.
74 12 : void ObjectContactOfPageView::setLazyInvalidate(ViewObjectContact& /*rVOC*/)
75 : {
76 : // do NOT call parent, but remember that something is to do by
77 : // starting the LazyInvalidateTimer
78 12 : Start();
79 12 : }
80 :
81 : // call this to support evtl. preparations for repaint
82 427 : void ObjectContactOfPageView::PrepareProcessDisplay()
83 : {
84 427 : if(IsActive())
85 : {
86 : static bool bInvalidateDuringPaint(true);
87 :
88 1 : if(bInvalidateDuringPaint)
89 : {
90 : // there are still non-triggered LazyInvalidate events, trigger these
91 1 : Timeout();
92 : }
93 : }
94 427 : }
95 :
96 : // From baseclass Timer, the timeout call triggered by te LazyInvalidate mechanism
97 12 : void ObjectContactOfPageView::Timeout()
98 : {
99 : // stop the timer
100 12 : Stop();
101 :
102 : // invalidate all LazyInvalidate VOCs new situations
103 12 : const sal_uInt32 nVOCCount(getViewObjectContactCount());
104 :
105 151 : for(sal_uInt32 a(0); a < nVOCCount; a++)
106 : {
107 139 : ViewObjectContact* pCandidate = getViewObjectContact(a);
108 139 : pCandidate->triggerLazyInvalidate();
109 : }
110 12 : }
111 :
112 : // Process the whole displaying
113 816 : void ObjectContactOfPageView::ProcessDisplay(DisplayInfo& rDisplayInfo)
114 : {
115 816 : const SdrPage* pStartPage = GetSdrPage();
116 :
117 816 : if(pStartPage && !rDisplayInfo.GetProcessLayers().IsEmpty())
118 : {
119 816 : const ViewContact& rDrawPageVC = pStartPage->GetViewContact();
120 :
121 816 : if(rDrawPageVC.GetObjectCount())
122 : {
123 816 : DoProcessDisplay(rDisplayInfo);
124 : }
125 : }
126 :
127 : // after paint take care of the evtl. scheduled asynchronious commands.
128 : // Do this by resetting the timer contained there. Thus, after the paint
129 : // that timer will be triggered and the events will be executed.
130 816 : if(HasEventHandler())
131 : {
132 0 : sdr::event::TimerEventHandler& rEventHandler = GetEventHandler();
133 :
134 0 : if(!rEventHandler.IsEmpty())
135 : {
136 0 : rEventHandler.Restart();
137 : }
138 : }
139 816 : }
140 :
141 : // Process the whole displaying. Only use given DsiplayInfo, do not access other
142 : // OutputDevices then the given ones.
143 816 : void ObjectContactOfPageView::DoProcessDisplay(DisplayInfo& rDisplayInfo)
144 : {
145 : // visualize entered group when that feature is switched on and it's not
146 : // a print output. #i29129# No ghosted display for printing.
147 816 : sal_Bool bVisualizeEnteredGroup(DoVisualizeEnteredGroup() && !isOutputToPrinter());
148 :
149 : // Visualize entered groups: Set to ghosted as default
150 : // start. Do this only for the DrawPage, not for MasterPages
151 816 : if(bVisualizeEnteredGroup)
152 : {
153 816 : rDisplayInfo.SetGhostedDrawMode();
154 : }
155 :
156 : // #114359# save old and set clip region
157 816 : OutputDevice* pOutDev = TryToGetOutputDevice();
158 : OSL_ENSURE(0 != pOutDev, "ObjectContactOfPageView without OutDev, someone has overloaded TryToGetOutputDevice wrong (!)");
159 816 : sal_Bool bClipRegionPushed(sal_False);
160 816 : const Region& rRedrawArea(rDisplayInfo.GetRedrawArea());
161 :
162 816 : if(!rRedrawArea.IsEmpty())
163 : {
164 816 : bClipRegionPushed = sal_True;
165 816 : pOutDev->Push(PUSH_CLIPREGION);
166 816 : pOutDev->IntersectClipRegion(rRedrawArea);
167 : }
168 :
169 : // Get start node and process DrawPage contents
170 816 : const ViewObjectContact& rDrawPageVOContact = GetSdrPage()->GetViewContact().GetViewObjectContact(*this);
171 :
172 : // update current ViewInformation2D at the ObjectContact
173 816 : const double fCurrentTime(getPrimitiveAnimator().GetTime());
174 816 : OutputDevice& rTargetOutDev = GetPageWindow().GetPaintWindow().GetTargetOutputDevice();
175 816 : basegfx::B2DRange aViewRange;
176 :
177 : // create ViewRange
178 816 : if(isOutputToRecordingMetaFile())
179 : {
180 10 : if(isOutputToPDFFile() || isOutputToPrinter())
181 : {
182 : // #i98402# if it's a PDF export, set the ClipRegion as ViewRange. This is
183 : // mainly because SW does not use DrawingLayer Page-Oriented and if not doing this,
184 : // all existing objects will be collected as primitives and processed.
185 : // OD 2009-03-05 #i99876# perform the same also for SW on printing.
186 0 : const Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect());
187 :
188 : aViewRange = basegfx::B2DRange(
189 0 : aLogicClipRectangle.Left(), aLogicClipRectangle.Top(),
190 0 : aLogicClipRectangle.Right(), aLogicClipRectangle.Bottom());
191 : }
192 : }
193 : else
194 : {
195 : // use visible pixels, but transform to world coordinates
196 806 : const Size aOutputSizePixel(rTargetOutDev.GetOutputSizePixel());
197 806 : aViewRange = basegfx::B2DRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight());
198 :
199 : // if a clip region is set, use it
200 806 : if(!rDisplayInfo.GetRedrawArea().IsEmpty())
201 : {
202 : // get logic clip range and create discrete one
203 806 : const Rectangle aLogicClipRectangle(rDisplayInfo.GetRedrawArea().GetBoundRect());
204 : basegfx::B2DRange aLogicClipRange(
205 1612 : aLogicClipRectangle.Left(), aLogicClipRectangle.Top(),
206 2418 : aLogicClipRectangle.Right(), aLogicClipRectangle.Bottom());
207 806 : basegfx::B2DRange aDiscreteClipRange(aLogicClipRange);
208 806 : aDiscreteClipRange.transform(rTargetOutDev.GetViewTransformation());
209 :
210 : // align the discrete one to discrete boundaries (pixel bounds). Also
211 : // expand X and Y max by one due to Rectangle definition source
212 : aDiscreteClipRange.expand(basegfx::B2DTuple(
213 : floor(aDiscreteClipRange.getMinX()),
214 806 : floor(aDiscreteClipRange.getMinY())));
215 : aDiscreteClipRange.expand(basegfx::B2DTuple(
216 806 : 1.0 + ceil(aDiscreteClipRange.getMaxX()),
217 1612 : 1.0 + ceil(aDiscreteClipRange.getMaxY())));
218 :
219 : // intersect current ViewRange with ClipRange
220 806 : aViewRange.intersect(aDiscreteClipRange);
221 : }
222 :
223 : // transform to world coordinates
224 806 : aViewRange.transform(rTargetOutDev.GetInverseViewTransformation());
225 : }
226 :
227 : // update local ViewInformation2D
228 : const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D(
229 : basegfx::B2DHomMatrix(),
230 : rTargetOutDev.GetViewTransformation(),
231 : aViewRange,
232 : GetXDrawPageForSdrPage(GetSdrPage()),
233 : fCurrentTime,
234 816 : uno::Sequence<beans::PropertyValue>());
235 816 : updateViewInformation2D(aNewViewInformation2D);
236 :
237 : // get whole Primitive2DSequence; this will already make use of updated ViewInformation2D
238 : // and may use the MapMode from the Target OutDev in the DisplayInfo
239 816 : drawinglayer::primitive2d::Primitive2DSequence xPrimitiveSequence(rDrawPageVOContact.getPrimitive2DSequenceHierarchy(rDisplayInfo));
240 :
241 : // if there is something to show, use a primitive processor to render it. There
242 : // is a choice between VCL and Canvas processors currently. The decision is made in
243 : // createBaseProcessor2DFromOutputDevice and takes into accout things like the
244 : // Target is a MetaFile, a VDev or something else. The Canvas renderer is triggered
245 : // currently using the shown boolean. Canvas is not yet the default.
246 816 : if(xPrimitiveSequence.hasElements())
247 : {
248 : // prepare OutputDevice (historical stuff, maybe soon removed)
249 100 : rDisplayInfo.ClearGhostedDrawMode(); // reset, else the VCL-paint with the processor will not do the right thing
250 100 : pOutDev->SetLayoutMode(0); // reset, default is no BiDi/RTL
251 :
252 : // create renderer
253 : drawinglayer::processor2d::BaseProcessor2D* pProcessor2D =
254 : drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(
255 100 : rTargetOutDev, getViewInformation2D());
256 :
257 100 : if(pProcessor2D)
258 : {
259 100 : pProcessor2D->process(xPrimitiveSequence);
260 100 : delete pProcessor2D;
261 : }
262 : }
263 :
264 : // #114359# restore old ClipReghion
265 816 : if(bClipRegionPushed)
266 : {
267 816 : pOutDev->Pop();
268 : }
269 :
270 : // Visualize entered groups: Reset to original DrawMode
271 816 : if(bVisualizeEnteredGroup)
272 : {
273 816 : rDisplayInfo.ClearGhostedDrawMode();
274 816 : }
275 816 : }
276 :
277 : // test if visualizing of entered groups is switched on at all
278 1848 : bool ObjectContactOfPageView::DoVisualizeEnteredGroup() const
279 : {
280 1848 : SdrView& rView = GetPageWindow().GetPageView().GetView();
281 1848 : return rView.DoVisualizeEnteredGroup();
282 : }
283 :
284 : // get active group's (the entered group) ViewContact
285 816 : const ViewContact* ObjectContactOfPageView::getActiveViewContact() const
286 : {
287 816 : SdrObjList* pActiveGroupList = GetPageWindow().GetPageView().GetObjList();
288 :
289 816 : if(pActiveGroupList)
290 : {
291 816 : if(pActiveGroupList->ISA(SdrPage))
292 : {
293 : // It's a Page itself
294 816 : return &(((SdrPage*)pActiveGroupList)->GetViewContact());
295 : }
296 0 : else if(pActiveGroupList->GetOwnerObj())
297 : {
298 : // Group object
299 0 : return &(pActiveGroupList->GetOwnerObj()->GetViewContact());
300 : }
301 : }
302 0 : else if(GetSdrPage())
303 : {
304 : // use page of associated SdrPageView
305 0 : return &(GetSdrPage()->GetViewContact());
306 : }
307 :
308 0 : return 0;
309 : }
310 :
311 : // Invalidate given rectangle at the window/output which is represented by
312 : // this ObjectContact.
313 18 : void ObjectContactOfPageView::InvalidatePartOfView(const basegfx::B2DRange& rRange) const
314 : {
315 : // invalidate at associated PageWindow
316 18 : GetPageWindow().InvalidatePageWindow(rRange);
317 18 : }
318 :
319 : // Get info if given Rectangle is visible in this view
320 0 : bool ObjectContactOfPageView::IsAreaVisible(const basegfx::B2DRange& rRange) const
321 : {
322 : // compare with the visible rectangle
323 0 : if(rRange.isEmpty())
324 : {
325 : // no range -> not visible
326 0 : return false;
327 : }
328 : else
329 : {
330 0 : const OutputDevice& rTargetOutDev = GetPageWindow().GetPaintWindow().GetTargetOutputDevice();
331 0 : const Size aOutputSizePixel(rTargetOutDev.GetOutputSizePixel());
332 0 : basegfx::B2DRange aLogicViewRange(0.0, 0.0, aOutputSizePixel.getWidth(), aOutputSizePixel.getHeight());
333 :
334 0 : aLogicViewRange.transform(rTargetOutDev.GetInverseViewTransformation());
335 :
336 0 : if(!aLogicViewRange.isEmpty() && !aLogicViewRange.overlaps(rRange))
337 : {
338 0 : return false;
339 : }
340 : }
341 :
342 : // call parent
343 0 : return ObjectContact::IsAreaVisible(rRange);
344 : }
345 :
346 : // Get info about the need to visualize GluePoints
347 222 : bool ObjectContactOfPageView::AreGluePointsVisible() const
348 : {
349 222 : return GetPageWindow().GetPageView().GetView().ImpIsGlueVisible();
350 : }
351 :
352 : // check if text animation is allowed.
353 115 : bool ObjectContactOfPageView::IsTextAnimationAllowed() const
354 : {
355 115 : SdrView& rView = GetPageWindow().GetPageView().GetView();
356 115 : const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions();
357 115 : return rOpt.GetIsAllowAnimatedText();
358 : }
359 :
360 : // check if graphic animation is allowed.
361 115 : bool ObjectContactOfPageView::IsGraphicAnimationAllowed() const
362 : {
363 115 : SdrView& rView = GetPageWindow().GetPageView().GetView();
364 115 : const SvtAccessibilityOptions& rOpt = rView.getAccessibilityOptions();
365 115 : return rOpt.GetIsAllowAnimatedGraphics();
366 : }
367 :
368 : // check if asynchronious graphis loading is allowed. Default is sal_False.
369 0 : bool ObjectContactOfPageView::IsAsynchronGraphicsLoadingAllowed() const
370 : {
371 0 : SdrView& rView = GetPageWindow().GetPageView().GetView();
372 0 : return rView.IsSwapAsynchron();
373 : }
374 :
375 : // check if buffering of MasterPages is allowed. Default is sal_False.
376 0 : bool ObjectContactOfPageView::IsMasterPageBufferingAllowed() const
377 : {
378 0 : SdrView& rView = GetPageWindow().GetPageView().GetView();
379 0 : return rView.IsMasterPagePaintCaching();
380 : }
381 :
382 : // print?
383 2324 : bool ObjectContactOfPageView::isOutputToPrinter() const
384 : {
385 2324 : return (OUTDEV_PRINTER == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType());
386 : }
387 :
388 : // window?
389 0 : bool ObjectContactOfPageView::isOutputToWindow() const
390 : {
391 0 : return (OUTDEV_WINDOW == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType());
392 : }
393 :
394 : // VirtualDevice?
395 0 : bool ObjectContactOfPageView::isOutputToVirtualDevice() const
396 : {
397 0 : return (OUTDEV_VIRDEV == mrPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType());
398 : }
399 :
400 : // recording MetaFile?
401 816 : bool ObjectContactOfPageView::isOutputToRecordingMetaFile() const
402 : {
403 816 : GDIMetaFile* pMetaFile = mrPageWindow.GetPaintWindow().GetOutputDevice().GetConnectMetaFile();
404 816 : return (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
405 : }
406 :
407 : // pdf export?
408 10 : bool ObjectContactOfPageView::isOutputToPDFFile() const
409 : {
410 10 : return (0 != mrPageWindow.GetPaintWindow().GetOutputDevice().GetPDFWriter());
411 : }
412 :
413 : // gray display mode
414 0 : bool ObjectContactOfPageView::isDrawModeGray() const
415 : {
416 0 : const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode());
417 0 : return (nDrawMode == (DRAWMODE_GRAYLINE|DRAWMODE_GRAYFILL|DRAWMODE_BLACKTEXT|DRAWMODE_GRAYBITMAP|DRAWMODE_GRAYGRADIENT));
418 : }
419 :
420 : // gray display mode
421 0 : bool ObjectContactOfPageView::isDrawModeBlackWhite() const
422 : {
423 0 : const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode());
424 0 : return (nDrawMode == (DRAWMODE_BLACKLINE|DRAWMODE_BLACKTEXT|DRAWMODE_WHITEFILL|DRAWMODE_GRAYBITMAP|DRAWMODE_WHITEGRADIENT));
425 : }
426 :
427 : // high contrast display mode
428 0 : bool ObjectContactOfPageView::isDrawModeHighContrast() const
429 : {
430 0 : const sal_uInt32 nDrawMode(mrPageWindow.GetPaintWindow().GetOutputDevice().GetDrawMode());
431 0 : return (nDrawMode == (DRAWMODE_SETTINGSLINE|DRAWMODE_SETTINGSFILL|DRAWMODE_SETTINGSTEXT|DRAWMODE_SETTINGSGRADIENT));
432 : }
433 :
434 : // access to SdrPageView
435 256 : SdrPageView* ObjectContactOfPageView::TryToGetSdrPageView() const
436 : {
437 256 : return &(mrPageWindow.GetPageView());
438 : }
439 :
440 :
441 : // access to OutputDevice
442 816 : OutputDevice* ObjectContactOfPageView::TryToGetOutputDevice() const
443 : {
444 816 : SdrPreRenderDevice* pPreRenderDevice = mrPageWindow.GetPaintWindow().GetPreRenderDevice();
445 :
446 816 : if(pPreRenderDevice)
447 : {
448 0 : return &(pPreRenderDevice->GetPreRenderDevice());
449 : }
450 : else
451 : {
452 816 : return &(mrPageWindow.GetPaintWindow().GetOutputDevice());
453 : }
454 : }
455 :
456 : // set all UNO controls displayed in the view to design/alive mode
457 0 : void ObjectContactOfPageView::SetUNOControlsDesignMode( bool _bDesignMode ) const
458 : {
459 0 : const sal_uInt32 nCount(getViewObjectContactCount());
460 :
461 0 : for(sal_uInt32 a(0); a < nCount; a++)
462 : {
463 0 : const ViewObjectContact* pVOC = getViewObjectContact(a);
464 0 : const ViewObjectContactOfUnoControl* pUnoObjectVOC = dynamic_cast< const ViewObjectContactOfUnoControl* >(pVOC);
465 :
466 0 : if(pUnoObjectVOC)
467 : {
468 0 : pUnoObjectVOC->setControlDesignMode(_bDesignMode);
469 : }
470 : }
471 0 : }
472 : } // end of namespace contact
473 : } // end of namespace sdr
474 :
475 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|