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

Armin Le Grand Armin.Le.Grand at cib.de
Wed Nov 15 17:56:13 UTC 2017


 sw/source/core/draw/dflyobj.cxx  |   11 +++---
 sw/source/core/frmedt/fefly1.cxx |   19 ++++++++++-
 sw/source/core/inc/flyfrms.hxx   |    1 
 sw/source/core/inc/frame.hxx     |   34 +++++++++-----------
 sw/source/core/layout/fly.cxx    |   32 ++++++++++++++++++-
 sw/source/core/layout/wsfrm.cxx  |   64 ++++++++++++++++++++++++++++++++-------
 6 files changed, 124 insertions(+), 37 deletions(-)

New commits:
commit 724a9c37c94ea3fc03b17ec9b2798db312e715f3
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Nov 15 18:51:21 2017 +0100

    RotateFlyFrame3: Further adaptions
    
    Restructured TransformableSwFrame to directly re-create
    last non-transformed SwFrame(s) from the SwFrameAreaDefinition
    from the current Transformations, offering the untransformed
    SwRect(s) now for usage.
    Identified and corrected erro when FlyFrame was translated
    using keyboard, the accessing method needed to adapt positon
    in the transformed case.
    Started to look at Contour stuff, adapted a set contour to be
    correctly used by adapting it as needed in the transformed case.
    
    Change-Id: I0d5f14958bcd6f826b9abd53f1f47b7d0bc5a0e2

diff --git a/sw/source/core/draw/dflyobj.cxx b/sw/source/core/draw/dflyobj.cxx
index bc16d4712ce2..a4466f1f9085 100644
--- a/sw/source/core/draw/dflyobj.cxx
+++ b/sw/source/core/draw/dflyobj.cxx
@@ -1000,13 +1000,14 @@ void SwVirtFlyDrawObj::NbcResize(const Point& rRef, const Fraction& xFact, const
         basegfx::B2DVector aScale, aTranslate;
         double fRotate, fShearX;
         aNewMat.decompose(aScale, aTranslate, fRotate, fShearX);
+        const basegfx::B2DVector aAbsScale(basegfx::absolute(aScale));
 
-        // create new modified OutRect
+        // create new modified, but untransformed OutRect
         aOutRect = tools::Rectangle(
-            basegfx::fround(aCenter.getX() - (0.5 * aScale.getX())),
-            basegfx::fround(aCenter.getY() - (0.5 * aScale.getY())),
-            basegfx::fround(aCenter.getX() + (0.5 * aScale.getX())),
-            basegfx::fround(aCenter.getY() + (0.5 * aScale.getY())));
+            basegfx::fround(aCenter.getX() - (0.5 * aAbsScale.getX())),
+            basegfx::fround(aCenter.getY() - (0.5 * aAbsScale.getY())),
+            basegfx::fround(aCenter.getX() + (0.5 * aAbsScale.getX())),
+            basegfx::fround(aCenter.getY() + (0.5 * aAbsScale.getY())));
 
         // restore FrameAreas so that actions below not adapted to new
         // full transformations take the correct actions
diff --git a/sw/source/core/frmedt/fefly1.cxx b/sw/source/core/frmedt/fefly1.cxx
index f36eac32c09c..105689dbf848 100644
--- a/sw/source/core/frmedt/fefly1.cxx
+++ b/sw/source/core/frmedt/fefly1.cxx
@@ -368,7 +368,24 @@ void SwFEShell::SetFlyPos( const Point& rAbsPos )
     // Set an anchor starting from the absolute position for paragraph bound Flys
     // Anchor and new RelPos will be calculated and set by the Fly
     if ( pFly->IsFlyAtContentFrame() )
-        static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos( rAbsPos );
+    {
+        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
+            // transformed coordinates to untransformed state
+            TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(pFly)->getTransformableSwFrame());
+            const SwRect aUntransformedFrameArea(pTransformableSwFrame->getUntransformedFrameArea());
+            const Point aNewAbsPos(
+                rAbsPos.X() + aUntransformedFrameArea.Left() - pFly->getFrameArea().Left(),
+                rAbsPos.Y() + aUntransformedFrameArea.Top() - pFly->getFrameArea().Top());
+            static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos(aNewAbsPos);
+        }
+        else
+        {
+            static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos( rAbsPos );
+        }
+    }
     else
     {
             const SwFrame *pAnch = pFly->GetAnchorFrame();
diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx
index 5334a0269447..eaae5b89059d 100644
--- a/sw/source/core/inc/flyfrms.hxx
+++ b/sw/source/core/inc/flyfrms.hxx
@@ -25,6 +25,7 @@
 
 // #i28701#
 class SwFlyAtContentFrame;
+class SwNoTextFrame;
 
 double getLocalFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame);
 
diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx
index c0df129946f1..cc455a995008 100644
--- a/sw/source/core/inc/frame.hxx
+++ b/sw/source/core/inc/frame.hxx
@@ -213,8 +213,8 @@ public:
 };
 
 /// RotateFlyFrame3: Helper class when you want to make your SwFrame derivate
-/// transformable. It provides some tooling to do so. To use,
-/// derive your SwFrame from it
+/// transformable. It provides some tooling to do so. To use, add as member
+/// (see e.g. SwFlyFreeFrame which uses 'std::unique_ptr< TransformableSwFrame >')
 class SW_DLLPUBLIC TransformableSwFrame
 {
 private:
@@ -222,54 +222,50 @@ private:
     SwFrameAreaDefinition&  mrSwFrameAreaDefinition;
 
     // FrameAreaTransformation and FramePrintAreaTransformation
-    // here when more than translate/scale is used (e.g. rotation)
+    // !identtity when needed (translate/scale is used (e.g. rotation))
     basegfx::B2DHomMatrix   maFrameAreaTransformation;
     basegfx::B2DHomMatrix   maFramePrintAreaTransformation;
 
-    // last saved versions of SwRect(s) from SwFrameAreaDefinition,
-    // set from adaptFrameAreasToTransformations before modifying
-    // SwFrameAreaDefinition(s), used for restore from
-    // restoreFrameAreas
-    SwRect                  maSavedFrameArea;
-    SwRect                  maSavedFramePrintArea;
-
 public:
     TransformableSwFrame(SwFrameAreaDefinition& rSwFrameAreaDefinition)
     :   mrSwFrameAreaDefinition(rSwFrameAreaDefinition),
         maFrameAreaTransformation(),
-        maFramePrintAreaTransformation(),
-        maSavedFrameArea(),
-        maSavedFramePrintArea()
+        maFramePrintAreaTransformation()
     {
     }
 
-    // Support for Transformations for inner frame of a SwGrfNode
+    // get SwFrameArea in transformation form
     const basegfx::B2DHomMatrix& getLocalFrameAreaTransformation() const
     {
         return maFrameAreaTransformation;
     }
 
+    // get SwFramePrintArea in transformation form
     const basegfx::B2DHomMatrix& getLocalFramePrintAreaTransformation() const
     {
         return maFramePrintAreaTransformation;
     }
 
+    // Helpers to re-create the untransformed SwRect(s) originally
+    // in the SwFrameAreaDefinition, based on the current Transformations.
+    SwRect getUntransformedFrameArea() const;
+    SwRect getUntransformedFramePrintArea() const;
+
     // Helper method to re-create FrameAreaTransformations based on the
-    // curent FrameAreaDefinition, given rotation and Center
+    // curent FrameAreaDefinition transformed by given rotation and Center
     void createFrameAreaTransformations(
         double fRotation,
         const basegfx::B2DPoint& rCenter);
 
     // Tooling method to reset the SwRect(s) in the current
     // SwFrameAreaDefinition which are already apapted to
-    // Transformation back to the untransformed state that was
-    // last saved (see adaptFrameAreasToTransformations).
+    // Transformation back to the untransformed state, using
+    // the getUntransformedFrame*Area calls above when needed.
     // Only the SwRect(s) are changed back, not the transformations.
     void restoreFrameAreas();
 
     // Re-Creates the SwRect(s) as BoundAreas based on the current
-    // set Transformations, also saves the last SwRect(s) to the save
-    // values.
+    // set Transformations.
     void adaptFrameAreasToTransformations();
 
     // Modify current definitions by applying the given transformation
diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
index 684b989d76b8..5163fbb3f3c4 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -62,6 +62,8 @@
 #include <IDocumentLayoutAccess.hxx>
 #include <textboxhelper.hxx>
 #include <txtfly.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
 
 using namespace ::com::sun::star;
 
@@ -2431,8 +2433,9 @@ bool SwFlyFrame::GetContour( tools::PolyPolygon&   rContour,
 {
     vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
     bool bRet = false;
-    if( GetFormat()->GetSurround().IsContour() && Lower() &&
-        Lower()->IsNoTextFrame() )
+    const bool bIsCandidate(Lower() && Lower()->IsNoTextFrame());
+
+    if(bIsCandidate && GetFormat()->GetSurround().IsContour())
     {
         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>
@@ -2524,6 +2527,31 @@ bool SwFlyFrame::GetContour( tools::PolyPolygon&   rContour,
             bRet = true;
         }
     }
+
+    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);
+        }
+    }
+
     return bRet;
 }
 
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index d090d056f127..08debf8408e2 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -150,6 +150,55 @@ void SwFrameAreaDefinition::transform_translate(const Point& rOffset)
     }
 }
 
+SwRect TransformableSwFrame::getUntransformedFrameArea() const
+{
+    const basegfx::B2DHomMatrix& rSource(getLocalFrameAreaTransformation());
+
+    if(rSource.isIdentity())
+    {
+        return mrSwFrameAreaDefinition.getFrameArea();
+    }
+    else
+    {
+        basegfx::B2DVector aScale, aTranslate;
+        double fRotate, fShearX;
+        rSource.decompose(aScale, aTranslate, fRotate, fShearX);
+        const basegfx::B2DPoint aCenter(rSource * basegfx::B2DPoint(0.5, 0.5));
+        const basegfx::B2DVector aAbsScale(basegfx::absolute(aScale));
+
+        return SwRect(
+            basegfx::fround(aCenter.getX() - (0.5 * aAbsScale.getX())),
+            basegfx::fround(aCenter.getY() - (0.5 * aAbsScale.getY())),
+            basegfx::fround(aAbsScale.getX()),
+            basegfx::fround(aAbsScale.getY()));
+    }
+}
+
+SwRect TransformableSwFrame::getUntransformedFramePrintArea() const
+{
+    const basegfx::B2DHomMatrix& rSource(getLocalFramePrintAreaTransformation());
+
+    if(rSource.isIdentity())
+    {
+        return mrSwFrameAreaDefinition.getFramePrintArea();
+    }
+    else
+    {
+        basegfx::B2DVector aScale, aTranslate;
+        double fRotate, fShearX;
+        rSource.decompose(aScale, aTranslate, fRotate, fShearX);
+        const basegfx::B2DPoint aCenter(rSource * basegfx::B2DPoint(0.5, 0.5));
+        const basegfx::B2DVector aAbsScale(basegfx::absolute(aScale));
+        const SwRect aUntransformedFrameArea(getUntransformedFrameArea());
+
+        return SwRect(
+            basegfx::fround(aCenter.getX() - (0.5 * aAbsScale.getX())) - aUntransformedFrameArea.Left(),
+            basegfx::fround(aCenter.getY() - (0.5 * aAbsScale.getY())) - aUntransformedFrameArea.Top(),
+            basegfx::fround(aAbsScale.getX()),
+            basegfx::fround(aAbsScale.getY()));
+    }
+}
+
 void TransformableSwFrame::createFrameAreaTransformations(
     double fRotation,
     const basegfx::B2DPoint& rCenter)
@@ -182,7 +231,6 @@ void TransformableSwFrame::adaptFrameAreasToTransformations()
 
         if(aNewFrm != mrSwFrameAreaDefinition.getFrameArea())
         {
-            maSavedFrameArea = mrSwFrameAreaDefinition.getFrameArea();
             SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(mrSwFrameAreaDefinition);
             aFrm.setSwRect(aNewFrm);
         }
@@ -200,7 +248,6 @@ void TransformableSwFrame::adaptFrameAreasToTransformations()
 
         if(aNewPrt != mrSwFrameAreaDefinition.getFramePrintArea())
         {
-            maSavedFramePrintArea = mrSwFrameAreaDefinition.getFramePrintArea();
             SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(mrSwFrameAreaDefinition);
             aPrt.setSwRect(aNewPrt);
         }
@@ -210,20 +257,17 @@ void TransformableSwFrame::adaptFrameAreasToTransformations()
 void TransformableSwFrame::restoreFrameAreas()
 {
     // This can be done fully based on the Transformations currently
-    // set (and I did this in the beginning and it may be necessary
-    // again later), but for simplicity and performance now done using
-    // the last save values for the SwRect(s), see above
-
-    if(!getLocalFrameAreaTransformation().isIdentity() && maSavedFrameArea != mrSwFrameAreaDefinition.getFrameArea())
+    // set, so use this. Only needed when transformation *is* used
+    if(!getLocalFrameAreaTransformation().isIdentity())
     {
         SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(mrSwFrameAreaDefinition);
-        aFrm.setSwRect(maSavedFrameArea);
+        aFrm.setSwRect(getUntransformedFrameArea());
     }
 
-    if(!getLocalFramePrintAreaTransformation().isIdentity() && maSavedFramePrintArea != mrSwFrameAreaDefinition.getFramePrintArea())
+    if(!getLocalFramePrintAreaTransformation().isIdentity())
     {
         SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(mrSwFrameAreaDefinition);
-        aPrt.setSwRect(maSavedFramePrintArea);
+        aPrt.setSwRect(getUntransformedFramePrintArea());
     }
 }
 


More information about the Libreoffice-commits mailing list