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

Armin Le Grand Armin.Le.Grand at cib.de
Fri Nov 3 13:50:38 UTC 2017


 sw/source/core/doc/notxtfrm.cxx  |   75 +++++++++++++++++++-------
 sw/source/core/inc/flyfrms.hxx   |   10 +++
 sw/source/core/inc/frame.hxx     |   34 ++++++++----
 sw/source/core/inc/notxtfrm.hxx  |   10 +++
 sw/source/core/layout/flylay.cxx |   89 ++++++++++++++++++++-----------
 sw/source/core/layout/wsfrm.cxx  |  110 +++++++++++++++++++++++++++------------
 6 files changed, 234 insertions(+), 94 deletions(-)

New commits:
commit 86376903ae9dbb6c3857db72b178ae2673f3f88c
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Fri Nov 3 14:45:42 2017 +0100

    RotateFlyFrame3: Added transformation support to SwFrame
    
    The layout element SwFrame now has methods to get linear
    transformations for the geometry-defining FrameAreaDefinitions.
    These return by default the SwRect (without being relative
    for the FramePrintArea to make things easier), but are
    replaced by the now two SwFrame derivates that support
    rotation. The layout will now use the BoundRects of the
    transformations, thus supporting a future that will allow
    all kinds of free transformations (including mirror, rotation
    and shear)
    
    Change-Id: I18b85f5ddc2970a1b8c137d30b0c2ee49bb8df72

diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index 4631dbb7a2e3..4a040cedfb9d 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -143,7 +143,9 @@ static void lcl_PaintReplacement( const SwRect &rRect, const OUString &rText,
 }
 
 SwNoTextFrame::SwNoTextFrame(SwNoTextNode * const pNode, SwFrame* pSib )
-    : SwContentFrame( pNode, pSib )
+:   SwContentFrame( pNode, pSib ),
+    maFrameAreaTransformation(),
+    maFramePrintAreaTransformation()
 {
     mnFrameType = SwFrameType::NoTxt;
 }
@@ -493,34 +495,63 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
         }
     }
 
-    // RotateFlyFrame3 - inner frame
-    // After the layout is finished, apply possible set rotation to it
+    // RotateFlyFrame3 - outer frame
+    // After the unrotated layout is finished, apply possible set rotation to it
     const double fRotation(getRotation());
 
-    if(0.0 != fRotation)
+    if(basegfx::fTools::equalZero(fRotation))
     {
-        SwRect aFrameArea(getFrameArea());
-        SwRect aFramePrintArea(getFramePrintArea());
-        const Point aCenter(aFrameArea.Center());
+        // reset transformations to show that they are not used
+        maFrameAreaTransformation.identity();
+        maFramePrintAreaTransformation.identity();
+    }
+    else
+    {
+        // save Transformations to local maFrameAreaTransformation
+        // and maFramePrintAreaTransformation.
+        const Point aCenter(getFrameArea().Center());
+        const basegfx::B2DPoint aB2DCenter(aCenter.X(), aCenter.Y());
+
+        createFrameAreaTransformations(
+            maFrameAreaTransformation,
+            maFramePrintAreaTransformation,
+            fRotation,
+            aB2DCenter);
+
+        // create BoundRects of FrameAreas and re-set the FrameArea definitions
+        // to represent the rotated geometry in the layout object
+        setFrameAreaDefinitionsToBoundRangesOfTransformations(
+            maFrameAreaTransformation,
+            maFramePrintAreaTransformation);
+    }
+}
 
-        // apply rotation and re-set the FrameArea definitions
-        rotateFrameAreaDefinitionAroundPoint(aFrameArea, aFramePrintArea, aCenter, fRotation);
+// RotateFlyFrame3 - Support for Transformations - outer frame
+basegfx::B2DHomMatrix SwNoTextFrame::getFrameAreaTransformation() const
+{
+    if(!maFrameAreaTransformation.isIdentity())
+    {
+        // use pre-created transformation
+        return maFrameAreaTransformation;
+    }
 
-        if(aFrameArea != getFrameArea())
-        {
-            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
-            aFrm.setSwRect(aFrameArea);
-        }
+    // call parent
+    return SwContentFrame::getFrameAreaTransformation();
+}
 
-        if(aFramePrintArea != getFramePrintArea())
-        {
-            SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
-            aPrt.setSwRect(aFramePrintArea);
-        }
+basegfx::B2DHomMatrix SwNoTextFrame::getFramePrintAreaTransformation() const
+{
+    if(!maFramePrintAreaTransformation.isIdentity())
+    {
+        // use pre-created transformation
+        return maFramePrintAreaTransformation;
     }
+
+    // call parent
+    return SwContentFrame::getFramePrintAreaTransformation();
 }
 
-// RotateFlyFrame3 - inner frame
+// RotateFlyFrame3 - outer frame
 // Check if we contain a SwGrfNode and get possible rotation from it
 double SwNoTextFrame::getRotation() const
 {
@@ -701,7 +732,9 @@ void SwNoTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
                             }
 
                             // RotateFlyFrame3 - invalidate needed for ContentFrame (inner, this)
-                            // and LayoutFrame (outer, GetUpper)
+                            // and LayoutFrame (outer, GetUpper). It is possible to only invalidate
+                            // the outer frame, but that leads to an in-between state that gets
+                            // potentially painted
                             InvalidateAll_();
 
                             if(GetUpper())
diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx
index 91b4188fb48a..3b6ce2292bce 100644
--- a/sw/source/core/inc/flyfrms.hxx
+++ b/sw/source/core/inc/flyfrms.hxx
@@ -40,6 +40,12 @@ class SwFlyFreeFrame : public SwFlyFrame
 
     SwRect maUnclippedFrame;
 
+    // RotateFlyFrame3 - Support for Transformations, hold
+    // FrameAreaTransformation and FramePrintAreaTransformation
+    // here when rotation is used
+    basegfx::B2DHomMatrix   maFrameAreaTransformation;
+    basegfx::B2DHomMatrix   maFramePrintAreaTransformation;
+
     void CheckClip( const SwFormatFrameSize &rSz );  //'Emergency' Clipping.
 
     /** determines, if direct environment of fly frame has 'auto' size
@@ -119,6 +125,10 @@ public:
 
     // RotateFlyFrame3 - Support for outer Frame of a SwGrfNode
     virtual double getRotation() const override;
+
+    // RotateFlyFrame3 - Support for Transformations for outer Frame of a SwGrfNode
+    basegfx::B2DHomMatrix getFrameAreaTransformation() const;
+    basegfx::B2DHomMatrix getFramePrintAreaTransformation() const;
 };
 
 // Flys that are bound to LayoutFrames and not to Content
diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx
index dbef917b206e..ddd4da107e30 100644
--- a/sw/source/core/inc/frame.hxx
+++ b/sw/source/core/inc/frame.hxx
@@ -144,6 +144,20 @@ protected:
     void setFrameAreaSizeValid(bool bNew);
     void setFramePrintAreaValid(bool bNew);
 
+    // helper method to create FrameAreaTransformations based on the
+    // curent FrameAreaDefinition
+    void createFrameAreaTransformations(
+        basegfx::B2DHomMatrix& rFrameAreaTransformation,
+        basegfx::B2DHomMatrix& rFramePrintAreaTransformation,
+        double fRotation,
+        const basegfx::B2DPoint& rCenter) const;
+
+    // helper method to set FrameAreaDefinitions based on given
+    // transformations
+    void setFrameAreaDefinitionsToBoundRangesOfTransformations(
+        const basegfx::B2DHomMatrix& rFrameAreaTransformation,
+        const basegfx::B2DHomMatrix& rFramePrintAreaTransformation);
+
 public:
     SwFrameAreaDefinition();
 
@@ -196,15 +210,6 @@ public:
     };
 };
 
-// RotateFlyFrame3 - Helper method that rotates a FrameAreaDefinition content
-// around a given point. It takes care for FramePrintArea being relative to
-// FrameArea and creates the rotated BoundRects
-void rotateFrameAreaDefinitionAroundPoint(
-    SwRect& rFrameArea,
-    SwRect& rFramePrintArea,
-    const Point& rCenter,
-    double fRotation);
-
 /**
  * Base class of the Writer layout elements.
  *
@@ -834,6 +839,17 @@ public:
     // only used for SwGrfNode in inner SwFrame of a SwFlyFrame, but may
     // be used in the future. Default returns 0.0 (no rotation)
     virtual double getRotation() const;
+
+    // RotateFlyFrame3 - Support for Transformations
+    // Hand out the Transformations for the current FrameAreaDefinition
+    // for the FrameArea and FramePrintArea.
+    // FramePrintArea is not relative to FrameArea in this
+    // transformation representation (to make it easier to use and understand).
+    // There is no 'set' method since SwFrame is a layout obejct. For
+    // some cases rotation will be included (used for SwGrfNode in inner
+    // SwFrame of a SwFlyFrame)
+    basegfx::B2DHomMatrix getFrameAreaTransformation() const;
+    basegfx::B2DHomMatrix getFramePrintAreaTransformation() const;
 };
 
 inline bool SwFrame::IsInDocBody() const
diff --git a/sw/source/core/inc/notxtfrm.hxx b/sw/source/core/inc/notxtfrm.hxx
index a1936193af44..29163e3117d2 100644
--- a/sw/source/core/inc/notxtfrm.hxx
+++ b/sw/source/core/inc/notxtfrm.hxx
@@ -30,6 +30,12 @@ class SwNoTextFrame: public SwContentFrame
 {
     friend void FrameFinit();
 
+    // RotateFlyFrame3 - Support for Transformation, hold
+    // FrameAreaTransformation and FramePrintAreaTransformation
+    // here when rotation is used
+    basegfx::B2DHomMatrix   maFrameAreaTransformation;
+    basegfx::B2DHomMatrix   maFramePrintAreaTransformation;
+
     const Size& GetSize() const;
 
     void Format ( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr ) override;
@@ -60,6 +66,10 @@ public:
 
     // RotateFlyFrame3 - Support for inner frame of a SwGrfNode
     virtual double getRotation() const override;
+
+    // RotateFlyFrame3 - Support for Transformations for inner frame of a SwGrfNode
+    basegfx::B2DHomMatrix getFrameAreaTransformation() const;
+    basegfx::B2DHomMatrix getFramePrintAreaTransformation() const;
 };
 
 #endif
diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx
index 7a2b6de8891b..96c466a604be 100644
--- a/sw/source/core/layout/flylay.cxx
+++ b/sw/source/core/layout/flylay.cxx
@@ -44,13 +44,16 @@
 
 using namespace ::com::sun::star;
 
-SwFlyFreeFrame::SwFlyFreeFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) :
-    SwFlyFrame( pFormat, pSib, pAnch ),
+SwFlyFreeFrame::SwFlyFreeFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch )
+:   SwFlyFrame( pFormat, pSib, pAnch ),
     // #i34753#
     mbNoMakePos( false ),
     // #i37068#
     mbNoMoveOnCheckClip( false ),
-    maUnclippedFrame( )
+    maUnclippedFrame( ),
+    // RotateFlyFrame3
+    maFrameAreaTransformation(),
+    maFramePrintAreaTransformation()
 {
 }
 
@@ -223,36 +226,35 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
     }
 
     // RotateFlyFrame3 - inner frame
+    // After the unrotated layout is finished, apply possible set rotation to it
     const double fRotation(getRotation());
 
-    if(0.0 != fRotation)
+    if(basegfx::fTools::equalZero(fRotation))
     {
-        SwRect aFrameArea(getFrameArea());
-        SwRect aFramePrintArea(getFramePrintArea());
-        Point aCenter(aFrameArea.Center());
-
-        if(GetUpper())
-        {
-            // get center from outer frame (layout frame)
-            const SwRect aUpperFrameArea(GetUpper()->getFrameArea());
-
-            aCenter = aUpperFrameArea.Center();
-        }
-
-        // apply rotation and re-set the FrameArea definitions
-        rotateFrameAreaDefinitionAroundPoint(aFrameArea, aFramePrintArea, aCenter, fRotation);
-
-        if(aFrameArea != getFrameArea())
-        {
-            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
-            aFrm.setSwRect(aFrameArea);
-        }
-
-        if(aFramePrintArea != getFramePrintArea())
-        {
-            SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
-            aPrt.setSwRect(aFramePrintArea);
-        }
+        // reset transformations to show that they are not used
+        maFrameAreaTransformation.identity();
+        maFramePrintAreaTransformation.identity();
+    }
+    else
+    {
+        // save Transformations to local maFrameAreaTransformation
+        // and maFramePrintAreaTransformation.
+
+        // get center from outer frame (layout frame) to be on the safe side
+        const Point aCenter(GetUpper() ? GetUpper()->getFrameArea().Center() : getFrameArea().Center());
+        const basegfx::B2DPoint aB2DCenter(aCenter.X(), aCenter.Y());
+
+        createFrameAreaTransformations(
+            maFrameAreaTransformation,
+            maFramePrintAreaTransformation,
+            fRotation,
+            aB2DCenter);
+
+        // create BoundRects of FrameAreas and re-set the FrameArea definitions
+        // to represent the rotated geometry in the layout object
+        setFrameAreaDefinitionsToBoundRangesOfTransformations(
+            maFrameAreaTransformation,
+            maFramePrintAreaTransformation);
     }
 
     Unlock();
@@ -266,7 +268,32 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
 #endif
 }
 
-// RotateFlyFrame3
+// RotateFlyFrame3 - Support for Transformations - outer frame
+basegfx::B2DHomMatrix SwFlyFreeFrame::getFrameAreaTransformation() const
+{
+    if(!maFrameAreaTransformation.isIdentity())
+    {
+        // use pre-created transformation
+        return maFrameAreaTransformation;
+    }
+
+    // call parent
+    return SwFlyFrame::getFrameAreaTransformation();
+}
+
+basegfx::B2DHomMatrix SwFlyFreeFrame::getFramePrintAreaTransformation() const
+{
+    if(!maFramePrintAreaTransformation.isIdentity())
+    {
+        // use pre-created transformation
+        return maFramePrintAreaTransformation;
+    }
+
+    // call parent
+    return SwFlyFrame::getFramePrintAreaTransformation();
+}
+
+// RotateFlyFrame3 - inner frame
 double SwFlyFreeFrame::getRotation() const
 {
     // SwLayoutFrame::Lower() != SwFrame::GetLower(), but SwFrame::GetLower()
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index 2942558251d7..8700bbe65f7d 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -105,54 +105,98 @@ SwFrameAreaDefinition::FramePrintAreaWriteAccess::~FramePrintAreaWriteAccess()
     }
 }
 
-void rotateFrameAreaDefinitionAroundPoint(
-    SwRect& rFrameArea,
-    SwRect& rFramePrintArea,
-    const Point& rCenter,
-    double fRotation)
+void SwFrameAreaDefinition::createFrameAreaTransformations(
+    basegfx::B2DHomMatrix& rFrameAreaTransformation,
+    basegfx::B2DHomMatrix& rFramePrintAreaTransformation,
+    double fRotation,
+    const basegfx::B2DPoint& rCenter) const
 {
-    if(!basegfx::fTools::equalZero(fRotation) && rFrameArea.HasArea())
+    // save Transformations to rFrameAreaTransformation and
+    // rFramePrintAreaTransformation. Do not forget that PrintArea
+    // is *relative* to FrameArea
+    const basegfx::B2DHomMatrix aRotateAroundCenter(
+        basegfx::utils::createRotateAroundPoint(
+            rCenter.getX(),
+            rCenter.getY(),
+            fRotation));
+    rFrameAreaTransformation = aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix(
+        getFrameArea().Width(), getFrameArea().Height(),
+        getFrameArea().Left(), getFrameArea().Top());
+    rFramePrintAreaTransformation = aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix(
+        getFramePrintArea().Width(), getFramePrintArea().Height(),
+        getFramePrintArea().Left() + getFrameArea().Left(), getFramePrintArea().Top() + getFrameArea().Top());
+}
+
+void SwFrameAreaDefinition::setFrameAreaDefinitionsToBoundRangesOfTransformations(
+    const basegfx::B2DHomMatrix& rFrameAreaTransformation,
+    const basegfx::B2DHomMatrix& rFramePrintAreaTransformation)
+{
+    if(!rFrameAreaTransformation.isIdentity())
     {
-        basegfx::B2DRange aFrameRange(
-            rFrameArea.Left(),
-            rFrameArea.Top(),
-            rFrameArea.Right(),
-            rFrameArea.Bottom());
-        const basegfx::B2DPoint aOldTopLeft(aFrameRange.getMinimum());
-        const basegfx::B2DHomMatrix aRotateAroundCenter(basegfx::utils::createRotateAroundPoint(rCenter.X(), rCenter.Y(), fRotation));
+        basegfx::B2DRange aRangeFrameArea(0.0, 0.0, 1.0, 1.0);
 
-        aFrameRange.transform(aRotateAroundCenter);
-        rFrameArea = SwRect(
-            basegfx::fround(aFrameRange.getMinX()),
-            basegfx::fround(aFrameRange.getMinY()),
-            basegfx::fround(aFrameRange.getWidth()),
-            basegfx::fround(aFrameRange.getHeight()));
+        aRangeFrameArea.transform(rFrameAreaTransformation);
 
-        if(rFramePrintArea.HasArea())
+        const SwRect aNewFrm(
+            basegfx::fround(aRangeFrameArea.getMinX()), basegfx::fround(aRangeFrameArea.getMinY()),
+            basegfx::fround(aRangeFrameArea.getWidth()), basegfx::fround(aRangeFrameArea.getHeight()));
+
+        if(aNewFrm != getFrameArea())
         {
-            basegfx::B2DRange aFramePrintRange(
-                rFramePrintArea.Left() + aOldTopLeft.getX(),
-                rFramePrintArea.Top() + aOldTopLeft.getY(),
-                rFramePrintArea.Right() + aOldTopLeft.getX(),
-                rFramePrintArea.Bottom() + aOldTopLeft.getY());
-            const basegfx::B2DPoint aNewTopLeft(aFrameRange.getMinimum());
+            maFrameArea = aNewFrm;
+        }
+    }
+
+    if(!rFramePrintAreaTransformation.isIdentity())
+    {
+        basegfx::B2DRange aRangeFramePrintArea(0.0, 0.0, 1.0, 1.0);
+
+        aRangeFramePrintArea.transform(rFramePrintAreaTransformation);
+
+        const SwRect aNewPrt(
+            basegfx::fround(aRangeFramePrintArea.getMinX()) - getFrameArea().Left(),
+            basegfx::fround(aRangeFramePrintArea.getMinY()) - getFrameArea().Top(),
+            basegfx::fround(aRangeFramePrintArea.getWidth()),
+            basegfx::fround(aRangeFramePrintArea.getHeight()));
 
-            aFramePrintRange.transform(aRotateAroundCenter);
-            rFramePrintArea = SwRect(
-                basegfx::fround(aFramePrintRange.getMinX() - aNewTopLeft.getX()),
-                basegfx::fround(aFramePrintRange.getMinY() - aNewTopLeft.getY()),
-                basegfx::fround(aFramePrintRange.getWidth()),
-                basegfx::fround(aFramePrintRange.getHeight()));
+        if(aNewPrt != getFramePrintArea())
+        {
+            maFramePrintArea = aNewPrt;
         }
     }
 }
 
-// RotateFlyFrame3 - get a possible rotation from SwFrame, default returns 0.0 (no rotation)
+// RotateFlyFrame3 - get a possible rotation from SwFrame
 double SwFrame::getRotation() const
 {
+    // default returns 0.0 (no rotation)
     return 0.0;
 }
 
+// RotateFlyFrame3 - Support for Transformations
+basegfx::B2DHomMatrix SwFrame::getFrameAreaTransformation() const
+{
+    // default implementation hands out FrameArea (outer frame)
+    const SwRect& rFrameArea(getFrameArea());
+
+    return basegfx::utils::createScaleTranslateB2DHomMatrix(
+        rFrameArea.Width(), rFrameArea.Height(),
+        rFrameArea.Left(), rFrameArea.Top());
+}
+
+basegfx::B2DHomMatrix SwFrame::getFramePrintAreaTransformation() const
+{
+    // default implementation hands out FramePrintArea (outer frame)
+    // Take into account that FramePrintArea is relative to FrameArea
+    const SwRect& rFrameArea(getFrameArea());
+    const SwRect& rFramePrintArea(getFramePrintArea());
+
+    return basegfx::utils::createScaleTranslateB2DHomMatrix(
+        rFramePrintArea.Width(), rFramePrintArea.Height(),
+        rFramePrintArea.Left() + rFrameArea.Left(),
+        rFramePrintArea.Top() + rFrameArea.Top());
+}
+
 SwFrame::SwFrame( SwModify *pMod, SwFrame* pSib )
 :   SwFrameAreaDefinition(),
     SwClient( pMod ),


More information about the Libreoffice-commits mailing list