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.gr...@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 ), _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits