[Libreoffice-commits] core.git: Branch 'feature/RotateFlyFrame3' - sw/source

Armin Le Grand Armin.Le.Grand at cib.de
Thu Nov 16 17:49:51 UTC 2017


 sw/source/core/draw/dflyobj.cxx   |    8 -
 sw/source/core/frmedt/fefly1.cxx  |    2 
 sw/source/core/inc/flyfrms.hxx    |    7 -
 sw/source/core/layout/fly.cxx     |  219 +++++++++++++++++++++-----------------
 sw/source/core/layout/flylay.cxx  |   42 +++++++
 sw/source/core/layout/frmtool.cxx |   20 ++-
 sw/source/core/text/txtfly.cxx    |   17 ++
 7 files changed, 206 insertions(+), 109 deletions(-)

New commits:
commit 255147eae820b26a8522814711066a1d883a7106
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Thu Nov 16 18:47:29 2017 +0100

    RotateFlyFrame3: add support for AutoContour
    
    For transformed FlyFrames with no Border and no Padding it
    would be nice to immediately start using AutoContour, added
    first implementation to do so
    
    Change-Id: I9f82d6ff3be8e1b8fb39b33836935b32879f405c

diff --git a/sw/source/core/draw/dflyobj.cxx b/sw/source/core/draw/dflyobj.cxx
index a4466f1f9085..2dd8cffbf300 100644
--- a/sw/source/core/draw/dflyobj.cxx
+++ b/sw/source/core/draw/dflyobj.cxx
@@ -632,9 +632,9 @@ void SwVirtFlyDrawObj::NbcSetLogicRect(const tools::Rectangle& )
 //  SwVirtFlyDrawObj::Move() and Resize()
 void SwVirtFlyDrawObj::NbcMove(const Size& rSiz)
 {
-    if(GetFlyFrame()->IsFlyFreeFrame() && static_cast<SwFlyFreeFrame*>(GetFlyFrame())->isTransformableSwFrame())
+    if(GetFlyFrame()->IsFlyFreeFrame() && static_cast< SwFlyFreeFrame* >(GetFlyFrame())->isTransformableSwFrame())
     {
-        // When we have a change and are in transformed state (e.g. rotation used),
+        // RotateFlyFrame3: When we have a change and are in transformed state (e.g. rotation used),
         // we need to fall back to the un-transformed state to keep the old code below
         // working properly. Restore FrameArea and use aOutRect from old FrameArea.
         TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(GetFlyFrame())->getTransformableSwFrame());
@@ -825,7 +825,7 @@ void SwVirtFlyDrawObj::NbcCrop(const basegfx::B2DPoint& rRef, double fxFact, dou
 
     const bool bIsTransformableSwFrame(
         GetFlyFrame()->IsFlyFreeFrame() &&
-        static_cast<SwFlyFreeFrame*>(GetFlyFrame())->isTransformableSwFrame());
+        static_cast< SwFlyFreeFrame* >(GetFlyFrame())->isTransformableSwFrame());
 
     if(bIsTransformableSwFrame)
     {
@@ -977,7 +977,7 @@ void SwVirtFlyDrawObj::NbcResize(const Point& rRef, const Fraction& xFact, const
     const bool bUseRightEdge((bVertX && !bVertL2RX ) || bRTL);
     const bool bIsTransformableSwFrame(
         GetFlyFrame()->IsFlyFreeFrame() &&
-        static_cast<SwFlyFreeFrame*>(GetFlyFrame())->isTransformableSwFrame());
+        static_cast< SwFlyFreeFrame* >(GetFlyFrame())->isTransformableSwFrame());
 
     if(bIsTransformableSwFrame)
     {
diff --git a/sw/source/core/frmedt/fefly1.cxx b/sw/source/core/frmedt/fefly1.cxx
index 105689dbf848..ece412fde57c 100644
--- a/sw/source/core/frmedt/fefly1.cxx
+++ b/sw/source/core/frmedt/fefly1.cxx
@@ -369,7 +369,7 @@ void SwFEShell::SetFlyPos( const Point& rAbsPos )
     // Anchor and new RelPos will be calculated and set by the Fly
     if ( pFly->IsFlyAtContentFrame() )
     {
-        if(pFly->IsFlyFreeFrame() && static_cast<SwFlyFreeFrame*>(pFly)->isTransformableSwFrame())
+        if(pFly->IsFlyFreeFrame() && static_cast< SwFlyFreeFrame* >(pFly)->isTransformableSwFrame())
         {
             // RotateFlyFrame3: When we have a change and are in transformed state (e.g. rotation used),
             // we need to correct the absolute position (rAbsPos) which was created in
diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx
index eaae5b89059d..1bde38f6784b 100644
--- a/sw/source/core/inc/flyfrms.hxx
+++ b/sw/source/core/inc/flyfrms.hxx
@@ -37,10 +37,10 @@ private:
     // #i34753# - flag for at-page anchored Writer fly frames
     // to prevent a positioning - call of method <MakeObjPos()> -, if Writer
     // fly frame is already clipped during its format by the object formatter.
-    bool mbNoMakePos;
+    bool            mbNoMakePos : 1;
 
     // #i37068# - flag to prevent move in method <CheckClip(..)>
-    bool mbNoMoveOnCheckClip;
+    bool            mbNoMoveOnCheckClip : 1;
 
     SwRect maUnclippedFrame;
 
@@ -134,6 +134,9 @@ public:
     TransformableSwFrame* getTransformableSwFrame() { return mpTransformableSwFrame.get(); }
     const TransformableSwFrame* getTransformableSwFrame() const { return mpTransformableSwFrame.get(); }
 
+    // RotateFlyFrame3 - Support for AutoContour
+    bool supportsAutoContour() const;
+
     // RotateFlyFrame3 - Support for Transformations
     virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const override;
     virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const override;
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
index 5163fbb3f3c4..4e7639411062 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -2303,8 +2303,18 @@ void SwFlyFrame::NotifyDrawObj()
     pObj->SetRectsDirty();
     pObj->SetChanged();
     pObj->BroadcastObjectChange();
+
     if ( GetFormat()->GetSurround().IsContour() )
+    {
+        ClrContourCache( pObj );
+    }
+    else if(IsFlyFreeFrame() && static_cast< const SwFlyFreeFrame* >(this)->supportsAutoContour())
+    {
+        // RotateFlyFrame3: Also need to clear when changes happen
+        // Caution: isTransformableSwFrame is already reset when resetting rotation, so
+        // *additionally* reset in SwFlyFreeFrame::MakeAll when no more rotation
         ClrContourCache( pObj );
+    }
 }
 
 Size SwFlyFrame::CalcRel( const SwFormatFrameSize &rSz ) const
@@ -2435,120 +2445,135 @@ bool SwFlyFrame::GetContour( tools::PolyPolygon&   rContour,
     bool bRet = false;
     const bool bIsCandidate(Lower() && Lower()->IsNoTextFrame());
 
-    if(bIsCandidate && GetFormat()->GetSurround().IsContour())
+    if(bIsCandidate)
     {
-        SwNoTextNode *pNd = const_cast<SwNoTextNode*>(static_cast<const SwNoTextNode*>(static_cast<const SwContentFrame*>(Lower())->GetNode()));
-        // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic>
-        // in order to avoid load of graphic, if <SwNoTextNode> contains a graphic
-        // node and method is called for paint.
-        const GraphicObject* pGrfObj = nullptr;
-        bool bGrfObjCreated = false;
-        const SwGrfNode* pGrfNd = pNd->GetGrfNode();
-        if ( pGrfNd && _bForPaint )
-        {
-            pGrfObj = &(pGrfNd->GetGrfObj());
-        }
-        else
-        {
-            pGrfObj = new GraphicObject( pNd->GetGraphic() );
-            bGrfObjCreated = true;
-        }
-        OSL_ENSURE( pGrfObj, "SwFlyFrame::GetContour() - No Graphic/GraphicObject found at <SwNoTextNode>." );
-        if ( pGrfObj && pGrfObj->GetType() != GraphicType::NONE )
+        if(GetFormat()->GetSurround().IsContour())
         {
-            if( !pNd->HasContour() )
+            SwNoTextNode *pNd = const_cast<SwNoTextNode*>(static_cast<const SwNoTextNode*>(static_cast<const SwContentFrame*>(Lower())->GetNode()));
+            // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic>
+            // in order to avoid load of graphic, if <SwNoTextNode> contains a graphic
+            // node and method is called for paint.
+            const GraphicObject* pGrfObj = nullptr;
+            bool bGrfObjCreated = false;
+            const SwGrfNode* pGrfNd = pNd->GetGrfNode();
+            if ( pGrfNd && _bForPaint )
             {
-                // OD 16.04.2003 #i13147# - no <CreateContour> for a graphic
-                // during paint. Thus, return (value of <bRet> should be <false>).
-                if ( pGrfNd && _bForPaint )
+                pGrfObj = &(pGrfNd->GetGrfObj());
+            }
+            else
+            {
+                pGrfObj = new GraphicObject( pNd->GetGraphic() );
+                bGrfObjCreated = true;
+            }
+            OSL_ENSURE( pGrfObj, "SwFlyFrame::GetContour() - No Graphic/GraphicObject found at <SwNoTextNode>." );
+            if ( pGrfObj && pGrfObj->GetType() != GraphicType::NONE )
+            {
+                if( !pNd->HasContour() )
                 {
-                    OSL_FAIL( "SwFlyFrame::GetContour() - No Contour found at <SwNoTextNode> during paint." );
-                    return bRet;
+                    // OD 16.04.2003 #i13147# - no <CreateContour> for a graphic
+                    // during paint. Thus, return (value of <bRet> should be <false>).
+                    if ( pGrfNd && _bForPaint )
+                    {
+                        OSL_FAIL( "SwFlyFrame::GetContour() - No Contour found at <SwNoTextNode> during paint." );
+                        return bRet;
+                    }
+                    pNd->CreateContour();
                 }
-                pNd->CreateContour();
-            }
-            pNd->GetContour( rContour );
-            // The Node holds the Polygon matching the original size of the graphic
-            // We need to include the scaling here
-            SwRect aClip;
-            SwRect aOrig;
-            Lower()->Calc(pRenderContext);
-            static_cast<const SwNoTextFrame*>(Lower())->GetGrfArea( aClip, &aOrig );
-            // OD 16.04.2003 #i13147# - copy method code <SvxContourDlg::ScaleContour(..)>
-            // in order to avoid that graphic has to be loaded for contour scale.
-            //SvxContourDlg::ScaleContour( rContour, aGrf, MapUnit::MapTwip, aOrig.SSize() );
-            {
-                OutputDevice*   pOutDev = Application::GetDefaultDevice();
-                const MapMode   aDispMap( MapUnit::MapTwip );
-                const MapMode   aGrfMap( pGrfObj->GetPrefMapMode() );
-                const Size      aGrfSize( pGrfObj->GetPrefSize() );
-                Size            aOrgSize;
-                Point           aNewPoint;
-                bool            bPixelMap = aGrfMap.GetMapUnit() == MapUnit::MapPixel;
-
-                if ( bPixelMap )
-                    aOrgSize = pOutDev->PixelToLogic( aGrfSize, aDispMap );
-                else
-                    aOrgSize = OutputDevice::LogicToLogic( aGrfSize, aGrfMap, aDispMap );
-
-                if ( aOrgSize.Width() && aOrgSize.Height() )
+                pNd->GetContour( rContour );
+                // The Node holds the Polygon matching the original size of the graphic
+                // We need to include the scaling here
+                SwRect aClip;
+                SwRect aOrig;
+                Lower()->Calc(pRenderContext);
+                static_cast<const SwNoTextFrame*>(Lower())->GetGrfArea( aClip, &aOrig );
+                // OD 16.04.2003 #i13147# - copy method code <SvxContourDlg::ScaleContour(..)>
+                // in order to avoid that graphic has to be loaded for contour scale.
+                //SvxContourDlg::ScaleContour( rContour, aGrf, MapUnit::MapTwip, aOrig.SSize() );
                 {
-                    double fScaleX = (double) aOrig.Width() / aOrgSize.Width();
-                    double fScaleY = (double) aOrig.Height() / aOrgSize.Height();
+                    OutputDevice*   pOutDev = Application::GetDefaultDevice();
+                    const MapMode   aDispMap( MapUnit::MapTwip );
+                    const MapMode   aGrfMap( pGrfObj->GetPrefMapMode() );
+                    const Size      aGrfSize( pGrfObj->GetPrefSize() );
+                    Size            aOrgSize;
+                    Point           aNewPoint;
+                    bool            bPixelMap = aGrfMap.GetMapUnit() == MapUnit::MapPixel;
+
+                    if ( bPixelMap )
+                        aOrgSize = pOutDev->PixelToLogic( aGrfSize, aDispMap );
+                    else
+                        aOrgSize = OutputDevice::LogicToLogic( aGrfSize, aGrfMap, aDispMap );
 
-                    for ( sal_uInt16 j = 0, nPolyCount = rContour.Count(); j < nPolyCount; j++ )
+                    if ( aOrgSize.Width() && aOrgSize.Height() )
                     {
-                        tools::Polygon& rPoly = rContour[ j ];
+                        double fScaleX = (double) aOrig.Width() / aOrgSize.Width();
+                        double fScaleY = (double) aOrig.Height() / aOrgSize.Height();
 
-                        for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
+                        for ( sal_uInt16 j = 0, nPolyCount = rContour.Count(); j < nPolyCount; j++ )
                         {
-                            if ( bPixelMap )
-                                aNewPoint = pOutDev->PixelToLogic( rPoly[ i ], aDispMap  );
-                            else
-                                aNewPoint = OutputDevice::LogicToLogic( rPoly[ i ], aGrfMap, aDispMap  );
+                            tools::Polygon& rPoly = rContour[ j ];
 
-                            rPoly[ i ] = Point( FRound( aNewPoint.getX() * fScaleX ), FRound( aNewPoint.getY() * fScaleY ) );
+                            for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
+                            {
+                                if ( bPixelMap )
+                                    aNewPoint = pOutDev->PixelToLogic( rPoly[ i ], aDispMap  );
+                                else
+                                    aNewPoint = OutputDevice::LogicToLogic( rPoly[ i ], aGrfMap, aDispMap  );
+
+                                rPoly[ i ] = Point( FRound( aNewPoint.getX() * fScaleX ), FRound( aNewPoint.getY() * fScaleY ) );
+                            }
                         }
                     }
                 }
+                // OD 17.04.2003 #i13147# - destroy created <GraphicObject>.
+                if ( bGrfObjCreated )
+                {
+                    delete pGrfObj;
+                }
+                rContour.Move( aOrig.Left(), aOrig.Top() );
+                if( !aClip.Width() )
+                    aClip.Width( 1 );
+                if( !aClip.Height() )
+                    aClip.Height( 1 );
+                rContour.Clip( aClip.SVRect() );
+                rContour.Optimize(PolyOptimizeFlags::CLOSE);
+                bRet = true;
             }
-            // OD 17.04.2003 #i13147# - destroy created <GraphicObject>.
-            if ( bGrfObjCreated )
-            {
-                delete pGrfObj;
-            }
-            rContour.Move( aOrig.Left(), aOrig.Top() );
-            if( !aClip.Width() )
-                aClip.Width( 1 );
-            if( !aClip.Height() )
-                aClip.Height( 1 );
-            rContour.Clip( aClip.SVRect() );
-            rContour.Optimize(PolyOptimizeFlags::CLOSE);
-            bRet = true;
         }
-    }
+        else
+        {
+            const SwFlyFreeFrame* pSwFlyFreeFrame(static_cast< const SwFlyFreeFrame* >(this));
 
-    if(bRet &&
-        rContour.Count() &&
-        IsFlyFreeFrame() &&
-        static_cast<const SwFlyFreeFrame*>(this)->isTransformableSwFrame())
-    {
-        // RotateFlyFrame: Need to adapt contour to transformation
-        basegfx::B2DVector aScale, aTranslate;
-        double fRotate, fShearX;
-        getFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
-
-        if(!basegfx::fTools::equalZero(fRotate))
-        {
-            basegfx::B2DPolyPolygon aSource(rContour.getB2DPolyPolygon());
-            const basegfx::B2DPoint aCenter(getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5));
-            const basegfx::B2DHomMatrix aRotateAroundCenter(
-                basegfx::utils::createRotateAroundPoint(
-                    aCenter.getX(),
-                    aCenter.getY(),
-                    fRotate));
-            aSource.transform(aRotateAroundCenter);
-            rContour = tools::PolyPolygon(aSource);
+            if(nullptr != pSwFlyFreeFrame && pSwFlyFreeFrame->supportsAutoContour())
+            {
+                // RotateFlyFrame: use untransformed SwFrame to allow text floating around.
+                // Will be transformed below
+                const TransformableSwFrame* pTransformableSwFrame(pSwFlyFreeFrame->getTransformableSwFrame());
+                const SwRect aFrameArea(pTransformableSwFrame->getUntransformedFrameArea());
+                rContour = tools::PolyPolygon(tools::Polygon(aFrameArea.SVRect()));
+
+                if(0 != rContour.Count())
+                {
+                    // Need to adapt contour to transformation
+                    basegfx::B2DVector aScale, aTranslate;
+                    double fRotate, fShearX;
+                    getFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
+
+                    if(!basegfx::fTools::equalZero(fRotate))
+                    {
+                        basegfx::B2DPolyPolygon aSource(rContour.getB2DPolyPolygon());
+                        const basegfx::B2DPoint aCenter(getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5));
+                        const basegfx::B2DHomMatrix aRotateAroundCenter(
+                            basegfx::utils::createRotateAroundPoint(
+                                aCenter.getX(),
+                                aCenter.getY(),
+                                fRotate));
+                        aSource.transform(aRotateAroundCenter);
+                        rContour = tools::PolyPolygon(aSource);
+                    }
+
+                    bRet = true;
+                }
+            }
         }
     }
 
diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx
index 8a8c714ef351..c3cf51baa343 100644
--- a/sw/source/core/layout/flylay.cxx
+++ b/sw/source/core/layout/flylay.cxx
@@ -27,6 +27,7 @@
 #include <hints.hxx>
 #include <sectfrm.hxx>
 #include <notxtfrm.hxx>
+#include <txtfly.hxx>
 
 #include <svx/svdpage.hxx>
 #include <editeng/ulspitem.hxx>
@@ -87,6 +88,8 @@ void SwFlyFreeFrame::DestroyImpl()
 
 SwFlyFreeFrame::~SwFlyFreeFrame()
 {
+    // we are possibly in ContourCache, make sure we vanish
+    ::ClrContourCache(GetVirtDrawObj());
 }
 
 // #i28701#
@@ -268,6 +271,14 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
     }
     else
     {
+        // RotateFlyFrame3: Also need to clear ContourCache (if used),
+        // usually done in SwFlyFrame::NotifyDrawObj, but there relies on
+        // being in transform mode which is already resetted then
+        if(isTransformableSwFrame())
+        {
+            ::ClrContourCache(GetVirtDrawObj());
+        }
+
         // reset transformations to show that they are not used
         mpTransformableSwFrame.reset();
     }
@@ -283,6 +294,37 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
 #endif
 }
 
+bool SwFlyFreeFrame::supportsAutoContour() const
+{
+    if(!isTransformableSwFrame())
+    {
+        // support only when transformed, else there is no free space
+        return false;
+    }
+
+    // Check for Borders. If we have Borders, do (currently) not support,
+    // since borders do not transform with the object.
+    // (Will need to be enhanced to take into account if we have Borders and if these
+    // transform with the object)
+    SwBorderAttrAccess aAccess(SwFrame::GetCache(), this);
+    const SwBorderAttrs &rAttrs(*aAccess.Get());
+
+    if(rAttrs.IsLine())
+    {
+        return false;
+    }
+
+    // Check for Padding. Do not support when padding is used, this will
+    // produce a covered space around the object (filled with fill defines)
+
+
+
+
+
+    // else, support
+    return true;
+}
+
 // RotateFlyFrame3 - Support for Transformations - outer frame
 basegfx::B2DHomMatrix SwFlyFreeFrame::getFrameAreaTransformation() const
 {
diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx
index 7144ee460dcd..2276f7fa2b99 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -2740,11 +2740,23 @@ void Notify( SwFlyFrame *pFly, SwPageFrame *pOld, const SwRect &rOld,
             pFly->NotifyBackground( pOld, aTmp, PREP_FLY_CHGD );
         }
     }
-    else if ( pOldPrt && *pOldPrt != pFly->getFramePrintArea() &&
-              pFly->GetFormat()->GetSurround().IsContour() )
+    else if(pOldPrt && *pOldPrt != pFly->getFramePrintArea())
     {
-        // #i24097#
-        pFly->NotifyBackground( pFly->FindPageFrame(), aFrame, PREP_FLY_ARRIVE );
+        bool bNotifyBackground(pFly->GetFormat()->GetSurround().IsContour());
+
+        if(!bNotifyBackground &&
+            pFly->IsFlyFreeFrame() &&
+            static_cast< const SwFlyFreeFrame* >(pFly)->supportsAutoContour())
+        {
+            // RotateFlyFrame3: Also notify for FlyFrames which allow AutoContour
+            bNotifyBackground = true;
+        }
+
+        if(bNotifyBackground)
+        {
+            // #i24097#
+            pFly->NotifyBackground( pFly->FindPageFrame(), aFrame, PREP_FLY_ARRIVE );
+        }
     }
 }
 
diff --git a/sw/source/core/text/txtfly.cxx b/sw/source/core/text/txtfly.cxx
index fff55186d725..2fb5c47a38a4 100644
--- a/sw/source/core/text/txtfly.cxx
+++ b/sw/source/core/text/txtfly.cxx
@@ -177,7 +177,22 @@ const SwRect SwContourCache::CalcBoundRect( const SwAnchoredObject* pAnchoredObj
 {
     SwRect aRet;
     const SwFrameFormat* pFormat = &(pAnchoredObj->GetFrameFormat());
-    if( pFormat->GetSurround().IsContour() &&
+    bool bHandleContour(pFormat->GetSurround().IsContour());
+
+    if(!bHandleContour)
+    {
+        // RotateFlyFrame3: Object has no set contour, but for rotated
+        // FlyFrames we can create a 'default' contour to make text
+        // flow around the free, non-covered
+        const SwFlyFreeFrame* pSwFlyFreeFrame(dynamic_cast< const SwFlyFreeFrame* >(pAnchoredObj));
+
+        if(nullptr != pSwFlyFreeFrame && pSwFlyFreeFrame->supportsAutoContour())
+        {
+            bHandleContour = true;
+        }
+    }
+
+    if( bHandleContour &&
         ( dynamic_cast< const SwFlyFrame *>( pAnchoredObj ) ==  nullptr ||
           ( static_cast<const SwFlyFrame*>(pAnchoredObj)->Lower() &&
             static_cast<const SwFlyFrame*>(pAnchoredObj)->Lower()->IsNoTextFrame() ) ) )


More information about the Libreoffice-commits mailing list