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