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

Generated by: LCOV version 1.11