LCOV - code coverage report
Current view: top level - svx/source/sdr/contact - viewobjectcontact.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 102 125 81.6 %
Date: 2014-04-11 Functions: 16 21 76.2 %
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             :         bool                                            mbTextAnimationAllowed : 1;
      62             : 
      63             :         // graphic animation allowed?
      64             :         bool                                            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) SAL_OVERRIDE;
      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       21835 :         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       21835 :     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       21835 :         mbGraphicAnimationAllowed(bGraphicAnimationAllowed)
      91             :     {
      92       21835 :     }
      93             : 
      94       21835 :     AnimatedExtractingProcessor2D::~AnimatedExtractingProcessor2D()
      95             :     {
      96       21835 :     }
      97             : 
      98       46308 :     void AnimatedExtractingProcessor2D::processBasePrimitive2D(const drawinglayer::primitive2d::BasePrimitive2D& rCandidate)
      99             :     {
     100             :         // known implementation, access directly
     101       46308 :         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             :             // #121194# With Graphic as Bitmap FillStyle, also check
     135             :             // for primitives filled with animated graphics
     136             :             case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D:
     137             :             case PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D:
     138             :             case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D:
     139             : 
     140             :             // decompose evtl. animated text contained in MaskPrimitive2D
     141             :             // or group rimitives
     142             :             case PRIMITIVE2D_ID_MASKPRIMITIVE2D :
     143             :             case PRIMITIVE2D_ID_GROUPPRIMITIVE2D :
     144             :             {
     145        9230 :                 process(rCandidate.get2DDecomposition(getViewInformation2D()));
     146        9230 :                 break;
     147             :             }
     148             : 
     149             :             default :
     150             :             {
     151             :                 // nothing to do for the rest
     152       37078 :                 break;
     153             :             }
     154             :         }
     155       46308 :     }
     156             : } // end of anonymous namespace
     157             : 
     158             : 
     159             : 
     160             : namespace sdr
     161             : {
     162             :     namespace contact
     163             :     {
     164       34852 :         ViewObjectContact::ViewObjectContact(ObjectContact& rObjectContact, ViewContact& rViewContact)
     165             :         :   mrObjectContact(rObjectContact),
     166             :             mrViewContact(rViewContact),
     167             :             maObjectRange(),
     168             :             mxPrimitive2DSequence(),
     169             :             mpPrimitiveAnimation(0),
     170       34852 :             mbLazyInvalidate(false)
     171             :         {
     172             :             // make the ViewContact remember me
     173       34852 :             mrViewContact.AddViewObjectContact(*this);
     174             : 
     175             :             // make the ObjectContact remember me
     176       34852 :             mrObjectContact.AddViewObjectContact(*this);
     177       34852 :         }
     178             : 
     179       69652 :         ViewObjectContact::~ViewObjectContact()
     180             :         {
     181             :             // invalidate in view
     182       34826 :             if(!maObjectRange.isEmpty())
     183             :             {
     184       16420 :                 GetObjectContact().InvalidatePartOfView(maObjectRange);
     185             :             }
     186             : 
     187             :             // delete PrimitiveAnimation
     188       34826 :             if(mpPrimitiveAnimation)
     189             :             {
     190           0 :                 delete mpPrimitiveAnimation;
     191           0 :                 mpPrimitiveAnimation = 0;
     192             :             }
     193             : 
     194             :             // take care of remebered ObjectContact. Remove from
     195             :             // OC first. The VC removal (below) CAN trigger a StopGettingViewed()
     196             :             // which (depending of it's implementation) may destroy other OCs. This
     197             :             // can trigger the deletion of the helper OC of a page visualising object
     198             :             // which IS the OC of this object. Eventually StopGettingViewed() needs
     199             :             // to get asynchron later
     200       34826 :             GetObjectContact().RemoveViewObjectContact(*this);
     201             : 
     202             :             // take care of remebered ViewContact
     203       34826 :             GetViewContact().RemoveViewObjectContact(*this);
     204       34826 :         }
     205             : 
     206       13153 :         const basegfx::B2DRange& ViewObjectContact::getObjectRange() const
     207             :         {
     208       13153 :             if(maObjectRange.isEmpty())
     209             :             {
     210             :                 // if range is not computed (new or LazyInvalidate objects), force it
     211        7802 :                 const DisplayInfo aDisplayInfo;
     212       15604 :                 const drawinglayer::primitive2d::Primitive2DSequence xSequence(getPrimitive2DSequence(aDisplayInfo));
     213             : 
     214        7802 :                 if(xSequence.hasElements())
     215             :                 {
     216        7102 :                     const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D());
     217             :                     const_cast< ViewObjectContact* >(this)->maObjectRange =
     218        7102 :                         drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xSequence, rViewInformation2D);
     219        7802 :                 }
     220             :             }
     221             : 
     222       13153 :             return maObjectRange;
     223             :         }
     224             : 
     225       12156 :         void ViewObjectContact::ActionChanged()
     226             :         {
     227       12156 :             if(!mbLazyInvalidate)
     228             :             {
     229             :                 // set local flag
     230        6627 :                 mbLazyInvalidate = true;
     231             : 
     232             :                 // force ObjectRange
     233        6627 :                 getObjectRange();
     234             : 
     235        6627 :                 if(!maObjectRange.isEmpty())
     236             :                 {
     237             :                     // invalidate current valid range
     238        6281 :                     GetObjectContact().InvalidatePartOfView(maObjectRange);
     239             : 
     240             :                     // reset ObjectRange, it needs to be recalculated
     241        6281 :                     maObjectRange.reset();
     242             :                 }
     243             : 
     244             :                 // register at OC for lazy invalidate
     245        6627 :                 GetObjectContact().setLazyInvalidate(*this);
     246             :             }
     247       12156 :         }
     248             : 
     249      102476 :         void ViewObjectContact::triggerLazyInvalidate()
     250             :         {
     251      102476 :             if(mbLazyInvalidate)
     252             :             {
     253             :                 // reset flag
     254        6489 :                 mbLazyInvalidate = false;
     255             : 
     256             :                 // force ObjectRange
     257        6489 :                 getObjectRange();
     258             : 
     259        6489 :                 if(!maObjectRange.isEmpty())
     260             :                 {
     261             :                     // invalidate current valid range
     262        6143 :                     GetObjectContact().InvalidatePartOfView(maObjectRange);
     263             :                 }
     264             :             }
     265      102476 :         }
     266             : 
     267             :         // Take some action when new objects are inserted
     268         488 :         void ViewObjectContact::ActionChildInserted(ViewContact& rChild)
     269             :         {
     270             :             // force creation of the new VOC and trigger it's refresh, so it
     271             :             // will take part in LazyInvalidate immediately
     272         488 :             rChild.GetViewObjectContact(GetObjectContact()).ActionChanged();
     273             : 
     274             :             // forward action to ObjectContact
     275             :             // const ViewObjectContact& rChildVOC = rChild.GetViewObjectContact(GetObjectContact());
     276             :             // GetObjectContact().InvalidatePartOfView(rChildVOC.getObjectRange());
     277         488 :         }
     278             : 
     279       21844 :         void ViewObjectContact::checkForPrimitive2DAnimations()
     280             :         {
     281             :             // remove old one
     282       21844 :             if(mpPrimitiveAnimation)
     283             :             {
     284           0 :                 delete mpPrimitiveAnimation;
     285           0 :                 mpPrimitiveAnimation = 0;
     286             :             }
     287             : 
     288             :             // check for animated primitives
     289       21844 :             if(mxPrimitive2DSequence.hasElements())
     290             :             {
     291       21835 :                 const bool bTextAnimationAllowed(GetObjectContact().IsTextAnimationAllowed());
     292       21835 :                 const bool bGraphicAnimationAllowed(GetObjectContact().IsGraphicAnimationAllowed());
     293             : 
     294       21835 :                 if(bTextAnimationAllowed || bGraphicAnimationAllowed)
     295             :                 {
     296       21835 :                     AnimatedExtractingProcessor2D aAnimatedExtractor(GetObjectContact().getViewInformation2D(),
     297       43670 :                         bTextAnimationAllowed, bGraphicAnimationAllowed);
     298       21835 :                     aAnimatedExtractor.process(mxPrimitive2DSequence);
     299             : 
     300       21835 :                     if(aAnimatedExtractor.getPrimitive2DSequence().hasElements())
     301             :                     {
     302             :                         // dervied primitiveList is animated, setup new PrimitiveAnimation
     303           0 :                         mpPrimitiveAnimation =  new sdr::animation::PrimitiveAnimation(*this, aAnimatedExtractor.getPrimitive2DSequence());
     304       21835 :                     }
     305             :                 }
     306             :             }
     307       21844 :         }
     308             : 
     309       21430 :         drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
     310             :         {
     311             :             // get the view-independent Primitive from the viewContact
     312       21430 :             drawinglayer::primitive2d::Primitive2DSequence xRetval(GetViewContact().getViewIndependentPrimitive2DSequence());
     313             : 
     314       21430 :             if(xRetval.hasElements())
     315             :             {
     316             :                 // handle GluePoint
     317       20860 :                 if(!GetObjectContact().isOutputToPrinter() && GetObjectContact().AreGluePointsVisible())
     318             :                 {
     319           0 :                     const drawinglayer::primitive2d::Primitive2DSequence xGlue(GetViewContact().createGluePointPrimitive2DSequence());
     320             : 
     321           0 :                     if(xGlue.hasElements())
     322             :                     {
     323           0 :                         drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xRetval, xGlue);
     324           0 :                     }
     325             :                 }
     326             : 
     327             :                 // handle ghosted
     328       20860 :                 if(isPrimitiveGhosted(rDisplayInfo))
     329             :                 {
     330           0 :                     const basegfx::BColor aRGBWhite(1.0, 1.0, 1.0);
     331             :                     const basegfx::BColorModifierSharedPtr aBColorModifier(
     332             :                         new basegfx::BColorModifier_interpolate(
     333             :                             aRGBWhite,
     334           0 :                             0.5));
     335             :                     const drawinglayer::primitive2d::Primitive2DReference xReference(
     336             :                         new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
     337             :                             xRetval,
     338           0 :                             aBColorModifier));
     339             : 
     340           0 :                     xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
     341             :                 }
     342             :             }
     343             : 
     344       21430 :             return xRetval;
     345             :         }
     346             : 
     347       33101 :         drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::getPrimitive2DSequence(const DisplayInfo& rDisplayInfo) const
     348             :         {
     349       33101 :             drawinglayer::primitive2d::Primitive2DSequence xNewPrimitiveSequence;
     350             : 
     351             :             // take care of redirectors and create new list
     352       33101 :             ViewObjectContactRedirector* pRedirector = GetObjectContact().GetViewObjectContactRedirector();
     353             : 
     354       33101 :             if(pRedirector)
     355             :             {
     356        4640 :                 xNewPrimitiveSequence = pRedirector->createRedirectedPrimitive2DSequence(*this, rDisplayInfo);
     357             :             }
     358             :             else
     359             :             {
     360       28461 :                 xNewPrimitiveSequence = createPrimitive2DSequence(rDisplayInfo);
     361             :             }
     362             : 
     363             :             // local up-to-date checks. New list different from local one?
     364       33101 :             if(!drawinglayer::primitive2d::arePrimitive2DSequencesEqual(mxPrimitive2DSequence, xNewPrimitiveSequence))
     365             :             {
     366             :                 // has changed, copy content
     367       21844 :                 const_cast< ViewObjectContact* >(this)->mxPrimitive2DSequence = xNewPrimitiveSequence;
     368             : 
     369             :                 // check for animated stuff
     370       21844 :                 const_cast< ViewObjectContact* >(this)->checkForPrimitive2DAnimations();
     371             : 
     372             :                 // always update object range when PrimitiveSequence changes
     373       21844 :                 const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D());
     374             :                 const_cast< ViewObjectContact* >(this)->maObjectRange =
     375       21844 :                     drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(mxPrimitive2DSequence, rViewInformation2D);
     376             :             }
     377             : 
     378             :             // return current Primitive2DSequence
     379       33101 :             return mxPrimitive2DSequence;
     380             :         }
     381             : 
     382           0 :         bool ViewObjectContact::isPrimitiveVisible(const DisplayInfo& /*rDisplayInfo*/) const
     383             :         {
     384             :             // default: always visible
     385           0 :             return true;
     386             :         }
     387             : 
     388       18819 :         bool ViewObjectContact::isPrimitiveGhosted(const DisplayInfo& rDisplayInfo) const
     389             :         {
     390             :             // default: standard check
     391       18819 :             return (GetObjectContact().DoVisualizeEnteredGroup() && !GetObjectContact().isOutputToPrinter() && rDisplayInfo.IsGhostedDrawModeActive());
     392             :         }
     393             : 
     394      139454 :         drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::getPrimitive2DSequenceHierarchy(DisplayInfo& rDisplayInfo) const
     395             :         {
     396      139454 :             drawinglayer::primitive2d::Primitive2DSequence xRetval;
     397             : 
     398             :             // check model-view visibility
     399      139454 :             if(isPrimitiveVisible(rDisplayInfo))
     400             :             {
     401       25293 :                 xRetval = getPrimitive2DSequence(rDisplayInfo);
     402             : 
     403       25293 :                 if(xRetval.hasElements())
     404             :                 {
     405             :                     // get ranges
     406       24625 :                     const drawinglayer::geometry::ViewInformation2D& rViewInformation2D(GetObjectContact().getViewInformation2D());
     407       24625 :                     const basegfx::B2DRange aObjectRange(drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence(xRetval, rViewInformation2D));
     408       24625 :                     const basegfx::B2DRange aViewRange(rViewInformation2D.getViewport());
     409             : 
     410             :                     // check geometrical visibility
     411       24625 :                     if(!aViewRange.isEmpty() && !aViewRange.overlaps(aObjectRange))
     412             :                     {
     413             :                         // not visible, release
     414        3450 :                         xRetval.realloc(0);
     415             :                     }
     416             :                 }
     417             :             }
     418             : 
     419      139454 :             return xRetval;
     420             :         }
     421             : 
     422       29220 :         drawinglayer::primitive2d::Primitive2DSequence ViewObjectContact::getPrimitive2DSequenceSubHierarchy(DisplayInfo& rDisplayInfo) const
     423             :         {
     424       29220 :             const sal_uInt32 nSubHierarchyCount(GetViewContact().GetObjectCount());
     425       29220 :             drawinglayer::primitive2d::Primitive2DSequence xSeqRetval;
     426             : 
     427      189006 :             for(sal_uInt32 a(0); a < nSubHierarchyCount; a++)
     428             :             {
     429      159786 :                 const ViewObjectContact& rCandidate(GetViewContact().GetViewContact(a).GetViewObjectContact(GetObjectContact()));
     430             : 
     431      159786 :                 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xSeqRetval, rCandidate.getPrimitive2DSequenceHierarchy(rDisplayInfo));
     432             :             }
     433             : 
     434       29220 :             return xSeqRetval;
     435             :         }
     436             :     } // end of namespace contact
     437             : } // end of namespace sdr
     438             : 
     439             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10