LCOV - code coverage report
Current view: top level - libreoffice/svx/source/sdr/contact - viewobjectcontact.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 99 125 79.2 %
Date: 2012-12-27 Functions: 15 21 71.4 %
Legend: Lines: hit not hit

          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/viewobjectcontact.hxx>
      21             : #include <svx/sdr/contact/viewcontact.hxx>
      22             : #include <svx/sdr/contact/objectcontact.hxx>
      23             : #include <svx/sdr/contact/displayinfo.hxx>
      24             : #include <vcl/region.hxx>
      25             : #include <svx/sdr/animation/objectanimator.hxx>
      26             : #include <svx/sdr/animation/animationstate.hxx>
      27             : #include <svx/sdr/contact/viewobjectcontactredirector.hxx>
      28             : #include <basegfx/numeric/ftools.hxx>
      29             : #include <basegfx/color/bcolor.hxx>
      30             : #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
      31             : #include <basegfx/tools/canvastools.hxx>
      32             : #include <drawinglayer/primitive2d/animatedprimitive2d.hxx>
      33             : #include <drawinglayer/processor2d/baseprocessor2d.hxx>
      34             : #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
      35             : 
      36             : //////////////////////////////////////////////////////////////////////////////
      37             : 
      38             : using namespace com::sun::star;
      39             : 
      40             : //////////////////////////////////////////////////////////////////////////////
      41             : 
      42             : namespace
      43             : {
      44             :     // animated extractor
      45             : 
      46             :     // Necessary to filter a sequence of animated primitives from
      47             :     // a sequence of primitives to find out if animated or not. The decision for
      48             :     // what to decompose is hard-coded and only done for knowingly animated primitives
      49             :     // to not decompose too deeply and unnecessarily. This implies that the list
      50             :     // which is view-specific needs to be expanded by hand when new animated objects
      51             :     // are added. This may eventually be changed to a dynamically configurable approach
      52             :     // if necessary.
      53             :     class AnimatedExtractingProcessor2D : public drawinglayer::processor2d::BaseProcessor2D
      54             :     {
      55             :     protected:
      56             :         // the found animated primitives
      57             :         drawinglayer::primitive2d::Primitive2DSequence  maPrimitive2DSequence;
      58             : 
      59             :         // bitfield
      60             :         // text animation allowed?
      61             :         unsigned                                        mbTextAnimationAllowed : 1;
      62             : 
      63             :         // graphic animation allowed?
      64             :         unsigned                                        mbGraphicAnimationAllowed : 1;
      65             : 
      66             :         // as tooling, the process() implementation takes over API handling and calls this
      67             :         // virtual render method when the primitive implementation is BasePrimitive2D-based.
      68             :         virtual void processBasePrimitive2D(const drawinglayer::primitive2d::BasePrimitive2D& rCandidate);
      69             : 
      70             :     public:
      71             :         AnimatedExtractingProcessor2D(
      72             :             const drawinglayer::geometry::ViewInformation2D& rViewInformation,
      73             :             bool bTextAnimationAllowed,
      74             :             bool bGraphicAnimationAllowed);
      75             :         virtual ~AnimatedExtractingProcessor2D();
      76             : 
      77             :         // data access
      78         130 :         const drawinglayer::primitive2d::Primitive2DSequence& getPrimitive2DSequence() const { return maPrimitive2DSequence; }
      79           0 :         bool isTextAnimationAllowed() const { return mbTextAnimationAllowed; }
      80           0 :         bool isGraphicAnimationAllowed() const { return mbGraphicAnimationAllowed; }
      81             :     };
      82             : 
      83         130 :     AnimatedExtractingProcessor2D::AnimatedExtractingProcessor2D(
      84             :         const drawinglayer::geometry::ViewInformation2D& rViewInformation,
      85             :         bool bTextAnimationAllowed,
      86             :         bool bGraphicAnimationAllowed)
      87             :     :   drawinglayer::processor2d::BaseProcessor2D(rViewInformation),
      88             :         maPrimitive2DSequence(),
      89             :         mbTextAnimationAllowed(bTextAnimationAllowed),
      90         130 :         mbGraphicAnimationAllowed(bGraphicAnimationAllowed)
      91             :     {
      92         130 :     }
      93             : 
      94         130 :     AnimatedExtractingProcessor2D::~AnimatedExtractingProcessor2D()
      95             :     {
      96         130 :     }
      97             : 
      98         185 :     void AnimatedExtractingProcessor2D::processBasePrimitive2D(const drawinglayer::primitive2d::BasePrimitive2D& rCandidate)
      99             :     {
     100             :         // known implementation, access directly
     101         185 :         switch(rCandidate.getPrimitive2DID())
     102             :         {
     103             :             // add and accept animated primitives directly, no need to decompose
     104             :             case PRIMITIVE2D_ID_ANIMATEDSWITCHPRIMITIVE2D :
     105             :             case PRIMITIVE2D_ID_ANIMATEDBLINKPRIMITIVE2D :
     106             :             case PRIMITIVE2D_ID_ANIMATEDINTERPOLATEPRIMITIVE2D :
     107             :             {
     108           0 :                 const drawinglayer::primitive2d::AnimatedSwitchPrimitive2D& rSwitchPrimitive = static_cast< const drawinglayer::primitive2d::AnimatedSwitchPrimitive2D& >(rCandidate);
     109             : 
     110           0 :                 if((rSwitchPrimitive.isTextAnimation() && isTextAnimationAllowed())
     111           0 :                     || (rSwitchPrimitive.isGraphicAnimation() && isGraphicAnimationAllowed()))
     112             :                 {
     113           0 :                     const drawinglayer::primitive2d::Primitive2DReference xReference(const_cast< drawinglayer::primitive2d::BasePrimitive2D* >(&rCandidate));
     114           0 :                     drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(maPrimitive2DSequence, xReference);
     115             :                 }
     116           0 :                 break;
     117             :             }
     118             : 
     119             :             // decompose animated gifs where SdrGrafPrimitive2D produces a GraphicPrimitive2D
     120             :             // which then produces the animation infos (all when used/needed)
     121             :             case PRIMITIVE2D_ID_SDRGRAFPRIMITIVE2D :
     122             :             case PRIMITIVE2D_ID_GRAPHICPRIMITIVE2D :
     123             : 
     124             :             // decompose SdrObjects with evtl. animated text
     125             :             case PRIMITIVE2D_ID_SDRCAPTIONPRIMITIVE2D :
     126             :             case PRIMITIVE2D_ID_SDRCONNECTORPRIMITIVE2D :
     127             :             case PRIMITIVE2D_ID_SDRCUSTOMSHAPEPRIMITIVE2D :
     128             :             case PRIMITIVE2D_ID_SDRELLIPSEPRIMITIVE2D :
     129             :             case PRIMITIVE2D_ID_SDRELLIPSESEGMENTPRIMITIVE2D :
     130             :             case PRIMITIVE2D_ID_SDRMEASUREPRIMITIVE2D :
     131             :             case PRIMITIVE2D_ID_SDRPATHPRIMITIVE2D :
     132             :             case PRIMITIVE2D_ID_SDRRECTANGLEPRIMITIVE2D :
     133             : 
     134             :             // decompose evtl. animated text contained in MaskPrimitive2D
     135             :             // or group rimitives
     136             :             case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
     137             :             case PRIMITIVE2D_ID_GROUPPRIMITIVE2D :
     138             :             {
     139          34 :                 process(rCandidate.get2DDecomposition(getViewInformation2D()));
     140          34 :                 break;
     141             :             }
     142             : 
     143             :             default :
     144             :             {
     145             :                 // nothing to do for the rest
     146         151 :                 break;
     147             :             }
     148             :         }
     149         185 :     }
     150             : } // end of anonymous namespace
     151             : 
     152             : //////////////////////////////////////////////////////////////////////////////
     153             : 
     154             : namespace sdr
     155             : {
     156             :     namespace contact
     157             :     {
     158        1740 :         ViewObjectContact::ViewObjectContact(ObjectContact& rObjectContact, ViewContact& rViewContact)
     159             :         :   mrObjectContact(rObjectContact),
     160             :             mrViewContact(rViewContact),
     161             :             maObjectRange(),
     162             :             mxPrimitive2DSequence(),
     163             :             mpPrimitiveAnimation(0),
     164        1740 :             mbLazyInvalidate(false)
     165             :         {
     166             :             // make the ViewContact remember me
     167        1740 :             mrViewContact.AddViewObjectContact(*this);
     168             : 
     169             :             // make the ObjectContact remember me
     170        1740 :             mrObjectContact.AddViewObjectContact(*this);
     171        1740 :         }
     172             : 
     173         236 :         ViewObjectContact::~ViewObjectContact()
     174             :         {
     175             :             // invalidate in view
     176         118 :             if(!maObjectRange.isEmpty())
     177             :             {
     178          15 :                 GetObjectContact().InvalidatePartOfView(maObjectRange);
     179             :             }
     180             : 
     181             :             // delete PrimitiveAnimation
     182         118 :             if(mpPrimitiveAnimation)
     183             :             {
     184           0 :                 delete mpPrimitiveAnimation;
     185           0 :                 mpPrimitiveAnimation = 0;
     186             :             }
     187             : 
     188             :             // take care of remebered ObjectContact. Remove from
     189             :             // OC first. The VC removal (below) CAN trigger a StopGettingViewed()
     190             :             // which (depending of it's implementation) may destroy other OCs. This
     191             :             // can trigger the deletion of the helper OC of a page visualising object
     192             :             // which IS the OC of this object. Eventually StopGettingViewed() needs
     193             :             // to get asynchron later
     194         118 :             GetObjectContact().RemoveViewObjectContact(*this);
     195             : 
     196             :             // take care of remebered ViewContact
     197         118 :             GetViewContact().RemoveViewObjectContact(*this);
     198         118 :         }
     199             : 
     200          40 :         const basegfx::B2DRange& ViewObjectContact::getObjectRange() const
     201             :         {
     202          40 :             if(maObjectRange.isEmpty())
     203             :             {
     204             :                 // if range is not computed (new or LazyInvalidate objects), force it
     205          40 :                 const DisplayInfo aDisplayInfo;
     206          40 :                 const drawinglayer::primitive2d::Primitive2DSequence xSequence(getPrimitive2DSequence(aDisplayInfo));
     207             : 
     208          40 :                 if(xSequence.hasElements())
     209             :                 {
     210          20 :                     const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D());
     211             :                     const_cast< ViewObjectContact* >(this)->maObjectRange =
     212          20 :                         drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xSequence, rViewInformation2D);
     213          40 :                 }
     214             :             }
     215             : 
     216          40 :             return maObjectRange;
     217             :         }
     218             : 
     219          12 :         void ViewObjectContact::ActionChanged()
     220             :         {
     221          12 :             if(!mbLazyInvalidate)
     222             :             {
     223             :                 // set local flag
     224          12 :                 mbLazyInvalidate = true;
     225             : 
     226             :                 // force ObjectRange
     227          12 :                 getObjectRange();
     228             : 
     229          12 :                 if(!maObjectRange.isEmpty())
     230             :                 {
     231             :                     // invalidate current valid range
     232           9 :                     GetObjectContact().InvalidatePartOfView(maObjectRange);
     233             : 
     234             :                     // reset ObjectRange, it needs to be recalculated
     235           9 :                     maObjectRange.reset();
     236             :                 }
     237             : 
     238             :                 // register at OC for lazy invalidate
     239          12 :                 GetObjectContact().setLazyInvalidate(*this);
     240             :             }
     241          12 :         }
     242             : 
     243         139 :         void ViewObjectContact::triggerLazyInvalidate()
     244             :         {
     245         139 :             if(mbLazyInvalidate)
     246             :             {
     247             :                 // reset flag
     248          12 :                 mbLazyInvalidate = false;
     249             : 
     250             :                 // force ObjectRange
     251          12 :                 getObjectRange();
     252             : 
     253          12 :                 if(!maObjectRange.isEmpty())
     254             :                 {
     255             :                     // invalidate current valid range
     256           9 :                     GetObjectContact().InvalidatePartOfView(maObjectRange);
     257             :                 }
     258             :             }
     259         139 :         }
     260             : 
     261             :         // Take some action when new objects are inserted
     262           0 :         void ViewObjectContact::ActionChildInserted(ViewContact& rChild)
     263             :         {
     264             :             // force creation of the new VOC and trigger it's refresh, so it
     265             :             // will take part in LazyInvalidate immediately
     266           0 :             rChild.GetViewObjectContact(GetObjectContact()).ActionChanged();
     267             : 
     268             :             // forward action to ObjectContact
     269             :             // const ViewObjectContact& rChildVOC = rChild.GetViewObjectContact(GetObjectContact());
     270             :             // GetObjectContact().InvalidatePartOfView(rChildVOC.getObjectRange());
     271           0 :         }
     272             : 
     273         130 :         void ViewObjectContact::checkForPrimitive2DAnimations()
     274             :         {
     275             :             // remove old one
     276         130 :             if(mpPrimitiveAnimation)
     277             :             {
     278           0 :                 delete mpPrimitiveAnimation;
     279           0 :                 mpPrimitiveAnimation = 0;
     280             :             }
     281             : 
     282             :             // check for animated primitives
     283         130 :             if(mxPrimitive2DSequence.hasElements())
     284             :             {
     285         130 :                 const bool bTextAnimationAllowed(GetObjectContact().IsTextAnimationAllowed());
     286         130 :                 const bool bGraphicAnimationAllowed(GetObjectContact().IsGraphicAnimationAllowed());
     287             : 
     288         130 :                 if(bTextAnimationAllowed || bGraphicAnimationAllowed)
     289             :                 {
     290         130 :                     AnimatedExtractingProcessor2D aAnimatedExtractor(GetObjectContact().getViewInformation2D(),
     291         260 :                         bTextAnimationAllowed, bGraphicAnimationAllowed);
     292         130 :                     aAnimatedExtractor.process(mxPrimitive2DSequence);
     293             : 
     294         130 :                     if(aAnimatedExtractor.getPrimitive2DSequence().hasElements())
     295             :                     {
     296             :                         // dervied primitiveList is animated, setup new PrimitiveAnimation
     297           0 :                         mpPrimitiveAnimation =  new sdr::animation::PrimitiveAnimation(*this, aAnimatedExtractor.getPrimitive2DSequence());
     298         130 :                     }
     299             :                 }
     300             :             }
     301         130 :         }
     302             : 
     303         284 :         drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
     304             :         {
     305             :             // get the view-independent Primitive from the viewContact
     306         284 :             drawinglayer::primitive2d::Primitive2DSequence xRetval(GetViewContact().getViewIndependentPrimitive2DSequence());
     307             : 
     308         284 :             if(xRetval.hasElements())
     309             :             {
     310             :                 // handle GluePoint
     311         237 :                 if(!GetObjectContact().isOutputToPrinter() && GetObjectContact().AreGluePointsVisible())
     312             :                 {
     313           0 :                     const drawinglayer::primitive2d::Primitive2DSequence xGlue(GetViewContact().createGluePointPrimitive2DSequence());
     314             : 
     315           0 :                     if(xGlue.hasElements())
     316             :                     {
     317           0 :                         drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xRetval, xGlue);
     318           0 :                     }
     319             :                 }
     320             : 
     321             :                 // handle ghosted
     322         237 :                 if(isPrimitiveGhosted(rDisplayInfo))
     323             :                 {
     324           0 :                     const basegfx::BColor aRGBWhite(1.0, 1.0, 1.0);
     325           0 :                     const basegfx::BColorModifier aBColorModifier(aRGBWhite, 0.5, basegfx::BCOLORMODIFYMODE_INTERPOLATE);
     326           0 :                     const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::ModifiedColorPrimitive2D(xRetval, aBColorModifier));
     327           0 :                     xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
     328             :                 }
     329             :             }
     330             : 
     331         284 :             return xRetval;
     332             :         }
     333             : 
     334         300 :         drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::getPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
     335             :         {
     336         300 :             drawinglayer::primitive2d::Primitive2DSequence xNewPrimitiveSequence;
     337             : 
     338             :             // take care of redirectors and create new list
     339         300 :             ViewObjectContactRedirector* pRedirector = GetObjectContact().GetViewObjectContactRedirector();
     340             : 
     341         300 :             if(pRedirector)
     342             :             {
     343         244 :                 xNewPrimitiveSequence = pRedirector->createRedirectedPrimitive2DSequence(*this, rDisplayInfo);
     344             :             }
     345             :             else
     346             :             {
     347          56 :                 xNewPrimitiveSequence = createPrimitive2DSequence(rDisplayInfo);
     348             :             }
     349             : 
     350             :             // local up-to-date checks. New list different from local one?
     351         300 :             if(!drawinglayer::primitive2d::arePrimitive2DSequencesEqual(mxPrimitive2DSequence, xNewPrimitiveSequence))
     352             :             {
     353             :                 // has changed, copy content
     354         130 :                 const_cast< ViewObjectContact* >(this)->mxPrimitive2DSequence = xNewPrimitiveSequence;
     355             : 
     356             :                 // check for animated stuff
     357         130 :                 const_cast< ViewObjectContact* >(this)->checkForPrimitive2DAnimations();
     358             : 
     359             :                 // always update object range when PrimitiveSequence changes
     360         130 :                 const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D());
     361             :                 const_cast< ViewObjectContact* >(this)->maObjectRange =
     362         130 :                     drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(mxPrimitive2DSequence, rViewInformation2D);
     363             :             }
     364             : 
     365             :             // return current Primitive2DSequence
     366         300 :             return mxPrimitive2DSequence;
     367             :         }
     368             : 
     369           0 :         bool ViewObjectContact::isPrimitiveVisible(const DisplayInfo& /*rDisplayInfo*/) const
     370             :         {
     371             :             // default: always visible
     372           0 :             return true;
     373             :         }
     374             : 
     375         231 :         bool ViewObjectContact::isPrimitiveGhosted(const DisplayInfo& rDisplayInfo) const
     376             :         {
     377             :             // default: standard check
     378         231 :             return (GetObjectContact().DoVisualizeEnteredGroup() && !GetObjectContact().isOutputToPrinter() && rDisplayInfo.IsGhostedDrawModeActive());
     379             :         }
     380             : 
     381        8908 :         drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::getPrimitive2DSequenceHierarchy(DisplayInfo& rDisplayInfo) const
     382             :         {
     383        8908 :             drawinglayer::primitive2d::Primitive2DSequence xRetval;
     384             : 
     385             :             // check model-view visibility
     386        8908 :             if(isPrimitiveVisible(rDisplayInfo))
     387             :             {
     388         260 :                 xRetval = getPrimitive2DSequence(rDisplayInfo);
     389             : 
     390         260 :                 if(xRetval.hasElements())
     391             :                 {
     392             :                     // get ranges
     393         225 :                     const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D());
     394         225 :                     const basegfx::B2DRange aObjectRange(drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xRetval, rViewInformation2D));
     395         225 :                     const basegfx::B2DRange aViewRange(rViewInformation2D.getViewport());
     396             : 
     397             :                     // check geometrical visibility
     398         225 :                     if(!aViewRange.isEmpty() && !aViewRange.overlaps(aObjectRange))
     399             :                     {
     400             :                         // not visible, release
     401          20 :                         xRetval.realloc(0);
     402             :                     }
     403             :                 }
     404             :             }
     405             : 
     406        8908 :             return xRetval;
     407             :         }
     408             : 
     409        1169 :         drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::getPrimitive2DSequenceSubHierarchy(DisplayInfo& rDisplayInfo) const
     410             :         {
     411        1169 :             const sal_uInt32 nSubHierarchyCount(GetViewContact().GetObjectCount());
     412        1169 :             drawinglayer::primitive2d::Primitive2DSequence xSeqRetval;
     413             : 
     414       10885 :             for(sal_uInt32 a(0); a < nSubHierarchyCount; a++)
     415             :             {
     416        9716 :                 const ViewObjectContact& rCandidate(GetViewContact().GetViewContact(a).GetViewObjectContact(GetObjectContact()));
     417             : 
     418        9716 :                 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xSeqRetval, rCandidate.getPrimitive2DSequenceHierarchy(rDisplayInfo));
     419             :             }
     420             : 
     421        1169 :             return xSeqRetval;
     422             :         }
     423             :     } // end of namespace contact
     424             : } // end of namespace sdr
     425             : 
     426             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10