1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: viewobjectcontact.cxx,v $
10 * $Revision: 1.17.18.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <svx/sdr/contact/viewobjectcontact.hxx>
34 #include <svx/sdr/contact/viewcontact.hxx>
35 #include <svx/sdr/contact/objectcontact.hxx>
36 #include <svx/sdr/contact/displayinfo.hxx>
37 #include <vcl/region.hxx>
38 #include <svx/sdr/animation/objectanimator.hxx>
39 #include <svx/sdr/animation/animationstate.hxx>
40 #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
41 #include <basegfx/numeric/ftools.hxx>
42 #include <basegfx/color/bcolor.hxx>
43 #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
44 #include <basegfx/tools/canvastools.hxx>
45 #include <drawinglayer/primitive2d/animatedprimitive2d.hxx>
46 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
47 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
48 #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
50 //////////////////////////////////////////////////////////////////////////////
52 using namespace com::sun::star
;
54 //////////////////////////////////////////////////////////////////////////////
60 // Necessary to filter a sequence of animated primitives from
61 // a sequence of primitives to find out if animated or not. The decision for
62 // what to decompose is hard-coded and only done for knowingly animated primitives
63 // to not decompose too deeply and unnecessarily. This implies that the list
64 // which is view-specific needs to be expanded by hand when new animated objects
65 // are added. This may eventually be changed to a dynamically configurable approach
67 class AnimatedExtractingProcessor2D
: public drawinglayer::processor2d::BaseProcessor2D
70 // the found animated primitives
71 drawinglayer::primitive2d::Primitive2DSequence maPrimitive2DSequence
;
74 // text animation allowed?
75 unsigned mbTextAnimationAllowed
: 1;
77 // graphic animation allowed?
78 unsigned mbGraphicAnimationAllowed
: 1;
80 // as tooling, the process() implementation takes over API handling and calls this
81 // virtual render method when the primitive implementation is BasePrimitive2D-based.
82 virtual void processBasePrimitive2D(const drawinglayer::primitive2d::BasePrimitive2D
& rCandidate
);
85 AnimatedExtractingProcessor2D(
86 const drawinglayer::geometry::ViewInformation2D
& rViewInformation
,
87 bool bTextAnimationAllowed
,
88 bool bGraphicAnimationAllowed
);
89 virtual ~AnimatedExtractingProcessor2D();
92 const drawinglayer::primitive2d::Primitive2DSequence
& getPrimitive2DSequence() const { return maPrimitive2DSequence
; }
93 bool isTextAnimationAllowed() const { return mbTextAnimationAllowed
; }
94 bool isGraphicAnimationAllowed() const { return mbGraphicAnimationAllowed
; }
97 AnimatedExtractingProcessor2D::AnimatedExtractingProcessor2D(
98 const drawinglayer::geometry::ViewInformation2D
& rViewInformation
,
99 bool bTextAnimationAllowed
,
100 bool bGraphicAnimationAllowed
)
101 : drawinglayer::processor2d::BaseProcessor2D(rViewInformation
),
102 maPrimitive2DSequence(),
103 mbTextAnimationAllowed(bTextAnimationAllowed
),
104 mbGraphicAnimationAllowed(bGraphicAnimationAllowed
)
108 AnimatedExtractingProcessor2D::~AnimatedExtractingProcessor2D()
112 void AnimatedExtractingProcessor2D::processBasePrimitive2D(const drawinglayer::primitive2d::BasePrimitive2D
& rCandidate
)
114 // known implementation, access directly
115 switch(rCandidate
.getPrimitiveID())
117 // add and accept animated primitives directly, no need to decompose
118 case PRIMITIVE2D_ID_ANIMATEDSWITCHPRIMITIVE2D
:
119 case PRIMITIVE2D_ID_ANIMATEDBLINKPRIMITIVE2D
:
120 case PRIMITIVE2D_ID_ANIMATEDINTERPOLATEPRIMITIVE2D
:
122 const drawinglayer::primitive2d::AnimatedSwitchPrimitive2D
& rSwitchPrimitive
= static_cast< const drawinglayer::primitive2d::AnimatedSwitchPrimitive2D
& >(rCandidate
);
124 if((rSwitchPrimitive
.isTextAnimation() && isTextAnimationAllowed())
125 || (rSwitchPrimitive
.isGraphicAnimation() && isGraphicAnimationAllowed()))
127 const drawinglayer::primitive2d::Primitive2DReference
xReference(const_cast< drawinglayer::primitive2d::BasePrimitive2D
* >(&rCandidate
));
128 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(maPrimitive2DSequence
, xReference
);
133 // decompose animated gifs where SdrGrafPrimitive2D produces a GraphicPrimitive2D
134 // which then produces the animation infos (all when used/needed)
135 case PRIMITIVE2D_ID_SDRGRAFPRIMITIVE2D
:
136 case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D
:
138 // decompose SdrObjects with evtl. animated text
139 case PRIMITIVE2D_ID_SDRCAPTIONPRIMITIVE2D
:
140 case PRIMITIVE2D_ID_SDRCONNECTORPRIMITIVE2D
:
141 case PRIMITIVE2D_ID_SDRCUSTOMSHAPEPRIMITIVE2D
:
142 case PRIMITIVE2D_ID_SDRELLIPSEPRIMITIVE2D
:
143 case PRIMITIVE2D_ID_SDRELLIPSESEGMENTPRIMITIVE2D
:
144 case PRIMITIVE2D_ID_SDRMEASUREPRIMITIVE2D
:
145 case PRIMITIVE2D_ID_SDRPATHPRIMITIVE2D
:
146 case PRIMITIVE2D_ID_SDRRECTANGLEPRIMITIVE2D
:
148 // decompose evtl. animated text contained in MaskPrimitive2D
149 // or group rimitives
150 case PRIMITIVE2D_ID_MASKPRIMITIVE2D
:
151 case PRIMITIVE2D_ID_GROUPPRIMITIVE2D
:
153 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
159 // nothing to do for the rest
164 } // end of anonymous namespace
166 //////////////////////////////////////////////////////////////////////////////
172 ViewObjectContact::ViewObjectContact(ObjectContact
& rObjectContact
, ViewContact
& rViewContact
)
173 : mrObjectContact(rObjectContact
),
174 mrViewContact(rViewContact
),
176 mxPrimitive2DSequence(),
177 mpPrimitiveAnimation(0),
178 mbLazyInvalidate(false)
180 // make the ViewContact remember me
181 mrViewContact
.AddViewObjectContact(*this);
183 // make the ObjectContact remember me
184 mrObjectContact
.AddViewObjectContact(*this);
187 ViewObjectContact::~ViewObjectContact()
189 // invalidate in view
190 if(!maObjectRange
.isEmpty())
192 GetObjectContact().InvalidatePartOfView(maObjectRange
);
195 // delete PrimitiveAnimation
196 if(mpPrimitiveAnimation
)
198 delete mpPrimitiveAnimation
;
199 mpPrimitiveAnimation
= 0;
202 // take care of remebered ObjectContact. Remove from
203 // OC first. The VC removal (below) CAN trigger a StopGettingViewed()
204 // which (depending of it's implementation) may destroy other OCs. This
205 // can trigger the deletion of the helper OC of a page visualising object
206 // which IS the OC of this object. Eventually StopGettingViewed() needs
207 // to get asynchron later
208 GetObjectContact().RemoveViewObjectContact(*this);
210 // take care of remebered ViewContact
211 GetViewContact().RemoveViewObjectContact(*this);
214 const basegfx::B2DRange
& ViewObjectContact::getObjectRange() const
216 if(maObjectRange
.isEmpty())
218 // if range is not computed (new or LazyInvalidate objects), force it
219 const DisplayInfo aDisplayInfo
;
220 const drawinglayer::primitive2d::Primitive2DSequence
xSequence(getPrimitive2DSequence(aDisplayInfo
));
222 if(xSequence
.hasElements())
224 const drawinglayer::geometry::ViewInformation2D
& rViewInformation2D(GetObjectContact().getViewInformation2D());
225 const_cast< ViewObjectContact
* >(this)->maObjectRange
=
226 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xSequence
, rViewInformation2D
);
230 return maObjectRange
;
233 void ViewObjectContact::ActionChanged()
235 if(!mbLazyInvalidate
)
238 mbLazyInvalidate
= true;
243 if(!maObjectRange
.isEmpty())
245 // invalidate current valid range
246 GetObjectContact().InvalidatePartOfView(maObjectRange
);
248 // reset ObjectRange, it needs to be recalculated
249 maObjectRange
.reset();
252 // register at OC for lazy invalidate
253 GetObjectContact().setLazyInvalidate(*this);
257 void ViewObjectContact::triggerLazyInvalidate()
262 mbLazyInvalidate
= false;
267 if(!maObjectRange
.isEmpty())
269 // invalidate current valid range
270 GetObjectContact().InvalidatePartOfView(maObjectRange
);
275 // Take some action when new objects are inserted
276 void ViewObjectContact::ActionChildInserted(ViewContact
& rChild
)
278 // force creation of the new VOC and trigger it's refresh, so it
279 // will take part in LazyInvalidate immediately
280 rChild
.GetViewObjectContact(GetObjectContact()).ActionChanged();
282 // forward action to ObjectContact
283 // const ViewObjectContact& rChildVOC = rChild.GetViewObjectContact(GetObjectContact());
284 // GetObjectContact().InvalidatePartOfView(rChildVOC.getObjectRange());
287 void ViewObjectContact::checkForPrimitive2DAnimations()
290 if(mpPrimitiveAnimation
)
292 delete mpPrimitiveAnimation
;
293 mpPrimitiveAnimation
= 0;
296 // check for animated primitives
297 if(mxPrimitive2DSequence
.hasElements())
299 const bool bTextAnimationAllowed(GetObjectContact().IsTextAnimationAllowed());
300 const bool bGraphicAnimationAllowed(GetObjectContact().IsGraphicAnimationAllowed());
302 if(bTextAnimationAllowed
|| bGraphicAnimationAllowed
)
304 AnimatedExtractingProcessor2D
aAnimatedExtractor(GetObjectContact().getViewInformation2D(),
305 bTextAnimationAllowed
, bGraphicAnimationAllowed
);
306 aAnimatedExtractor
.process(mxPrimitive2DSequence
);
308 if(aAnimatedExtractor
.getPrimitive2DSequence().hasElements())
310 // dervied primitiveList is animated, setup new PrimitiveAnimation
311 mpPrimitiveAnimation
= new sdr::animation::PrimitiveAnimation(*this, aAnimatedExtractor
.getPrimitive2DSequence());
317 drawinglayer::primitive2d::Primitive2DSequence
ViewObjectContact::createPrimitive2DSequence(const DisplayInfo
& rDisplayInfo
) const
319 // get the view-independent Primitive from the viewContact
320 drawinglayer::primitive2d::Primitive2DSequence
xRetval(GetViewContact().getViewIndependentPrimitive2DSequence());
322 if(xRetval
.hasElements())
325 if(!GetObjectContact().isOutputToPrinter() && GetObjectContact().AreGluePointsVisible())
327 const drawinglayer::primitive2d::Primitive2DSequence
xGlue(GetViewContact().createGluePointPrimitive2DSequence());
329 if(xGlue
.hasElements())
331 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xRetval
, xGlue
);
336 if(isPrimitiveGhosted(rDisplayInfo
))
338 const basegfx::BColor
aRGBWhite(1.0, 1.0, 1.0);
339 const basegfx::BColorModifier
aBColorModifier(aRGBWhite
, 0.5, basegfx::BCOLORMODIFYMODE_INTERPOLATE
);
340 const drawinglayer::primitive2d::Primitive2DReference
xReference(new drawinglayer::primitive2d::ModifiedColorPrimitive2D(xRetval
, aBColorModifier
));
341 xRetval
= drawinglayer::primitive2d::Primitive2DSequence(&xReference
, 1);
348 drawinglayer::primitive2d::Primitive2DSequence
ViewObjectContact::getPrimitive2DSequence(const DisplayInfo
& rDisplayInfo
) const
350 drawinglayer::primitive2d::Primitive2DSequence xNewPrimitiveSequence
;
352 // take care of redirectors and create new list
353 ViewObjectContactRedirector
* pRedirector
= GetObjectContact().GetViewObjectContactRedirector();
357 xNewPrimitiveSequence
= pRedirector
->createRedirectedPrimitive2DSequence(*this, rDisplayInfo
);
361 xNewPrimitiveSequence
= createPrimitive2DSequence(rDisplayInfo
);
364 // local up-to-date checks. New list different from local one?
365 if(!drawinglayer::primitive2d::arePrimitive2DSequencesEqual(mxPrimitive2DSequence
, xNewPrimitiveSequence
))
367 // has changed, copy content
368 const_cast< ViewObjectContact
* >(this)->mxPrimitive2DSequence
= xNewPrimitiveSequence
;
370 // check for animated stuff
371 const_cast< ViewObjectContact
* >(this)->checkForPrimitive2DAnimations();
373 // always update object range when PrimitiveSequence changes
374 const drawinglayer::geometry::ViewInformation2D
& rViewInformation2D(GetObjectContact().getViewInformation2D());
375 const_cast< ViewObjectContact
* >(this)->maObjectRange
=
376 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(mxPrimitive2DSequence
, rViewInformation2D
);
379 // return current Primitive2DSequence
380 return mxPrimitive2DSequence
;
383 bool ViewObjectContact::isPrimitiveVisible(const DisplayInfo
& /*rDisplayInfo*/) const
385 // default: always visible
389 bool ViewObjectContact::isPrimitiveGhosted(const DisplayInfo
& rDisplayInfo
) const
391 // default: standard check
392 return (GetObjectContact().DoVisualizeEnteredGroup() && !GetObjectContact().isOutputToPrinter() && rDisplayInfo
.IsGhostedDrawModeActive());
395 drawinglayer::primitive2d::Primitive2DSequence
ViewObjectContact::getPrimitive2DSequenceHierarchy(DisplayInfo
& rDisplayInfo
) const
397 drawinglayer::primitive2d::Primitive2DSequence xRetval
;
399 // check model-view visibility
400 if(isPrimitiveVisible(rDisplayInfo
))
402 xRetval
= getPrimitive2DSequence(rDisplayInfo
);
404 if(xRetval
.hasElements())
407 const drawinglayer::geometry::ViewInformation2D
& rViewInformation2D(GetObjectContact().getViewInformation2D());
408 const basegfx::B2DRange
aObjectRange(drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xRetval
, rViewInformation2D
));
409 const basegfx::B2DRange
aViewRange(rViewInformation2D
.getViewport());
411 // check geometrical visibility
412 if(!aViewRange
.isEmpty() && !aViewRange
.overlaps(aObjectRange
))
414 // not visible, release
423 drawinglayer::primitive2d::Primitive2DSequence
ViewObjectContact::getPrimitive2DSequenceSubHierarchy(DisplayInfo
& rDisplayInfo
) const
425 const sal_uInt32
nSubHierarchyCount(GetViewContact().GetObjectCount());
426 drawinglayer::primitive2d::Primitive2DSequence xSeqRetval
;
428 for(sal_uInt32
a(0); a
< nSubHierarchyCount
; a
++)
430 const ViewObjectContact
& rCandidate(GetViewContact().GetViewContact(a
).GetViewObjectContact(GetObjectContact()));
432 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xSeqRetval
, rCandidate
.getPrimitive2DSequenceHierarchy(rDisplayInfo
));
437 } // end of namespace contact
438 } // end of namespace sdr
440 //////////////////////////////////////////////////////////////////////////////